diff --git a/BUILD.gn b/BUILD.gn index 7b8b538769dfc216994ed26445f9b757d1059841..f8a5297c4da9e7ffcc8243ecfa63ff7b669cc6a8 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -332,6 +332,7 @@ if (!ark_standalone_build) { "$ark_root/libpandabase/tests:unittest", "$ark_root/libpandafile/tests:unittest", "$ark_root/libziparchive/tests:unittest", + "$ark_root/libabckit/tests:unittest", ] } diff --git a/abc2program/BUILD.gn b/abc2program/BUILD.gn index cd858387d501415f2eab1a910f0a0dff0b197e9c..52d932848548793fa12becac1f0de8b4da7623ea 100644 --- a/abc2program/BUILD.gn +++ b/abc2program/BUILD.gn @@ -116,6 +116,8 @@ ohos_static_library("abc2program_frontend_static") { ohos_executable("abc2prog") { sources = [ "abc2prog_main.cpp" ] + cflags_cc = ["-Wno-unused-command-line-argument"] + include_dirs = [ "$target_gen_dir", "$root_gen_dir/libpandabase", @@ -138,8 +140,9 @@ ohos_executable("abc2prog") { external_deps = [ sdk_libc_secshared_dep ] libs = platform_libs + ldflags = ["-Wno-unused-command-line-argument"] if (!is_mac && !is_mingw) { - ldflags = platform_ldflags + ldflags += platform_ldflags } install_enable = false diff --git a/abc2program/abc2program_driver.cpp b/abc2program/abc2program_driver.cpp index 3192a13e39e07cae0d6e0f01cb0c7f5b0149f413..6f217d3de16eb694cf0a497c6eade4f101bfb61c 100644 --- a/abc2program/abc2program_driver.cpp +++ b/abc2program/abc2program_driver.cpp @@ -54,9 +54,6 @@ bool Abc2ProgramDriver::Compile(const std::string &input_file_path, pandasm::Pro for (size_t i = 0; i < classes.size(); i++) { uint32_t class_idx = classes[i]; panda_file::File::EntityId record_id(class_idx); - if (file.IsExternal(record_id)) { - continue; - } abc2program::Abc2ProgramEntityContainer entity_container( file, program_, compiler_.GetDebugInfoExtractor(), class_idx); abc2program::AbcClassProcessor class_processor(record_id, entity_container); diff --git a/abc2program/abc_annotation_processor.cpp b/abc2program/abc_annotation_processor.cpp index 04db737936540c7f524b86200292e38c975d4c81..ebc5c1b5d6702ec69e46e5d9d51edba50d84488c 100644 --- a/abc2program/abc_annotation_processor.cpp +++ b/abc2program/abc_annotation_processor.cpp @@ -15,6 +15,8 @@ #include "abc_annotation_processor.h" #include "abc2program_log.h" +#include "abc_literal_array_processor.h" +#include "file-inl.h" namespace panda::abc2program { @@ -24,12 +26,14 @@ AbcAnnotationProcessor::AbcAnnotationProcessor(panda_file::File::EntityId entity : AbcFileEntityProcessor(entity_id, entity_container), function_(function) { annotation_data_accessor_ = std::make_unique(*file_, entity_id_); - auto type_descriptor_name = GetStringById(annotation_data_accessor_->GetClassId()); - annotation_name_ = pandasm::Type::FromDescriptor(type_descriptor_name).GetName(); + annotation_name_ = pandasm::Type::FromDescriptor(GetStringById(annotation_data_accessor_->GetClassId())).GetName(); } void AbcAnnotationProcessor::FillProgramData() { + if (annotation_name_.empty()) { + return; + } FillAnnotation(); } @@ -48,16 +52,54 @@ void AbcAnnotationProcessor::FillAnnotationElements(std::vectorGetCount(); ++i) { auto annotation_data_accessor_elem = annotation_data_accessor_->GetElement(i); auto annotation_elem_name = GetStringById(annotation_data_accessor_elem.GetNameId()); - auto value = annotation_data_accessor_elem.GetScalarValue().GetValue(); auto value_type = pandasm::Value::GetCharAsType(annotation_data_accessor_->GetTag(i).GetItem()); switch (value_type) { + case pandasm::Value::Type::U1: { + auto value = annotation_data_accessor_elem.GetScalarValue().Get(); + pandasm::AnnotationElement annotation_element( + annotation_elem_name, std::make_unique( + pandasm::ScalarValue::Create(value))); + elements.emplace_back(annotation_element); + break; + } case pandasm::Value::Type::U32: { + auto value = annotation_data_accessor_elem.GetScalarValue().Get(); pandasm::AnnotationElement annotation_element( annotation_elem_name, std::make_unique( pandasm::ScalarValue::Create(value))); elements.emplace_back(annotation_element); break; } + case pandasm::Value::Type::F64: { + auto value = annotation_data_accessor_elem.GetScalarValue().Get(); + pandasm::AnnotationElement annotation_element( + annotation_elem_name, std::make_unique( + pandasm::ScalarValue::Create(value))); + elements.emplace_back(annotation_element); + break; + } + case pandasm::Value::Type::STRING: { + auto value = annotation_data_accessor_elem.GetScalarValue().Get(); + std::string_view string_value { + reinterpret_cast(file_->GetStringData(panda_file::File::EntityId(value)).data)}; + pandasm::AnnotationElement annotation_element( + annotation_elem_name, std::make_unique( + pandasm::ScalarValue::Create(string_value))); + elements.emplace_back(annotation_element); + break; + } + case pandasm::Value::Type::LITERALARRAY: { + auto value = annotation_data_accessor_elem.GetScalarValue().Get(); + panda_file::LiteralDataAccessor lit_data_accessor(*file_, file_->GetLiteralArraysId()); + AbcLiteralArrayProcessor lit_array_proc(panda_file::File::EntityId{value}, entity_container_, lit_data_accessor); + lit_array_proc.FillProgramData(); + std::string name = entity_container_.GetLiteralArrayIdName(panda_file::File::EntityId{value}); + pandasm::AnnotationElement annotation_element( + annotation_elem_name, std::make_unique( + pandasm::ScalarValue::Create(name))); + elements.emplace_back(annotation_element); + break; + } default: UNREACHABLE(); } diff --git a/abc2program/abc_class_processor.cpp b/abc2program/abc_class_processor.cpp index 8e65728f831a74ee0c7b6e5d17eb317204c64402..27c65ffd749fea022f60e5f5c5703d3653037b16 100644 --- a/abc2program/abc_class_processor.cpp +++ b/abc2program/abc_class_processor.cpp @@ -14,6 +14,7 @@ */ #include +#include #include "abc_class_processor.h" #include "abc_field_processor.h" #include "abc_literal_array_processor.h" @@ -25,7 +26,14 @@ namespace panda::abc2program { AbcClassProcessor::AbcClassProcessor(panda_file::File::EntityId entity_id, Abc2ProgramEntityContainer &entity_container) : AbcFileEntityProcessor(entity_id, entity_container), record_(pandasm::Record("", LANG_ECMA)) { - class_data_accessor_ = std::make_unique(*file_, entity_id_); + if (!file_->IsExternal(entity_id_)) { + class_data_accessor_ = std::make_unique(*file_, entity_id_); + } +} + +bool IsSystemType(const std::string &type_name) +{ + return type_name.find('[') != std::string::npos; } void AbcClassProcessor::FillProgramData() @@ -39,7 +47,12 @@ void AbcClassProcessor::FillProgramData() void AbcClassProcessor::FillRecord() { FillRecordName(); - record_.metadata->SetAccessFlags(class_data_accessor_->GetAccessFlags()); + if (IsSystemType(record_.name)) { + return; + } + if (!file_->IsExternal(entity_id_)) { + record_.metadata->SetAccessFlags(class_data_accessor_->GetAccessFlags()); + } ASSERT(program_->record_table.count(record_.name) == 0); FillRecordData(); program_->record_table.emplace(record_.name, std::move(record_)); @@ -76,6 +89,9 @@ void AbcClassProcessor::FillRecordAnnotations() void AbcClassProcessor::FillRecordSourceFile() { + if (file_->IsExternal(entity_id_)) { + return; + } std::optional source_file_id = class_data_accessor_->GetSourceFileId(); if (source_file_id.has_value()) { record_.source_file = GetStringById(source_file_id.value()); diff --git a/abc2program/abc_field_processor.cpp b/abc2program/abc_field_processor.cpp index 38907e59a29a66eaf0b9e60e799d5fa53290de10..b92357bf54845dcc51071fa9f8930223f675763e 100644 --- a/abc2program/abc_field_processor.cpp +++ b/abc2program/abc_field_processor.cpp @@ -14,7 +14,11 @@ */ #include "abc_field_processor.h" +#include #include "abc2program_log.h" +#include "abc_literal_array_processor.h" +#include "file-inl.h" +#include "literal_data_accessor.h" namespace panda::abc2program { @@ -73,14 +77,18 @@ void AbcFieldProcessor::FillMetaDataValue() { switch (field_.type.GetId()) { case panda_file::Type::TypeId::U32: { - uint32_t module_literal_array_id = field_data_accessor_->GetValue().value(); + uint32_t val = field_data_accessor_->GetValue().value(); if (record_.name == ES_MODULE_RECORD || field_.name == MODULE_RECORD_IDX) { - entity_container_.AddModuleLiteralArrayId(module_literal_array_id); - auto module_literal_array_id_name = entity_container_.GetLiteralArrayIdName(module_literal_array_id); + entity_container_.AddModuleLiteralArrayId(val); + auto module_literal_array_id_name = entity_container_.GetLiteralArrayIdName(val); field_.metadata->SetValue(pandasm::ScalarValue::Create( module_literal_array_id_name)); + } else if (record_.name == ES_SCOPE_NAMES_RECORD || field_.name == ES_SCOPE_NAMES_RECORD) { + entity_container_.AddUnnestedLiteralArrayId(val); + auto literal_array_id_name = entity_container_.GetLiteralArrayIdName(val); + field_.metadata->SetValue(pandasm::ScalarValue::Create( + literal_array_id_name)); } else { - const uint32_t val = field_data_accessor_->GetValue().value(); field_.metadata->SetValue(pandasm::ScalarValue::Create(val)); } break; @@ -90,7 +98,44 @@ void AbcFieldProcessor::FillMetaDataValue() field_.metadata->SetValue(pandasm::ScalarValue::Create(val)); break; } - default: + case panda_file::Type::TypeId::F64: { + std::optional val = field_data_accessor_->GetValue(); + if (val.has_value()) { + field_.metadata->SetValue(pandasm::ScalarValue::Create(val.value())); + } + break; + } + case panda_file::Type::TypeId::U1: { + std::optional val = field_data_accessor_->GetValue(); + if (val.has_value()) { + field_.metadata->SetValue(pandasm::ScalarValue::Create(val.value())); + } + break; + } + case panda_file::Type::TypeId::REFERENCE: { + if (field_.type.GetName() == "panda.String") { + std::optional string_offset_val = field_data_accessor_->GetValue(); + if (string_offset_val.has_value()) { + std::string_view val {reinterpret_cast( + file_->GetStringData(panda_file::File::EntityId(string_offset_val.value())).data)}; + field_.metadata->SetValue(pandasm::ScalarValue::Create(val)); + } + break; + } + } + [[fallthrough]]; default: + if (field_.type.GetRank() > 0) { + std::optional litarray_offset_val = field_data_accessor_->GetValue(); + if (litarray_offset_val.has_value()) { + panda_file::LiteralDataAccessor literal_data_accessor(*file_, file_->GetLiteralArraysId()); + AbcLiteralArrayProcessor abcLitarrayProcessor{panda_file::File::EntityId{litarray_offset_val.value()}, entity_container_, literal_data_accessor}; + abcLitarrayProcessor.FillProgramData(); + std::string name = entity_container_.GetLiteralArrayIdName(litarray_offset_val.value()); + field_.metadata->SetValue(pandasm::ScalarValue::Create( + std::string_view {name})); + } + break; + } UNREACHABLE(); } } diff --git a/abc2program/common/abc2program_entity_container.cpp b/abc2program/common/abc2program_entity_container.cpp index 2aa7afa5a3983f820d98bf6089203f7be9f40122..d3ffe32fd46e96a71d2f1d3e7faf12b25293c7f1 100644 --- a/abc2program/common/abc2program_entity_container.cpp +++ b/abc2program/common/abc2program_entity_container.cpp @@ -118,9 +118,9 @@ void Abc2ProgramEntityContainer::AddModuleLiteralArrayId(uint32_t module_literal module_literal_array_id_set_.insert(module_literal_array_id); } -void Abc2ProgramEntityContainer::AddUnnestedLiteralArrayId(const panda_file::File::EntityId &literal_array_id) +void Abc2ProgramEntityContainer::AddUnnestedLiteralArrayId(uint32_t literal_array_id) { - unnested_literal_array_id_set_.insert(literal_array_id.GetOffset()); + unnested_literal_array_id_set_.insert(literal_array_id); } void Abc2ProgramEntityContainer::AddProcessedNestedLiteralArrayId(uint32_t nested_literal_array_id) diff --git a/abc2program/common/abc2program_entity_container.h b/abc2program/common/abc2program_entity_container.h index 4142ba5101b159c0a665be45160ef5e84f50c0ba..20d57765378b956811106ce936fe09725a34ea7e 100644 --- a/abc2program/common/abc2program_entity_container.h +++ b/abc2program/common/abc2program_entity_container.h @@ -49,7 +49,7 @@ public: const std::unordered_set &GetUnnestedLiteralArrayIdSet() const; std::unordered_set &GetUnprocessedNestedLiteralArrayIdSet(); void AddModuleLiteralArrayId(uint32_t module_literal_array_id); - void AddUnnestedLiteralArrayId(const panda_file::File::EntityId &literal_array_id); + void AddUnnestedLiteralArrayId(uint32_t literal_array_id); void AddProcessedNestedLiteralArrayId(uint32_t nested_literal_array_id); void TryAddUnprocessedNestedLiteralArrayId(uint32_t nested_literal_array_id); std::string GetLiteralArrayIdName(uint32_t literal_array_id); diff --git a/abc2program/common/abc_code_converter.cpp b/abc2program/common/abc_code_converter.cpp index 2a6e9194e5515e5304c43d80d46559a3e13fdb42..2a158795ede2e1e3708c91f54ab884d4c4f1aa37 100644 --- a/abc2program/common/abc_code_converter.cpp +++ b/abc2program/common/abc_code_converter.cpp @@ -34,7 +34,7 @@ std::string AbcCodeConverter::IDToString(BytecodeInstruction bc_ins, panda_file: return str_constant; } else { ASSERT(bc_ins.IsIdMatchFlag(idx, BytecodeInstruction::Flags::LITERALARRAY_ID)); - entity_container_.AddUnnestedLiteralArrayId(entity_id); + entity_container_.AddUnnestedLiteralArrayId(entity_id.GetOffset()); return entity_container_.GetLiteralArrayIdName(entity_id); } } diff --git a/abc2program/common/abc_file_utils.h b/abc2program/common/abc_file_utils.h index 52c2eae77055aebbc85d70091bdb974907a9a9e4..e8c18645531ad85b10424fe47c94eb59fa499839 100644 --- a/abc2program/common/abc_file_utils.h +++ b/abc2program/common/abc_file_utils.h @@ -28,6 +28,7 @@ constexpr std::string_view ARRAY_TYPE_PREFIX = "["; constexpr std::string_view ANY_TYPE_NAME = "any"; constexpr std::string_view ES_TYPE_ANNOTATION_NAME = "_ESTypeAnnotation"; constexpr std::string_view ES_MODULE_RECORD = "_ESModuleRecord"; +constexpr std::string_view ES_SCOPE_NAMES_RECORD = "scopeNames"; constexpr std::string_view MODULE_RECORD_IDX = "moduleRecordIdx"; constexpr std::string_view CONCURRENT_MODULE_REQUEST_ANN_RECORD_TYPE_DESCRIPTOR = "L_ESConcurrentModuleRequestsAnnotation;"; diff --git a/abc2program/program_dump.cpp b/abc2program/program_dump.cpp index 7a75d58fde64fa413b8a7da1e2ee3dbad0921399..0fe98d2ee937da99cb81a906d467d76f8f74ebbd 100644 --- a/abc2program/program_dump.cpp +++ b/abc2program/program_dump.cpp @@ -15,6 +15,7 @@ #include "program_dump.h" #include "abc2program_log.h" +#include "abc_literal_array_processor.h" #include "common/abc_file_utils.h" #include "dump_utils.h" #include "os/file.h" @@ -149,6 +150,13 @@ void PandasmProgramDumper::DumpAnnotationData(std::ostream &os, const pandasm::A os << DUMP_CONTENT_SPACE << element.GetName(); if (element.GetValue()->IsArray()) { DumpArrayValue(os, *(element.GetValue()->GetAsArray())); + } else if (element.GetValue()->GetType() == pandasm::Value::Type::LITERALARRAY) { + std::string lit_array_name = element.GetValue()->GetAsScalar()->GetValue(); + + auto iter = program_->literalarray_table.find(lit_array_name); + ASSERT(iter != program_->literalarray_table.end()); + auto lit_array = iter->second; + os << SerializeLiteralArray(lit_array); } else { DumpScalarValue(os, *(element.GetValue()->GetAsScalar())); } diff --git a/assembler/annotation.cpp b/assembler/annotation.cpp index b9f46219731ab1d5246c0f7596fa40ba7e2559cb..61bfa8590ac59f392180535497c8582acac4eac5 100644 --- a/assembler/annotation.cpp +++ b/assembler/annotation.cpp @@ -258,4 +258,15 @@ void AnnotationData::SetOrAddElementByIndex(size_t ele_idx, AnnotationElement && } elements_[ele_idx] = std::forward(element); } + +void AnnotationData::DeleteAnnotationElementByName(const std::string_view &annotation_elem_name) +{ + auto annotation_elem_iter = std::find_if(elements_.begin(), elements_.end(), + [&](pandasm::AnnotationElement &annotation_element) -> bool { + return annotation_element.GetName() == annotation_elem_name; + }); + if (annotation_elem_iter != elements_.end()) { + (void)elements_.erase(annotation_elem_iter); + } +} } // namespace panda::pandasm diff --git a/assembler/annotation.h b/assembler/annotation.h index 66503608aaf767ebbf628c0b1ea6f3b5f17b0d3b..8e750b4a113ca3b57ddc3624cfbe905c883763c3 100644 --- a/assembler/annotation.h +++ b/assembler/annotation.h @@ -61,6 +61,8 @@ public: elements_.push_back(std::forward(element)); } + void DeleteAnnotationElementByName(const std::string_view &annotation_elem_name); + void SetOrAddElementByIndex(size_t ele_idx, AnnotationElement &&element); private: @@ -298,6 +300,9 @@ public: case '*': type = Type::STRING_NULLPTR; break; + case '#': + type = Type::LITERALARRAY; + break; case '0': default: type = Type::UNKNOWN; @@ -360,6 +365,9 @@ public: case '@': type = Type::METHOD_HANDLE; break; + case '#': + type = Type::LITERALARRAY; + break; case '0': default: type = Type::UNKNOWN; diff --git a/assembler/meta.h b/assembler/meta.h index 24735cd07b3f15b6c5bb846fe557d529ffb91c12..5634c29751a17ec988b79ebfa861ce4f56c960e2 100644 --- a/assembler/meta.h +++ b/assembler/meta.h @@ -208,6 +208,18 @@ public: annotations_.insert(annotations_.end(), annotations.begin(), annotations.end()); } + void DeleteAnnotationElementByName(const std::string_view &annotation_name) + { + auto annotation_iter = std::find_if(annotations_.begin(), annotations_.end(), + [&](pandasm::AnnotationData &annotation) -> bool { + return annotation.GetName() == annotation_name; + }); + if (annotation_iter == annotations_.end()) { + return; + } + annotation_iter->DeleteAnnotationElementByName(annotation_name); + } + void DeleteAnnotationByName(const std::string_view &annotation_name) { auto annotation_iter = std::find_if(annotations_.begin(), annotations_.end(), @@ -219,6 +231,18 @@ public: } } + void AddAnnotationElementByName(const std::string_view &annotation_name, AnnotationElement &&element) + { + auto annotation_iter = std::find_if(annotations_.begin(), annotations_.end(), + [&](pandasm::AnnotationData &annotation) -> bool { + return annotation.GetName() == annotation_name; + }); + if (annotation_iter == annotations_.end()) { + return; + } + annotation_iter->AddElement(std::move(element)); + } + void SetOrAddAnnotationElementByIndex(size_t anno_idx, size_t ele_idx, AnnotationElement &&element) { ASSERT(anno_idx < annotations_.size()); diff --git a/bundle.json b/bundle.json index fe238d76942fe8aa78648f9c409a4b527c966358..fcb8d7e920d4952dabb6f7d8384222736e38665c 100644 --- a/bundle.json +++ b/bundle.json @@ -43,6 +43,7 @@ "sub_component": [ "//arkcompiler/runtime_core:arkcompiler_params", "//arkcompiler/runtime_core/arkplatform:arkplatform_packages", + "//arkcompiler/runtime_core/libabckit:libabckit_packages", "//arkcompiler/runtime_core/static_core:ark_packages", "//arkcompiler/runtime_core:ark_device_packages" ], diff --git a/cmake/PostPlugins.cmake b/cmake/PostPlugins.cmake index 426082a8e081ad44b09241d7b96a51d35cbd7694..3c7b61df657ea1beb1355e01f17686143ae3227c 100644 --- a/cmake/PostPlugins.cmake +++ b/cmake/PostPlugins.cmake @@ -23,6 +23,7 @@ add_custom_target(plugin_options_merge DEPENDS ${GEN_PLUGIN_OPTIONS_YAML}) include(assembler/extensions/AssemblerExtPostPlugins.cmake) include(bytecode_optimizer/templates/BytecodeOptPostPlugins.cmake) +include(libabckit/src/codegen/templates_dynamic/LibabckitPostPlugins.cmake) include(runtime/RuntimeEnableRelayoutPostPlugins.cmake) include(runtime/RuntimeLanguageContextPostPlugins.cmake) include(runtime/RuntimeIntrinsicsPostPlugins.cmake) diff --git a/isa/isa.yaml b/isa/isa.yaml index 18cf55fe7f9ef95aaa03a06ecc5b312b91fcafda..a9ecb3d41406a7442aeee8b015e8f200528c9abb 100644 --- a/isa/isa.yaml +++ b/isa/isa.yaml @@ -410,7 +410,7 @@ groups: acc: inout:top opcode_idx: [0xd7] format: [op_imm_8] - properties: [ic_slot, eight_bit_ic] + properties: [ic_slot, two_slot, eight_bit_ic] - sig: ldprivateproperty imm1:u8, imm2:u16, imm3:u16 acc: inout:top opcode_idx: [0xd8] @@ -889,13 +889,13 @@ groups: opcode_idx: [0x13] format: [pref_op_imm_8] prefix: callruntime - properties: [ic_slot, eight_bit_ic] + properties: [ic_slot, one_slot, eight_bit_ic] - sig: callruntime.isfalse imm:u8 acc: inout:top opcode_idx: [0x14] format: [pref_op_imm_8] prefix: callruntime - properties: [ic_slot, eight_bit_ic] + properties: [ic_slot, one_slot, eight_bit_ic] - title: throw instructions description: throw instructions diff --git a/libabckit/API_DESIGN.md b/libabckit/API_DESIGN.md new file mode 100644 index 0000000000000000000000000000000000000000..718ed1b1f60140d99c9f0fb99f0aa7233b984aec --- /dev/null +++ b/libabckit/API_DESIGN.md @@ -0,0 +1,107 @@ +# General design + +## Compatibility policy + +For each release of the library, minimum supported version of `.abc` is +provided. The API implemented by the library is guaranteed to work with `.abc` +files which are no older than the minimum supported version. Example: + +- `abcKit` API version: `1` +- Minimum supported `.abc` version: `3` +- Latest publicly released `.abc` version: `5` + +It means that `abcKit` can handle `.abc` files with format versions `5`, `4`, +and `3`. Older format versions are not supported. + +Forward compatibility is not guaranteed. + +## Metadata manipulation + +Metadata manipulation API is split into two separate APIs: Metadata inspection +API and metadata manipulation API. + +### Metadata inspection API + +Inspection API allows user to inspect an `.abc` file. + +### Metadata manipulation API + +Manipulation API allows user to modify items in an `.abc` file. To ensure +consistent update of the file, the library has an implicit update order of the +entities: first, file-level entities are updated, then class-level entities are +updated, then method-level entities are updated, etc. The user has no control +over the traversal order, which is a feature introduced for guarding +against unintentional data corruption. + +All internal `abckit_*` data structures are immutable, which means that if an +`updateXXX` happens during manipulation, a new `XXX` entity is created based +on the original entitity and a "diff" provided by the user through the API. + +## Bytecode manipulation + +### IR convetions + +- All graphs start with an implicit `start` pseudo-block +- `start` blocks contains all function arguments (`Parammeter` opcode) + and constants (`Constant` opcode) +- All "return" blocks implicitly connect to a special `end` pseudo-block + +- leave only link/unlink basicBlocks? no remove/add predecessors/successors + disconnectBB - remove +- set start/end BB - remove? if not, what happens to the old one? risky operation + +## API guarantees + +Guarantees outlined below hold only for this version of API. As the API evolves +further, the guarantees may change as well. + +- The API provided by the library takes `.abc` files as input and produces + `.abc` files as output. +- If the input `.abc` is malformed, validity of the output is not guaranteed. +- If the input `.abc` is well-formed, the output `.abc` is guaranteed to be + valid (**FIXME**: clarify the meaning of `valid`). +- However, any semantic difference between the original and transformed `.abc` + is the responsibility of the user: bytecode manipulation API provided by the + library implies that user can potentially introduce any changes to the program + logic. + +## Memory ownership rules + +### `abckit_*` pointers + +All `abckit_*` pointers (`abckit_Class`, `abckit_Method`, etc.) are by design +opaque, owned by the library and intended to be accessed only through the API +provided by the library. Any other access leads to undefined behavior, +including possible `.abc` layout corruption, unpredictable changes of runtime +semantics, etc. + +### Allocation rules + +**FIXME**: TBD for metadata and bytecode manipulation API. + +## Restrictions + +### Removal of items + +In general, removing existing items from `.abc` files is **not** supported, with +following exceptions: + +- Elimination of bytecode instructions is **supported**. +- Removal of annotations is **supported**. + +## Implementation details + +This section is informative and subject to change at any time. + +### Mapping between `libabckit` opaque pointers and `libarkfile` items + +- `abckit_File`: `panda_file::ItemContainer` +- `abckit_Class`: `panda_file::ClassItem` +- `abckit_Field`: `panda_file::FieldItem` +- `abckit_Method`: `panda_file::MethodItem` +- `abckit_Annotation`: `panda_file::AnnotationItem` +- `abckit_AnnotationElement`: `panda_file::AnnotationItem::Elem` +- `abckit_Value`: `panda_file::ValueItem` +- `abckit_String`: `panda_file::StringItem` +- `abckit_Type`: `panda_file::TypeItem` +- `abckit_Code`: `panda_file::CodeItem` diff --git a/libabckit/BUILD.gn b/libabckit/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..465a27ba6342d4005eac6f24c9d86422f96c9386 --- /dev/null +++ b/libabckit/BUILD.gn @@ -0,0 +1,274 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +# import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +declare_args() { + enable_libabckit_coverage = false +} + +config("libabckit_coverage") { + if (enable_libabckit_coverage) { + cflags = [ + "-fprofile-instr-generate", + "-fcoverage-mapping", + "-mllvm", + "-runtime-counter-relocation", + ] + + ldflags = [ + "-fprofile-instr-generate", + "-fcoverage-mapping", + ] + } +} + +action("get_abckit_status") { + script = "scripts/get-abckit-status.py" + outputs = [ "$target_gen_dir/abckit_status.csv" ] +} + +ohos_executable("abckit_canary") { + cflags = ["-std=c99", "-pedantic", "-Wall", "-Wextra", "-Werror"] + sources = [ + "tests/canary.c", + ] + include_dirs = [ + "$ark_root/libabckit", + ] + install_enable = false + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +group("libabckit_packages") { + if (enable_libabckit) { + deps = [ + "abckit:abckit(${host_toolchain})", + ":libabckit(${host_toolchain})", + ":abckit_examples(${host_toolchain})", + ":abckit_canary(${host_toolchain})", + ":get_abckit_status", + ] + } +} + +config("libabckit_public_config") { + include_dirs = [ "include" ] +} + +ohos_source_set("libabckit_static") { + sources = [ + "src/abckit_impl.cpp", + "src/statuses_impl.cpp", + "src/ir_impl.cpp", + "src/isa_static_impl.cpp", + "src/isa_dynamic_impl.cpp", + "src/ir_interface_impl.cpp", + "src/metadata_inspect_impl.cpp", + "src/metadata_modify_impl.cpp", + ] + + include_dirs = [ + "$ark_root", + "$target_gen_dir/src" + ] + + configs = [ "$abckit_root:libabckit_coverage" ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +ohos_source_set("libabckit_adapter_static_source_set") { + sources = [ + "src/adapter_static/abckit_static.cpp", + "src/adapter_static/metadata_inspect_static.cpp", + "src/adapter_static/metadata_modify_static.cpp", + "src/adapter_static/ir_static.cpp", + "src/adapter_static/runtime_adapter_static.cpp", + "src/adapter_static/helpers_static.cpp", + ] + + ins_create_wrapper_dyn_dir = get_label_info("$ark_root/libabckit/src/wrappers:isa_gen_libabckit_ins_create_wrapper_api_inc", "target_gen_dir") + intrinsics_gen_dir = get_label_info("$ark_root/libabckit/src/adapter_dynamic/templates:isa_gen_libabckit_dyn_intrinsics_enum_inl", "target_gen_dir") + include_dirs = [ + "$ark_root/static_core", # this target should not include headers from dynamic runtime, so static_core must be listed first + "$ark_root", + "$ark_root/libabckit", + "$ark_root/include", + "$target_gen_dir/src/codegen", + "$target_gen_dir/src/adapter_static", + "$target_gen_dir/src/adapter_dynamic/generated", + "$target_gen_dir/libabckit/src", + "$intrinsics_gen_dir/../generated", + "$ins_create_wrapper_dyn_dir" + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/static_core:ark_config", # FIXME + "$ark_root/static_core/bytecode_optimizer:bytecodeopt_public_config", + "$ark_root/static_core/compiler:arkcompiler_public_config", + "$ark_root/static_core/libpandafile:arkfile_public_config", + "$ark_root/static_core/libpandabase:arkbase_public_config", + "$ark_root/static_core/runtime:arkruntime_public_config", # FIXME + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/static_core/abc2program:arkts_abc2program", + "$ark_root/static_core/assembler:libarktsassembler", + "$ark_root/static_core/bytecode_optimizer:libarktsbytecodeopt", + "$ark_root/static_core/libpandafile:libarktsfile", + "$ark_root/static_core/libpandabase:libarktsbase", + "$ark_root/static_core/assembler:libarktsassembler", + "$ark_root/static_core/bytecode_optimizer:libarktsbytecodeopt", + "src/adapter_static:get_intrinsic_id_static_inc", + "src/adapter_dynamic/templates:isa_gen_libabckit_inst_props_helpers_dynamic_inc", + "src/templates/dyn_intrinsics:isa_gen_libabckit_get_dyn_intrinsics_names_inc", + "src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_enum_inc", + "src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_flags_inc", + "src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_inl", + "src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_opcodes_inc", + "src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_vreg_width_h", + ":concat_bct_intrinsics_yaml", + ] +} + +bct_yaml = "bct_compiler_intrinsics.yaml" + +action("crop_bct_intrinsics_yaml") { + script = "./scripts/fix_intrinsics_yml.sh" + args = [rebase_path("src/$bct_yaml"), rebase_path("$target_gen_dir/generated/$bct_yaml")] + inputs = ["src/$bct_yaml"] + outputs = ["$target_gen_dir/generated/$bct_yaml"] +} + +runtime_intrinsics_gen_dir = get_label_info("$ark_root/static_core/runtime:arkruntime_gen_intrinsics_yaml(${host_toolchain})", "target_gen_dir") +concat_yamls("concat_bct_intrinsics_yaml") { + extra_dependencies = ["$ark_root/static_core/runtime:arkruntime_gen_intrinsics_yaml(${host_toolchain})", + ":crop_bct_intrinsics_yaml" + ] + output_file = "$runtime_intrinsics_gen_dir/bct_intrinsics.yaml" + default_file = "$runtime_intrinsics_gen_dir/intrinsics.yaml" + add_yamls = ["$target_gen_dir/generated/$bct_yaml"] +} + +ohos_source_set("libabckit_adapter_dynamic_source_set") { + sources = [ + "src/adapter_dynamic/abckit_dynamic.cpp", + "src/adapter_dynamic/helpers_dynamic.cpp", + "src/adapter_dynamic/metadata_inspect_dynamic.cpp", + "src/adapter_dynamic/metadata_modify_dynamic.cpp", + ] + + ins_create_wrapper_dyn_dir = get_label_info("$ark_root/libabckit/src/wrappers:isa_gen_libabckit_ins_create_wrapper_api_inc", "target_gen_dir") + include_dirs = [ + "$ark_root", + "$ark_root/libabckit", + "$ark_root/include", + "$ins_create_wrapper_dyn_dir" + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root:ark_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/abc2program:abc2program", + "$ark_root/libpandafile:libarkfile", + "src/templates/dyn_intrinsics:isa_gen_libabckit_get_dyn_intrinsics_names_inc", + "src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_enum_inc", + "src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_flags_inc", + "src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_inl", + "src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_opcodes_inc", + "src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_vreg_width_h", + ":concat_bct_intrinsics_yaml", + "src/wrappers/graph_wrapper:libabckit_graph_wrapper_source_set", + ] + + # external_deps = [ + # "ets_runtime:libark_jsruntime", + # ] +} + +ohos_shared_library("libabckit") { + deps = [ + ":libabckit_static", + ":libabckit_adapter_dynamic_source_set", + ":libabckit_adapter_static_source_set", + "src/codegen:libabckit_codegen_static_source_set", + "src/codegen:libabckit_codegen_dynamic_source_set", + "src/wrappers:libabckit_pandasm_wrapper_source_set", + "src/wrappers:libabckit_abcfile_wrapper_source_set", + "src/irbuilder_dynamic:libabckit_ir_builder_dynamic_source_set", + "src/mem_manager:libabckit_mem_manager_source_set" + ] + + configs = [ "$abckit_root:libabckit_coverage" ] + + external_deps = [ "hilog:libhilog" ] + output_extension = "so" + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +# Temporary target with API usage examples +ohos_executable("abckit_examples") { + sources = [ + "examples/example_dynamic_if_else.cpp", + "examples/example_dynamic_loop.cpp", + "examples/example_if_else.cpp", + "examples/example_if_without_else.cpp", + "examples/example_loop.cpp", + "examples/example_loop_inner_if_else.cpp", + "examples/example_loop_inner_if_without_else.cpp", + "examples/loggable.cpp", + "examples/replace_first_inst.cpp", + "examples/throw_if_deprecated.cpp", + + "external_examples/dynamic_add_try_catch.cpp", + "external_examples/dynamic_check_parameters.cpp", + "external_examples/dynamic_replace_call_site.cpp", + "external_examples/dynamic_router_table.cpp", + "external_examples/static_add_try_catch.cpp", + "external_examples/static_check_parameters.cpp", + "external_examples/static_replace_call_site.cpp", + "external_examples/static_router_table.cpp", + + "external_examples/stub_main.cpp", + ] + include_dirs = [ + "$ark_root/libabckit", + "$ark_root/include", + ] + deps = [ ":libabckit" ] + install_enable = true + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} diff --git a/libabckit/abckit/BUILD.gn b/libabckit/abckit/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9f28f56f76531901255a04cf58754b2d5c189ca8 --- /dev/null +++ b/libabckit/abckit/BUILD.gn @@ -0,0 +1,36 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +# import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ohos_executable("abckit") { + sources = [ + "abckit.cpp", + ] + include_dirs = [ + "$ark_root/libabckit/include", + ] + configs = [ + "$ark_root/libpandabase:arkbase_public_config", + ] + deps = [ + "$ark_root/libabckit:libabckit", + "$ark_root/libpandabase:libarkbase", + ] + install_enable = false + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} diff --git a/libabckit/abckit/abckit.cpp b/libabckit/abckit/abckit.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3478c30c077f52067381f7627600da205cb7c819 --- /dev/null +++ b/libabckit/abckit/abckit.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2024 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 "abckit.h" +#include "utils/pandargs.h" + +#include +#include +#include + +namespace fs = std::filesystem; + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + + +void PrintHelp(panda::PandArgParser &pa_parser) +{ + std::cerr << "Usage:" << std::endl; + std::cerr << "abckit --plugin-path --input-file [--output-file ]" << std::endl; + std::cerr << "Supported options:" << std::endl; + std::cerr << pa_parser.GetHelpString() << std::endl; +} + +bool ProcessArgs(panda::PandArgParser &pa_parser, const panda::PandArg &plugin_path, + const panda::PandArg &input_file, int argc, const char **argv) +{ + if (!pa_parser.Parse(argc, argv)) { + std::cerr << "ERROR: Failed to parse arguments\n"; + PrintHelp(pa_parser); + return false; + } + + if (input_file.GetValue().empty()) { + std::cerr << "ERROR: --input-file is required\n"; + PrintHelp(pa_parser); + return false; + } + + if (!fs::exists(input_file.GetValue())) { + std::cerr << "ERROR: file doesn't exist: " << input_file.GetValue() << '\n'; + PrintHelp(pa_parser); + return false; + } + + if (plugin_path.GetValue().empty()) { + std::cerr << "ERROR: --plugin-path is required\n"; + PrintHelp(pa_parser); + return false; + } + + if (!fs::exists(plugin_path.GetValue())) { + std::cerr << "ERROR: file doesn't exist: " << plugin_path.GetValue() << '\n'; + PrintHelp(pa_parser); + return false; + } + + return true; +} + +int main(int argc, const char **argv) +{ + // std::cerr.setstate(std::ios::failbit); + panda::PandArg help("help", false, "Print this message and exit"); + panda::PandArg plugin_path("plugin-path", "", "Path to abckit plugin"); + panda::PandArg input_file("input-file", "", "Path to input abc file"); + panda::PandArg output_file("output-file", "", "Path to output abc file"); + + panda::PandArgParser pa_parser; + pa_parser.Add(&help); + pa_parser.Add(&plugin_path); + pa_parser.Add(&input_file); + pa_parser.Add(&output_file); + if (!ProcessArgs(pa_parser, plugin_path, input_file, argc, argv)) { + return 1; + } + + if (help.GetValue()) { + PrintHelp(pa_parser); + return 0; + } + + void *handler = dlopen(plugin_path.GetValue().c_str(), RTLD_LAZY); + if (handler == nullptr) { + std::cerr << "ERROR: failed load plugin: " << plugin_path.GetValue() << '\n'; + return 1; + } + auto *Entry = reinterpret_cast(dlsym(handler, "Entry")); + if (Entry == nullptr) { + std::cerr << "ERROR: failed find symbol 'Entry'\n"; + return 1; + } + + abckit_File *ctxI = impl->OpenAbc(input_file.GetValue().c_str()); + if(impl->GetLastError() != abckit_Status_NO_ERROR || ctxI == nullptr) { + std::cerr << "ERROR: failed to open: " << input_file.GetValue() << '\n'; + return 1; + } + + int ret = Entry(ctxI); + if (ret != 0) { + std::cerr << "ERROR: plugin returned non-zero return code"; + return ret; + } + + if (!output_file.GetValue().empty()) { + impl->WriteAbc(ctxI, output_file.GetValue().c_str()); + if(impl->GetLastError() != abckit_Status_NO_ERROR || ctxI == nullptr) { + std::cerr << "ERROR: failed to write: " << output_file.GetValue() << '\n'; + return 1; + } + } + + return 0; +} diff --git a/libabckit/abckit/stress_plugin/BUILD.gn b/libabckit/abckit/stress_plugin/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..40ffe6df4888cbc370ccd7d158cfd9ba5a471f78 --- /dev/null +++ b/libabckit/abckit/stress_plugin/BUILD.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2024 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. + +# import("//arkcompiler/runtime_core/ark_config.gni") +# import("//arkcompiler/runtime_core/static_core/ark_config.gni") +# import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +# import("//arkcompiler/runtime_core/static_vm_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") + +abckit_plugin("abckit_stress_plugin") { + sources = [ + "stress.cpp", + ] + + install_enable = false + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} diff --git a/libabckit/abckit/stress_plugin/stress.cpp b/libabckit/abckit/stress_plugin/stress.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a55d26ea66eef4733eb0a7fee30b8cf947bf806 --- /dev/null +++ b/libabckit/abckit/stress_plugin/stress.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2024 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 "abckit.h" +#include "statuses.h" + +#include + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + std::size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + + auto name = new char[len] {}; + implI->abckit_StringToString(ctxI, str, name, &len); + + std::string res {name}; + delete[] name; + + return res; +} + +static void TransformMethod(abckit_ModifyContext *ctxM, abckit_Method *method, [[maybe_unused]] void *data) +{ + if (implI->MethodIsNative(method) || implI->MethodIsAbstract(method) || implI->MethodIsExternal(method)) { + return; + } + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + if (impl->GetLastError() != abckit_Status_NO_ERROR) { + return; + } + abckit_Code *newCode = impl->graphToCode(ctxG); + if (impl->GetLastError() != abckit_Status_NO_ERROR) { + return; + } + implM->MethodSetCode(ctxM, method, newCode); +} + +extern "C" int Entry(abckit_File *ctxI) +{ + std::cout << "Stress test plugin Entry\n"; + bool hasError = false; + + implI->FileEnumerateModules(ctxI, &hasError, [](abckit_Module *m, void *data) { + bool *hasError = (bool*)data; + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *klass, void *data) { + bool *hasError = (bool*)data; + implI->ClassEnumerateMethods(klass, data, [](abckit_Method *method, void *data) { + bool *hasError = (bool*)data; + auto *MethodCtxI = implI->MethodGetInspectContext(method); + auto mname = implI->MethodGetName(method); + auto methodName = abckit_StringToString(MethodCtxI, mname); + std::cout << "Transforming method: " << methodName << '\n'; + impl->TransformMethod(method, nullptr, TransformMethod); + if (impl->GetLastError() != abckit_Status_NO_ERROR) { + *hasError = true; + } + return !(*hasError); + }); + return !(*hasError); + }); + + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *method, void *data) { + bool *hasError = (bool*)data; + auto *MethodCtxI = implI->MethodGetInspectContext(method); + auto mname = implI->MethodGetName(method); + auto methodName = abckit_StringToString(MethodCtxI, mname); + std::cout << "Transforming method: " << methodName << '\n'; + impl->TransformMethod(method, nullptr, TransformMethod); + if (impl->GetLastError() != abckit_Status_NO_ERROR) { + *hasError = true; + } + return !(*hasError); + }); + + return !(*hasError); + }); + + return hasError ? 1 : 0; +} diff --git a/libabckit/examples/example_dynamic_if_else.cpp b/libabckit/examples/example_dynamic_if_else.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d463fbc9dd2653a1bfea81e8731c3c303141d544 --- /dev/null +++ b/libabckit/examples/example_dynamic_if_else.cpp @@ -0,0 +1,136 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/abckit.h" +#include "include/isa/isa_static.h" + +// This example shows creation of the dynamic graph for the following function. +// +// function main() { +// let a = 1 +// if (a) { +// a = 5 +// } else { +// a = 0 +// } +// return a; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x1 +// 2. abckit_Opcode_Constant 0x2 +// 3. abckit_Opcode_Constant 0x0 +// 4. abckit_Opcode_Constant 0x5 +// bb0: preds: [start], succs: [bb1, bb2] +// 6. abckit_DynOpcode_isfalse 1 +// 10 abckit_Opcode_Cmp NE 6, 3 +// 11 abckit_Opcode_IfImm NE b 10, 0x0 +// bb1: preds: [bb0], succs: [bb3] +// 12 abckit_Opcode_CastValueToAnyType ECMASCRIPT_INT_TYPE 3 +// bb2: preds: [bb0], succs: [bb3] +// 14 abckit_Opcode_CastValueToAnyType ECMASCRIPT_INT_TYPE 4 +// bb3: preds: [bb1, bb2], succs: [end] +// 16 abckit_Opcode_Phi 12, 14 +// 17 abckit_Opcode_Return 16 +// end bb: preds: [bb3], succs: [] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createIfElseDynamic(abckit_Method *method) +{ + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0x2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst3 = implG->GcreateConstantU64(ctxG, 0x0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst4 = implG->GcreateConstantU64(ctxG, 0x5); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst4); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst6 = dynG->IcreateIsfalse(ctxG, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + // dynG->IsetTargetType(inst6, abckit_TypeId_I32); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb0, inst6); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst10 = dynG->IcreateIf(ctxG, inst6, abckit_IsaApiDynamicConditionCode_CC_NE); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb0, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb3 + abckit_BasicBlock *bb3 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst16 = implG->BBcreatePhi(bb3, 2, inst3, inst4); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst16); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst17 = dynG->IcreateReturn(ctxG, inst16); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst17); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb2, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/example_dynamic_loop.cpp b/libabckit/examples/example_dynamic_loop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cf9ef6c50991ce6066109ac7c5d5926b3ad60063 --- /dev/null +++ b/libabckit/examples/example_dynamic_loop.cpp @@ -0,0 +1,142 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/abckit.h" + +// This example shows creation of the graph for the following JS code +// +// let a = 0; +// for (let i = 0; i < 10; i++) { +// a += 2; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x0 +// 2. abckit_Opcode_Constant 0xa +// 3. abckit_Opcode_Constant 0x2 +// +// bb0: preds: [start bb], succs: [bb1] +// 6. abckit_Opcode_CastValueToAnyType ECMASCRIPT_INT_TYPE 1 +// +// bb1: preds: [bb0, bb2], succs: [bb3, bb2] +// 9. abckit_Opcode_Phi 6, 17 +// 10. abckit_Opcode_Phi 6, 19 +// 11. abckit_Opcode_CastValueToAnyType ECMASCRIPT_INT_TYPE 2 +// 12. abckit_DynOpcode_lessdyn 10, 11 +// 13. abckit_Opcode_CastValueToAnyType ECMASCRIPT_BOOLEAN_TYPE 1 +// 14. abckit_Opcode_Cmp EQ 12, 13 +// 15. abckit_Opcode_IfImm NE 14, 0x0 +// +// bb2: preds: [bb1], succs: [bb1] +// 16. abckit_Opcode_CastValueToAnyType ECMASCRIPT_INT_TYPE 3 +// 17. abckit_DynOpcode_add2 9, 16 +// 19. abckit_DynOpcode_incdyn 10 +// +// bb3: preds: [bb1], succs: [bb 5] +// 21.any abckit_Opcode_CastValueToAnyType ECMASCRIPT_UNDEFINED_TYPE 1 +// 22.any abckit_Opcode_Return 21 +// +// end bb preds: [bb3] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createDynamicLoop(abckit_Method *method) +{ + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0xa); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst3 = implG->GcreateConstantU64(ctxG, 0x2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst9 = implG->BBcreatePhi(bb1, 1, inst1); + abckit_Inst *inst10 = implG->BBcreatePhi(bb1, 1, inst1); + + abckit_Inst *inst12 = dynG->IcreateLess(ctxG, inst10, inst2); + implG->BBaddInstBack(bb1, inst12); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst14 = dynG->IcreateIf(ctxG, inst12, abckit_IsaApiDynamicConditionCode_CC_EQ); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb1, inst14); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst17 = dynG->IcreateAdd2(ctxG, inst9, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst17); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IappendInput(inst9, inst17); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst19 = dynG->IcreateInc(ctxG, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst19); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IappendInput(inst10, inst19); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb3 + abckit_BasicBlock *bb3 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst22 = dynG->IcreateReturn(ctxG, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst22); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/example_if_else.cpp b/libabckit/examples/example_if_else.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6856f1ebffac7b201bed547725d6f47f7b496e9f --- /dev/null +++ b/libabckit/examples/example_if_else.cpp @@ -0,0 +1,119 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/abckit.h" + +// This example shows creation of the graph for the following function. +// +// function main() { +// let a = 1 +// if (a) { +// a = 5 +// } else { +// a = 0 +// } +// return a; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x1 +// 2. abckit_Opcode_Constant 0x0 +// 3. abckit_Opcode_Constant 0x5 +// bb0: preds: [start], succs: [bb1, bb2] +// 7. abckit_Opcode_Cmp EQ, 1, 2 +// 8. abckit_Opcode_IfImm NE, 7, 0x0 +// bb1: preds: [bb0], succs: [bb3] +// bb2: preds: [bb0], succs: [bb3] +// bb3: preds: [bb1, bb2], succs: [end] +// 11. abckit_Opcode_Phi 3, 2 +// 12. abckit_Opcode_Return 11 +// end bb: preds: [bb3], succs: [] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createIfElseStatic(abckit_Method *method) +{ + const auto impl = abckit_GetApiImpl(1); + + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0x0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst3 = implG->GcreateConstantU64(ctxG, 0x5); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst7 = statG->IcreateIf(ctxG, inst1, inst2, abckit_IsaApiStaticConditionCode_CC_EQ); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb0, inst7); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb3 + abckit_BasicBlock *bb3 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst11 = implG->BBcreatePhi(bb3, 2, inst3, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst12 = statG->IcreateReturn(ctxG, inst11); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst12); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb2, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/example_if_without_else.cpp b/libabckit/examples/example_if_without_else.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66500ff972b7153865d02f92590a333bb412ab41 --- /dev/null +++ b/libabckit/examples/example_if_without_else.cpp @@ -0,0 +1,111 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/abckit.h" +#include "include/isa/isa_static.h" + +// This example shows creation of the graph for the following function. +// +// function main() { +// let a = 1 +// if (a) { +// a = 5 +// } +// return a; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x1 +// 2. abckit_Opcode_Constant 0x0 +// 3. abckit_Opcode_Constant 0x5 +// bb0: preds: [start], succs: [bb1, bb2] +// 7. abckit_Opcode_Cmp EQ, 1, 2 +// 8. abckit_Opcode_IfImm NE, 7, 0x0 +// bb1: preds: [bb0], succs: [bb2] +// bb2: preds: [bb1, bb0], succs: [end] +// 10. abckit_Opcode_Phi 3, 1 +// 11. abckit_Opcode_Return 10 +// end bb: preds: [bb2], succs: [] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createIfWithoutElse(abckit_Method *method) +{ + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst3 = implG->GcreateConstantU64(ctxG, 5); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst7 = statG->IcreateIf(ctxG, inst1, inst2, abckit_IsaApiStaticConditionCode_CC_EQ); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb0, inst7); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst10 = implG->BBcreatePhi(bb2, 2, inst3, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst11 = statG->IcreateReturn(ctxG, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst11); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb2, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/example_loop.cpp b/libabckit/examples/example_loop.cpp new file mode 100644 index 0000000000000000000000000000000000000000..14f7af6bc237233381be3b59eaf9fa1babea9682 --- /dev/null +++ b/libabckit/examples/example_loop.cpp @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/abckit.h" + +// This example shows creation of the graph for the following function. +// +// function main() { +// let a = 1; +// while (a < 10) { +// a += a; +// } +// return a; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x1 +// 2. abckit_Opcode_Constant 0xa +// bb0: preds: [start], succs: [bb1] +// bb1: preds: [bb0], succs: [bb2] +// bb2: preds: [bb1, bb3], succs: [bb3, bb4] +// 5. abckit_Opcode_Phi 1, 8 +// 6. abckit_Opcode_Cmp LE 5, 2 +// 7. abckit_Opcode_IfImm NE 6, 0x0 +// bb3: preds: [bb2], succs: [bb2] +// 8. abckit_Opcode_Add 5, 5 +// bb4: preds: [bb2], succs: [end] +// 10. abckit_Opcode_Return 5 +// end bb: preds: [bb4], succs: [] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createLoop(abckit_Method *method) +{ + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0xa); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *inst5 = implG->BBcreatePhi(bb2, 1, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // NOTE: This condition code is wrong, since LE is absent in mainline + abckit_Inst *inst6 = statG->IcreateIf(ctxG, inst5, inst2, abckit_IsaApiStaticConditionCode_CC_NE); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst6); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb3 + abckit_BasicBlock *bb3 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst8 = statG->IcreateAdd(ctxG, inst5, inst5); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst8); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IappendInput(inst5, inst8); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb4 + abckit_BasicBlock *bb4 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst10 = statG->IcreateReturn(ctxG, inst5); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb4, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb4, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb4, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/example_loop_inner_if_else.cpp b/libabckit/examples/example_loop_inner_if_else.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4b57c397f4c3c39d09bba0632ca8ac6b4bcd610f --- /dev/null +++ b/libabckit/examples/example_loop_inner_if_else.cpp @@ -0,0 +1,178 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/abckit.h" + +// This example shows creation of the graph for the following function. +// +// function main() { +// let a = 1; +// while (a < 10) { +// if (a % 2) { +// a *= 2 +// } else { +// a += a +// } +// } +// return a; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x1 +// 2. abckit_Opcode_Constant 0xa +// 3. abckit_Opcode_Constant 0x2 +// 4. abckit_Opcode_Constant 0x0 +// bb0: preds: [start], succs: [bb1] +// bb1: preds: [bb0], succs: [bb2] +// bb2: preds: [bb1, bb4, bb5], succs: [bb3, bb6] +// 7. abckit_Opcode_Phi 1, 13, 15 +// 8. abckit_Opcode_Cmp LE 2, 7 +// 9. abckit_Opcode_IfImm NE 8, 0x0 +// bb3: preds: [bb2], succs: [bb4, bb5] +// 10. Mod 7, 3 +// 11. abckit_Opcode_Cmp EQ 10, 4 +// 12. abckit_Opcode_IfImm NE 11, 0x0 +// bb4: preds: [bb3], succs: [bb2] +// 13. abckit_Opcode_Mul 7, 3 +// bb5: preds: [bb3], succs: [bb2] +// 15. abckit_Opcode_Add 7, 7 +// bb6: preds: [bb2], succs: [end] +// 17. abckit_Opcode_Return 7 +// end bb: preds: [bb6], succs: [] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createLoopIfElse(abckit_Method *method) +{ + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0xa); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst3 = implG->GcreateConstantU64(ctxG, 0x2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst4 = implG->GcreateConstantU64(ctxG, 0x0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst4); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst7 = implG->BBcreatePhi(bb2, 2, inst1, inst2); + + // NOTE: This condition code is wrong, since LE is absent in mainline + abckit_Inst *inst8 = statG->IcreateIf(ctxG, inst2, inst7, abckit_IsaApiStaticConditionCode_CC_NE); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst8); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb3 + abckit_BasicBlock *bb3 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst10 = statG->IcreateMod(ctxG, inst7, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst11 = statG->IcreateIf(ctxG, inst10, inst4, abckit_IsaApiStaticConditionCode_CC_EQ); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst11); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb4 + abckit_BasicBlock *bb4 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst13 = statG->IcreateMul(ctxG, inst7, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb4, inst13); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb5 + abckit_BasicBlock *bb5 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst15 = statG->IcreateAdd(ctxG, inst7, inst7); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb5, inst15); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb6 + abckit_BasicBlock *bb6 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst17 = statG->IcreateReturn(ctxG, inst7); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb6, inst17); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implG->IsetInput(inst7, inst13, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IsetInput(inst7, inst15, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb6, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bb4, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bb5, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb4, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb5, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb6, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/example_loop_inner_if_without_else.cpp b/libabckit/examples/example_loop_inner_if_without_else.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ba5bc3a1c5692ab7ab531b85cdcf2e43d22647e2 --- /dev/null +++ b/libabckit/examples/example_loop_inner_if_without_else.cpp @@ -0,0 +1,205 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/abckit.h" + +// This example shows creation of the graph for the following function. +// +// function main() { +// let a = 1; +// while (a < 10) { +// if (a % 2) { +// a *= 2 +// } +// a += 1 +// } +// return a; +// } +// +// start bb: preds: [], succs: [bb0] +// 1. abckit_Opcode_Constant 0x1 +// 2. abckit_Opcode_Constant 0xa +// 3. abckit_Opcode_Constant 0x2 +// 4. abckit_Opcode_Constant 0x0 +// bb0: preds: [start], succs: [bb1] +// 5. abckit_Opcode_CreateVar +// 6. abckit_Opcode_StoreVar 5, 1 +// bb1: preds: [bb0], succs: [bb2] +// bb2: preds: [bb1], succs: [bb3, bb6] +// 7. abckit_Opcode_LoadVar 5 +// 8. abckit_Opcode_Cmp LE 2, 7 +// 9. abckit_Opcode_IfImm NE 8, 0x0 +// bb3: preds: [bb2], succs: [bb4, bb5] +// 10. Mod 7, 3 +// 11. abckit_Opcode_Cmp EQ 10, 4 +// 12. abckit_Opcode_IfImm NE 11, 0x0 +// bb4: preds: [bb3], succs: [bb5] +// 13. abckit_Opcode_Mul 7, 3 +// 14. abckit_Opcode_StoreVar 5, 13 +// bb5: preds: [bb3], succs: [bb2] +// 15. abckit_Opcode_LoadVar 5 +// 16. abckit_Opcode_Add 15, 1 +// 17. abckit_Opcode_StoreVar 5, 16 +// bb6: preds: [bb2], succs: [end] +// 18. abckit_Opcode_Return 7 +// end bb: preds: [bb6], succs: [] + +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto impl = abckit_GetApiImpl(1); + +abckit_Code *createLoopIf(abckit_Method *method) +{ + auto *ctxI = implI->MethodGetInspectContext(method); + auto *code = implI->MethodGetCode(method); + auto *ctxG = impl->codeToGraph(ctxI, code); + + // Get start and end basic blocks + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_BasicBlock *bbEnd = implG->GgetEndBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Fill bbStart + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst2 = implG->GcreateConstantU64(ctxG, 0xa); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst3 = implG->GcreateConstantU64(ctxG, 0x2); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst4 = implG->GcreateConstantU64(ctxG, 0x0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst4); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb0 + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst5 = nullptr; // implG->IcreateCreateVar(ctxG); // FIXME + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb0, inst5); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst6 = nullptr; // implG->IcreateStoreVar(ctxG, inst5, inst1); // FIXME + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb0, inst6); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb1 + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb2 + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst7 = nullptr; // implG->IcreateLoadVar(ctxG, inst5); // FIXME + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst7); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // NOTE: This condition code is wrong, since LE is absent in mainline + abckit_Inst *inst8 = statG->IcreateIf(ctxG, inst2, inst7, abckit_IsaApiStaticConditionCode_CC_NE); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb2, inst8); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb3 + abckit_BasicBlock *bb3 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst10 = statG->IcreateMod(ctxG, inst7, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst10); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst11 = statG->IcreateIf(ctxG, inst10, inst4, abckit_IsaApiStaticConditionCode_CC_EQ); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb3, inst11); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb4 + abckit_BasicBlock *bb4 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst13 = statG->IcreateMul(ctxG, inst7, inst3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb4, inst13); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst14 = nullptr; // implG->IcreateStoreVar(ctxG, inst5, inst13); // FIXME + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb4, inst14); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb5 + abckit_BasicBlock *bb5 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst15 = nullptr; // implG->IcreateLoadVar(ctxG, inst5); // FIXME + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb5, inst15); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst16 = statG->IcreateAdd(ctxG, inst15, inst1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb5, inst16); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst17 = nullptr; // implG->IcreateStoreVar(ctxG, inst5, inst16); // FIXME + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb5, inst17); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill bb6 + abckit_BasicBlock *bb6 = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst18 = statG->IcreateReturn(ctxG, inst7); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bb6, inst18); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Connect basic blocks + implG->BBconnectBlocks(bbStart, bb0, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb0, bb1, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb3, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb2, bb6, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bb4, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb3, bb5, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb4, bb5, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb5, bb2, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb6, bbEnd, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + + return newCode; +} diff --git a/libabckit/examples/loggable.cpp b/libabckit/examples/loggable.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7dde5127c44b893c431fa08c2dd0b197af28de24 --- /dev/null +++ b/libabckit/examples/loggable.cpp @@ -0,0 +1,185 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/abckit.h" + +// In this example for each method annotated with "@loggable" insert LOG("methodName") at beginning of the method +// +// // Before AOP: +// +// @loggable function Foo() { +// return 10; +// } +// @loggable function Bar() { +// return 20; +// } +// +// // After AOP: +// +// @loggable function Foo() { +// LOG("Foo"); +// return 10; +// } +// @loggable function Bar() { +// LOG("Bar"); +// return 20; +// } + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static std::string GetString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + return std::string(name); +} + +static void InsertLog(abckit_Method **f, abckit_Graph *ctxG, abckit_String *str) +{ + // Get first bb next to start bb + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + abckit_BasicBlock *bb = nullptr; + implG->BBvisitSuccBlocks( + startBB, (void *)&bb, + []([[maybe_unused]] abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, void *data) { + auto **bb2 = (abckit_BasicBlock **)data; + *bb2 = succBasicBlock; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create LoadString instruction for call method name + abckit_Inst *loadStringInst = statG->IcreateLoadString(ctxG, str); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstFront(bb, loadStringInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create call instruction + abckit_Inst *callInst = statG->IcreateCallStatic(ctxG, *f, 1, loadStringInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertAfter(callInst, loadStringInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void TransformMethod(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_String *methodNameStr = implI->MethodGetName(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto methodName = GetString(ctxI, methodNameStr); + + // Create value string with call method name + auto nameValue = implM->CreateString(ctxM, methodName.c_str()); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform code of loggable method + abckit_Code *oldCode = implI->MethodGetCode(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + InsertLog(reinterpret_cast(data), ctxG, nameValue); + abckit_Code *newCode = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implM->MethodSetCode(ctxM, method, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static bool CheckIfLoggable(abckit_Method *method) +{ + bool isLoggable = false; + implI->MethodEnumerateAnnotations(method, &isLoggable, [](abckit_Annotation *a, void *d) { + abckit_File *ctx = implI->AnnotationGetInspectContext(a); + auto annoClass = implI->AnnotationGetInterface(a); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = GetString(ctx, implI->AnnotationInterfaceGetName(annoClass)); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + if (std::strcmp(name.c_str(), "loggable") == 0) { + *(reinterpret_cast(d)) = true; + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return isLoggable; +} + +static bool MethodHandler(abckit_Method *m, void *data) +{ + bool isMethodLoggable = CheckIfLoggable(m); + + if (isMethodLoggable) { + impl->TransformMethod(m, data, TransformMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } + + return true; +} + +int Loggable() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + if (impl->GetLastError() != abckit_Status_NO_ERROR) { + return 1; + } + + abckit_Method *logFn = nullptr; + + // Find "LOG" method + implI->FileEnumerateModules(ctx, &logFn, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *f, void *data1) { + abckit_File *ctxI = implI->MethodGetInspectContext(f); + auto **logFn1 = (abckit_Method **)data1; + + abckit_String *mNameStr = implI->MethodGetName(f); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto mName = GetString(ctxI, mNameStr); + if (mName == "LOG") { + *logFn1 = f; + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto logFn2 = reinterpret_cast(data); + return *logFn2 == nullptr; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform loggable methods + implI->FileEnumerateModules(ctx, &logFn, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, MethodHandler); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, MethodHandler); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/examples/replace_first_inst.cpp b/libabckit/examples/replace_first_inst.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73d752c3f5bfab6dc2ba7855cab51da9f86b53e6 --- /dev/null +++ b/libabckit/examples/replace_first_inst.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/abckit.h" + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void blockVisitor(abckit_BasicBlock *bb, void *data) +{ + (void)data; + + abckit_Inst *firstInst = implG->BBgetFirstInst(bb); + implG->Iremove(firstInst); + implG->Iremove(firstInst); +} + +static void RemoveFirstInstPass(abckit_Graph *ctxG) +{ + implG->GvisitBlocksRPO(ctxG, NULL, blockVisitor); +} + +static void TransformMethods(abckit_ModifyContext *ctxM, abckit_Method *method, [[maybe_unused]] void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + RemoveFirstInstPass(ctxG); + abckit_Code *newCode = impl->graphToCode(ctxG); + implM->MethodSetCode(ctxM, method, newCode); +} + +int ReplaceFirstInst() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform methods + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, TransformMethods); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, TransformMethods); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/examples/throw_if_deprecated.cpp b/libabckit/examples/throw_if_deprecated.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f36661ddd924de5e232e1479ff74a745b79d8b69 --- /dev/null +++ b/libabckit/examples/throw_if_deprecated.cpp @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/abckit.h" + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void ThrowIfDeprecatedPass(abckit_Graph *ctxG, abckit_Inst *acc) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + abckit_Inst *startInst = implG->BBgetFirstInst(startBB); + abckit_Inst *newInst = dynG->IcreateThrow(ctxG, acc); + implG->IinsertBefore(startInst, newInst); +} + +static void TransformMethods(abckit_ModifyContext *ctxM, abckit_Method *method, [[maybe_unused]] void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + bool isDeprecated = false; + implI->MethodEnumerateAnnotations(method, &isDeprecated, [](abckit_Annotation *a, void *d) { + abckit_File *ctx = implI->AnnotationGetInspectContext(a); + auto annoClass = implI->AnnotationGetInterface(a); + auto nameStr = implI->AnnotationInterfaceGetName(annoClass); + + size_t len = 0; + implI->abckit_StringToString(ctx, nameStr, nullptr, &len); + auto name = new char[len]; + implI->abckit_StringToString(ctx, nameStr, name, &len); + + if (std::strcmp(name, "Deprecated") == 0) { + *(reinterpret_cast(d)) = true; + delete[] name; + return false; + } + + delete[] name; + return true; + }); + + if (!isDeprecated) { + return; + } + + auto oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + ThrowIfDeprecatedPass(ctxG, nullptr); + abckit_Code *newCode = impl->graphToCode(ctxG); + + implM->MethodSetCode(ctxM, method, newCode); +} + +int ThrowIfDeprecated() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform methods + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, TransformMethods); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, TransformMethods); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/dynamic_add_try_catch.cpp b/libabckit/external_examples/dynamic_add_try_catch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c3ec2af60965ad16b224a1e9f69e9649cbbae521 --- /dev/null +++ b/libabckit/external_examples/dynamic_add_try_catch.cpp @@ -0,0 +1,180 @@ +#include +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/metadata.h" + +// In this example: +// Suppose that some api is throwable, we need to wrap implementaton of throwable API into try-catch statement +// +// before AOP +// +// // throwable function +// function Foo() { +// // business logic +// } +// +// start BB +// | +// BB 1 +// /|\ +// ... <- any combination of basic blocks +// \|/ +// BB N +// | +// end BB +// +// +// // after AOP +// +// function Foo() { +// try { +// // business logic +// } catch (e) { +// console.log(e); +// return 1; +// } +// } +// +// start BB +// | +// V +// helper BB1 +// | +// V +// try_begin BB +// | +// |-----|-----| +// V | +// BB 1 | +// /|\ | +// ... | +// \|/ | +// BB N | +// | | +// V | +// try_end BB | +// | V +// |------>catch_begin BB +// | | +// v V +// helper BB2 catch BB +// | | +// | | +// |->end BB <-| +// +// start BB +// preds: [] +// 32.i32 Constant 0x1 -> (v33) +// succs:[helper BB1] +// +// catch_begin BB +// preds: [try_end BB, try_begin BB] +// 12.any CatchPhi (v30) +// succs: [catch BB] + +// catch BB +// preds: [catch_begin BB] +// 26.any Intrinsic.tryldglobalbyname (v30, v28) +// 28.any Intrinsic.ldobjbyname v26 -> (v30) +// 30.any Intrinsic.callthis1 v26, v12, v28 +// 33.void Intrinsic.return v32 +// succs: [end BB] +// +// NOTE: If user want to wrap only some instructions into try block (for example, wrap a single call to function), +// user should just create separate basic block, which contains only instructions, that are needed to wrap. +// Whole other logic doesn't change. + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void AddTryCatch(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + abckit_File *ctxI = (abckit_File *)data; + + abckit_Code *oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + abckit_BasicBlock *endBB = implG->GgetEndBasicBlock(ctxG); + abckit_BasicBlock *startSucc = implG->BBgetSuccBlock(startBB, 0); + + // add constant to start block + abckit_Inst *constInst = implG->GcreateConstantI64(ctxG, 1); + implG->BBaddInstBack(startBB, constInst); + + // create catch begin basic block + abckit_BasicBlock *catchBeginBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *catchPhi_Inst = dynG->IcreateCatchPhi(ctxG, 0); + implG->BBaddInstBack(catchBeginBB, catchPhi_Inst); + + // create catch block + abckit_BasicBlock *catchBB = implG->BBcreateEmpty(ctxG); + // TODO: obtain string + abckit_String *strConsole = nullptr; + abckit_Inst *tryldglobalbynameInst = dynG->IcreateTryldglobalbyname(ctxG, strConsole); + // TODO: obtain string + abckit_String *strLog = nullptr; + abckit_Inst *ldobjbynameInst = dynG->IcreateLdobjbyname(ctxG, tryldglobalbynameInst, strLog); + abckit_Inst *callthis1Inst = + dynG->IcreateCallthis1(ctxG, tryldglobalbynameInst, catchPhi_Inst, ldobjbynameInst); + abckit_Inst *returnInst = dynG->IcreateReturn(ctxG, constInst); + implG->BBaddInstBack(catchBB, tryldglobalbynameInst); + implG->BBaddInstBack(catchBB, ldobjbynameInst); + implG->BBaddInstBack(catchBB, callthis1Inst); + implG->BBaddInstBack(catchBB, returnInst); + + // create empty catch end block + abckit_BasicBlock *catchEnd = implG->BBcreateEmpty(ctxG); + + implG->BBconnectBlocks(catchBeginBB, catchBB, 1); + implG->BBconnectBlocks(catchBB, catchEnd, 1); + + implG->GinsertTryCatch(startSucc, endBB, catchBeginBB, catchEnd); + + abckit_Code *newCode = impl->graphToCode(ctxG); + implM->MethodSetCode(ctxM, method, newCode); +} + +int DynamicAddTryCatch() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform methods + implI->FileEnumerateModules(ctx, (void *)ctx, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, AddTryCatch); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, AddTryCatch); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} \ No newline at end of file diff --git a/libabckit/external_examples/dynamic_check_parameters.cpp b/libabckit/external_examples/dynamic_check_parameters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73f420c803bf4d5b062331a2a6e7fc8252dfc69c --- /dev/null +++ b/libabckit/external_examples/dynamic_check_parameters.cpp @@ -0,0 +1,276 @@ +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/metadata.h" + +// Prepend input validation for "handle" methods of all classes that +// are marked with @Handler annotations. +// +// app.ets +// +// // Before transformation +// +// @Handler +// class StringHandler { +// handler(arr: string[], idx: number): number { +// // logic +// } +// } +// +// // After transformation +// +// @Handler +// class StringHandler { +// handler(arr: string[], idx: number): number { +// if (idx >= arr.length) { +// return -1 +// } +// // logic +// } +// } + +// In terms of basic blocks: +// +// Before: +// +// bbStart +// | +// bbSucc +// +// After: +// +// bbStart +// | +// bbCondition------+ +// | | +// | true | false +// | | +// bbTrueBranch | +// | | +// bbSucc<----------+ + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +static abckit_Code *addParameterCheck(abckit_ModifyContext *ctxM, abckit_Method *method) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + abckit_Code *oldCode = implI->MethodGetCode(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(oldCode != nullptr); + + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(ctxG != nullptr); + + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(bbStart != nullptr); + + abckit_BasicBlock *bbOrigStartSucc = nullptr; + implG->BBvisitSuccBlocks( + bbStart, static_cast(&bbOrigStartSucc), + []([[maybe_unused]] abckit_BasicBlock *bbCurrent, [[maybe_unused]] abckit_BasicBlock *bbSucc, void *data) { + auto bb = static_cast(data); + assert(*bb == nullptr); // Only single successor for bbStart + assert(bbSucc != nullptr); + *bb = bbSucc; + }); + assert(bbOrigStartSucc != nullptr); + + // TODO: Here we rely on the fact that at least two parameters exist, + // so asserts are enough. Add proper verbose error handling if needed. + + // param_arr := Parameter0 + abckit_Inst *inst = implG->BBgetFirstInst(bbStart); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst != nullptr); + + abckit_IsaApiDynamicOpcode opcode = dynG->IgetOpcode(inst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(opcode == abckit_IsaApiDynamicOpcode_Parameter); + + abckit_Inst *param_arr = inst; + + // param_idx := Parameter1 + inst = implG->IgetNext(inst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst != nullptr); + assert(inst != param_arr); + + opcode = dynG->IgetOpcode(inst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(opcode == abckit_IsaApiDynamicOpcode_Parameter); + + abckit_Inst *param_idx = inst; + + // Create extra instructions for bbStart: + + // inst_const_m1 := Constant -1 + abckit_Inst *inst_const_m1 = implG->GcreateConstantU64(ctxG, static_cast(-1)); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_const_m1 != nullptr); + + // Create instructions for bbCondition: + + // inst_arr_len := dyn.LdObjByName(param_arr, StringId("length")) + + // Create value string with call method name + [[maybe_unused]] auto lengthPropValue = implM->CreateString(ctxM, "length"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *inst_arr_len = dynG->IcreateLdobjbyname(ctxG, param_arr, lengthPropValue); + + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_arr_len != nullptr); + + // inst_cmp := dyn.GreaterEqDyn(GE, param_idx, inst_arr_len) + abckit_Inst *inst_cmp = dynG->IcreateGreatereq(ctxG, param_idx, inst_arr_len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_cmp != nullptr); + + // Create instructions for the true branch: + + // inst_return := Return(inst_const_m1) + abckit_Inst *inst_return = dynG->IcreateReturn(ctxG, inst_const_m1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_return != nullptr); + + // Append constants to the bbStart: + implG->BBaddInstBack(bbStart, inst_const_m1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill the basic block for the condition: + abckit_BasicBlock *bbCondition = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(bbCondition != nullptr); + implG->BBaddInstBack(bbCondition, inst_arr_len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbCondition, inst_cmp); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill the basic block for the true branch: + abckit_BasicBlock *bbTrueBranch = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(bbTrueBranch != nullptr); + implG->BBaddInstBack(bbTrueBranch, inst_return); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // + // Re-connecting basic blocks: + // + + // bbStart -> bbCondition + implG->BBconnectBlocks(bbStart, bbCondition, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // bbCondition -> bbTrueBranch + implG->BBconnectBlocks(bbCondition, bbTrueBranch, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // bbCondition -> bbOrigStartSucc + implG->BBconnectBlocks(bbCondition, bbOrigStartSucc, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // bbTrueBranch -> bbOrigStartSucc + implG->BBconnectBlocks(bbTrueBranch, bbOrigStartSucc, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *code = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(code != nullptr); + return code; +} + +static void transformMethod(abckit_ModifyContext *ctxM, abckit_Method *method, [[maybe_unused]] void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + abckit_Class *klass = implI->MethodGetParentClass(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(klass != nullptr); + + auto name = abckit_StringToString(ctxI, implI->MethodGetName(method)); + if (std::strcmp(name.c_str(), "handle") != 0) { + return; + } + + bool classIsHandler = false; + implI->ClassEnumerateAnnotations(klass, &classIsHandler, [](abckit_Annotation *anno, void *isHandler) { + abckit_File *ctx = implI->AnnotationGetInspectContext(anno); + auto annoKlass = implI->AnnotationGetInterface(anno); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(annoKlass != nullptr); + assert(implI->AnnotationInterfaceGetName(annoKlass) != nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoName = abckit_StringToString(ctx, implI->AnnotationInterfaceGetName(annoKlass)); + if (std::strcmp(annoName.c_str(), "Handler") == 0) { + *(reinterpret_cast(isHandler)) = true; + return false; + } + return true; + }); + + if (!classIsHandler) { + return; + } + + auto newCode = addParameterCheck(ctxM, method); + implM->MethodSetCode(ctxM, method, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +int DynamicCheckParameters() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform methods + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, transformMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, transformMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/dynamic_replace_call_site.cpp b/libabckit/external_examples/dynamic_replace_call_site.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad062b593cdd250bac16fb624a1eb98aa0e0d560 --- /dev/null +++ b/libabckit/external_examples/dynamic_replace_call_site.cpp @@ -0,0 +1,356 @@ +#include +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/metadata.h" + +// In this example: +// * "FooWrapper" function is created, "FooWrapper" consumes same arguments as "Foo", calls "Foo" and returns "Foo" +// result +// * All "Foo" calls are replaced with "FooWrapper" calls +// +// NOTE: instead of finding all methods with "@CallSiteReplacement" annotation, we stop at the first one we find and +// change call site only for it. This is done for the sake of breavity of the example. Implementing this for several +// methods annotated with "@CallSiteReplacement" annotation will not be any different. +// +// // Given: +// +// import {LinearLayout} from "./layout" +// +// ApiControl.ets +// @interface CallSiteReplacement { +// targetClass: string +// methodName: string +// } +// export class ApiControl { +// @CallSiteReplacement({targetClass = "com.meituan.LinearLayout", methodName = "setOrientation"}) +// // It means that we need to replace all the call-site of com.meituan.LinearLayout.setOrientation" with +// "ApiControl.fixOrientationLinearLayout" public static void fixOrientationLinearLayout(target: LinearLayout, +// orientation: number) { +// // business logic +// } +// } +// +// // Before AOP: +// +// class MyClass { +// foo() { +// // ... +// let appColumn = new LinearLayout(); +// appColumn.setOrientation(LinearLayout.VERTICAL); +// // ... +// } +// +// // After AOP: +// +// import {LinearLayout} from "./layout" +// import {ApiControl} from "./ApiControl" +// class MyClass { +// foo() { +// // ... +// let appColumn = new LinearLayout(); +// ApiControl.fixOrientationLinearLayout(appColumn, LinearLayout.VERTICAL); +// // ... +// } + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +struct UserData { + abckit_Method *ReplacementMethod = nullptr; + std::string targetClass = ""; + std::string methodName = ""; + abckit_File *ctxI = nullptr; + abckit_ModifyContext *ctxM = nullptr; +}; + +static void ReplaceCallSiteVisitor(abckit_BasicBlock *bb, void *data) +{ + abckit_Graph *ctxG = implG->BBgetGraph(bb); + auto *userData = (UserData *)data; + auto *ctxI = userData->ctxI; + auto *ctxM = userData->ctxM; + + abckit_Inst *curInst = implG->BBgetFirstInst(bb); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode resOpcode = dynG->IgetOpcode(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + if (resOpcode != abckit_IsaApiDynamicOpcode_callthis1) { + curInst = implG->IgetNext(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + continue; + } + + // TODO: maybe provide sugar for dynamic calls to get method name and object name more easily? + abckit_Inst *ldobjbynameInst; + abckit_Inst *newobjrangeInst; + implG->IvisitInputs(curInst, (void *)&ldobjbynameInst, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t imputIdx, void *data2) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(input); + abckit_BasicBlock *inst_bb = implG->IgetBasicBlock(inst); + [[maybe_unused]] abckit_Graph *graph = implG->BBgetGraph(inst_bb); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + if (curOpcode == abckit_IsaApiDynamicOpcode_ldobjbyname) { + (*(abckit_Inst **)data2) = input; + } + }); + implG->IvisitInputs(curInst, (void *)&newobjrangeInst, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data2) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(input); + abckit_BasicBlock *inst_bb = implG->IgetBasicBlock(inst); + [[maybe_unused]] abckit_Graph *graph = implG->BBgetGraph(inst_bb); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + if (curOpcode == abckit_IsaApiDynamicOpcode_newobjrange) { + (*(abckit_Inst **)data2) = input; + } + }); + abckit_Inst *tryldglobalbynameInst = implG->IgetInput(newobjrangeInst, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // TODO rewrite example and obtain string more properly + [[maybe_unused]] uint64_t typeIdObject = implG->IgetImmediate(ldobjbynameInst, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + // TODO rewrite example and obtain string more properly + [[maybe_unused]] uint64_t typeIdMethod = implG->IgetImmediate(tryldglobalbynameInst, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // TODO rewrite example and obtain string more properly + abckit_String *objectNameString = nullptr; + auto objectNameStr = abckit_StringToString(ctxI, objectNameString); + + // TODO rewrite example and obtain string more properly + abckit_String *methodNameString = nullptr; + auto methodNameStr = abckit_StringToString(ctxI, methodNameString); + + if (methodNameStr != userData->methodName || objectNameStr != userData->targetClass) { + continue; + } + + // need to create string literals, so that they can be called from tryldglobalbyname and ldobjbyname + // TODO assign this value to newtryldglobalbynameInst below + [[maybe_unused]] auto newObjectNameValue = implM->CreateString(ctxM, userData->methodName.c_str()); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + // TODO assign this value to ldobjbynameInst in creator function + [[maybe_unused]] auto newMethodNameValue = implM->CreateString(ctxM, userData->targetClass.c_str()); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // for shorter let's reuse old instruction + abckit_Inst *newtryldglobalbynameInst = dynG->IcreateTryldglobalbyname(ctxG, newObjectNameValue); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::vector inputs; + implG->IvisitInputs(curInst, (void *)&inputs, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data2) { + auto inputs2 = (std::vector *)data2; + inputs2->push_back(input); + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::vector users; + implG->IvisitUsers(curInst, (void *)&users, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *user, void *data2) { + auto users2 = (std::vector *)data2; + users2->push_back(user); + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *callthisNew = + dynG->IcreateCallthis1(ctxG, newtryldglobalbynameInst, ldobjbynameInst, newobjrangeInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // methods arguments + for (size_t i = 0; i < inputs.size(); i++) { + implG->IsetInput(callthisNew, inputs[i], i + 3); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } + for (auto *user : users) { + std::vector userInputs; + implG->IvisitInputs(user, (void *)&userInputs, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data2) { + auto userInputs2 = (std::vector *)data2; + userInputs2->push_back(input); + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + for (size_t i = 0; i < userInputs.size(); i++) { + if (userInputs[i] == curInst) { + implG->IsetInput(user, callthisNew, i); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } + } + } + + implG->IinsertBefore(newtryldglobalbynameInst, curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(callthisNew, curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->Iremove(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + curInst = implG->IgetNext(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } +} + +void ReplaceCallSite(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto oldCode = implI->MethodGetCode(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + (reinterpret_cast(data))->ctxM = ctxM; + implG->GvisitBlocksRPO(ctxG, data, ReplaceCallSiteVisitor); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implM->MethodSetCode(ctxM, method, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void FindCallSiteReplacement(abckit_File *ctxI, UserData *data) +{ + implI->FileEnumerateModules(ctxI, &data, [](abckit_Module *m, void *data) { + auto **userData = (UserData **)data; + + implI->ModuleEnumerateClasses(m, (void *)data, [](abckit_Class *klass, void *data1) { + auto **userData1 = (UserData **)data1; + + implI->ClassEnumerateMethods(klass, (void *)userData1, [](abckit_Method *method, void *data2) { + auto **userData2 = (UserData **)data2; + + implI->MethodEnumerateAnnotations(method, (void *)userData2, [](abckit_Annotation *anno, void *data3) { + abckit_File *ctxI3 = implI->AnnotationGetInspectContext(anno); + auto **userData3 = (UserData **)data3; + + auto annoClass = implI->AnnotationGetInterface(anno); + abckit_String *anName = implI->AnnotationInterfaceGetName(annoClass); + + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoName = abckit_StringToString(ctxI3, anName); + + if (std::strcmp(annoName.c_str(), "CallSiteReplacement") != 0) { + return true; + } + + implI->AnnotationEnumerateElements( + anno, (void *)userData3, [](abckit_AnnotationElement *elem, void *data4) { + auto **userData4 = (UserData **)data4; + + auto ctxI4 = implI->AnnotationElementGetInspectContext(elem); + + auto anElName = implI->AnnotationElementGetName(elem); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI4, anElName); + + if (std::strcmp(name.c_str(), "targetClass") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(elem); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto s = implI->ValueGetString(ctxI4, val); + (*userData4)->targetClass = abckit_StringToString(ctxI4, s); + } else if (std::strcmp(name.c_str(), "methodName") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(elem); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto s = implI->ValueGetString(ctxI4, val); + (*userData4)->methodName = abckit_StringToString(ctxI4, s); + } + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return false; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + if (!(*userData2)->targetClass.empty() && !(*userData2)->methodName.empty()) { + (*userData2)->ReplacementMethod = method; + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + if ((*userData1)->ReplacementMethod != nullptr) { + return false; + } + return true; + }); + + if ((*userData)->ReplacementMethod != nullptr) { + return false; + } + return true; + }); + + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +int DynamicReplaceCallSite() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + UserData userData = {}; + userData.ctxI = ctx; + + FindCallSiteReplacement(ctx, &userData); + assert(userData.ReplacementMethod != nullptr); + + // Transform methods + implI->FileEnumerateModules(ctx, (void *)(&userData), [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, ReplaceCallSite); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, ReplaceCallSite); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/dynamic_router_table.cpp b/libabckit/external_examples/dynamic_router_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f91142c3cab3ec397e13f1abb01be0502a69df75 --- /dev/null +++ b/libabckit/external_examples/dynamic_router_table.cpp @@ -0,0 +1,315 @@ +#include +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_dynamic.h" +#include "../include/metadata.h" + +// before AOP +// +// IRouterHandler.ets +// export abstract class IRouterHandler { +// handle(): void; +// } +// +// export enum Thread { +// WORKER, +// TASKPOOL +// } +// +// export @interface Router { +// schme: string; +// path: string; +// thread: Thread; +// } + +// xxxHandler.ets // we have many such classes +// import {Router, IRouterHandler, Thread} from "./IRouterHandler" +// {schema: "imeituan", path: "/xxx", thread: Thread.WORKER} +// export class xxxHandler extends IRouterHandler { +// void handle() { +// // business logic +// } +// } + +// routerMap.ets +// import {IRouterHandler} from "./IRouterHandler" +// export let routerMap = new Map([ +// ]); + +// after AOP +// +// need to insert code into routerMap.ets and remove annotations +// routerMap.ets +// import {IRouterHandler} from "./IRouterHandler"; + +// import {xxxHandler} from "./xxxHandler"; +// we have many such imports + +// export let routerMap = new Map(); +// +// routerMap.set("imeituan/xxx", new xxxHandler()) // [schema + path, new handler()] +// // ... // we have many such pairs +// + +// // xxxHandler.ets // we have many such classes +// import {Router, IRouterHandler, Thread} from "./IRouterHandler" +// export class xxxHandler extends IRouterHandler { // annotation is removed +// void handle() { +// // business logic +// } +// } + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + std::size_t len = 0; + + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(len > 0); + + auto name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::string res {name}; + delete[] name; + + return res; +} + +struct AnnoInfo { + std::string schema; + std::string path; + abckit_String *str; + abckit_Class *klass; + abckit_Method *ctor; + abckit_Annotation *anno; +} typedef AnnoInfo; + +struct UserInfo { + std::vector annoInfo; + abckit_Class *globalClass; + abckit_Field *routerMap; + abckit_File *ctxI; + abckit_ModifyContext *ctxM; +} typedef UserInfo; + +static void processAnnotations(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data) +{ + [[maybe_unused]] abckit_File *ctxI = implI->ClassGetInspectContext(klass); + auto userData = reinterpret_cast(data); + AnnoInfo newData; + implI->ClassEnumerateAnnotations(klass, &newData, [](abckit_Annotation *anno, void *data1) { + abckit_File *ctx = implI->AnnotationGetInspectContext(anno); + auto annoClass = implI->AnnotationGetInterface(anno); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto str = implI->AnnotationInterfaceGetName(annoClass); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoName = abckit_StringToString(ctx, str); + + if (std::strcmp(annoName.c_str(), "Router") != 0) { + return true; + } + + AnnoInfo *userData1 = (AnnoInfo *)data1; + userData1->anno = const_cast(anno); + + implI->AnnotationEnumerateElements(anno, userData1, [](abckit_AnnotationElement *annoElement, void *data2) { + auto ctx2 = implI->AnnotationElementGetInspectContext(annoElement); + + auto aes = implI->AnnotationElementGetName(annoElement); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoElementName = abckit_StringToString(ctx2, aes); + + AnnoInfo *newData2 = (AnnoInfo *)data2; + if (std::strcmp(annoElementName.c_str(), "schema") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetString(ctx2, val); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto valName = abckit_StringToString(ctx2, vs); + newData2->schema = valName; + } + + if (std::strcmp(annoElementName.c_str(), "path") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetString(ctx2, val); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto valName = abckit_StringToString(ctx2, vs); + newData2->path = valName; + } + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ClassEnumerateMethods(klass, (void *)&newData, [](abckit_Method *method, void *data1) { + abckit_File *ctx = implI->MethodGetInspectContext(method); + auto str = implI->MethodGetName(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto methodName = abckit_StringToString(ctx, str); + + // TODO: provide a shortcut for searching constructors + if (std::strcmp(methodName.c_str(), "CTOR") == 0) { + ((AnnoInfo *)data1)->ctor = const_cast(method); + return false; + } + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::string concatString = std::string(newData.schema) + std::string(newData.path); + auto stringValue = implM->CreateString(ctxM, concatString.c_str()); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + newData.str = stringValue; + + newData.klass = klass; + userData->annoInfo.push_back(newData); + implM->ClassRemoveAnnotation(ctxM, klass, newData.anno); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void addSetCall(abckit_BasicBlock *bb, void *data) +{ + abckit_Graph *ctxG = implG->BBgetGraph(bb); + UserInfo *userData = (UserInfo *)data; + + abckit_Inst *lastInst = implG->BBgetLastInst(bb); + + for (auto annoInfo : userData->annoInfo) { + abckit_Inst *ldlocalmodulevarInst = dynG->IcreateLdlocalmodulevar(ctxG, nullptr /*TODO: ExportDescriptor*/); + auto routerMapValue = implM->CreateString(userData->ctxM, "GLOBAL"); + // TODO set routerMapValue to ldlocalmodulevarInst + implG->IinsertBefore(ldlocalmodulevarInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + routerMapValue = implM->CreateString(userData->ctxM, "routerMap"); + // TODO set routerMapValue to ldobjbynameInst + abckit_Inst *ldobjbynameInst = dynG->IcreateLdobjbyname(ctxG, ldlocalmodulevarInst, routerMapValue); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(ldobjbynameInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *loadStringInst = dynG->IcreateLoadString(ctxG, annoInfo.str); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(loadStringInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *defineClassWithBufferInst = dynG->IcreateDefineclasswithbuffer( + ctxG, nullptr, nullptr, 0, nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + [[maybe_unused]] auto classNameStr = implI->ClassGetName(annoInfo.klass); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + // TODO set classNameStr to defineClassWithBufferInst + implG->IinsertBefore(defineClassWithBufferInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *setMethodinst = dynG->IcreateDefineclasswithbuffer(ctxG, nullptr, nullptr, 0, nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + [[maybe_unused]] auto classValue = implM->CreateString(userData->ctxM, "set"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + // TODO set classValue to setMethodinst + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(setMethodinst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *newObjectInst = dynG->IcreateNewobjrange(ctxG, 0, setMethodinst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(newObjectInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // finally, add element to std::Map + abckit_Inst *callthis2Inst = dynG->IcreateCallthis2( + ctxG, ldlocalmodulevarInst, loadStringInst, newObjectInst, ldobjbynameInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(callthis2Inst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } +} + +static void modifyInitGlobal(abckit_ModifyContext *ctxM, abckit_Module *m, void *data) +{ + abckit_Method *initMethod = nullptr; + + auto ctxI = implI->ModuleGetInspectContext(m); + + auto moduleNameStr = implI->ModuleGetName(m); + auto moduleName = abckit_StringToString(ctxI, moduleNameStr); + if (moduleName != "MyModule") { + return; + } + + implI->ModuleEnumerateTopLevelFunctions(m, &initMethod, [](abckit_Method *method, void *d) { + abckit_File *ctx = implI->MethodGetInspectContext(method); + auto name = abckit_StringToString(ctx, implI->MethodGetName(method)); + if (std::strcmp(name.c_str(), "_$init$_") == 0) { + *(reinterpret_cast(d)) = const_cast(method); + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(initMethod != nullptr); + + abckit_Code *oldCode = implI->MethodGetCode(initMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implG->GvisitBlocksRPO(ctxG, data, addSetCall); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implM->MethodSetCode(ctxM, initMethod, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +int DynamicRouterTable() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + UserInfo userInfo; + + // Transform + implI->FileEnumerateModules(ctx, (void *)&userInfo, [](abckit_Module *m, void *data) { + impl->TransformModule(m, data, modifyInitGlobal); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + impl->TransformClass(c, data, processAnnotations); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/static_add_try_catch.cpp b/libabckit/external_examples/static_add_try_catch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ba6d3f2775f885c4ff999959391d857ea020221 --- /dev/null +++ b/libabckit/external_examples/static_add_try_catch.cpp @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/metadata.h" + +// In this example: +// Suppose that some api is throwable, we need to add try-catch for some particular important call-site +// +// // before AOP +// function Foo() { +// // business logic +// let tmp = THROWABLE_FUNC(); +// // business logic +// } +// +// // after AOP +// function Foo() { +// // business logic +// let tmp: int = 0; +// try { +// tmp = THROWABLE_FUNC(); +// } catch(e) { +// LOG(e); +// tmp = 0; +// } +// // business logic +// } +// +// IR: +// // before AOP +// bb3 +// 1.i32 CallStatic 68156 ETSGLOBAL::THROWABLE_FUNC +// +// // after AOP +// bb0 (start) preds: [] succs: [bb1] +// 1.i64 Constant 0x0 +// +// bb1 preds: [bb0] succs: [bb2] +// +// bb2 (try_begin) preds: [bb1] succs: [bb3, bb5] +// 0. Try +// +// bb3 (try) preds: [bb2] succs: [bb4] +// 2.i32 CallStatic 68109 ETSGLOBAL::THROWABLE_FUNC +// +// bb4 (try_end) preds: [bb3] succs: [bb7, bb5] +// +// bb5 (catch_begin) preds: [bb2, bb4] succs: [bb6] +// 3.ref CatchPhi +// +// bb6 (catch) preds: [bb5] succs: [bb7] +// 4.void CallStatic 68029 ETSGLOBAL::LOG v3 +// +// bb7 preds: [bb4, bb6] succs: [bb8] +// 5p.i32 Phi v2(bb4), v1(bb6) +// + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +struct UserData { + abckit_Method *logMethod = nullptr; + abckit_Method *throwableFunc = nullptr; +}; + +static std::string GetString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + return std::string(name); +} + +static void AddTryCatchVisitor(abckit_BasicBlock *bb, void *data) +{ + abckit_Graph *ctxG = implG->BBgetGraph(bb); + auto *userData = (UserData *)data; + + abckit_Inst *curInst = implG->BBgetFirstInst(bb); + while (curInst != nullptr) { + abckit_IsaApiStaticOpcode resOpcode = statG->IgetOpcode(curInst); + if (resOpcode != abckit_IsaApiStaticOpcode_CallStatic) { + curInst = implG->IgetNext(curInst); + continue; + } + + auto callee = implG->IgetMethod(curInst); + if (callee != userData->throwableFunc) { + continue; + } + + abckit_BasicBlock *bb0 = implG->BBcreateEmpty(ctxG); + abckit_BasicBlock *bb1 = implG->BBcreateEmpty(ctxG); + abckit_BasicBlock *bb2 = implG->BBcreateEmpty(ctxG); + abckit_BasicBlock *bb3 = implG->IgetBasicBlock(curInst); + abckit_BasicBlock *bb4 = implG->BBcreateEmpty(ctxG); + abckit_BasicBlock *bb5 = implG->BBcreateEmpty(ctxG); + abckit_BasicBlock *bb6 = implG->BBcreateEmpty(ctxG); + abckit_BasicBlock *bb7 = implG->BBcreateEmpty(ctxG); + + // Get predecessor and successor basic blocks + std::vector preds; + implG->BBvisitPredBlocks( + bb3, (void *)&preds, + []([[maybe_unused]] abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *predBasicBlock, void *data2) { + auto preds2 = reinterpret_cast *>(data2); + preds2->emplace_back(predBasicBlock); + }); + std::vector succs; + implG->BBvisitSuccBlocks( + bb3, (void *)&succs, + []([[maybe_unused]] abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, void *data2) { + auto succs2 = reinterpret_cast *>(data2); + succs2->emplace_back(succBasicBlock); + }); + + // Reconnect predecessor blocks to bb0 + for (auto *pred : preds) { + implG->BBdisconnectBlocks(pred, bb3); + implG->BBconnectBlocks(pred, bb0, 1); + } + // Reconnect bb7 to successor blocks + for (auto *succ : succs) { + implG->BBdisconnectBlocks(bb3, succ); + implG->BBconnectBlocks(bb7, succ, 1); + } + // Connect new basic blocks + implG->BBconnectBlocks(bb0, bb1, 1); + implG->BBconnectBlocks(bb1, bb2, 1); + implG->BBconnectBlocks(bb2, bb3, 1); + implG->BBconnectBlocks(bb2, bb5, 1); + implG->BBconnectBlocks(bb3, bb4, 1); + implG->BBconnectBlocks(bb4, bb5, 1); + implG->BBconnectBlocks(bb4, bb7, 1); + implG->BBconnectBlocks(bb5, bb6, 1); + implG->BBconnectBlocks(bb6, bb7, 1); + + // bb0 + abckit_Inst *inst1 = implG->GcreateConstantU64(ctxG, 0x0); + implG->BBaddInstBack(bb0, inst1); + + // bb2 + abckit_Inst *inst0 = statG->IcreateTry(ctxG); + implG->BBaddInstBack(bb2, inst0); + + // bb3 + + // bb5 + abckit_Inst *inst3 = statG->IcreateCatchPhi(ctxG, 0); + implG->BBaddInstBack(bb5, inst3); + + // bb6 + abckit_Inst *inst4 = statG->IcreateCallStatic(ctxG, userData->logMethod, 1, inst3); + implG->BBaddInstBack(bb6, inst4); + + // bb7 + abckit_Inst *inst5p = implG->BBcreatePhi(bb7, 2, inst1, curInst); + + // Get outputs from old CallStatic + std::vector users; + implG->IvisitUsers(curInst, (void *)&users, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *user, void *data2) { + auto users2 = (std::vector *)data2; + users2->push_back(user); + }); + + // Replace last + for (auto *user : users) { + std::vector userInputs; + implG->IvisitInputs(user, (void *)&userInputs, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data2) { + auto userInputs2 = (std::vector *)data2; + userInputs2->push_back(input); + }); + for (size_t i = 0; i < userInputs.size(); i++) { + if (userInputs[i] == curInst) { + implG->IsetInput(user, inst5p, i); + } + } + } + } +} + +static void AddTryCatch(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + abckit_Code *oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + implG->GvisitBlocksRPO(ctxG, data, AddTryCatchVisitor); + abckit_Code *newCode = impl->graphToCode(ctxG); + implM->MethodSetCode(ctxM, method, newCode); +} + +int StaticAddTryCatch() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + UserData userData = {}; + implI->FileEnumerateModules(ctx, &userData, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *method, void *data) { + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto *userData2 = (UserData *)data; + abckit_String *nameStr = implI->MethodGetName(method); + auto name = GetString(ctxI, nameStr); + if (name == "LOG") { + userData2->logMethod = method; + } + if (name == "THROWABLE_FUNC") { + userData2->throwableFunc = method; + } + return true; + }); + return true; + }); + + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform methods + implI->FileEnumerateModules(ctx, &userData, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, AddTryCatch); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, AddTryCatch); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/static_check_parameters.cpp b/libabckit/external_examples/static_check_parameters.cpp new file mode 100644 index 0000000000000000000000000000000000000000..476c3394ef6eead33252f43046fd451af4709f93 --- /dev/null +++ b/libabckit/external_examples/static_check_parameters.cpp @@ -0,0 +1,268 @@ +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" +#include "../include/metadata.h" + +// Prepend input validation for "handle" methods of all classes that +// are marked with @Handler annotations. +// +// app.ets +// +// // Before transformation +// +// @Handler +// class StringHandler { +// handler(arr: string[], idx: number): number { +// // logic +// } +// } +// +// // After transformation +// +// @Handler +// class StringHandler { +// handler(arr: string[], idx: number): number { +// if (idx >= arr.length) { +// return -1 +// } +// // logic +// } +// } + +// In terms of basic blocks: +// +// Before: +// +// bbStart +// | +// bbSucc +// +// After: +// +// bbStart +// | +// bbCondition------+ +// | | +// | true | false +// | | +// bbTrueBranch | +// | | +// bbSucc<----------+ + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +static abckit_Code *addParameterCheck(abckit_Method *method) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + abckit_Code *oldCode = implI->MethodGetCode(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(oldCode != nullptr); + + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(ctxG != nullptr); + + abckit_BasicBlock *bbStart = implG->GgetStartBasicBlock(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(bbStart != nullptr); + + abckit_BasicBlock *bbOrigStartSucc = nullptr; + implG->BBvisitSuccBlocks( + bbStart, static_cast(&bbOrigStartSucc), + []([[maybe_unused]] abckit_BasicBlock *bbCurrent, [[maybe_unused]] abckit_BasicBlock *bbSucc, void *data) { + auto bb = static_cast(data); + assert(*bb == nullptr); // Only single successor for bbStart + assert(bbSucc != nullptr); + *bb = bbSucc; + }); + assert(bbOrigStartSucc != nullptr); + + // TODO: Here we rely on the fact that at least two parameters exist, + // so asserts are enough. Add proper verbose error handling if needed. + + // param_arr := Parameter0 + abckit_Inst *inst = implG->BBgetFirstInst(bbStart); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst != nullptr); + abckit_IsaApiStaticOpcode opcode = statG->IgetOpcode(inst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(opcode == abckit_IsaApiStaticOpcode_Parameter); + abckit_Inst *param_arr = inst; + + // param_idx := Parameter1 + inst = implG->IgetNext(inst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst != nullptr); + assert(inst != param_arr); + opcode = statG->IgetOpcode(inst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(opcode == abckit_IsaApiStaticOpcode_Parameter); + abckit_Inst *param_idx = inst; + + // Create extra instructions for bbStart: + + // inst_const_m1 := Constant -1 + abckit_Inst *inst_const_m1 = implG->GcreateConstantU64(ctxG, static_cast(-1)); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_const_m1 != nullptr); + + // Create instructions for bbCondition: + + // inst_arr_len := LenArray(param_arr) + abckit_Inst *inst_arr_len = statG->IcreateLenArray(ctxG, param_arr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_arr_len != nullptr); + + // inst_cmp := Cmp(GE, param_idx, inst_arr_len) + // NOTE: wrong condition code, there should be GE. But GE is absent in the mainline + abckit_Inst *inst_cmp = statG->IcreateCmp(ctxG, param_idx, inst_arr_len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_cmp != nullptr); + + // Create instructions for the true branch: + + // inst_return := Return(inst_const_m1) + abckit_Inst *inst_return = statG->IcreateReturn(ctxG, inst_const_m1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(inst_return != nullptr); + + // Append constants to the bbStart: + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbStart, inst_const_m1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill the basic block for the condition: + abckit_BasicBlock *bbCondition = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(bbCondition != nullptr); + implG->BBaddInstBack(bbCondition, inst_arr_len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstBack(bbCondition, inst_cmp); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Create and fill the basic block for the true branch: + abckit_BasicBlock *bbTrueBranch = implG->BBcreateEmpty(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(bbTrueBranch != nullptr); + implG->BBaddInstBack(bbTrueBranch, inst_return); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // + // Re-connecting basic blocks: + // + + // bbStart -> bbCondition + implG->BBconnectBlocks(bbStart, bbCondition, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // bbCondition -> bbTrueBranch + implG->BBconnectBlocks(bbCondition, bbTrueBranch, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // bbCondition -> bbOrigStartSucc + implG->BBconnectBlocks(bbCondition, bbOrigStartSucc, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // bbTrueBranch -> bbOrigStartSucc + implG->BBconnectBlocks(bbTrueBranch, bbOrigStartSucc, 1); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *code = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(code != nullptr); + return code; +} + +static void transformMethod(abckit_ModifyContext *ctxM, abckit_Method *method, [[maybe_unused]] void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto klass = implI->MethodGetParentClass(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(klass != nullptr); + + auto name = abckit_StringToString(ctxI, implI->MethodGetName(method)); + if (std::strcmp(name.c_str(), "handle") != 0) { + return; + } + + bool classIsHandler = false; + implI->ClassEnumerateAnnotations(klass, &classIsHandler, [](abckit_Annotation *anno, void *isHandler) { + abckit_File *ctx = implI->AnnotationGetInspectContext(anno); + auto annoKlass = implI->AnnotationGetInterface(anno); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(annoKlass != nullptr); + assert(implI->AnnotationInterfaceGetName(annoKlass) != nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoName = abckit_StringToString(ctx, implI->AnnotationInterfaceGetName(annoKlass)); + if (std::strcmp(annoName.c_str(), "Handler") == 0) { + *(reinterpret_cast(isHandler)) = true; + return false; + } + return true; + }); + + if (!classIsHandler) { + return; + } + + auto newCode = addParameterCheck(method); + implM->MethodSetCode(ctxM, method, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +int StaticCheckParameters() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // Transform methods + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, transformMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, transformMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/static_replace_call_site.cpp b/libabckit/external_examples/static_replace_call_site.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00034aac7fdd313ba1eccb63f5ae8637aca8ca28 --- /dev/null +++ b/libabckit/external_examples/static_replace_call_site.cpp @@ -0,0 +1,311 @@ +#include +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/metadata.h" +#include "../include/isa/isa_static.h" +#include "../include/ir_core.h" + +// In this example: +// * "FooWrapper" function is created, "FooWrapper" consumes same arguments as "Foo", calls "Foo" and returns "Foo" +// result +// * All "Foo" calls are replaced with "FooWrapper" calls +// +// NOTE: instead of finding all methods with "@CallSiteReplacement" annotation, we stop at the first one we find and +// change call site only for it. This is done for the sake of breavity of the example. Implementing this for several +// methods annotated with "@CallSiteReplacement" annotation will not be any different. +// +// // Given: +// +// import {LinearLayout} from "./layout" +// +// ApiControl.ets +// @interface CallSiteReplacement { +// targetClass: string +// methodName: string +// } +// export class ApiControl { +// @CallSiteReplacement({targetClass = "com.meituan.LinearLayout", methodName = "setOrientation"}) +// // It means that we need to replace all the call-site of com.meituan.LinearLayout.setOrientation" with +// "ApiControl.fixOrientationLinearLayout" public static void fixOrientationLinearLayout(target: LinearLayout, +// orientation: number) { +// // business logic +// } +// } +// +// // Before AOP: +// +// class MyClass { +// foo() { +// // ... +// let appColumn = new LinearLayout(); +// appColumn.setOrientation(LinearLayout.VERTICAL); +// // ... +// } +// +// // After AOP: +// +// import {LinearLayout} from "./layout" +// import {ApiControl} from "./ApiControl" +// class MyClass { +// foo() { +// // ... +// let appColumn = new LinearLayout(); +// ApiControl.fixOrientationLinearLayout(appColumn, LinearLayout.VERTICAL); +// // ... +// } + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +struct UserData { + abckit_Method *ReplacementMethod = nullptr; + std::string targetClass = ""; + std::string methodName = ""; + abckit_File *ctxI = nullptr; +}; + +static void ReplaceCallSiteVisitor(abckit_BasicBlock *bb, void *data) +{ + abckit_Graph *ctxG = implG->BBgetGraph(bb); + auto *userData = (UserData *)data; + auto *ctxI = userData->ctxI; + + abckit_Inst *curInst = implG->BBgetFirstInst(bb); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + while (curInst != nullptr) { + abckit_IsaApiStaticOpcode resOpcode = statG->IgetOpcode(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + if (resOpcode != abckit_IsaApiStaticOpcode_CallVirtual) { + curInst = implG->IgetNext(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + continue; + } + + auto callee = implG->IgetMethod(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + abckit_Class *klass = implI->MethodGetParentClass(callee); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto cname = implI->ClassGetName(klass); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto className = abckit_StringToString(ctxI, cname); + + auto mname = implI->MethodGetName(callee); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto methodName = abckit_StringToString(ctxI, mname); + + if (methodName != userData->methodName || className != userData->targetClass) { + continue; + } + + std::vector inputs; + implG->IvisitInputs(curInst, (void *)&inputs, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data2) { + auto inputs2 = (std::vector *)data2; + inputs2->push_back(input); + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::vector users; + implG->IvisitUsers(curInst, (void *)&users, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *user, void *data2) { + auto users2 = (std::vector *)data2; + users2->push_back(user); + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *callStatic = statG->IcreateCallStatic(ctxG, userData->ReplacementMethod, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + for (auto *inputInst : inputs) { + abckit_IsaApiStaticOpcode newObjectOpcode = statG->IgetOpcode(inputInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + if (newObjectOpcode == abckit_IsaApiStaticOpcode_NewObject) { + implG->IsetInput(callStatic, inputInst, 0); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + break; + } + } + + for (size_t i = 0; i < inputs.size(); i++) { + implG->IsetInput(callStatic, inputs[i], i + 1); + } + for (auto *user : users) { + std::vector userInputs; + implG->IvisitInputs(user, (void *)&userInputs, + []([[maybe_unused]] abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data2) { + auto userInputs2 = (std::vector *)data2; + userInputs2->push_back(input); + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + for (size_t i = 0; i < userInputs.size(); i++) { + if (userInputs[i] == curInst) { + implG->IsetInput(user, callStatic, i); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } + } + } + + implG->IinsertBefore(callStatic, curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->Iremove(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + curInst = implG->IgetNext(curInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } +} + +static void ReplaceCallSite(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto oldCode = implI->MethodGetCode(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implG->GvisitBlocksRPO(ctxG, data, ReplaceCallSiteVisitor); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implM->MethodSetCode(ctxM, method, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void FindCallSiteReplacement(abckit_File *ctxI, UserData *data) +{ + implI->FileEnumerateModules(ctxI, &data, [](abckit_Module *m, void *data) { + auto **userData = (UserData **)data; + + implI->ModuleEnumerateClasses(m, (void *)data, [](abckit_Class *klass, void *data) { + auto **userData1 = (UserData **)data; + + implI->ClassEnumerateMethods(klass, (void *)userData1, [](abckit_Method *method, void *data2) { + auto **userData2 = (UserData **)data2; + + implI->MethodEnumerateAnnotations(method, (void *)userData2, [](abckit_Annotation *anno, void *data3) { + abckit_File *ctxI3 = implI->AnnotationGetInspectContext(anno); + auto **userData3 = (UserData **)data3; + + auto annoClass = implI->AnnotationGetInterface(anno); + abckit_String *anName = implI->AnnotationInterfaceGetName(annoClass); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoName = abckit_StringToString(ctxI3, anName); + + if (std::strcmp(annoName.c_str(), "CallSiteReplacement") != 0) { + return true; + } + + implI->AnnotationEnumerateElements( + anno, (void *)userData3, [](abckit_AnnotationElement *elem, void *data4) { + auto **userData4 = (UserData **)data4; + auto ctxI4 = implI->AnnotationElementGetInspectContext(elem); + + auto anElName = implI->AnnotationElementGetName(elem); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI4, anElName); + + if (std::strcmp(name.c_str(), "targetClass") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(elem); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto s = implI->ValueGetString(ctxI4, val); + (*userData4)->targetClass = abckit_StringToString(ctxI4, s); + } else if (std::strcmp(name.c_str(), "methodName") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(elem); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto s = implI->ValueGetString(ctxI4, val); + (*userData4)->methodName = abckit_StringToString(ctxI4, s); + } + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return false; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + if (!(*userData2)->targetClass.empty() && !(*userData2)->methodName.empty()) { + (*userData2)->ReplacementMethod = method; + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + if ((*userData1)->ReplacementMethod != nullptr) { + return false; + } + return true; + }); + if ((*userData)->ReplacementMethod != nullptr) { + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +int ExternalExampleStaticReplaceCallSite() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + UserData userData = {}; + userData.ctxI = ctx; + + FindCallSiteReplacement(ctx, &userData); + assert(userData.ReplacementMethod != nullptr); + + // Transform methods + implI->FileEnumerateModules(ctx, &userData, [](abckit_Module *m, void *data) { + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, ReplaceCallSite); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + implI->ClassEnumerateMethods(c, data, [](abckit_Method *m, void *data) { + impl->TransformMethod(m, data, ReplaceCallSite); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/static_router_table.cpp b/libabckit/external_examples/static_router_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd65bfaf76f65a70601304d852cb32a4a7c64e9f --- /dev/null +++ b/libabckit/external_examples/static_router_table.cpp @@ -0,0 +1,304 @@ +#include +#include +#include +#include +#include + +#include "../include/abckit.h" +#include "../include/metadata.h" +#include "../include/ir_core.h" +#include "../include/isa/isa_static.h" + +// before AOP +// +// IRouterHandler.ets +// export abstract class IRouterHandler { +// handle(): void; +// } +// +// export enum Thread { +// WORKER, +// TASKPOOL +// } +// +// export @interface Router { +// schme: string; +// path: string; +// thread: Thread; +// } + +// xxxHandler.ets // we have many such classes +// import {Router, IRouterHandler, Thread} from "./IRouterHandler" +// {schema: "imeituan", path: "/xxx", thread: Thread.WORKER} +// export class xxxHandler extends IRouterHandler { +// void handle() { +// // business logic +// } +// } + +// routerMap.ets +// import {IRouterHandler} from "./IRouterHandler" +// export function routerMap() : new Map { +// let routerMap = new Map() +// return routerMap +//} + +// after AOP +// +// need to insert code into routerMap.ets and remove annotations +// routerMap.ets +// import {IRouterHandler} from "./IRouterHandler"; + +// import {xxxHandler} from "./xxxHandler"; +// we have many such imports + +// export function routerMap() : new Map { +// let routerMap = new Map() +// routerMap.set("imeituan/xxx", new xxxHandler()) // [schema + path, new handler()] +// // ... // we have many such pairs +// return routerMap +//} + +// // xxxHandler.ets // we have many such classes +// import {Router, IRouterHandler, Thread} from "./IRouterHandler" +// export class xxxHandler extends IRouterHandler { // annotation is removed +// void handle() { +// // business logic +// } +// } + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +struct AnnoInfo { + std::string schema; + std::string path; + abckit_String *str; + abckit_Class *klass; + abckit_Method *ctor; + abckit_Annotation *anno; +} typedef AnnoInfo; + +struct UserInfo { + std::vector annoInfo; + abckit_Class *globalClass; + abckit_Field *routerMap; // FIXME(igelhaus): Change to abckit_Method +} typedef UserInfo; + +static void processAnnotations(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data) +{ + [[maybe_unused]] abckit_File *ctxI = implI->ClassGetInspectContext(klass); + UserInfo *userData = (UserInfo *)data; + AnnoInfo newData; + implI->ClassEnumerateAnnotations(klass, &newData, [](abckit_Annotation *anno, void *data1) { + abckit_File *ctx = implI->AnnotationGetInspectContext(anno); + auto annoClass = implI->AnnotationGetInterface(anno); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto str = implI->AnnotationInterfaceGetName(annoClass); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoName = abckit_StringToString(ctx, str); + + if (strcmp(annoName.c_str(), "Router") != 0) { + return true; + } + + auto userData1 = reinterpret_cast(data1); + userData1->anno = const_cast(anno); + + implI->AnnotationEnumerateElements(anno, &userData1, [](abckit_AnnotationElement *annoElement, void *data2) { + auto ctx2 = implI->AnnotationElementGetInspectContext(annoElement); + + auto aes = implI->AnnotationElementGetName(annoElement); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto annoElementName = abckit_StringToString(ctx2, aes); + + AnnoInfo *newData2 = (AnnoInfo *)data2; + if (strcmp(annoElementName.c_str(), "schema") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetString(ctx2, val); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto valName = abckit_StringToString(ctx2, vs); + newData2->schema = valName; + } + + if (strcmp(annoElementName.c_str(), "path") == 0) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetString(ctx2, val); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto valName = abckit_StringToString(ctx2, vs); + newData2->path = valName; + } + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ClassEnumerateMethods(klass, &newData, [](abckit_Method *method, void *data1) { + abckit_File *ctx = implI->MethodGetInspectContext(method); + auto str = implI->MethodGetName(method); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + auto methodName = abckit_StringToString(ctx, str); + + // TODO: provide a shortcut for searching constructors + if (strcmp(methodName.c_str(), "CTOR")) { + ((AnnoInfo *)data1)->ctor = const_cast(method); + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::string concatString = std::string(newData.schema) + std::string(newData.path); + auto stringValue = implM->CreateString(ctxM, concatString.c_str()); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + newData.str = stringValue; + + newData.klass = klass; + userData->annoInfo.push_back(newData); + implM->ClassRemoveAnnotation(ctxM, klass, newData.anno); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void addSetCall(abckit_BasicBlock *bb, void *data) +{ + abckit_Graph *ctxG = implG->BBgetGraph(bb); + UserInfo *userData = (UserInfo *)data; + + abckit_Inst *lastInst = implG->BBgetLastInst(bb); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + for (auto annoInfo : userData->annoInfo) { + + // TODO rewrite example using new intrinsics + + // abckit_Inst *loadStatic = implG->IcreateLoadStatic(ctxG, nullptr, userData->routerMap); + + // ^^ there is no IcreateLoadStatic() now. + // check 9a08bb76993ff37d34d4da317d57c93dc313094e for it + + abckit_Inst *loadStatic = nullptr; + + // routermap is a static field in global class + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(loadStatic, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *loadStringInst = statG->IcreateLoadString(ctxG, annoInfo.str); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(loadStringInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Inst *newObjectInst = statG->IcreateNewObject(ctxG, nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(newObjectInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // call to constructor + abckit_Inst *callStaticInst = statG->IcreateCallStatic(ctxG, annoInfo.ctor, 1, newObjectInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(callStaticInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + // finally, add element to std::Map + // suppose that we somehow get set method for std::map fom stdlib + // NOTE: objectPtr is absent + abckit_Method *setMethod = nullptr; + abckit_Inst *callVirtualInst = + statG->IcreateCallVirtual(ctxG, newObjectInst, setMethod, 2, loadStatic, loadStringInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + implG->IinsertBefore(callVirtualInst, lastInst); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + } +} + +static void modifyInitGlobal(abckit_ModifyContext *ctxM, abckit_Module *m, void *data) +{ + abckit_Method *routerMapMethod = nullptr; + + auto ctxI = implI->ModuleGetInspectContext(m); + + auto moduleNameStr = implI->ModuleGetName(m); + auto moduleName = abckit_StringToString(ctxI, moduleNameStr); + if (moduleName != "MyModule") { + return; + } + + implI->ModuleEnumerateTopLevelFunctions(m, &routerMapMethod, [](abckit_Method *method, void *d) { + abckit_File *ctx = implI->MethodGetInspectContext(method); + auto name = abckit_StringToString(ctx, implI->MethodGetName(method)); + if (std::strcmp(name.c_str(), "routerMap") == 0) { + *(reinterpret_cast(d)) = const_cast(method); + return false; + } + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(routerMapMethod != nullptr); + // (reinterpret_cast(data))->routerMap = routerMapMethod; + + abckit_Code *oldCode = implI->MethodGetCode(routerMapMethod); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implG->GvisitBlocksRPO(ctxG, data, addSetCall); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + abckit_Code *newCode = impl->graphToCode(ctxG); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implM->MethodSetCode(ctxM, routerMapMethod, newCode); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +int StaticRouterTable() +{ + abckit_File *ctx = impl->OpenAbc("./sts.abc"); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + UserInfo userInfo; + + // Transform methods + implI->FileEnumerateModules(ctx, &userInfo, [](abckit_Module *m, void *data) { + impl->TransformModule(m, data, modifyInitGlobal); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *c, void *data) { + impl->TransformClass(c, data, processAnnotations); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + return 0; +} diff --git a/libabckit/external_examples/stub_main.cpp b/libabckit/external_examples/stub_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce5f3d8b5fc5322b2522f7f5576edc546141bad3 --- /dev/null +++ b/libabckit/external_examples/stub_main.cpp @@ -0,0 +1,19 @@ +/** + * Copyright (c) 2024 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. + */ + +int main() +{ + return 0; +} diff --git a/libabckit/include/abckit.h b/libabckit/include/abckit.h new file mode 100644 index 0000000000000000000000000000000000000000..ca8baed7ffaeb782be5bbf72427aca69973e139c --- /dev/null +++ b/libabckit/include/abckit.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_H +#define LIBABCKIT_H + +#include + +#include "statuses.h" +#include "ir_core.h" +#include "metadata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBABCKIT_VERSION 1 + +typedef struct abckit_ModifyApi abckit_ModifyApi; +typedef struct abckit_InspectApi abckit_InspectApi; +typedef struct abckit_GraphApi abckit_GraphApi; + +struct abckit_Api { + int apiVersion; + + /* + * Applies to: ArkTS, JavaScript + */ + enum abckit_Status (*GetLastError)(void); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*OpenAbc)( + /* in */ const char *path); + + /* + * Applies to: ArkTS, JavaScript + * + * NOTE: destroys inspect context + */ + void (*WriteAbc)( + /* in */ abckit_File *ctx, + /* in */ const char *path); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*DestroyInspectContext)( + /* in */ abckit_File *ctx); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*TransformModule)( + /* in */ abckit_Module *ctx, + /* in-out */ void *data, + /* in */ + void (*cb)( + /* in */ abckit_ModifyContext *ctxM, + /* in */ abckit_Module *m, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*TransformClass)( + /* in */ abckit_Class *ctx, + /* in-out */ void *data, + /* in */ + void (*cb)( + /* in */ abckit_ModifyContext *ctxM, + /* in */ abckit_Class *klass, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*TransformMethod)( + /* in */ abckit_Method *ctx, + /* in-out */ void *data, + /* in */ + void (*cb)( + /* in */ abckit_ModifyContext *ctxM, + /* in */ abckit_Method *method, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Graph *(*codeToGraph)( + /* in */ abckit_File *ctxI, + /* in */ abckit_Code *code); + + /* + * Applies to: ArkTS, JavaScript + * + * NOTE: destroys graph context + */ + abckit_Code *(*graphToCode)( + /* in */ abckit_Graph *ctx); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*DestroyGraphContext)( + /* in */ abckit_Graph *ctx); +}; + +struct abckit_Api const *abckit_GetApiImpl(int version); +struct abckit_ModifyApi const *abckit_GetModifyApiImpl(int version); +struct abckit_InspectApi const *abckit_GetInspectApiImpl(int version); +struct abckit_GraphApi const *abckit_GetGraphApiImpl(int version); +struct abckit_IsaApiStatic const *abckit_GetIsaApiStaticImpl(int version); +struct abckit_IsaApiDynamic const *abckit_GetIsaApiDynamicImpl(int version); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBABCKIT_H */ diff --git a/libabckit/include/ir_core.h b/libabckit/include/ir_core.h new file mode 100644 index 0000000000000000000000000000000000000000..cb1af0445e3161541e7ee5d0f98c6d5144ff0aa5 --- /dev/null +++ b/libabckit/include/ir_core.h @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_IR_H +#define LIBABCKIT_IR_H + +#include +#include +#include + +#include "metadata.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum abckit_Isa_Type { + /* + * For invalid input. + */ + abckit_Isa_Type_UNSUPPORTED, + /* + * For .abc files that use mainline ISA. + */ + abckit_Isa_Type_DYNAMIC, + /* + * For .abc files that use panda ISA. + */ + abckit_Isa_Type_STATIC, +}; + +typedef struct abckit_Graph abckit_Graph; +typedef struct abckit_BasicBlock abckit_BasicBlock; +typedef struct abckit_Inst abckit_Inst; + +/* ======================================== + * Api for IR manipulation + * ======================================== */ + +struct abckit_GraphApi { + + enum abckit_Isa_Type (*GraphGetIsa)( + /* in */ abckit_Graph *ctx); + + /* ======================================== + * Api for Graph manipulation + * ======================================== */ + + abckit_BasicBlock *(*GgetStartBasicBlock)( + /* in */ abckit_Graph *ctx); + + abckit_BasicBlock *(*GgetEndBasicBlock)( + /* in */ abckit_Graph *ctx); + + uint32_t (*GgetNumberOfBasicBlocks)( + /* in */ abckit_Graph *ctx); + + void (*GvisitBlocksRPO)( + /* in */ abckit_Graph *ctx, + /* in-out */ void *data, + /* in */ + void (*cb)(/* in */ abckit_BasicBlock *bb, /* in-out */ void *data)); + + abckit_BasicBlock *(*GgetBasicBlock)( + /* in */ abckit_Graph *ctx, + /* in */ uint32_t id); + + abckit_Inst *(*GgetParameter)( + /* in */ abckit_Graph *ctx, + /* in */ uint32_t index); + + void (*GinsertTryCatch)( + /* in */ abckit_BasicBlock *tryFirstBB, + /* in */ abckit_BasicBlock *tryLastBB, + /* in */ abckit_BasicBlock *catchBeginBB, + /* in */ abckit_BasicBlock *catchEndBB); + + void (*Gdump)( + /* in */ abckit_Graph *ctx, + /* in */ int fd); + + abckit_Inst *(*GcreateConstantI32)( + /* in */ abckit_Graph *ctx, + /* in */ int32_t value); + + abckit_Inst *(*GcreateConstantI64)( + /* in */ abckit_Graph *ctx, + /* in */ int64_t value); + + abckit_Inst *(*GcreateConstantU64)( + /* in */ abckit_Graph *ctx, + /* in */ uint64_t value); + + abckit_Inst *(*GcreateConstantF64)( + /* in */ abckit_Graph *ctx, + /* in */ double value); + + void (*GrunPassRemoveUnreachableBlocks)( + /* in */ abckit_Graph *ctx); + + /* ======================================== + * Api for basic block manipulation + * ======================================== */ + + abckit_BasicBlock *(*BBcreateEmpty)( + /* in */ abckit_Graph *ctx); + + uint32_t (*BBgetId)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_Graph *(*BBgetGraph)( + /* in */ abckit_BasicBlock *basicBlock); + + uint64_t (*BBgetPredBlockCount)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_BasicBlock *(*BBgetPredBlock)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ int32_t index); + + void (*BBsetPredBlock)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_BasicBlock *predBlock, + /* in */ int32_t index); + + void (*BBsetPredBlocks)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ size_t argCount, + /* in abckit_BasicBlock *predBlocks... */...); + + void (*BBvisitPredBlocks)( + /* in */ abckit_BasicBlock *basicBlock, + /* in-out */ void *data, + /* in */ + void (*cb)(/* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_BasicBlock *predBasicBlock, /* in-out */ void *data)); + + uint64_t (*BBgetSuccBlockCount)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_BasicBlock *(*BBgetSuccBlock)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ int32_t index); + + void (*BBsetSuccBlock)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_BasicBlock *succBlock, + /* in */ int32_t index); + + void (*BBsetSuccBlocks)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ size_t argCount, + /* in abckit_BasicBlock *succBlocks... */...); + + void (*BBvisitSuccBlocks)( + /* in */ abckit_BasicBlock *basicBlock, + /* in-out */ void *data, + /* in */ + void (*cb)(/* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_BasicBlock *succBasicBlock, /* in-out */ void *data)); + + abckit_BasicBlock *(*BBgetTrueBranch)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_BasicBlock *(*BBgetFalseBranch)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_BasicBlock *(*BBsplitBlockAfterInstruction)( + /* in */ abckit_Inst *inst, + /* in */ bool makeEdge); + + /* creates edge between basic blocks */ + void (*BBconnectBlocks)( + /* in */ abckit_BasicBlock *bb1, + /* in */ abckit_BasicBlock *bb2, + /* in */ bool connectViaTrueEdge); + + /* breaks edge between basic blocks */ + void (*BBdisconnectBlocks)( + /* in */ abckit_BasicBlock *bb1, + /* in */ abckit_BasicBlock *bb2); + + void (*BBaddInstFront)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_Inst *inst); + + void (*BBaddInstBack)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_Inst *inst); + + /* Remove all instructions from bb */ + void (*BBclear)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_Inst *(*BBgetFirstInst)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_Inst *(*BBgetLastInst)( + /* in */ abckit_BasicBlock *basicBlock); + + uint32_t (*BBgetNumberOfInstructions)( + /* in */ abckit_BasicBlock *basicBlock); + + abckit_BasicBlock *(*BBgetImmediateDominator)( + /* in */ abckit_BasicBlock *basicBlock); + + /* checks that basicBlock is dominated by dominator */ + bool (*BBcheckDominance)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_BasicBlock *dominator); + + void (*BBvisitDominatedBlocks)( + /* in */ abckit_BasicBlock *basicBlock, + /* in-out */ void *data, + /* in */ + void (*cb)(/* in */ abckit_BasicBlock *basicBlock, + /* in */ abckit_BasicBlock *dominatedBasicBlock, /* in-out */ void *data)); + + bool (*BBisStart)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisEnd)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisLoopHead)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisLoopPrehead)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisTryBegin)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisTry)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisTryEnd)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisCatchBegin)( + /* in */ abckit_BasicBlock *basicBlock); + + bool (*BBisCatch)( + /* in */ abckit_BasicBlock *basicBlock); + + void (*BBdump)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ int fd); + + abckit_Inst *(*BBcreatePhi)( + /* in */ abckit_BasicBlock *basicBlock, + /* in */ size_t argCount, + /* in */... /* phi inputs */); + + /* + * Applies to: ETS, JS + */ + void (*Iremove)( + /* in */ abckit_Inst *inst); + + uint32_t (*IgetId)( + /* in */ abckit_Inst *inst); + + abckit_Inst *(*IgetNext)( + /* in */ abckit_Inst *inst); + + abckit_Inst *(*IgetPrev)( + /* in */ abckit_Inst *inst); + + void (*IinsertAfter)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Inst *next); + + void (*IinsertBefore)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Inst *prev); + + /* NOTE JS: for JS this will return any */ + abckit_Type *(*IgetType)( + /* in */ abckit_Inst *inst); + + abckit_BasicBlock *(*IgetBasicBlock)( + /* in */ abckit_Inst *inst); + + /* checks that inst is dominated by dominator */ + bool (*IcheckDominance)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Inst *dominator); + + bool (*IcheckIsCall)( + /* in */ abckit_Inst *inst); + + uint32_t (*IgetUserCount)( + /* in */ abckit_Inst *inst); + + /* NOTE JS: for JS this visit only intrinsic inputs, + intrinsic name itself is omitted */ + void (*IvisitUsers)( + /* in */ abckit_Inst *inst, + /* in-out */ void *data, + /* in */ + void (*cb)(/* in */ abckit_Inst *inst, /* in */ abckit_Inst *user, + /* in-out */ void *data)); + + uint32_t (*IgetInputCount)( + /* in */ abckit_Inst *inst); + + /* NOTE JS: for JS implicitly index = index + 1 (omit intrinsic name) */ + abckit_Inst *(*IgetInput)( + /* in */ abckit_Inst *inst, + /* in */ uint32_t index); + + void (*IvisitInputs)( + /* in */ abckit_Inst *inst, + /* in-out */ void *data, + /* in */ + void (*cb)(/* in */ abckit_Inst *inst, /* in */ abckit_Inst *input, /* in */ size_t inputIdx, + /* in-out */ void *data)); + + /* can overwrite existing input + NOTE JS: for JS implicitly index = index + 1 (omit intrinsic name) */ + void (*IsetInput)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Inst *input, + /* in */ uint32_t index); + + /* can overwrite existing input + NOTE JS: for JS implicitly index = index + 1 (omit intrinsic name) */ + void (*IsetInputs)( + /* in */ abckit_Inst *inst, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + void (*IappendInput)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Inst *input); + + void (*Idump)( + /* in */ abckit_Inst *inst, + /* in */ int fd); + + abckit_Method *(*IgetMethod)( + /* in */ abckit_Inst *inst); + + void (*IsetMethod)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Method *method); + + uint64_t (*IgetImmediate)( + /* in */ abckit_Inst *inst, + /* in */ size_t idx); + + void (*IsetImmediate)( + /* in */ abckit_Inst *inst, + /* in */ size_t idx, + /* in */ uint64_t imm); + + uint64_t (*IgetImmediateCount)( + /* in */ abckit_Inst *inst); + + abckit_LiteralArray *(*IgetLiteralArray)( + /* in */ abckit_Inst *inst); + + void (*IsetLiteralArray)( + /* in */ abckit_Inst *inst, + /* in */ abckit_LiteralArray *la); + + abckit_String *(*IgetString)( + /* in */ abckit_Inst *inst); + + void (*IsetString)( + /* in */ abckit_Inst *inst, + /* in */ abckit_String *la); + + int64_t (*IgetConstantValueI64)( + /* in */ abckit_Inst *inst); + + uint64_t (*IgetConstantValueU64)( + /* in */ abckit_Inst *inst); + + double (*IgetConstantValueF64)( + /* in */ abckit_Inst *inst); +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LIBABCKIT_IR_H */ diff --git a/libabckit/include/isa/isa_dynamic.h b/libabckit/include/isa/isa_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..be17480da2f7a529efd95c234b9c903618d69934 --- /dev/null +++ b/libabckit/include/isa/isa_dynamic.h @@ -0,0 +1,1201 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_ISA_ISA_DYNAMIC_H +#define LIBABCKIT_ISA_ISA_DYNAMIC_H + +#include +#include +#include + +#include "../metadata.h" +#include "../ir_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum abckit_IsaApiDynamicOpcode { + abckit_IsaApiDynamicOpcode_INVALID, + abckit_IsaApiDynamicOpcode_Constant, + abckit_IsaApiDynamicOpcode_Parameter, + abckit_IsaApiDynamicOpcode_LoadString, + abckit_IsaApiDynamicOpcode_Try, + abckit_IsaApiDynamicOpcode_CatchPhi, + abckit_IsaApiDynamicOpcode_Phi, + + abckit_IsaApiDynamicOpcode_asyncfunctionenter, + abckit_IsaApiDynamicOpcode_asyncfunctionreject, + abckit_IsaApiDynamicOpcode_asyncfunctionresolve, + abckit_IsaApiDynamicOpcode_asyncgeneratorreject, + abckit_IsaApiDynamicOpcode_asyncgeneratorresolve, + abckit_IsaApiDynamicOpcode_callarg0, + abckit_IsaApiDynamicOpcode_callthis0, + abckit_IsaApiDynamicOpcode_callarg1, + abckit_IsaApiDynamicOpcode_callthis1, + abckit_IsaApiDynamicOpcode_callargs2, + abckit_IsaApiDynamicOpcode_callthis2, + abckit_IsaApiDynamicOpcode_callargs3, + abckit_IsaApiDynamicOpcode_callthis3, + abckit_IsaApiDynamicOpcode_closeiterator, + abckit_IsaApiDynamicOpcode_copydataproperties, + abckit_IsaApiDynamicOpcode_copyrestargs, + abckit_IsaApiDynamicOpcode_createarraywithbuffer, + abckit_IsaApiDynamicOpcode_createasyncgeneratorobj, + abckit_IsaApiDynamicOpcode_createemptyarray, + abckit_IsaApiDynamicOpcode_createemptyobject, + abckit_IsaApiDynamicOpcode_creategeneratorobj, + abckit_IsaApiDynamicOpcode_createiterresultobj, + abckit_IsaApiDynamicOpcode_createobjectwithbuffer, + abckit_IsaApiDynamicOpcode_createobjectwithexcludedkeys, + abckit_IsaApiDynamicOpcode_createregexpwithliteral, + abckit_IsaApiDynamicOpcode_debugger, + abckit_IsaApiDynamicOpcode_dec, + abckit_IsaApiDynamicOpcode_defineclasswithbuffer, + abckit_IsaApiDynamicOpcode_definegettersetterbyvalue, + abckit_IsaApiDynamicOpcode_definemethod, + abckit_IsaApiDynamicOpcode_delobjprop, + abckit_IsaApiDynamicOpcode_eq, + abckit_IsaApiDynamicOpcode_exp, + abckit_IsaApiDynamicOpcode_getasynciterator, + abckit_IsaApiDynamicOpcode_getiterator, + abckit_IsaApiDynamicOpcode_getnextpropname, + abckit_IsaApiDynamicOpcode_getpropiterator, + abckit_IsaApiDynamicOpcode_getresumemode, + abckit_IsaApiDynamicOpcode_gettemplateobject, + abckit_IsaApiDynamicOpcode_getunmappedargs, + abckit_IsaApiDynamicOpcode_greater, + abckit_IsaApiDynamicOpcode_greatereq, + abckit_IsaApiDynamicOpcode_inc, + abckit_IsaApiDynamicOpcode_isfalse, + abckit_IsaApiDynamicOpcode_isin, + abckit_IsaApiDynamicOpcode_istrue, + abckit_IsaApiDynamicOpcode_if, + abckit_IsaApiDynamicOpcode_ldbigint, + abckit_IsaApiDynamicOpcode_ldfalse, + abckit_IsaApiDynamicOpcode_ldglobal, + abckit_IsaApiDynamicOpcode_ldglobalvar, + abckit_IsaApiDynamicOpcode_ldhole, + abckit_IsaApiDynamicOpcode_ldinfinity, + abckit_IsaApiDynamicOpcode_ldlexvar, + abckit_IsaApiDynamicOpcode_ldnan, + abckit_IsaApiDynamicOpcode_ldnull, + abckit_IsaApiDynamicOpcode_ldobjbyindex, + abckit_IsaApiDynamicOpcode_ldobjbyname, + abckit_IsaApiDynamicOpcode_ldobjbyvalue, + abckit_IsaApiDynamicOpcode_ldsuperbyname, + abckit_IsaApiDynamicOpcode_ldsuperbyvalue, + abckit_IsaApiDynamicOpcode_ldsymbol, + abckit_IsaApiDynamicOpcode_ldtrue, + abckit_IsaApiDynamicOpcode_ldundefined, + abckit_IsaApiDynamicOpcode_less, + abckit_IsaApiDynamicOpcode_lesseq, + abckit_IsaApiDynamicOpcode_newlexenv, + abckit_IsaApiDynamicOpcode_noteq, + abckit_IsaApiDynamicOpcode_poplexenv, + abckit_IsaApiDynamicOpcode_resumegenerator, + abckit_IsaApiDynamicOpcode_return, + abckit_IsaApiDynamicOpcode_returnundefined, + abckit_IsaApiDynamicOpcode_setgeneratorstate, + abckit_IsaApiDynamicOpcode_setobjectwithproto, + abckit_IsaApiDynamicOpcode_starrayspread, + abckit_IsaApiDynamicOpcode_stglobalvar, + abckit_IsaApiDynamicOpcode_stlexvar, + abckit_IsaApiDynamicOpcode_stmodulevar, + abckit_IsaApiDynamicOpcode_stobjbyindex, + abckit_IsaApiDynamicOpcode_stobjbyname, + abckit_IsaApiDynamicOpcode_stobjbyvalue, + abckit_IsaApiDynamicOpcode_stownbyindex, + abckit_IsaApiDynamicOpcode_stownbyname, + abckit_IsaApiDynamicOpcode_stownbyvalue, + abckit_IsaApiDynamicOpcode_stricteq, + abckit_IsaApiDynamicOpcode_strictnoteq, + abckit_IsaApiDynamicOpcode_stsuperbyname, + abckit_IsaApiDynamicOpcode_stsuperbyvalue, + abckit_IsaApiDynamicOpcode_supercallspread, + abckit_IsaApiDynamicOpcode_suspendgenerator, + abckit_IsaApiDynamicOpcode_throw_constassignment, + abckit_IsaApiDynamicOpcode_throw_deletesuperproperty, + abckit_IsaApiDynamicOpcode_throw_ifnotobject, + abckit_IsaApiDynamicOpcode_throw_ifsupernotcorrectcall, + abckit_IsaApiDynamicOpcode_throw_patternnoncoercible, + abckit_IsaApiDynamicOpcode_tonumber, + abckit_IsaApiDynamicOpcode_tryldglobalbyname, + abckit_IsaApiDynamicOpcode_trystglobalbyname, + abckit_IsaApiDynamicOpcode_typeof, + abckit_IsaApiDynamicOpcode_apply, + abckit_IsaApiDynamicOpcode_asyncfunctionawaituncaught, + abckit_IsaApiDynamicOpcode_callrange, + abckit_IsaApiDynamicOpcode_callruntime_callinit, + abckit_IsaApiDynamicOpcode_callruntime_createprivateproperty, + abckit_IsaApiDynamicOpcode_callruntime_definefieldbyindex, + abckit_IsaApiDynamicOpcode_callruntime_definefieldbyvalue, + abckit_IsaApiDynamicOpcode_callruntime_defineprivateproperty, + abckit_IsaApiDynamicOpcode_callruntime_definesendableclass, + abckit_IsaApiDynamicOpcode_callruntime_ldsendableclass, + abckit_IsaApiDynamicOpcode_callruntime_notifyconcurrentresult, + abckit_IsaApiDynamicOpcode_callruntime_topropertykey, + abckit_IsaApiDynamicOpcode_callruntime_ldsendableexternalmodulevar, + abckit_IsaApiDynamicOpcode_callruntime_wideldsendableexternalmodulevar, + abckit_IsaApiDynamicOpcode_callruntime_newsendableenv, + abckit_IsaApiDynamicOpcode_callruntime_widenewsendableenv, + abckit_IsaApiDynamicOpcode_callruntime_stsendablevar, + abckit_IsaApiDynamicOpcode_callruntime_widestsendablevar, + abckit_IsaApiDynamicOpcode_callruntime_ldsendablevar, + abckit_IsaApiDynamicOpcode_callruntime_wideldsendablevar, + abckit_IsaApiDynamicOpcode_callruntime_istrue, + abckit_IsaApiDynamicOpcode_callruntime_isfalse, + + abckit_IsaApiDynamicOpcode_callthisrange, + abckit_IsaApiDynamicOpcode_definepropertybyname, + abckit_IsaApiDynamicOpcode_definefieldbyname, + abckit_IsaApiDynamicOpcode_definefunc, + + abckit_IsaApiDynamicOpcode_add2, + abckit_IsaApiDynamicOpcode_sub2, + abckit_IsaApiDynamicOpcode_mul2, + abckit_IsaApiDynamicOpcode_div2, + abckit_IsaApiDynamicOpcode_mod2, + abckit_IsaApiDynamicOpcode_and2, + abckit_IsaApiDynamicOpcode_or2, + abckit_IsaApiDynamicOpcode_xor2, + abckit_IsaApiDynamicOpcode_ashr2, + abckit_IsaApiDynamicOpcode_shl2, + abckit_IsaApiDynamicOpcode_shr2, + abckit_IsaApiDynamicOpcode_neg, + abckit_IsaApiDynamicOpcode_not, + abckit_IsaApiDynamicOpcode_lda_str, + abckit_IsaApiDynamicOpcode_throw, + + abckit_IsaApiDynamicOpcode_dynamicimport, + abckit_IsaApiDynamicOpcode_getmodulenamespace, + abckit_IsaApiDynamicOpcode_instanceof, + abckit_IsaApiDynamicOpcode_ldexternalmodulevar, + abckit_IsaApiDynamicOpcode_ldfunction, + abckit_IsaApiDynamicOpcode_ldlocalmodulevar, + abckit_IsaApiDynamicOpcode_ldnewtarget, + abckit_IsaApiDynamicOpcode_ldprivateproperty, + abckit_IsaApiDynamicOpcode_ldthis, + abckit_IsaApiDynamicOpcode_ldthisbyname, + abckit_IsaApiDynamicOpcode_ldthisbyvalue, + abckit_IsaApiDynamicOpcode_newlexenvwithname, + abckit_IsaApiDynamicOpcode_newobjapply, + abckit_IsaApiDynamicOpcode_newobjrange, + abckit_IsaApiDynamicOpcode_stconsttoglobalrecord, + abckit_IsaApiDynamicOpcode_stownbynamewithnameset, + abckit_IsaApiDynamicOpcode_stownbyvaluewithnameset, + abckit_IsaApiDynamicOpcode_stprivateproperty, + abckit_IsaApiDynamicOpcode_stthisbyname, + abckit_IsaApiDynamicOpcode_stthisbyvalue, + abckit_IsaApiDynamicOpcode_sttoglobalrecord, + abckit_IsaApiDynamicOpcode_supercallarrowrange, + abckit_IsaApiDynamicOpcode_supercallthisrange, + abckit_IsaApiDynamicOpcode_testin, + abckit_IsaApiDynamicOpcode_throw_notexists, + abckit_IsaApiDynamicOpcode_throw_undefinedifhole, + abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, + abckit_IsaApiDynamicOpcode_tonumeric, + abckit_IsaApiDynamicOpcode_wide_callrange, + abckit_IsaApiDynamicOpcode_wide_callthisrange, + abckit_IsaApiDynamicOpcode_wide_copyrestargs, + abckit_IsaApiDynamicOpcode_wide_createobjectwithexcludedkeys, + abckit_IsaApiDynamicOpcode_wide_getmodulenamespace, + abckit_IsaApiDynamicOpcode_wide_ldexternalmodulevar, + abckit_IsaApiDynamicOpcode_wide_ldlexvar, + abckit_IsaApiDynamicOpcode_wide_ldlocalmodulevar, + abckit_IsaApiDynamicOpcode_wide_ldobjbyindex, + abckit_IsaApiDynamicOpcode_wide_ldpatchvar, + abckit_IsaApiDynamicOpcode_wide_newlexenv, + abckit_IsaApiDynamicOpcode_wide_newlexenvwithname, + abckit_IsaApiDynamicOpcode_wide_newobjrange, + abckit_IsaApiDynamicOpcode_wide_stlexvar, + abckit_IsaApiDynamicOpcode_wide_stmodulevar, + abckit_IsaApiDynamicOpcode_wide_stobjbyindex, + abckit_IsaApiDynamicOpcode_wide_stownbyindex, + abckit_IsaApiDynamicOpcode_wide_stpatchvar, + abckit_IsaApiDynamicOpcode_wide_supercallarrowrange, + abckit_IsaApiDynamicOpcode_wide_supercallthisrange, +}; + +enum abckit_IsaApiDynamicConditionCode { + abckit_IsaApiDynamicConditionCode_CC_NONE = 0, + abckit_IsaApiDynamicConditionCode_CC_EQ, /* == */ + abckit_IsaApiDynamicConditionCode_CC_NE, /* != */ + abckit_IsaApiDynamicConditionCode_CC_LT, /* < */ + abckit_IsaApiDynamicConditionCode_CC_LE, /* <= */ + abckit_IsaApiDynamicConditionCode_CC_GT, /* > */ + abckit_IsaApiDynamicConditionCode_CC_GE, /* >= */ + // Unsigned integers. + abckit_IsaApiDynamicConditionCode_CC_B, /* < */ + abckit_IsaApiDynamicConditionCode_CC_BE, /* <= */ + abckit_IsaApiDynamicConditionCode_CC_A, /* > */ + abckit_IsaApiDynamicConditionCode_CC_AE, /* >= */ + // Compare result of bitwise AND with zero + abckit_IsaApiDynamicConditionCode_CC_TST_EQ, /* (lhs AND rhs) == 0 */ + abckit_IsaApiDynamicConditionCode_CC_TST_NE, /* (lhs AND rhs) != 0 */ +}; + +/* + * API for dynamic ISA. + * Supported targets: abckit_Target_TS, abckit_Target_JS, abckit_Target_ArkTS_v1. + */ +struct abckit_IsaApiDynamic { + abckit_Module *(*IgetModule)( + /* in */ abckit_Inst *inst); + + void (*IsetModule)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Module *md); + + enum abckit_IsaApiDynamicConditionCode (*IgetConditionCode)( + /* in */ abckit_Inst *inst); + + void (*IsetConditionCode)( + /* in */ abckit_Inst *inst, + /* in */ enum abckit_IsaApiDynamicConditionCode cc); + + enum abckit_IsaApiDynamicOpcode (*IgetOpcode)( + /* in */ abckit_Inst *inst); + + abckit_ImportDescriptor *(*IgetImportDescriptor)( + /* in */ abckit_Inst *inst); + + void (*IsetImportDescriptor)( + /* in */ abckit_Inst *inst, + /* in */ abckit_ImportDescriptor *id); + + abckit_ExportDescriptor *(*IgetExportDescriptor)( + /* in */ abckit_Inst *inst); + + void (*IsetExportDescriptor)( + /* in */ abckit_Inst *inst, + /* in */ abckit_ExportDescriptor *ed); + + abckit_Inst *(*IcreateLoadString)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_String *str); + + abckit_Inst *(*IcreateCmp)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateLdnan)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdinfinity)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdundefined)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdnull)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdsymbol)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdglobal)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdtrue)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdfalse)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdhole)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdnewtarget)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdthis)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreatePoplexenv)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateGetunmappedargs)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateAsyncfunctionenter)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateLdfunction)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateDebugger)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateGetpropiterator)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateGetiterator)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateCloseiterator)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateGetasynciterator)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateLdprivateproperty)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16, */ uint64_t imm0, + /* u16 */ uint64_t imm1); + + abckit_Inst *(*IcreateStprivateproperty)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16, */ uint64_t imm0, + /* u16, */ uint64_t imm1, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateTestin)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16, */ uint64_t imm0, + /* u16 */ uint64_t imm1); + + abckit_Inst *(*IcreateDefinefieldbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string, + /* in */ abckit_Inst *input0); + + // abckit_Inst *(*IcreateDefinepropertybyname)( + // /* in */ abckit_Graph *ctxG, + // /* in */ abckit_Inst *acc, + // /* in */ abckit_String *string, + // /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCreateemptyobject)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateCreateemptyarray)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateCreategeneratorobj)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCreateiterresultobj)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCreateobjectwithexcludedkeys)( + /* in */ abckit_Graph *ctxG, + /* u8, */ uint64_t imm0, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateWideCreateobjectwithexcludedkeys)( + /* in */ abckit_Graph *ctxG, + /* u16, */ uint64_t imm0, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCreatearraywithbuffer)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_LiteralArray *literalArray); + + abckit_Inst *(*IcreateCreateobjectwithbuffer)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_LiteralArray *literalArray); + + abckit_Inst *(*IcreateCreateregexpwithliteral)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_String *string, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateNewobjapply)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateNewobjrange)( + /* in */ abckit_Graph *ctxG, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateWideNewobjrange)( + /* in */ abckit_Graph *ctxG, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateNewlexenv)( + /* in */ abckit_Graph *ctxG, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateWideNewlexenv)( + /* in */ abckit_Graph *ctxG, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateNewlexenvwithname)( + /* in */ abckit_Graph *ctxG, + /* u8, */ uint64_t imm0, + /* in */ abckit_LiteralArray *literalArray); + + abckit_Inst *(*IcreateWideNewlexenvwithname)( + /* in */ abckit_Graph *ctxG, + /* u16, */ uint64_t imm0, + /* in */ abckit_LiteralArray *literalArray); + + abckit_Inst *(*IcreateCreateasyncgeneratorobj)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateAsyncgeneratorresolve)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1, + /* in */ abckit_Inst *input2); + + abckit_Inst *(*IcreateAdd2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateSub2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateMul2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateDiv2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateMod2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateEq)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateNoteq)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateLess)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateLesseq)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateGreater)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateGreatereq)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateShl2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateShr2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateAshr2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateAnd2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateOr2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateXor2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateExp)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateTypeof)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateTonumber)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateTonumeric)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateNeg)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateNot)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateInc)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateDec)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateIstrue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateIsfalse)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateIsin)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateInstanceof)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateStrictnoteq)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateStricteq)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallruntimeNotifyconcurrentresult)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateCallruntimeDefinefieldbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCallruntimeDefinefieldbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u32, */ uint64_t imm0, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallruntimeTopropertykey)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateCallruntimeCreateprivateproperty)( + /* in */ abckit_Graph *ctxG, + /* u16, */ uint64_t imm0, + /* in */ abckit_LiteralArray *literalArray); + + abckit_Inst *(*IcreateCallruntimeDefineprivateproperty)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16, */ uint64_t imm0, + /* u16, */ uint64_t imm1, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallruntimeCallinit)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallruntimeDefinesendableclass)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Method *method, + /* in */ abckit_LiteralArray *literalArray, + /* u16, */ uint64_t imm0, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallruntimeLdsendableclass)( + /* in */ abckit_Graph *ctxG, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateCallruntimeLdsendableexternalmodulevar)( + /* in */ abckit_Graph *ctxG, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateCallruntimeWideldsendableexternalmodulevar)( + /* in */ abckit_Graph *ctxG, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateCallruntimeNewsendableenv)( + /* in */ abckit_Graph *ctxG, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateCallruntimeWidenewsendableenv)( + /* in */ abckit_Graph *ctxG, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateCallruntimeStsendablevar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u8, */ uint64_t imm0, + /* u8 */ uint64_t imm1); + + abckit_Inst *(*IcreateCallruntimeWidestsendablevar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16, */ uint64_t imm0, + /* u16 */ uint64_t imm1); + + abckit_Inst *(*IcreateCallruntimeLdsendablevar)( + /* in */ abckit_Graph *ctxG, + /* u8, */ uint64_t imm0, + /* u8 */ uint64_t imm1); + + abckit_Inst *(*IcreateCallruntimeWideldsendablevar)( + /* in */ abckit_Graph *ctxG, + /* u16, */ uint64_t imm0, + /* u16 */ uint64_t imm1); + + abckit_Inst *(*IcreateCallruntimeIstrue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateCallruntimeIsfalse)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateThrow)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateThrowNotexists)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateThrowPatternnoncoercible)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateThrowDeletesuperproperty)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateThrowConstassignment)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateThrowIfnotobject)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateThrowUndefinedifhole)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateThrowIfsupernotcorrectcall)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateThrowUndefinedifholewithname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateCallarg0)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateCallarg1)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallargs2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCallargs3)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1, + /* in */ abckit_Inst *input2); + + abckit_Inst *(*IcreateCallrange)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateWideCallrange)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateSupercallspread)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateApply)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCallthis0)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCallthis1)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCallthis2)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1, + /* in */ abckit_Inst *input2); + + abckit_Inst *(*IcreateCallthis3)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1, + /* in */ abckit_Inst *input2, + /* in */ abckit_Inst *input3); + + abckit_Inst *(*IcreateCallthisrange)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateWideCallthisrange)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateSupercallthisrange)( + /* in */ abckit_Graph *ctxG, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateWideSupercallthisrange)( + /* in */ abckit_Graph *ctxG, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateSupercallarrowrange)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateWideSupercallarrowrange)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ size_t argCount, + /* in abckit_Inst *inputs... */...); + + abckit_Inst *(*IcreateDefinegettersetterbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1, + /* in */ abckit_Inst *input2, + /* in */ abckit_Inst *input3); + + abckit_Inst *(*IcreateDefinefunc)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Method *method, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateDefinemethod)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Method *method, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateDefineclasswithbuffer)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Method *method, + /* in */ abckit_LiteralArray *literalArray, + /* u16, */ uint64_t imm0, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateResumegenerator)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateGetresumemode)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateGettemplateobject)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateGetnextpropname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateDelobjprop)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateSuspendgenerator)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateAsyncfunctionawaituncaught)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCopydataproperties)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateStarrayspread)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateSetobjectwithproto)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateLdobjbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateStobjbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateStownbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateLdsuperbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateStsuperbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateLdobjbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateWideLdobjbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u32 */ uint64_t imm0); + + abckit_Inst *(*IcreateStobjbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateWideStobjbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* u32 */ uint64_t imm0); + + abckit_Inst *(*IcreateStownbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateWideStownbyindex)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* u32 */ uint64_t imm0); + + abckit_Inst *(*IcreateAsyncfunctionresolve)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateAsyncfunctionreject)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateCopyrestargs)( + /* in */ abckit_Graph *ctxG, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateWideCopyrestargs)( + /* in */ abckit_Graph *ctxG, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateLdlexvar)( + /* in */ abckit_Graph *ctxG, + /* u8, */ uint64_t imm0, + /* u8 */ uint64_t imm1); + + abckit_Inst *(*IcreateWideLdlexvar)( + /* in */ abckit_Graph *ctxG, + /* u16, */ uint64_t imm0, + /* u16 */ uint64_t imm1); + + abckit_Inst *(*IcreateStlexvar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u8, */ uint64_t imm0, + /* u8 */ uint64_t imm1); + + abckit_Inst *(*IcreateWideStlexvar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16, */ uint64_t imm0, + /* u16 */ uint64_t imm1); + + abckit_Inst *(*IcreateGetmodulenamespace)( + /* in */ abckit_Graph *ctxG, + /* u8 */ abckit_Module *md); + + abckit_Inst *(*IcreateWideGetmodulenamespace)( + /* in */ abckit_Graph *ctxG, + /* u16 */ abckit_Module *md); + + abckit_Inst *(*IcreateStmodulevar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u8 */ abckit_ExportDescriptor *ed); + + abckit_Inst *(*IcreateWideStmodulevar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16 */ abckit_ExportDescriptor *ed); + + abckit_Inst *(*IcreateTryldglobalbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateTrystglobalbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateLdglobalvar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateStglobalvar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateLdobjbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateStobjbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateStownbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateLdsuperbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateStsuperbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateLdlocalmodulevar)( + /* in */ abckit_Graph *ctxG, + /* u8 */ abckit_ExportDescriptor *ed); + + abckit_Inst *(*IcreateWideLdlocalmodulevar)( + /* in */ abckit_Graph *ctxG, + /* u16 */ abckit_ExportDescriptor *ed); + + abckit_Inst *(*IcreateLdexternalmodulevar)( + /* in */ abckit_Graph *ctxG, + /* u8 */ abckit_ImportDescriptor *id); + + abckit_Inst *(*IcreateWideLdexternalmodulevar)( + /* in */ abckit_Graph *ctxG, + /* u16 */ abckit_ImportDescriptor *id); + + abckit_Inst *(*IcreateStconsttoglobalrecord)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateSttoglobalrecord)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateStownbyvaluewithnameset)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateStownbynamewithnameset)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateLdbigint)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateLdthisbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateStthisbyname)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_String *string); + + abckit_Inst *(*IcreateLdthisbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateStthisbyvalue)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateWideLdpatchvar)( + /* in */ abckit_Graph *ctxG, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateWideStpatchvar)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u16 */ uint64_t imm0); + + abckit_Inst *(*IcreateDynamicimport)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateAsyncgeneratorreject)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateSetgeneratorstate)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc, + /* u8 */ uint64_t imm0); + + abckit_Inst *(*IcreateReturn)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateReturnundefined)( + /* in */ abckit_Graph *ctxG); + + abckit_Inst *(*IcreateIf)( + /* in */ abckit_Graph *ctxG, + /* in */ abckit_Inst *input, + /* in */ enum abckit_IsaApiDynamicConditionCode cc); + + abckit_Inst *(*IcreateTry)( + /* in */ abckit_Graph *ctx); + + abckit_Inst *(*IcreateCatchPhi)( + /* in */ abckit_Graph *ctx, + /* in */ size_t argCount, + /* in */... /* catchPhi inputs */); +}; + +#ifdef __cplusplus +} +#endif + +#endif // LIBABCKIT_ISA_ISA_DYNAMIC_H diff --git a/libabckit/include/isa/isa_static.h b/libabckit/include/isa/isa_static.h new file mode 100644 index 0000000000000000000000000000000000000000..cffd92eef412b1a4770a88b0380fe8261c49e51b --- /dev/null +++ b/libabckit/include/isa/isa_static.h @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_ISA_ISA_STATIC_H +#define LIBABCKIT_ISA_ISA_STATIC_H + +#include +#include +#include + +#include "../metadata.h" +#include "../ir_core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum abckit_IsaApiStaticOpcode { + abckit_IsaApiStaticOpcode_INVALID, + abckit_IsaApiStaticOpcode_Constant, + abckit_IsaApiStaticOpcode_Parameter, + abckit_IsaApiStaticOpcode_LoadString, + abckit_IsaApiStaticOpcode_Return, + abckit_IsaApiStaticOpcode_Try, + abckit_IsaApiStaticOpcode_CatchPhi, + abckit_IsaApiStaticOpcode_Phi, + + /* Static Opcodes. Directly implemented by IR opcodes in compiler. + * IR semantics can be found in + * https://gitee.com/openharmony/arkcompiler_runtime_core/blob/master/static_core/compiler/optimizer/ir/instructions.yaml + * Can be used only in static IR */ + + /* Unary operations: */ + abckit_IsaApiStaticOpcode_Neg, + abckit_IsaApiStaticOpcode_Not, + + /* BinaryOperation: */ + abckit_IsaApiStaticOpcode_Cmp, + abckit_IsaApiStaticOpcode_Add, + abckit_IsaApiStaticOpcode_Sub, + abckit_IsaApiStaticOpcode_Mul, + abckit_IsaApiStaticOpcode_Div, + abckit_IsaApiStaticOpcode_Mod, + abckit_IsaApiStaticOpcode_Shl, + abckit_IsaApiStaticOpcode_Shr, + abckit_IsaApiStaticOpcode_AShr, + abckit_IsaApiStaticOpcode_And, + abckit_IsaApiStaticOpcode_Or, + abckit_IsaApiStaticOpcode_Xor, + + /* Cast: */ + abckit_IsaApiStaticOpcode_Cast, + + /* Object manipulation: */ + abckit_IsaApiStaticOpcode_NullPtr, + abckit_IsaApiStaticOpcode_NewArray, + abckit_IsaApiStaticOpcode_NewObject, + abckit_IsaApiStaticOpcode_InitObject, + abckit_IsaApiStaticOpcode_LoadArray, + abckit_IsaApiStaticOpcode_StoreArray, + abckit_IsaApiStaticOpcode_LoadObject, + abckit_IsaApiStaticOpcode_StoreObject, + abckit_IsaApiStaticOpcode_LoadStatic, + abckit_IsaApiStaticOpcode_StoreStatic, + abckit_IsaApiStaticOpcode_LenArray, + abckit_IsaApiStaticOpcode_LoadConstArray, + abckit_IsaApiStaticOpcode_CheckCast, + abckit_IsaApiStaticOpcode_IsInstance, + abckit_IsaApiStaticOpcode_IsUndefined, + abckit_IsaApiStaticOpcode_LoadUndefined, + abckit_IsaApiStaticOpcode_Equals, + + /* Return: */ + abckit_IsaApiStaticOpcode_ReturnVoid, + + /* Calls: */ + abckit_IsaApiStaticOpcode_CallStatic, + abckit_IsaApiStaticOpcode_CallVirtual, + + /* BinaryImmOperation: */ + abckit_IsaApiStaticOpcode_AddI, + abckit_IsaApiStaticOpcode_SubI, + abckit_IsaApiStaticOpcode_MulI, + abckit_IsaApiStaticOpcode_DivI, + abckit_IsaApiStaticOpcode_ModI, + abckit_IsaApiStaticOpcode_ShlI, + abckit_IsaApiStaticOpcode_ShrI, + abckit_IsaApiStaticOpcode_AShrI, + abckit_IsaApiStaticOpcode_AndI, + abckit_IsaApiStaticOpcode_OrI, + abckit_IsaApiStaticOpcode_XorI, + + /* Exceptions */ + abckit_IsaApiStaticOpcode_Throw, + + /* Condition */ + abckit_IsaApiStaticOpcode_If, +}; + +enum abckit_IsaApiStaticConditionCode { + abckit_IsaApiStaticConditionCode_CC_NONE = 0, + abckit_IsaApiStaticConditionCode_CC_EQ, /* == */ + abckit_IsaApiStaticConditionCode_CC_NE, /* != */ + abckit_IsaApiStaticConditionCode_CC_LT, /* < */ + abckit_IsaApiStaticConditionCode_CC_LE, /* <= */ + abckit_IsaApiStaticConditionCode_CC_GT, /* > */ + abckit_IsaApiStaticConditionCode_CC_GE, /* >= */ + // Unsigned integers. + abckit_IsaApiStaticConditionCode_CC_B, /* < */ + abckit_IsaApiStaticConditionCode_CC_BE, /* <= */ + abckit_IsaApiStaticConditionCode_CC_A, /* > */ + abckit_IsaApiStaticConditionCode_CC_AE, /* >= */ + // Compare result of bitwise AND with zero + abckit_IsaApiStaticConditionCode_CC_TST_EQ, /* (lhs AND rhs) == 0 */ + abckit_IsaApiStaticConditionCode_CC_TST_NE, /* (lhs AND rhs) != 0 */ +}; + +struct abckit_IsaApiStatic { + abckit_Class *(*IgetClass)( + /* in */ abckit_Inst *inst); + + void (*IsetClass)( + /* in */ abckit_Inst *inst, + /* in */ abckit_Class *klass); + + enum abckit_IsaApiStaticConditionCode (*IgetConditionCode)( + /* in */ abckit_Inst *inst); + + void (*IsetConditionCode)( + /* in */ abckit_Inst *inst, + /* in */ enum abckit_IsaApiStaticConditionCode cc); + + enum abckit_IsaApiStaticOpcode (*IgetOpcode)( + /* in */ abckit_Inst *inst); + + /* For Cast instructions */ + void (*IsetTargetType)( + /* in */ abckit_Inst *inst, + /* in */ enum abckit_TypeId t); + + /* For Cast instructions */ + enum abckit_TypeId (*IgetTargetType)( + /* in */ abckit_Inst *inst); + + abckit_Inst *(*IcreateCmp)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateLoadString)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_String *str); + + abckit_Inst *(*IcreateReturn)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateIf)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1, + /* in */ enum abckit_IsaApiStaticConditionCode cc); + + abckit_Inst *(*IcreateTry)( + /* in */ abckit_Graph *ctx); + + abckit_Inst *(*IcreateCatchPhi)( + /* in */ abckit_Graph *ctx, + /* in */ size_t argCount, + /* in */... /* catchPhi inputs */); + + abckit_Inst *(*IcreateNeg)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateNot)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0); + + abckit_Inst *(*IcreateAdd)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateSub)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateMul)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateDiv)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateMod)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateShl)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateShr)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateAShr)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateAnd)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateOr)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateXor)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCast)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ enum abckit_TypeId targetType); + + abckit_Inst *(*GcreateNullPtr)( + /* in */ abckit_Graph *ctx); + + abckit_Inst *(*IcreateNewArray)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Class *inputClass, + /* in */ abckit_Inst *inputSize); + + abckit_Inst *(*IcreateNewObject)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Class *inputClass); + + abckit_Inst *(*IcreateInitObject)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Method *inputMethod, + /* in */ size_t argCount, + /* in */... /* method params */); + + abckit_Inst *(*IcreateLoadArray)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *arrayRef, + /* in */ abckit_Inst *idx, + /* in */ enum abckit_TypeId return_type_id); + + abckit_Inst *(*IcreateStoreArray)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *arrayRef, + /* in */ abckit_Inst *idx, + /* in */ abckit_Inst *value, + /* in */ enum abckit_TypeId value_type_id); + + abckit_Inst *(*IcreateStoreArrayWide)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *arrayRef, + /* in */ abckit_Inst *idx, + /* in */ abckit_Inst *value, + /* in */ enum abckit_TypeId value_type_id); + + abckit_Inst *(*IcreateLenArray)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *arr); + + abckit_Inst *(*IcreateLoadConstArray)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_LiteralArray *literalArray); + + abckit_Inst *(*IcreateCheckCast)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *inputObj, + /* in */ abckit_Type *targetType); + + abckit_Inst *(*IcreateIsInstance)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *inputObj, + /* in */ abckit_Type *targetType); + + abckit_Inst *(*IcreateLoadUndefined)( + /* in */ abckit_Graph *ctx); + + abckit_Inst *(*IcreateReturnVoid)( + /* in */ abckit_Graph *ctx); + + abckit_Inst *(*IcreateEquals)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ abckit_Inst *input1); + + abckit_Inst *(*IcreateCallStatic)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Method *inputMethod, + /* in */ size_t argCount, + /* in */... /* method params */); + + abckit_Inst *(*IcreateCallVirtual)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *inputObj, + /* in */ abckit_Method *inputMethod, + /* in */ size_t argCount, + /* in */... /* method params */); + + abckit_Inst *(*IcreateAddI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateSubI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateMulI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateDivI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateModI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateShlI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateShrI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateAShrI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateAndI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateOrI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateXorI)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *input0, + /* in */ uint64_t imm); + + abckit_Inst *(*IcreateThrow)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *acc); + + abckit_Inst *(*IcreateIsUndefined)( + /* in */ abckit_Graph *ctx, + /* in */ abckit_Inst *inputObj); +}; + +#ifdef __cplusplus +} +#endif + +#endif // LIBABCKIT_ISA_ISA_STATIC_H diff --git a/libabckit/include/metadata.h b/libabckit/include/metadata.h new file mode 100644 index 0000000000000000000000000000000000000000..62a66e6b072165856bf96f44956c0f7d1510043e --- /dev/null +++ b/libabckit/include/metadata.h @@ -0,0 +1,1019 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_METADATA_H +#define LIBABCKIT_METADATA_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +enum abckit_TypeId { + abckit_TypeId_INVALID, + abckit_TypeId_VOID, + abckit_TypeId_U1, + abckit_TypeId_I8, + abckit_TypeId_U8, + abckit_TypeId_I16, + abckit_TypeId_U16, + abckit_TypeId_I32, + abckit_TypeId_U32, + abckit_TypeId_F32, + abckit_TypeId_F64, + abckit_TypeId_I64, + abckit_TypeId_U64, + abckit_TypeId_STRING, + abckit_TypeId_ANY, + abckit_TypeId_REFERENCE, + abckit_TypeId_LITERALARRAY +}; + +/* FIXME: (knazarov) may need to prune this enum in order to only expose user-friendly literal types */ +enum abckit_LiteralTag { + /* common */ + abckit_LiteralTag_INVALID, + abckit_LiteralTag_TAGVALUE, + abckit_LiteralTag_BOOL, + abckit_LiteralTag_BYTE, + abckit_LiteralTag_SHORT, + abckit_LiteralTag_INTEGER, + abckit_LiteralTag_LONG, + abckit_LiteralTag_FLOAT, + abckit_LiteralTag_DOUBLE, + abckit_LiteralTag_STRING, + abckit_LiteralTag_METHOD, + abckit_LiteralTag_GENERATORMETHOD, + abckit_LiteralTag_ACCESSOR, + abckit_LiteralTag_METHODAFFILIATE, + abckit_LiteralTag_ARRAY_U1, + abckit_LiteralTag_ARRAY_U8, + abckit_LiteralTag_ARRAY_I8, + abckit_LiteralTag_ARRAY_U16, + abckit_LiteralTag_ARRAY_I16, + abckit_LiteralTag_ARRAY_U32, + abckit_LiteralTag_ARRAY_I32, + abckit_LiteralTag_ARRAY_U64, + abckit_LiteralTag_ARRAY_I64, + abckit_LiteralTag_ARRAY_F32, + abckit_LiteralTag_ARRAY_F64, + abckit_LiteralTag_ARRAY_STRING, + abckit_LiteralTag_ASYNCGENERATORMETHOD, + abckit_LiteralTag_NULLVALUE, + + /* static */ + abckit_LiteralTag_BIGINT, + abckit_LiteralTag_ASYNCMETHOD, + + /* dynamic */ + abckit_LiteralTag_LITERALBUFFERINDEX, + abckit_LiteralTag_LITERALARRAY, + abckit_LiteralTag_BUILTINTYPEINDEX, + abckit_LiteralTag_GETTER, + abckit_LiteralTag_SETTER +}; + +#define ABCKIT_VERSION_SIZE 4 +typedef uint8_t *abckit_File_Version; + +typedef struct abckit_Class abckit_Class; +typedef struct abckit_AnnotationInterface abckit_AnnotationInterface; +typedef struct abckit_AnnotationInterfaceField abckit_AnnotationInterfaceField; +typedef struct abckit_Field abckit_Field; +typedef struct abckit_Method abckit_Method; +typedef struct abckit_Annotation abckit_Annotation; +typedef struct abckit_AnnotationElement abckit_AnnotationElement; +typedef struct abckit_Value abckit_Value; +typedef struct abckit_String abckit_String; +typedef struct abckit_Type abckit_Type; +typedef struct abckit_Code abckit_Code; +typedef struct abckit_Module abckit_Module; +typedef struct abckit_ImportDescriptor abckit_ImportDescriptor; +typedef struct abckit_ExportDescriptor abckit_ExportDescriptor; + +typedef struct abckit_LiteralArray abckit_LiteralArray; +typedef struct abckit_Literal abckit_Literal; + +typedef struct abckit_ModifyContext abckit_ModifyContext; +typedef struct abckit_File abckit_File; + +struct abckit_InspectApi { + /* ======================================== + * File + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File_Version (*FileGetVersion)( + /* in */ abckit_File *ctx); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*FileEnumerateModules)( + /* in */ abckit_File *ctxI, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Module *module, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*FileEnumerateExternalModules)( + /* in */ abckit_File *ctxI, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Module *module, + /* in-out */ void *data)); + + /* ======================================== + * Module + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*ModuleGetInspectContext)( + /* in */ abckit_Module *m); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*ModuleGetName)( + /* in */ abckit_Module *m); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*ModuleIsExternal)( + /* in */ abckit_Module *m); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleEnumerateImports)( + /* in */ abckit_Module *m, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_ImportDescriptor *i, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleEnumerateExports)( + /* in */ abckit_Module *m, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_ExportDescriptor *i, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleEnumerateClasses)( + /* in */ abckit_Module *m, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Class *klass, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleEnumerateTopLevelFunctions)( + /* in */ abckit_Module *m, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Method *method, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleEnumerateAnonymousFunctions)( + /* in */ abckit_Module *m, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Method *method, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleEnumerateAnnotationInterfaces)( + /* in */ abckit_Module *m, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_AnnotationInterface *ai, + /* in-out */ void *data)); + + /* ======================================== + * ImportDescriptor + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*ImportDescriptorGetInspectContext)( + /* in */ abckit_ImportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*ImportDescriptorGetImportingModule)( + /* in */ abckit_ImportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*ImportDescriptorGetImportedModule)( + /* in */ abckit_ImportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*ImportDescriptorGetName)( + /* in */ abckit_ImportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*ImportDescriptorGetAlias)( + /* in */ abckit_ImportDescriptor *i); + + /* ======================================== + * ExportDescriptor + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*ExportDescriptorGetInspectContext)( + /* in */ abckit_ExportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*ExportDescriptorGetExportingModule)( + /* in */ abckit_ExportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*ExportDescriptorGetExportedModule)( + /* in */ abckit_ExportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*ExportDescriptorGetName)( + /* in */ abckit_ExportDescriptor *e); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*ExportDescriptorGetAlias)( + /* in */ abckit_ExportDescriptor *e); + + /* ======================================== + * Class + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*ClassGetInspectContext)( + /* in */ abckit_Class *klass); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*ClassGetModule)( + /* in */ abckit_Class *klass); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*ClassGetName)( + /* in */ abckit_Class *klass); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ClassEnumerateMethods)( + /* in */ abckit_Class *klass, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Method *method, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ClassEnumerateAnnotations)( + /* in */ abckit_Class *klass, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Annotation *anno, + /* in-out */ void *data)); + + /* ======================================== + * AnnotationInterface + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*AnnotationInterfaceGetInspectContext)( + /* in */ abckit_AnnotationInterface *anno); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*AnnotationInterfaceGetModule)( + /* in */ abckit_AnnotationInterface *anno); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*AnnotationInterfaceGetName)( + /* in */ abckit_AnnotationInterface *ai); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*AnnotationInterfaceEnumerateFields)( + /* in */ abckit_AnnotationInterface *ai, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_AnnotationInterfaceField *fld, + /* in-out */ void *data)); + + /* ======================================== + * AnnotationInterfaceField + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*AnnotationInterfaceFieldGetInspectContext)( + /* in */ abckit_AnnotationInterfaceField *anno); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_AnnotationInterface *(*AnnotationInterfaceFieldGetInterface)( + /* in */ abckit_AnnotationInterfaceField *fld); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*AnnotationInterfaceFieldGetName)( + /* in */ abckit_AnnotationInterfaceField *fld); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Type *(*AnnotationInterfaceFieldGetType)( + /* in */ abckit_AnnotationInterfaceField *fld); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Value *(*AnnotationInterfaceFieldGetDefaultValue)( + /* in */ abckit_AnnotationInterfaceField *fld); + + /* ======================================== + * Method + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*MethodGetInspectContext)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*MethodGetModule)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*MethodGetName)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Class *(*MethodGetParentClass)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*MethodEnumerateAnnotations)( + /* in */ abckit_Method *method, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_Annotation *anno, + /* in-out */ void *data)); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Code *(*MethodGetCode)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*MethodIsStatic)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*MethodIsNative)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*MethodIsAbstract)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*MethodIsExternal)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*MethodIsCtor)( + /* in */ abckit_Method *method); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*MethodIsAnonymous)( + /* in */ abckit_Method *method); + + /* ======================================== + * Annotation + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*AnnotationGetInspectContext)( + /* out */ abckit_Annotation *anno); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_AnnotationInterface *(*AnnotationGetInterface)( + /* in */ abckit_Annotation *anno); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*AnnotationEnumerateElements)( + /* in */ abckit_Annotation *anno, + /* in-out */ void *data, + /* in */ + bool (*cb)(/* in */ abckit_AnnotationElement *ae, + /* in-out */ void *data)); + + /* ======================================== + * AnnotationElement + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_File *(*AnnotationElementGetInspectContext)( + /* in */ abckit_AnnotationElement *ae); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Annotation *(*AnnotationElementGetAnnotation)( + /* in */ abckit_AnnotationElement *ae); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*AnnotationElementGetName)( + /* in */ abckit_AnnotationElement *ae); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Value *(*AnnotationElementGetValue)( + /* in */ abckit_AnnotationElement *ae); + + /* ======================================== + * Type + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + enum abckit_TypeId (*TypeGetTypeId)( + /* in */ abckit_Type *t); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Class *(*TypeGetReferenceClass)( + /* in */ abckit_Type *t); + + /* ======================================== + * Value + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Type *(*ValueGetType)( + /* in */ abckit_File *ctx, + /* in */ abckit_Value *value); + + /* + * Applies to: ArkTS, JavaScript + * NOTE: Returns error if input value is not integer + */ + bool (*ValueGetU1)( + /* in */ abckit_File *ctx, + /* in */ abckit_Value *value); + + /* + * Applies to: ArkTS, JavaScript + * NOTE: Returns error if input value is not double + */ + double (*ValueGetDouble)( + /* in */ abckit_File *ctx, + /* in */ abckit_Value *value); + + /* + * Applies to: ArkTS, JavaScript + * NOTE: Returns error if input value is not id + */ + abckit_String *(*ValueGetString)( + /* in */ abckit_File *ctx, + /* in */ abckit_Value *value); + + /* + * Applies to: ArkTS, JavaScript + * NOTE: Returns error if input value is not array + */ + abckit_LiteralArray *(*ArrayValueGetLiteralArray)( + /* in */ abckit_File *ctx, + /* in */ abckit_Value *value); + + /* ======================================== + * String + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + void (*abckit_StringToString)( + /* in */ abckit_File *ctx, + /* in */ abckit_String *value, + /* out */ char *out, + /* out */ size_t *len); + + /* ======================================== + * LiteralArray + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + void (*LiteralArrayEnumerateElements)( + /* in */ abckit_File *ctx, + /* in */ abckit_LiteralArray *litArr, + /* in-out */ void *data, + bool (*cb)(/* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit, + /* in-out */ void *data)); + + /* ======================================== + * Literal + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + enum abckit_LiteralTag (*LiteralGetTag)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + bool (*LiteralGetBool)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + uint8_t (*LiteralGetU8)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + uint16_t (*LiteralGetU16)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + uint32_t (*LiteralGetU32)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + uint64_t (*LiteralGetU64)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + float (*LiteralGetFloat)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + double (*LiteralGetDouble)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_String *(*LiteralGetString)( + /* in */ abckit_File *ctx, + /* in */ abckit_Literal *lit); + +#include "v2/metadata_inspect_field.inc" +}; + +struct abckit_AnnotationInterfaceCreateParams { + const char *name; +}; + +struct abckit_AnnotationInterfaceFieldCreateParams { + const char *name; + abckit_Type *type; + abckit_Value *defaultValue; +}; + +struct abckit_AnnotationCreateParams { + abckit_AnnotationInterface *ai; +}; + +struct abckit_AnnotationElementCreateParams { + const char *name; + abckit_Value *value; +}; + +struct abckit_ImportFromDynamicModuleCreateParams { + /* + * Import name. + * For namespace imports equals to "*" + * For default imports equals to "default" + * For regular imports is the same as in user code. + */ + const char *name; + /* + * Alias name for the import. + * For namespace imports is the same as in user code. + * For delault import is the same as the default import name in user code. + * For regular imports is the same as in user code. + */ + const char *alias; + /* + * The module the entity is imported from. + */ + abckit_Module *module; +}; + +struct abckit_DynamicModuleExportCreateParams { + /* + * Name of the entity that should be exported. + * For star exports equals to "*". + * For indirect exports is the same as in user code. + * For local exports is the same as in user code. + */ + const char *name; + /* + * Alias under which entity should be exported. + * For star exports equals nullptr. + * For indirect exports is the same as in user code. + * For local exports is the same as in user code. + */ + const char *alias; + /* + * The module the entity is exported from. + */ + abckit_Module *module; +}; + +struct abckit_ExternalModuleCreateParams { + /* + * Name of the external module + */ + const char *name; + /* + * TODO:(knazarov) expand once multi-language API is merged + */ +}; + +struct abckit_ModifyApi { + /* ======================================== + * File + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Module *(*FileAddExternalModule)( + /* in */ abckit_File *ctx, + /* in */ const struct abckit_ExternalModuleCreateParams *params); + + /* ======================================== + * Module + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_ImportDescriptor *(*ModuleAddImportFromDynamicModule)( + /* in */ abckit_Module *m, + /* in */ const struct abckit_ImportFromDynamicModuleCreateParams *params); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleRemoveImport)( + /* in */ abckit_Module *m, + /* in */ abckit_ImportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_ExportDescriptor *(*DynamicModuleAddExport)( + /* in */ abckit_Module *m, + /* in */ const struct abckit_DynamicModuleExportCreateParams *params); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ModuleRemoveExport)( + /* in */ abckit_Module *m, + /* in */ abckit_ExportDescriptor *i); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_AnnotationInterface *(*ModuleAddAnnotationInterface)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Module *m, + /* in */ const struct abckit_AnnotationInterfaceCreateParams *params); + + /* ======================================== + * Class + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Annotation *(*ClassAddAnnotation)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Class *klass, + /* in */ const struct abckit_AnnotationCreateParams *params); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*ClassRemoveAnnotation)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Class *klass, + /* in */ abckit_Annotation *anno); + + /* ======================================== + * AnnotationInterface + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_AnnotationInterfaceField *(*AnnotationInterfaceAddField)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_AnnotationInterface *ai, + /* in */ const struct abckit_AnnotationInterfaceFieldCreateParams *params); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*AnnotationInterfaceRemoveField)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_AnnotationInterface *ai, + /* in */ abckit_AnnotationInterfaceField *field); + + /* ======================================== + * Method + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + void (*MethodSetCode)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Method *method, + /* in */ abckit_Code *code); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Annotation *(*MethodAddAnnotation)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Method *method, + /* in */ const struct abckit_AnnotationCreateParams *params); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*MethodRemoveAnnotation)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Method *method, + /* in */ abckit_Annotation *anno); + + /* ======================================== + * Annotation + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_AnnotationElement *(*AnnotationAddAnnotationElement)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Annotation *anno, + /* in */ struct abckit_AnnotationElementCreateParams *params); + + /* + * Applies to: ArkTS, JavaScript + */ + void (*AnnotationRemoveAnnotationElement)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Annotation *anno, + /* in */ abckit_AnnotationElement *elem); + + /* ======================================== + * Type + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Type *(*CreateType)( + /* in */ abckit_ModifyContext *ctx, + /* in */ enum abckit_TypeId id); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Type *(*CreateReferenceType)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Class *klass); + + /* ======================================== + * Value + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Value *(*CreateValueU1)( + /* in */ abckit_ModifyContext *ctx, + /* in */ bool value); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Value *(*CreateValueDouble)( + /* in */ abckit_ModifyContext *ctx, + /* in */ double value); + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_Value *(*CreateValueString)( + /* in */ abckit_ModifyContext *ctx, + /* in */ const char *value); + + /* + * Applies to: ArkTS, JavaScript + * NOTE: Returns error if at least one input value is not scalar + */ + abckit_Value *(*CreateLiteralArrayValue)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Value **value, + /* in */ size_t size); + + /* ======================================== + * String + * ======================================== */ + + /* + * Version 1 + */ + abckit_String *(*CreateString)( + /* in */ abckit_ModifyContext *ctx, + /* in */ const char *value); + + /* ======================================== + * LiteralArray + * ======================================== */ + + /* + * Applies to: ArkTS, JavaScript + */ + abckit_LiteralArray *(*CreateLiteralArray)( + /* in */ abckit_ModifyContext *ctx, + /* in */ abckit_Literal **value, + /* in */ size_t size); + + /* ======================================== + * Literal + * ======================================== */ + + abckit_Literal *(*CreateLiteralBool)( + /* in */ abckit_ModifyContext *ctx, + /* in */ bool value); + + abckit_Literal *(*CreateLiteralU8)( + /* in */ abckit_ModifyContext *ctx, + /* in */ uint8_t value); + + abckit_Literal *(*CreateLiteralU16)( + /* in */ abckit_ModifyContext *ctx, + /* in */ uint16_t value); + + abckit_Literal *(*CreateLiteralU32)( + /* in */ abckit_ModifyContext *ctx, + /* in */ uint32_t value); + + abckit_Literal *(*CreateLiteralU64)( + /* in */ abckit_ModifyContext *ctx, + /* in */ uint64_t value); + + abckit_Literal *(*CreateLiteralFloat)( + /* in */ abckit_ModifyContext *ctx, + /* in */ float value); + + abckit_Literal *(*CreateLiteralDouble)( + /* in */ abckit_ModifyContext *ctx, + /* in */ double value); + + abckit_Literal *(*CreateLiteralString)( + /* in */ abckit_ModifyContext *ctx, + /* in */ const char* value); +}; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* !LIBABCKIT_METADATA_H */ diff --git a/libabckit/include/statuses.h b/libabckit/include/statuses.h new file mode 100644 index 0000000000000000000000000000000000000000..a9922a11aef9af12f91e8dc6fcc85f57be1c7664 --- /dev/null +++ b/libabckit/include/statuses.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_STATUSES_H +#define LIBABCKIT_STATUSES_H + +#ifdef __cplusplus +extern "C" { +#endif + +enum abckit_Status { + abckit_Status_NO_ERROR, + abckit_Status_BAD_ARGUMENT, + abckit_Status_MEMORY_ALLOCATION, + abckit_Status_WRONG_MODE, + abckit_Status_WRONG_LITERAL_TYPE, + abckit_Status_UNSUPPORTED, + abckit_Status_WRONG_CTX, + abckit_Status_TODO +}; + +#ifdef __cplusplus +} +#endif + +#endif /* LIBABCKIT_STATUSES_H */ diff --git a/libabckit/include/v2/metadata_inspect_field.inc b/libabckit/include/v2/metadata_inspect_field.inc new file mode 100644 index 0000000000000000000000000000000000000000..0b6ea4bf869807a022311d394c2f8d9d6b8a56de --- /dev/null +++ b/libabckit/include/v2/metadata_inspect_field.inc @@ -0,0 +1,10 @@ +/* ======================================== + * Field + * ======================================== */ + +/* + * Applies to: ArkTS + */ +abckit_String *(*FieldGetName)( + /* in */ abckit_File *ctx, + /* in */ abckit_Field *field); diff --git a/libabckit/libabckit_config.gni b/libabckit/libabckit_config.gni new file mode 100644 index 0000000000000000000000000000000000000000..c19012b66384a40379a34e388ec321efdf8ace22 --- /dev/null +++ b/libabckit/libabckit_config.gni @@ -0,0 +1,49 @@ +# Copyright (c) 2024 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. + +import("//build/templates/cxx/cxx.gni") + +js_root = "//arkcompiler/ets_runtime" +abckit_root = "//arkcompiler/runtime_core/libabckit" + +template("abckit_plugin") { + ohos_shared_library("${target_name}") { + forward_variables_from(invoker, + "*", + [ + "configs", + "deps", + "include_dirs", + ]) + + deps = [ + "//arkcompiler/runtime_core/libabckit:libabckit", + ] + + include_dirs = [ + "//arkcompiler/runtime_core/libabckit/include", + ] + + if (defined(invoker.include_dirs)) { + deps += invoker.include_dirs + } + + if (defined(invoker.deps)) { + deps += invoker.deps + } + + if (defined(invoker.configs)) { + configs += invoker.configs + } + } +} diff --git a/libabckit/scripts/.gitignore b/libabckit/scripts/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..6187e7124c3d3c0378d654ee707e5338b78c18fc --- /dev/null +++ b/libabckit/scripts/.gitignore @@ -0,0 +1,2 @@ +abckit_status.csv + diff --git a/libabckit/scripts/common_gen_tests_api.rb b/libabckit/scripts/common_gen_tests_api.rb new file mode 100644 index 0000000000000000000000000000000000000000..e40772aac36dea4f1e028746f71ee914605276bd --- /dev/null +++ b/libabckit/scripts/common_gen_tests_api.rb @@ -0,0 +1,24 @@ +def collect_implemented_api_map(excluded_funcs) + implemented_api_raw = nil + Dir.chdir(File.dirname(__FILE__)) do + implemented_api_raw = `python get-abckit-status.py --print-implemented`.split(/\n/) + end + + implemented_api_map = {} + + implemented_api_raw.each do |api_func_raw| + domain, api_func = *api_func_raw.split(/::/) + + if excluded_funcs.include?(api_func) + next + end + + if implemented_api_map[domain].nil? + implemented_api_map[domain] = [api_func] + else + implemented_api_map[domain].append(api_func) + end + end + + return implemented_api_map +end \ No newline at end of file diff --git a/libabckit/scripts/create_merge_file.sh b/libabckit/scripts/create_merge_file.sh new file mode 100755 index 0000000000000000000000000000000000000000..ad06014323723cec3dead034e949de8f7b2150ab --- /dev/null +++ b/libabckit/scripts/create_merge_file.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +base="$(basename $1)" +tmp="$(echo $base | sed 's/\..*//')" +tmp_file="/tmp/merge_$tmp.txt" +echo "$base;$tmp;esm;$base;entry" > $tmp_file +dir="$(dirname $1)" +modules_dir="$dir/modules" +if [ -d $modules_dir ]; then + for file in $modules_dir/*; do + name=$(basename "$file") + tmp_module="$(echo $name | sed 's/\..*//')" + echo "modules/$name;modules/$tmp_module;esm;modules/$name;entry" >> $tmp_file + done +fi +/usr/bin/python3 "$(dirname $0)/../../../ets_runtime/test/quickfix/generate_merge_file.py" --input "$tmp_file" --output "$2" --prefix "$dir/" diff --git a/libabckit/scripts/dyn_inst_constructors_gen.rb b/libabckit/scripts/dyn_inst_constructors_gen.rb new file mode 100644 index 0000000000000000000000000000000000000000..7dcc016092f7f75df12c6d59fa977c3c3d3639a1 --- /dev/null +++ b/libabckit/scripts/dyn_inst_constructors_gen.rb @@ -0,0 +1,174 @@ +require 'ostruct' +require 'yaml' + +scripts_dir = File.dirname(__FILE__) +Dir.chdir(scripts_dir) + +isa = YAML.load_file('../../isa/isa.yaml')['groups'] +insts = [] + +def process_inst_params(inst_params) + inst_params.map! { |param| + # param can be either "some_id" or "v:in:any" + param_options = param.split(":") + processed_param = OpenStruct.new + processed_param.name = param_options[0][/[a-z_]*/] + processed_param.direction = param_options[1] ? param_options[1] : "in" + param = processed_param + } +end + +isa.each { |isa_title| + isa_title['instructions'].each { |isa_inst| + inst = OpenStruct.new + inst.opcode, *inst.params = isa_inst['sig'].split(' ') + inst.opcode = inst.opcode.split(".").map!{ |str| str.capitalize }.join + process_inst_params(inst.params) + inst.ic = isa_inst['properties'] ? + isa_inst['properties'].any?{ + |str| str.include? "ic_slot" or str.include? "jit_ic_slot" + } : false + inst.inacc = isa_inst['acc'] ? + (isa_inst['acc'] =~ /inout:/ or isa_inst['acc'] =~ /in:/): false + insts.append(inst) + } +} + +dyn_opcodes = File.open("../include/isa/isa_dynamic.h").read.split() + .select{ |str| + str.start_with?("abckit_IsaApiDynamicOpcode_") + }.map!{ |str| + str.delete_prefix("abckit_IsaApiDynamicOpcode_").chop!.split("_").map! { |str| + str.capitalize + }.join + } + +declaration_num = 0 +# tmp workaround: isa.yaml does not have If opcode, but opcodes.h does +declaration_num += 1 +puts "--> declarations" +insts.each { |inst| + next unless dyn_opcodes.include? inst.opcode + declaration_num += 1 + + indent = ' ' * 4 + inst_input = imm_input = 0 + + declaration = indent + "abckit_Inst *(*Icreate#{inst.opcode})(\n" + indent += ' ' * 4 + declaration += indent + "/* in */ abckit_Graph *ctxG" + + if inst.inacc + declaration += ",\n" + indent + declaration += "/* in */ abckit_Inst *acc" + end + + inst.params.each { |param| + # case when first inst param is imm number of ic_slot + next imm_input += 1 if inst.ic and param.name == "imm" and imm_input == 0 + + declaration += ",\n" + indent + declaration += "/* #{param.direction} */ " + + case param.name + when "v" + declaration += "abckit_Inst *input#{inst_input}" + inst_input += 1 + when "method_id" + declaration += "abckit_Method *method" + when "literalarray_id" + declaration += "abckit_LiteralArray *literalArray" + when "string_id" + declaration += "abckit_String *string" + when "imm" + case inst.opcode + when "Getmodulenamespace", "WideGetmodulenamespace" + declaration += "abckit_Module *md" + when "Ldexternalmodulevar", "WideLdexternalmodulevar" + declaration += "abckit_ImportDescriptor *id" + when "Ldlocalmodulevar", "WideLdlocalmodulevar", "Stmodulevar", "WideStmodulevar" + declaration += "abckit_ExportDescriptor *ed" + else + declaration += "uint64_t imm#{inst.ic ? imm_input - 1 : imm_input}" + end + imm_input += 1 + else + puts "Unknown type of inst param" + exit 1 + end + } + declaration += ");" + puts declaration + puts "\n" +} + +if declaration_num != dyn_opcodes.length() + puts "Missed some declarations" + puts "total printed declarations: #{declaration_num}" + puts "total dynamic opcodes: #{dyn_opcodes.length()}" + dyn_opcodes.each { |opcode| + next unless insts.index { |inst| inst.opcode == opcode }.nil? + puts "No declaration for #{opcode} opcode" + } + exit 1 +end + + +puts "--> definitions" +insts.each { |inst| + next unless dyn_opcodes.include? inst.opcode + + inst_input = imm_input = 0 + + definition = "extern \"C\" abckit_Inst *Icreate#{inst.opcode}(" + definition += "abckit_Graph *ctxG" + + if inst.inacc + definition += ", abckit_Inst *acc" + end + + inst.params.each { |param| + # case when first inst param is imm number of ic_slot + next imm_input += 1 if inst.ic and param.name == "imm" and imm_input == 0 + + case param.name + when "v" + definition += ", abckit_Inst *input#{inst_input}" + inst_input += 1 + when "method_id" + definition += ", abckit_Method *method" + when "literalarray_id" + definition += ", abckit_LiteralArray *literalArray" + when "string_id" + definition += ", abckit_String *string" + when "imm" + case inst.opcode + when "Getmodulenamespace", "WideGetmodulenamespace" + definition += ", abckit_Module *md" + when "Ldexternalmodulevar", "WideLdexternalmodulevar" + definition += ", abckit_ImportDescriptor *id" + when "Ldlocalmodulevar", "WideLdlocalmodulevar", "Stmodulevar", "WideStmodulevar" + definition += ", abckit_ExportDescriptor *ed" + else + definition += ", uint64_t imm#{inst.ic ? imm_input - 1 : imm_input}" + end + imm_input += 1 + else + puts "Unknown type of inst param" + exit 1 + end + } + indent = ' ' * 4 + definition += ")\n{\n"; + definition += indent + "LIBABCKIT_UNIMPLEMENTED\n"; + definition += "}\n"; + puts definition + puts "\n" +} + +puts "--> dyn instruction constructor names" +insts.each { |inst| + next unless dyn_opcodes.include? inst.opcode + constructor_name = "Icreate#{inst.opcode}," + puts constructor_name +} diff --git a/libabckit/scripts/fix_intrinsics_yml.sh b/libabckit/scripts/fix_intrinsics_yml.sh new file mode 100755 index 0000000000000000000000000000000000000000..1fe467da0756937868a611c234bc195861f43298 --- /dev/null +++ b/libabckit/scripts/fix_intrinsics_yml.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +sed 's/intrinsics://' $1 &> $2 diff --git a/libabckit/scripts/fix_static_codegen_plugin_files.sh b/libabckit/scripts/fix_static_codegen_plugin_files.sh new file mode 100755 index 0000000000000000000000000000000000000000..7c78d192e0401be30d855ecda64a66fd5a6b614b --- /dev/null +++ b/libabckit/scripts/fix_static_codegen_plugin_files.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e + +OUTPUT_DIR="${1}" +shift + +for FILE_PATH in "${@}" +do + basename "$FILE_PATH" + f="$(basename -- $FILE_PATH)" + echo "Fix plugin's file path in ${FILE_PATH}" + cat "${FILE_PATH}" | sed -r 's/BytecodeGen/CodeGenStatic/g' &> "${OUTPUT_DIR}/$f" + sed -i 's/plugins\/ets\/bytecode_optimizer\/visitors\///g' "${OUTPUT_DIR}/$f" +done diff --git a/libabckit/scripts/gen_null_arg_tests.rb b/libabckit/scripts/gen_null_arg_tests.rb new file mode 100644 index 0000000000000000000000000000000000000000..4c94f85349daafd81568dc03839686e00626485a --- /dev/null +++ b/libabckit/scripts/gen_null_arg_tests.rb @@ -0,0 +1,30 @@ +require 'erb' +require_relative 'common_gen_tests_api' + +abckit_scripts = File.dirname(__FILE__) +abckit_root = File.expand_path("../", abckit_scripts) +abckit_test = File.join(abckit_root, "/tests/null_args_tests/") + +excluded_funcs = [ + "GetLastError" +] + +implemented_api_map = collect_implemented_api_map(excluded_funcs) +null_args_tests_erb = File.join(abckit_test, "null_args_tests.cpp.erb") +implemented_api_map.each_key do |domain| + iteration = 0 + index = 0 + slice_size = 100 + api_funcs_arr = implemented_api_map[domain] + total_domain_api_funcs = api_funcs_arr.length + + puts "#{domain}: #{total_domain_api_funcs}" + + while index < total_domain_api_funcs do + testfile_fullpath = File.join(abckit_test, "null_args_tests_#{domain}_#{iteration}.cpp") + res = ERB.new(File.read(null_args_tests_erb), nil, "%").result(binding) + File.write(testfile_fullpath, res) + iteration += 1 + index += slice_size + end +end diff --git a/libabckit/scripts/gen_wrong_ctx_tests.rb b/libabckit/scripts/gen_wrong_ctx_tests.rb new file mode 100644 index 0000000000000000000000000000000000000000..d7aa7936ec55db9d8f999c4da2785d4ec4050d3b --- /dev/null +++ b/libabckit/scripts/gen_wrong_ctx_tests.rb @@ -0,0 +1,261 @@ +require 'erb' +require_relative 'common_gen_tests_api' + +abckit_scripts = File.dirname(__FILE__) +abckit_root = File.expand_path("../", abckit_scripts) +abckit_test = File.join(abckit_root, "/tests/wrong_ctx_tests/") + +excluded_funcs = [ + "GetLastError", +] + +funcs_without_two_abckit_entites = [ + "DestroyGraphContext", + "DestroyInspectContext", + "OpenAbc", + "WriteAbc", + "TransformModule", + "TransformMethod", + "graphToCode", + "FileGetVersion", + "FileEnumerateModules", + "FileEnumerateExternalModules", + "ModuleGetInspectContext", + "ModuleGetName", + "ModuleIsExternal", + "ModuleEnumerateImports", + "ModuleEnumerateExports", + "ModuleEnumerateClasses", + "ModuleEnumerateTopLevelFunctions", + "ImportDescriptorGetInspectContext", + "ImportDescriptorGetImportedModule", + "ImportDescriptorGetImportingModule", + "ImportDescriptorGetName", + "ImportDescriptorGetAlias", + "ExportDescriptorGetInspectContext", + "ExportDescriptorGetExportingModule", + "ExportDescriptorGetExportedModule", + "ExportDescriptorGetName", + "ExportDescriptorGetAlias", + "ClassGetInspectContext", + "ClassGetModule", + "ClassGetName", + "ClassEnumerateMethods", + "MethodGetInspectContext", + "MethodGetModule", + "MethodGetName", + "MethodGetParentClass", + "MethodEnumerateAnnotations", + "MethodGetCode", + "MethodIsStatic", + "MethodIsNative", + "MethodIsAbstract", + "MethodIsExternal", + "MethodIsCtor", + "MethodIsAnonymous", + "AnnotationGetInspectContext", + "AnnotationEnumerateElements", + "TypeGetTypeId", + "TypeGetReferenceClass", + "LiteralArrayEnumerateElements", + "ArrayValueGetLiteralArray", + "LiteralGetBool", + "LiteralGetDouble", + "LiteralGetFloat", + "LiteralGetString", + "LiteralGetTag", + "LiteralGetU16", + "LiteralGetU32", + "LiteralGetU64", + "LiteralGetU8", + "ValueGetDouble", + "ValueGetString", + "ValueGetType", + "ValueGetU1", + "abckit_StringToString", + "CreateLiteralArray", + "CreateLiteralArrayValue", + "CreateLiteralBool", + "CreateLiteralDouble", + "CreateLiteralFloat", + "CreateLiteralString", + "CreateLiteralU16", + "CreateLiteralU32", + "CreateLiteralU64", + "CreateLiteralU8", + "CreateReferenceType", + "CreateString", + "CreateType", + "CreateValueDouble", + "CreateValueString", + "CreateValueU1", + "ModuleAddImportFromDynamicModule", + "ModuleRemoveExport", + "ModuleRemoveImport", + "IsetConditionCode", + "IsetExportDescriptor", + "IsetInput", + "IsetInputs", + "IsetLiteralArray", + "IsetModule", + "IsetTargetType", + "IvisitInputs", + "IvisitUsers", + "IsetImportDescriptor", + "BBclear", + "BBcreateEmpty", + "BBdump", + "BBgetFalseBranch", + "BBgetTrueBranch", + "BBgetFirstInst", + "BBgetGraph", + "BBgetId", + "BBgetImmediateDominator", + "BBgetLastInst", + "BBgetNumberOfInstructions", + "BBgetPredBlock", + "BBgetPredBlockCount", + "BBgetSuccBlock", + "BBgetSuccBlockCount", + "BBgetTrueBranch", + "BBisCatch", + "BBisCatchBegin", + "BBisEnd", + "BBisLoopHead", + "BBisLoopPrehead", + "BBisStart", + "BBisTry", + "BBisTryBegin", + "BBisTryEnd", + "BBsplitBlockAfterInstruction", + "BBvisitDominatedBlocks", + "BBvisitPredBlocks", + "BBvisitSuccBlocks", + "BBcreatePhi", + "GcreateConstantF64", + "GcreateConstantI32", + "GcreateConstantI64", + "GcreateConstantU64", + "GcreateNullPtr", + "Gdump", + "GgetBasicBlock", + "GgetEndBasicBlock", + "GgetNumberOfBasicBlocks", + "GgetParameter", + "GgetStartBasicBlock", + "GrunPassRemoveUnreachableBlocks", + "GvisitBlocksRPO", + "IcheckIsCall", + "IcreateAsyncfunctionenter", + "IcreateCallruntimeCreateprivateproperty", + "IcreateCallruntimeLdsendableclass", + "IcreateCallruntimeLdsendableexternalmodulevar", + "IcreateCallruntimeLdsendablevar", + "IcreateCallruntimeNewsendableenv", + "IcreateCallruntimeWideldsendableexternalmodulevar", + "IcreateCallruntimeWideldsendablevar", + "IcreateCallruntimeWidenewsendableenv", + "IcreateCopyrestargs", + "IcreateCreatearraywithbuffer", + "IcreateCreateemptyarray", + "IcreateCreateemptyobject", + "IcreateCreateobjectwithbuffer", + "IcreateCreateregexpwithliteral", + "IcreateDebugger", + "IcreateGetunmappedargs", + "IcreateLdbigint", + "IcreateLdexternalmodulevar", + "IcreateLdfalse", + "IcreateLdfunction", + "IcreateLdglobal", + "IcreateLdglobalvar", + "IcreateLdhole", + "IcreateLdinfinity", + "IcreateLdlexvar", + "IcreateLdlocalmodulevar", + "IcreateLdnan", + "IcreateLdnewtarget", + "IcreateLdnull", + "IcreateLdsymbol", + "IcreateLdthis", + "IcreateLdthisbyname", + "IcreateLdtrue", + "IcreateLdundefined", + "IcreateNewlexenv", + "IcreateNewlexenvwithname", + "IcreatePoplexenv", + "IcreateReturnundefined", + "IcreateThrowDeletesuperproperty", + "IcreateThrowNotexists", + "IcreateThrowPatternnoncoercible", + "IcreateTryldglobalbyname", + "IcreateWideCopyrestargs", + "IcreateWideLdexternalmodulevar", + "IcreateWideLdlexvar", + "IcreateWideLdlocalmodulevar", + "IcreateWideLdpatchvar", + "IcreateWideNewlexenv", + "IcreateWideNewlexenvwithname", + "IcreateLoadString", + "IcreateReturnVoid", + "Idump", + "IgetBasicBlock", + "IgetConditionCode", + "IgetConstantValueF64", + "IgetConstantValueI64", + "IgetConstantValueU64", + "IgetExportDescriptor", + "IgetId", + "IgetImmediate", + "IgetImmediateCount", + "IgetImportDescriptor", + "IgetInput", + "IgetInputCount", + "IgetLiteralArray", + "IgetMethod", + "IgetModule", + "IgetNext", + "IgetOpcode", + "IgetPrev", + "IgetTargetType", + "IgetType", + "IgetUserCount", + "Iremove", + "IsetImmediate", + "IcreateLoadConstArray", + "IcreateLoadUndefined", + "IgetString", + "IsetString" +] + +funcs_varargs = [ + "IcreateNewobjrange", + "BBsetPredBlocks", + "BBsetSuccBlocks", + "IcreateWideSupercallthisrange", + "IcreateSupercallthisrange", + "IcreateWideNewobjrange" +] + +excluded_funcs += funcs_without_two_abckit_entites +excluded_funcs += funcs_varargs + +implemented_api_map = collect_implemented_api_map(excluded_funcs) +wrong_ctx_tests_erb = File.join(abckit_test, "wrong_ctx_tests.cpp.erb") +implemented_api_map.each_key do |domain| + iteration = 0 + index = 0 + slice_size = 100 + api_funcs_arr = implemented_api_map[domain] + total_domain_api_funcs = api_funcs_arr.length + + puts "#{domain}: #{total_domain_api_funcs}" + + while index < total_domain_api_funcs do + testfile_fullpath = File.join(abckit_test, "wrong_ctx_tests_#{domain}_#{iteration}.cpp") + res = ERB.new(File.read(wrong_ctx_tests_erb), nil, "%").result(binding) + File.write(testfile_fullpath, res) + iteration += 1 + index += slice_size + end +end \ No newline at end of file diff --git a/libabckit/scripts/gen_wrong_mode_tests.rb b/libabckit/scripts/gen_wrong_mode_tests.rb new file mode 100644 index 0000000000000000000000000000000000000000..a9e80c56048b94ea77fda271ad6e7d9cbad9c7cf --- /dev/null +++ b/libabckit/scripts/gen_wrong_mode_tests.rb @@ -0,0 +1,60 @@ +require 'erb' + +abckit_scripts = File.dirname(__FILE__) +abckit_root = File.expand_path("../", abckit_scripts) +abckit_test = File.join(abckit_root, "/tests/wrong_mode_tests/") + +implemented_api_raw = nil +Dir.chdir(abckit_scripts) do + implemented_api_raw = `python get-abckit-status.py --print-implemented`.split(/\n/) +end + +implemented_api_map = {} +# excluded_funcs = [ +# "IcreateLoadString" +# ] + +implemented_api_raw.each do |api_func_raw| + domain, api_func = *api_func_raw.split(/::/) + + # if excluded_funcs.include?(api_func) + # next + # end + # if domain.include? "IsaApiDynamicImpl" + + if api_func.include? "Icreate" and domain.include? "IsaApiDynamicImpl" + if implemented_api_map[domain].nil? + implemented_api_map[domain] = [api_func] + else + implemented_api_map[domain].append(api_func) + end + next + end + + if api_func.include? "Icreate" and domain.include? "IsaApiStaticImpl" + if implemented_api_map[domain].nil? + implemented_api_map[domain] = [api_func] + else + implemented_api_map[domain].append(api_func) + end + end +end + +wrong_mode_tests_erb = File.join(abckit_test, "wrong_mode_tests.cpp.erb") +implemented_api_map.each_key do |domain| + iteration = 0 + index = 0 + slice_size = 100 + api_funcs_arr = implemented_api_map[domain] + total_domain_api_funcs = api_funcs_arr.length + + puts "#{domain}: #{total_domain_api_funcs}" + + while index < total_domain_api_funcs do + testfile_fullpath = File.join(abckit_test, "wrong_mode_tests_#{domain}_#{iteration}.cpp") + res = ERB.new(File.read(wrong_mode_tests_erb), nil, "%").result(binding) + File.write(testfile_fullpath, res) + iteration += 1 + index += slice_size + end +end diff --git a/libabckit/scripts/get-abckit-status.py b/libabckit/scripts/get-abckit-status.py new file mode 100755 index 0000000000000000000000000000000000000000..649e3404996ca04a9cb957f3c93ef7a5e6d230b4 --- /dev/null +++ b/libabckit/scripts/get-abckit-status.py @@ -0,0 +1,217 @@ +#!/usr/bin/env python3 + +import argparse +import os +import re +import sys + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) + +TS = 'TS' +JS = 'JS' +ARKTS_STATIC = 'ArkTSStatic' +NO_ABC = 'NoABC' + +class Test: + def __init__(self, s): + err = f'Wrong test annotation: "{s}"' + + self.kind = '' + self.abc_kind = '' + self.api = '' + self.category = '' + + assert '// Test:' in s, err + s = s.replace('// Test:', '') + for entry in s.split(','): + key, value = entry.strip().split('=') + if key == 'test-kind': + assert value in ['api', 'scenario', 'internal'], err + self.kind = value + elif key == 'abc-kind': + assert value in [ARKTS_STATIC, JS, TS, NO_ABC], err + self.abc_kind = value + elif key == 'api': + self.api = value + elif key == 'category': + assert value in ['positive', 'negative-mode', 'negative-nullptr', 'negative-ctx', 'internal', 'negative'], err + self.category = value + else: + assert False, f'Wrong key: {key}' + + assert self.kind, err + assert self.abc_kind, err + assert self.category, err + if self.kind == 'api': + assert self.api, err + + +class API: + def __init__(self, name, domain, isImplemented): + self.name = name + self.domain = domain + self.isImplemented = isImplemented + self.DynamicPositiveTests = 0 + self.StaticPositiveTests = 0 + self.ArkTSStaticTests = 0 + self.JSTests = 0 + self.TSTests = 0 + self.NoABCTests = 0 + self.PositiveTests = 0 + self.NegativeTests = 0 + self.NegativeNullptrTests = 0 + self.NegativeCtxTests = 0 + self.NegativeModeTests = 0 + self.OtherTests = 0 + + +def collect_api(domain, path): + api = {} + with open(path) as f: + last_func = '' + hit_macro = True + for l in f.readlines(): + if 'extern "C"' in l: + assert hit_macro, f'Function {last_func} doesn\'t have IMPLEMENTED/UNIMPLEMENTED macro' + last_func = re.sub(r'[a-zA-Z0-9_\s\*"]+[ \*]+([a-zA-Z0-9_]+)\(.*$', r'\1', l.rstrip()) + last_func = last_func.replace('DYNAMIC', '') + hit_macro = False + assert 'extern ' not in last_func + if 'ABCKIT_IMPLEMENTED' in l: + assert not hit_macro, f'Function {last_func} doesn\'t have IMPLEMENTED/UNIMPLEMENTED macro' + hit_macro = True + assert f'{domain}::{last_func}' not in api + api[f'{domain}::{last_func}'] = API(last_func, domain, True) + if 'ABCKIT_UNIMPLEMENTED' in l: + assert not hit_macro, f'Function {last_func} doesn\'t have IMPLEMENTED/UNIMPLEMENTED macro' + hit_macro = True + assert f'{domain}::{last_func}' not in api + api[f'{domain}::{last_func}'] = API(last_func, domain, False) + return api + +def collect_tests(test_path, api): + tests = [] + with open(test_path, 'r') as f: + prev_line = '' + for line in f.readlines(): + if not 'TEST_F(' in line: + prev_line = line + continue + if 'DISABLED' in line: + continue + assert '// Test:' in prev_line, f'Test doesn\'t have annotation: {line}' + test = Test(prev_line) + if test.kind == 'api': + assert test.api in api, f'No such API: {test.api}' + tests.append(test) + return tests + +def get_args(): + parser = argparse.ArgumentParser(description="Abckit status script") + parser.add_argument("--print-implemented", action="store_true", default=False, help=f"Print list of implemented API and exit") + return parser.parse_args() + +def main(): + args = get_args() + + abckit_src_dir = os.path.join(SCRIPT_DIR, '..', 'src') + impl_files = { + "GraphApiImpl" : os.path.join(abckit_src_dir, 'ir_impl.cpp'), + "IsaApiStaticImpl" : os.path.join(abckit_src_dir, 'isa_static_impl.cpp'), + "IsaApiDynamicImpl" : os.path.join(abckit_src_dir, 'isa_dynamic_impl.cpp'), + "InspectApiImpl" : os.path.join(abckit_src_dir, 'metadata_inspect_impl.cpp'), + "ModifyApiImpl" : os.path.join(abckit_src_dir, 'metadata_modify_impl.cpp'), + "ApiImpl" : os.path.join(abckit_src_dir, 'abckit_impl.cpp') + } + + impl_total = [] + unimpl_total = [] + api = {} + for domain, file in impl_files.items(): + new_api = collect_api(domain, file) + for new_api_name in new_api: + assert new_api_name not in api + api[new_api_name] = new_api[new_api_name] + + if args.print_implemented: + implemented_api = list(map(lambda a: f"{api[a].domain}::{api[a].name}", filter(lambda a: api[a].isImplemented, api))) + implemented_api.sort() + print('\n'.join(implemented_api)) + return 0 + + tests = [] + tests_dir = os.path.join(SCRIPT_DIR, '..', 'tests') + for dirpath, dirnames, filenames in os.walk(tests_dir): + for name in filenames: + if name.endswith(".cpp"): + tests += collect_tests(os.path.join(dirpath, name), api) + + api_tests = {} + for test in tests: + if test.kind == 'api': + if test.abc_kind == ARKTS_STATIC: + api[test.api].ArkTSStaticTests += 1 + elif test.abc_kind == JS: + api[test.api].JSTests += 1 + elif test.abc_kind == TS: + api[test.api].TSTests += 1 + elif test.abc_kind == NO_ABC: + api[test.api].NoABCTests += 1 + + if test.category == 'positive': + api[test.api].PositiveTests += 1 + if test.abc_kind == TS or test.abc_kind == JS: + api[test.api].DynamicPositiveTests += 1 + if test.abc_kind == ARKTS_STATIC: + api[test.api].StaticPositiveTests += 1 + elif test.category == 'negative': + api[test.api].NegativeTests += 1 + elif test.category == 'negative-nullptr': + api[test.api].NegativeNullptrTests += 1 + elif test.category == 'negative-ctx': + api[test.api].NegativeCtxTests += 1 + elif test.category == 'negative-mode': + api[test.api].NegativeModeTests += 1 + else: + api[test.api].OtherTests += 1 + + csv = ( + 'api,isImplemented,DynamicPositiveTests,StaticPositiveTests,' + 'ArkTSStaticTests,JSTests,TSTests,NoABCTests,positiveTests,' + 'negativeTests,negativeNullptrTests,NegativeCtxTests,otherTests\n' + ) + for name in api: + csv += ( + f'{name},{api[name].isImplemented},{api[name].DynamicPositiveTests},{api[name].StaticPositiveTests},' + f'{api[name].ArkTSStaticTests},{api[name].JSTests},{api[name].TSTests},' + f'{api[name].NoABCTests},{api[name].PositiveTests},{api[name].NegativeTests},' + f'{api[name].NegativeNullptrTests},{api[name].NegativeCtxTests},{api[name].OtherTests}\n' + ) + with open(os.path.join(SCRIPT_DIR, './abckit_status.csv'), 'w') as f: + f.write(csv) + + apiTestCategory = lambda name: len(list(filter(lambda t: t.kind == 'api' and t.category == name, tests))) + apiLang = lambda name: len(list(filter(lambda t: t.kind == 'api' and t.abc_kind == name, tests))) + scenarioLang = lambda name: len(list(filter(lambda t: t.kind == 'scenario' and t.abc_kind == name, tests))) + + print(f'Total API: {len(api)}') + print(f'Implemented/Unimplemented API: {len([name for name in api if api[name].isImplemented])}/{len([name for name in api if not api[name].isImplemented])}') + print() + print(f'Total Tests: {len(tests)}') + print() + print(f'Total API tests: {len(list(filter(lambda t: t.kind == "api", tests)))}') + print(f'Positive/Negative/NullArg/WrongCtx/WrongMode API tests: {apiTestCategory("positive")}/{apiTestCategory("negative")}/{apiTestCategory("negative-nullptr")}/{apiTestCategory("negative-ctx")}/{apiTestCategory("negative-mode")}') + print(f'ArkTSStatic/JS/TS/NoABC API tests: {apiLang(ARKTS_STATIC)}/{apiLang(JS)}/{apiLang(TS)}/{apiLang(NO_ABC)}') + print() + print(f'Total scenario tests: {len(list(filter(lambda t: t.kind == "scenario", tests)))}') + print(f'ArkTSStatic/JS/TS scenario tests: {scenarioLang(ARKTS_STATIC)}/{scenarioLang(JS)}/{scenarioLang(TS)}') + print() + print(f'Internal tests: {len(list(filter(lambda t: t.kind == "internal", tests)))}') + + return 0 + + +if __name__ == '__main__': + sys.exit(main()) + + diff --git a/libabckit/scripts/inst_props_api.rb b/libabckit/scripts/inst_props_api.rb new file mode 100644 index 0000000000000000000000000000000000000000..77d2cc1a3bc5cc6898139874e8aee89a643377cc --- /dev/null +++ b/libabckit/scripts/inst_props_api.rb @@ -0,0 +1,28 @@ +# Copyright (c) 2024 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. +require 'ostruct' + +abckit_scripts = File.dirname(__FILE__) +abckit_root = File.expand_path('../', abckit_scripts) +opcodes_path = File.expand_path('include/isa/isa_dynamic.h', abckit_root) + +Opcodes = [] +File.open(opcodes_path, 'r').read.split() + .select{ |opcode| + opcode.start_with?('abckit_IsaApiDynamicOpcode_') + }.each{ |opcode| + res = OpenStruct.new + res.abckit_opcode = opcode.chop! + res.bc_opcode = opcode.delete_prefix('abckit_IsaApiDynamicOpcode_').split('_').map!{|str| str.downcase }.join('.') + Opcodes.append(res) + } diff --git a/libabckit/scripts/self-check.sh b/libabckit/scripts/self-check.sh new file mode 100755 index 0000000000000000000000000000000000000000..bcc88055b051248fefaaca32b8a7159328f23536 --- /dev/null +++ b/libabckit/scripts/self-check.sh @@ -0,0 +1,159 @@ +#!/bin/bash + +set -x +set -e +set -o pipefail + +OHOS_DIR= +DEBUG=true +SANITIZERS=false +COVERAGE=false + + +function print_usage +{ + set +x + echo "Usage: self-check.sh [options] [mode] --dir= " + echo " " + echo " -- path to OHOS root " + echo "Mode: " + echo " -d, --debug build in debug mode (default) " + echo " -r, --release build in release mode " + echo " -s, --sanitize build with sanitizers " + echo " -c, --coverage collect code coverage " + echo " " + echo "Options: " + echo " -h, --help print help text " + set -x +} + +function parse_cmd_args +{ + for i in "$@"; do + case $i in + -c|--coverage) + COVERAGE=true + shift + ;; + -s|--sanitize) + SANITIZERS=true + shift + ;; + -r|--release) + DEBUG=false + shift + ;; + -d|--debug) + DEBUG=true + shift + ;; + --dir=*) + OHOS_DIR="${i#*=}" + OHOS_DIR="${OHOS_DIR/#\~/$HOME}" + shift + ;; + -h|--help) + print_usage + exit 1 + ;; + *) + echo "Unknown option \"$i\"" + print_usage + exit 1 + ;; + esac + done +} + +function build_OHOS +{ + set -e + rm -rf out/ + + NO_DEVTOOL=1 ./build.sh --product-name rk3568 --gn-flags="--export-compile-commands" --gn-args is_debug="$DEBUG"\ + abckit_sanitizers="$SANITIZERS" enable_notice_collection=false enable_libabckit_coverage=$COVERAGE --build-target=libabckit_packages + set +e +} + +function build_and_run_tests +{ + set -e + ninja -w dupbuild=warn clang_x64/exe.unstripped/clang_x64/tests/unittest/arkcompiler/runtime_core/libabckit/AbcKitTest + + TMP= + LSAN_OPTIONS= + if [ "$SANITIZERS" = "true" ]; then + TMP=$(mktemp -p "$PWD") + # static_core/runtime has known memory leak issues + # check runtime_core/static_core/runtime/locks.cpp:45 + echo "leak:NewMutatorLock" > "$TMP" + # dynamic VM has memory leak issues + echo "leak:CreateJSVM" >> "$TMP" + LSAN_OPTIONS="suppressions=$TMP" + export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.6 + fi + + if [ "$COVERAGE" = "true" ]; then + export LLVM_PROFILE_FILE="abckit%m.profraw" + fi + + LD_LIBRARY_PATH=./clang_x64/lib.unstripped/clang_x64/arkcompiler/runtime_core/:\ +./clang_x64/lib.unstripped/clang_x64/arkcompiler/ets_runtime/:\ +./clang_x64/lib.unstripped/clang_x64/arkcompiler/ets_frontend/:\ +./clang_x64/lib.unstripped/clang_x64/thirdparty/icu/:\ +./clang_x64/lib.unstripped/clang_x64/thirdparty/zlib/ \ +LSAN_OPTIONS="$LSAN_OPTIONS" \ +./clang_x64/exe.unstripped/clang_x64/tests/unittest/arkcompiler/runtime_core/libabckit/AbcKitTest + + if [ "$SANITIZERS" = "false" ]; then + ninja -w dupbuild=warn abckit_stress_test_package + ../../arkcompiler/runtime_core/libabckit/tests/stress/stress.py && ../../arkcompiler/runtime_core/libabckit/tests/stress/StressEts.py \ + && ../../arkcompiler/runtime_core/libabckit/tests/stress/StressHermes.py && ../../arkcompiler/runtime_core/libabckit/tests/stress/StressNodeJS.py + fi + + if [ "$COVERAGE" = "true" ]; then + ../../prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-profdata merge -sparse abckit*.profraw -o abckit.profdata + + ../../prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-cov show \ + --instr-profile=./abckit.profdata \ + --summary-only --output-dir=abckit_coverage \ + ./clang_x64/lib.unstripped/clang_x64/arkcompiler/runtime_core/libabckit.so + + ../../prebuilts/clang/ohos/linux-x86_64/llvm/bin/llvm-cov report \ + --ignore-filename-regex='(.*third_party/.*|.*/runtime_core/static_core/.*|.*/runtime_core/libpandabase/.*|.*/arkcompiler/ets_frontend/|.*/runtime_core/libpandafile/.*|.*/runtime_core/assembler/.*|.*/runtime_core/platforms/.*)' \ + --instr-profile=./abckit.profdata ./clang_x64/lib.unstripped/clang_x64/arkcompiler/runtime_core/libabckit.so | \ + sed 's|\([^ ]\) \([^ ]\)|\1_\2|g' | \ + tr -s ' ' | \ + grep -v '\------------' | \ + grep -v 'Files_which_contain_no_functions:' | \ + sed 's| |,|g' > abckit_coverage.csv + + echo "Summary abckit coverage report file: $(realpath abckit_coverage.csv)" + echo "Verbose abckit coverage report dir: $(realpath abckit_coverage)" + fi + + if [ "$SANITIZERS" = "true" ]; then + rm "$TMP" + fi + + set +e +} + +parse_cmd_args "$@" + +if [ -z "$OHOS_DIR" ]; then + echo "ERROR: Path to OHOS root was not provided" + print_usage + exit 1 +fi + +pushd "$OHOS_DIR" || exit 1 +build_OHOS + +pushd out/rk3568 || exit 1 +build_and_run_tests + +popd || exit 1 +popd || exit 1 + +set +x diff --git a/libabckit/scripts/stress.sh b/libabckit/scripts/stress.sh new file mode 100755 index 0000000000000000000000000000000000000000..7aa2626cb122318b6ee98d831b58481b24e7ee9d --- /dev/null +++ b/libabckit/scripts/stress.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash + +set -e + +if [ -z "$1" ]; then + echo "usage: stress.sh input.abc [output.abc]" + exit 1 +fi + +INPUT="$1" +OUTPUT="${2:-/tmp/tmp.abc}" + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +OUT_DIR="$SCRIPT_DIR/../../../../out/rk3568" +ABCKIT="$OUT_DIR/clang_x64/exe.unstripped/clang_x64/arkcompiler/runtime_core/abckit" +STRESS_PLUGIN="$OUT_DIR/clang_x64/lib.unstripped/clang_x64/arkcompiler/runtime_core/libabckit_stress_plugin.so" + +export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:\ +$OUT_DIR/clang_x64/lib.unstripped/clang_x64/arkcompiler/runtime_core:\ +$OUT_DIR/clang_x64/lib.unstripped/clang_x64/arkcompiler/ets_runtime:\ +$OUT_DIR/clang_x64/lib.unstripped/clang_x64/arkcompiler/ets_frontend:\ +$OUT_DIR/clang_x64/lib.unstripped/clang_x64/thirdparty/icu:\ +$OUT_DIR/clang_x64/lib.unstripped/clang_x64/thirdparty/zlib" + +set -x +"$ABCKIT" --plugin-path "$STRESS_PLUGIN" --input-file "$INPUT" --output-file "$OUTPUT" diff --git a/libabckit/src/abckit_impl.cpp b/libabckit/src/abckit_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d1ce57c35675a244584f5900dbc6ece14dc383cd --- /dev/null +++ b/libabckit/src/abckit_impl.cpp @@ -0,0 +1,277 @@ +/** + * Copyright (c) 2024 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 "libabckit/include/abckit.h" + +#include "libabckit/include/statuses.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/statuses_impl.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/adapter_dynamic/abckit_dynamic.h" +#include "libabckit/src/adapter_static/abckit_static.h" +#include "libabckit/src/mem_manager/mem_manager.h" +#include "libabckit/src/logger.h" + +#include +#include + + +libabckit::logger *libabckit::logger::logger_ = nullptr; +thread_local libabckit::logger::MODE abckit_global_mode {libabckit::logger::MODE::RELEASE_MODE}; +thread_local libabckit::null_buffer libabckit::n_b{}; +thread_local std::ostream libabckit::null_stream {&n_b}; + + +namespace libabckit { + +extern "C" abckit_Status GetLastError() +{ + LIBABCKIT_IMPLEMENTED + return statuses::GetLastError(); +} + +extern "C" abckit_File *OpenAbc(const char *path) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(path, nullptr); + + LIBABCKIT_LOG(DEBUG) << path << '\n'; + + MemManager::Initialize(256_MB); + + abckit_File *ctxI = nullptr; + + ctxI = OpenAbcStatic(path); + if (ctxI != nullptr) { + return ctxI; + } + + LIBABCKIT_LOG(DEBUG) << std::string() + "Load file with path '" + path + "' failed for static mode, trying dynamic mode\n"; + + ctxI = OpenAbcDynamic(path); + if (ctxI != nullptr) { + return ctxI; + } + + LIBABCKIT_LOG(DEBUG) << std::string() + "Load file with path '" + path + "' failed, for static mode\n"; + + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + + return nullptr; +} + +extern "C" void WriteAbc(abckit_File *ctxI, const char *path) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxI, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(path, LIBABCKIT_RETURN_VOID); + + switch (ctxI->mode) { + case Mode::DYNAMIC: + WriteAbcDynamic(ctxI, path); + return; + case Mode::STATIC: + WriteAbcStatic(ctxI, path); + return; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void DestroyInspectContext(abckit_File *ctxI) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctxI); + + switch (ctxI->mode) { + case Mode::DYNAMIC: + DestroyInspectContextDynamic(ctxI); + return; + case Mode::STATIC: + DestroyInspectContextStatic(ctxI); + return; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void TransformModule(abckit_Module *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Module *m, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + TransformModuleDynamic(m, data, cb); + return; + case Mode::STATIC: + LIBABCKIT_UNREACHABLE + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void TransformClass(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(c, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + switch (c->m->ctxI->mode) { + case Mode::DYNAMIC: + TransformClassDynamic(c, data, cb); + return; + case Mode::STATIC: + TransformClassStatic(c, data, cb); + return; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void TransformMethod(abckit_Method *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Method *method, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + switch (m->m->ctxI->mode) { + case Mode::DYNAMIC: + TransformMethodDynamic(m, data, cb); + return; + case Mode::STATIC: + TransformMethodStatic(m, data, cb); + return; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Graph *codeToGraph(abckit_File *ctxI, abckit_Code *code) +{ + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(ctxI, nullptr); + LIBABCKIT_BAD_ARGUMENT(code, nullptr); + + LIBABCKIT_BAD_ARGUMENT(code->method, nullptr); + LIBABCKIT_WRONG_CTX(ctxI, code->method->m->ctxI, nullptr); + + switch (ctxI->mode) { + case Mode::DYNAMIC: + return codeToGraphDynamic(ctxI, code); + case Mode::STATIC: + return codeToGraphStatic(ctxI, code); + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Code *graphToCode(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + + switch (ctxG->ctxI->mode) { + case Mode::DYNAMIC: + return graphToCodeDynamic(ctxG); + case Mode::STATIC: + return graphToCodeStatic(ctxG); + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void DestroyGraphContext(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctxG); + + switch (ctxG->ctxI->mode) { + case Mode::DYNAMIC: + DestroyGraphContextDynamic(ctxG); + return; + case Mode::STATIC: + DestroyGraphContextStatic(ctxG); + return; + default: + LIBABCKIT_UNREACHABLE + } +} + +abckit_Api g_impl = { + // ======================================== + // Common API + // ======================================== + + LIBABCKIT_VERSION, + GetLastError, + + // ======================================== + // Inspection API entrypoints + // ======================================== + + OpenAbc, + WriteAbc, + DestroyInspectContext, + + // ======================================== + // Modification API entrypoints + // ======================================== + + TransformModule, + TransformClass, + TransformMethod, + + // ======================================== + // IR API entrypoints + // ======================================== + + codeToGraph, + graphToCode, + DestroyGraphContext, +}; + +} // namespace libabckit + +extern "C" abckit_Api const *abckit_GetApiImpl(int version) +{ + if (version != LIBABCKIT_VERSION) { + return nullptr; + } + return &libabckit::g_impl; +} diff --git a/libabckit/src/adapter_dynamic/abckit_dynamic.cpp b/libabckit/src/adapter_dynamic/abckit_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..500a6d14cf2359e5dda70fc26bdbdaca230da91c --- /dev/null +++ b/libabckit/src/adapter_dynamic/abckit_dynamic.cpp @@ -0,0 +1,1153 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/adapter_dynamic/abckit_dynamic.h" +#include "include/metadata.h" +#include "libabckit/src/adapter_dynamic/helpers_dynamic.h" + +#include "libabckit/src/macros.h" +#include "libabckit/src/logger.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/metadata_modify_impl.h" + +#include "libpandafile/file.h" +#include "libabckit/src/wrappers/graph_wrapper/graph_wrapper.h" +#include "libabckit/src/wrappers/abcfile_wrapper.h" + +#include "abc2program/abc2program_driver.h" +#include "assembler/annotation.h" +#include "assembler/assembly-program.h" +#include "assembler/assembly-function.h" +#include "assembler/assembly-record.h" +#include "assembler/assembly-emitter.h" + +#include +#include +#include +#include +#include +#include +#include + +using namespace panda; + +namespace { +constexpr const std::string_view TSTYPE_ANNO_RECORD_NAME = "_TestAnnotation"; + +bool IsServiceRecord(std::string name) +{ + return name == TSTYPE_ANNO_RECORD_NAME || + name == "_ESConcurrentModuleRequestsAnnotation" || + name == "L_ESSlotNumberAnnotation" || + name == "_ESSlotNumberAnnotation"; +} + +bool IsAnnotationInterface(const pandasm::Record &rec) +{ + return (rec.metadata->GetAccessFlags() & panda::ACC_ANNOTATION) != 0; +} + +bool IsExternal(const pandasm::Record &rec) +{ + return rec.metadata->IsForeign(); +} + +abckit_TypeId PandaTypeToAbcKitTypeId(const pandasm::Type &type) +{ + switch(type.GetId()) { + case panda_file::Type::TypeId::VOID: + return abckit_TypeId_VOID; + case panda_file::Type::TypeId::U1: + return abckit_TypeId_U1; + case panda_file::Type::TypeId::I8: + return abckit_TypeId_I8; + case panda_file::Type::TypeId::U8: + return abckit_TypeId_U8; + case panda_file::Type::TypeId::I16: + return abckit_TypeId_I16; + case panda_file::Type::TypeId::U16: + return abckit_TypeId_U16; + case panda_file::Type::TypeId::I32: + return abckit_TypeId_I32; + case panda_file::Type::TypeId::U32: + return abckit_TypeId_U32; + case panda_file::Type::TypeId::F32: + return abckit_TypeId_F32; + case panda_file::Type::TypeId::F64: + return abckit_TypeId_F64; + case panda_file::Type::TypeId::I64: + return abckit_TypeId_I64; + case panda_file::Type::TypeId::U64: + return abckit_TypeId_U64; + case panda_file::Type::TypeId::REFERENCE: + if (type.IsArray()) { + return PandaTypeToAbcKitTypeId(type.GetComponentType()); + } + return abckit_TypeId_REFERENCE; + default: + return abckit_TypeId::abckit_TypeId_INVALID; + } +} + +abckit_String *CreateNameString(std::string name, abckit_File *ctxI) +{ + if (ctxI->strings.find(name) != ctxI->strings.end()) { + return ctxI->strings.at(name).get(); + } + + auto s = std::make_unique(); + s->impl = name; + ctxI->strings.insert({name, std::move(s)}); + return ctxI->strings[name].get(); +} + +abckit_Module *TryFindModule(std::string name, abckit_File *ctxI) +{ + auto tryFindLocal = ctxI->localModules.find(name); + if (tryFindLocal != ctxI->localModules.end()) { + return tryFindLocal->second.get(); + } + auto tryFindExternal = ctxI->externalModules.find(name); + if (tryFindExternal != ctxI->externalModules.end()) { + return tryFindExternal->second.get(); + } + return nullptr; +} + +std::string GetModuleRequestName(uint16_t ModuleRequestsOffset, const pandasm::LiteralArray *litArr) +{ + ASSERT(litArr->literals_[ModuleRequestsOffset + 1].IsStringValue()); + std::string name = std::get(litArr->literals_[ModuleRequestsOffset + 1].value_); + if (name.substr(0, 2) == "./") { + std::string newName = name.substr(2); + return newName; + } + return name; +} + +struct ModuleUpdateData { + bool isRegularImportsChange = false; + bool isLocalExportsChange = false; + std::vector *newLiterals; + std::unordered_map *regularImportsIdxMap; + std::unordered_map *localExportsIdxMap; +}; + +struct ModuleIterateData { + abckit_Module *m; + abckit_ModulePayloadDyn *payload; + pandasm::LiteralArray *moduleLitArr; + std::pair isRegularImport; // {isImport, isRegular} + abckit_DynamicExportKind kind; + ModuleUpdateData *updateData; +}; + +bool IterateModuleSections(ModuleIterateData *data, + const std::function &requestIdxSectionModifier, + const std::function(ModuleIterateData *, size_t, size_t)> §ionModifier, + const std::function)> &postAction) +{ + auto idx = requestIdxSectionModifier(data); + + data->isRegularImport = {true, true}; + auto r = sectionModifier(data, idx, 3); + if (!postAction(data, r)) { + return false; + } + idx = r.first; + data->payload->RegularImportsOffset = r.second; + + data->isRegularImport = {true, false}; + r = sectionModifier(data, idx, 2); + if (!postAction(data, r)) { + return false; + } + idx = r.first; + data->payload->NamespaceImportsOffset = r.second; + + data->isRegularImport = {false, false}; + data->kind = abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT; + r = sectionModifier(data, idx, 2); + if (!postAction(data, r)) { + return false; + } + idx = r.first; + data->payload->LocalExportsOffset = r.second; + + data->kind = abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT; + r = sectionModifier(data, idx, 3); + if (!postAction(data, r)) { + return false; + } + idx = r.first; + data->payload->IndirectExportsOffset = r.second; + + data->kind = abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT; + r = sectionModifier(data, idx, 1); + if (!postAction(data, r)) { + return false; + } + idx = r.first; + data->payload->StarExportsOffset = r.second; + + return true; +} + +void DumpModuleArray(const pandasm::LiteralArray *moduleLitArr, std::string name) +{ + std::stringstream ss; + ss << "ModuleLiteralArray " << name << " \n["; + size_t idx = 0; + auto numModuleRequests = std::get(moduleLitArr->literals_[idx++].value_); + auto ModuleRequestsOffset = idx; + ss << "\n numModuleRequests " << numModuleRequests << " | offset " << idx << std::endl; + while(idx < ModuleRequestsOffset + numModuleRequests) { + ss << " [\n"; + ss << " module_request: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " ]\n"; + } + auto numRegularImports = std::get(moduleLitArr->literals_[idx++].value_); + auto RegularImportsOffset = idx; + ss << " numRegularImports " << numRegularImports << " | offset " << idx << std::endl; + while(idx < RegularImportsOffset + numRegularImports*3) { + ss << " [\n"; + ss << " localNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " importNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " moduleRequestIdx: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " ]\n"; + } + auto numNamespaceImports = std::get(moduleLitArr->literals_[idx++].value_); + auto NamespaceImportsOffset = idx; + ss << " numNamespaceImports " << numNamespaceImports << " | offset " << idx << std::endl; + while(idx < NamespaceImportsOffset + numNamespaceImports*2) { + ss << " [\n"; + ss << " localNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " moduleRequestIdx: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " ]\n"; + } + auto numLocalExports = std::get(moduleLitArr->literals_[idx++].value_); + auto LocalExportsOffset = idx; + ss << " numLocalExports " << numLocalExports << " | offset " << idx << std::endl; + while(idx < LocalExportsOffset + numLocalExports*2) { + ss << " [\n"; + ss << " localNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " exportNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " ]\n"; + } + auto numIndirectExports = std::get(moduleLitArr->literals_[idx++].value_); + auto IndirectExportsOffset = idx; + ss << " numIndirectExports " << numIndirectExports << " | offset " << idx << std::endl; + while(idx < IndirectExportsOffset + numIndirectExports*3) { + ss << " [\n"; + ss << " exportNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " importNameOffset: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " moduleRequestIdx: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " ]\n"; + } + auto numStarExports = std::get(moduleLitArr->literals_[idx++].value_); + auto StarExportsOffset = idx; + ss << " numStarExports " << numStarExports << " | offset " << idx << std::endl; + while(idx < StarExportsOffset + numStarExports) { + ss << " [\n"; + ss << " moduleRequestIdx: " << std::get(moduleLitArr->literals_[idx].value_) << std::endl; + idx++; + ss << " ]\n"; + } + ss << "]\n"; + LIBABCKIT_LOG(DEBUG) << ss.str(); +} + +bool FillExportDescriptor(ModuleIterateData *data, uint16_t idx, size_t recordIndexOff, + bool hasServiceImport = false, size_t serviceNamespaceImportIdx = 0) +{ + auto ed = std::make_unique(); + ed->exportingModule = data->m; + if (data->kind == abckit_DynamicExportKind_LOCAL_EXPORT) { + ed->exportedModule = data->m; + } else { + auto moduleRequestIdx = std::get(data->moduleLitArr->literals_[idx].value_); + auto exportedModuleName = GetModuleRequestName(moduleRequestIdx, data->moduleLitArr); + auto tryFindModule = TryFindModule(exportedModuleName, data->m->ctxI); + ed->exportedModule = tryFindModule; + } + ed->kind = abckit_ImportExportDescriptorKind::UNTYPED; + auto payloadDyn = abckit_DynamicExportDescriptorPayload(); + payloadDyn.kind = data->kind; + payloadDyn.hasServiceImport = hasServiceImport; + payloadDyn.serviceNamespaceImportIdx = serviceNamespaceImportIdx; + payloadDyn.moduleRecordIndexOff = recordIndexOff; + auto payload = abckit_ExportDescriptorPayload(); + payload.dyn = payloadDyn; + ed->payload = payload; + data->m->ed.push_back(std::move(ed)); + return true; +} + +std::pair FillImportSection(ModuleIterateData *data, size_t idx, size_t fieldNum) +{ + size_t recordIndexOff = 0; + size_t importRecordIndexOff = 0; + size_t numImports = std::get(data->moduleLitArr->literals_[idx++].value_); + size_t sectionOffset = idx; + bool skipFilling = false; + while(idx < sectionOffset + numImports * fieldNum) { + for (size_t i = 0; i < (fieldNum - 1); i++) { + auto name = std::get(data->moduleLitArr->literals_[idx++].value_); + if ((i == 0) && !(data->isRegularImport.second) && (name.find("=ens") != std::string::npos)) { + auto tmp = data->isRegularImport.second; + data->isRegularImport.second = false; + data->kind = abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT; + if (!FillExportDescriptor(data, idx++, importRecordIndexOff++, true, recordIndexOff)) { + return {0, 0}; + } + data->isRegularImport.second = tmp; + skipFilling = true; + recordIndexOff++; + break; + } + } + if (skipFilling) { + skipFilling = false; + continue; + } + + auto id = std::make_unique(); + auto moduleRequestIdx = std::get(data->moduleLitArr->literals_[idx++].value_); + + id->importingModule = data->m; + auto importedModuleName = GetModuleRequestName(moduleRequestIdx, data->moduleLitArr); + id->importedModule = TryFindModule(importedModuleName, data->m->ctxI); + id->kind = abckit_ImportExportDescriptorKind::UNTYPED; + auto payloadDyn = abckit_DynamicImportDescriptorPayload(); + payloadDyn.isRegularImport = data->isRegularImport.second; + payloadDyn.moduleRecordIndexOff = recordIndexOff++; + auto payload = abckit_ImportDescriptorPayload(); + payload.dyn = payloadDyn; + id->payload = payload; + data->m->id.push_back(std::move(id)); + } + + return {idx, sectionOffset}; +} + +abckit_ExportDescriptor *FindStarExport(ModuleIterateData *data, std::string serviceName) +{ + for (const auto &ed : data->m->ed) { + if (ed->payload.dyn.hasServiceImport) { + auto offset = data->payload->NamespaceImportsOffset + ed->payload.dyn.serviceNamespaceImportIdx * 2; + auto namespaceLocalName = std::get(data->moduleLitArr->literals_[offset].value_); + if (serviceName == namespaceLocalName) { + return ed.get(); + } + } + } + LIBABCKIT_LOG(DEBUG) << "Appropriate StarExport was not found for service namespace import '" << serviceName << "'" << std::endl; + libabckit::statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; +} + +std::pair FillExportSection(ModuleIterateData *data, size_t idx, size_t fieldNum) +{ + size_t recordIndexOff = 0; + size_t numExports = std::get(data->moduleLitArr->literals_[idx++].value_); + size_t sectionOffset = idx; + bool skipFilling = false; + while(idx < sectionOffset + numExports * fieldNum) { + for (size_t i = 0; i < (fieldNum - 1); i++) { + auto name = std::get(data->moduleLitArr->literals_[idx++].value_); + if ((i == 0) && (data->kind == abckit_DynamicExportKind_LOCAL_EXPORT) && (name.find("=ens") != std::string::npos)) { + auto *starExport = FindStarExport(data, name); + starExport->payload.dyn.moduleRecordIndexOff = recordIndexOff++; + skipFilling = true; + break; + } + } + if (skipFilling) { + skipFilling = false; + idx++; + continue; + } + if (!FillExportDescriptor(data, idx++, recordIndexOff++)) { + return {0, 0}; + } + } + + return {idx, sectionOffset}; +} + +size_t FillRequestIdxSection(ModuleIterateData *data) +{ + auto *ctxI = data->m->ctxI; + size_t idx = 0; + auto numModuleRequests = std::get(data->moduleLitArr->literals_[idx++].value_); + data->payload->ModuleRequestsOffset = idx; + auto moduleBasePath = std::filesystem::path("./" + data->m->moduleName->impl).remove_filename(); + while(idx < data->payload->ModuleRequestsOffset + numModuleRequests) { + auto relativePathStr = std::get(data->moduleLitArr->literals_[idx].value_); + auto moduleAbsPath = std::filesystem::weakly_canonical(moduleBasePath / std::filesystem::path(relativePathStr)); + auto moduleName = std::string(std::filesystem::relative(moduleAbsPath, std::filesystem::current_path()).c_str()); + data->moduleLitArr->literals_[idx++].value_ = "./" + moduleName; + data->m->md.push_back(TryFindModule(moduleName, ctxI)); + } + return idx; +} + +std::pair FillLiteralArraySection(ModuleIterateData *data, size_t idx, size_t fieldNum) +{ + if (data->isRegularImport.first) { + return FillImportSection(data, idx, fieldNum); + } + return FillExportSection(data, idx, fieldNum); +} + +std::string GetRecordFieldValue(const pandasm::Record *rec, const std::string &fieldName) +{ + for (const auto &field : rec->field_list) { + if (field.name == fieldName) { + return field.metadata->GetValue()->GetAsScalar()->GetValue(); + } + } + LIBABCKIT_LOG(DEBUG) << "'" << fieldName << "' field was not found for record " << rec->name << std::endl; + LIBABCKIT_UNREACHABLE +} + +pandasm::LiteralArray *GetLiteralArray(const pandasm::Program *prog, const std::string &arrName) +{ + auto it = prog->literalarray_table.find(arrName); + if (it != prog->literalarray_table.end()) { + return const_cast(&it->second); + } + LIBABCKIT_LOG(DEBUG) << "'" << arrName << "' array was not found in program" << std::endl; + LIBABCKIT_UNREACHABLE +} + +std::unique_ptr CreateModule(pandasm::Program *prog, const pandasm::Record *record, abckit_File *ctxI) { + auto m = std::make_unique(); + m->ctxI = ctxI; + m->moduleName = CreateNameString(record->name, ctxI); + LIBABCKIT_LOG(DEBUG) << m->moduleName->impl << std::endl; + + auto modulePayloadDyn = abckit_ModulePayloadDyn(); + modulePayloadDyn.record = reinterpret_cast(record); + + pandasm::LiteralArray *moduleLitArr = GetLiteralArray(prog, GetRecordFieldValue(record, "moduleRecordIdx")); + LIBABCKIT_LOG_DUMP(DumpModuleArray(moduleLitArr, m->moduleName->impl), DEBUG); + modulePayloadDyn.moduleLiteralArray = reinterpret_cast(moduleLitArr); + + modulePayloadDyn.scopeNamesLiteralArray = reinterpret_cast(GetLiteralArray(prog, GetRecordFieldValue(record, "scopeNames"))); + + ModuleIterateData iterData; + iterData.m = m.get(); + iterData.payload = &modulePayloadDyn; + iterData.moduleLitArr = moduleLitArr; + + if (!IterateModuleSections(&iterData, FillRequestIdxSection, FillLiteralArraySection, + [](ModuleIterateData *data, std::pair res) { return res.first != 0; })) { + return nullptr; + } + + modulePayloadDyn.absPaths = true; + auto modulePayload = abckit_ModulePayload(); + modulePayload.dyn = modulePayloadDyn; + m->impl = modulePayload; + return m; +} + +std::string GetClassPrefix(const std::string &funcName) +{ + for (auto &sub: {"<#", ">#", "=#"}) { + size_t pos = funcName.find(sub); + if (pos != std::string::npos) { + return funcName.substr(0, pos); + } + } + LIBABCKIT_UNREACHABLE +} + +void CreateClass(const std::string &functionName, panda::pandasm::Function &function, + abckit_File *ctxI, std::unordered_map &classPrefixToClass) +{ + std::string classPrefix = GetClassPrefix(functionName); + std::string moduleName = pandasm::GetOwnerName(functionName); + assert(ctxI->localModules.count(moduleName) != 0); + auto &m = ctxI->localModules[moduleName]; + auto c = std::make_unique(); + c->m = m.get(); + abckit_ClassPayload classPayload; + classPayload.fn = reinterpret_cast(&function); + c->impl = classPayload; + m->ct.emplace(functionName, std::move(c)); + assert(classPrefixToClass.count(classPrefix) == 0); + classPrefixToClass[classPrefix] = m->ct[functionName].get(); + LIBABCKIT_LOG(DEBUG) << "Module: " << moduleName << ", class prefix: " << classPrefix << ", constructor: " << functionName << '\n'; +} + +void CreateAnnotationInterface(abckit_File *ctxI, const std::string &recName, pandasm::Record &rec, + abckit_Module *module /* TODO: Remove after support of module in annotation interface record */) +{ + auto ai = std::make_unique(); + ai->impl = reinterpret_cast(&rec); + ai->m = module; // TODO: Remove after support of module in annotation interface record + + auto &fields = rec.field_list; + for (auto &field : fields) { + auto aiField = std::make_unique(); + + aiField->ai = ai.get(); + aiField->name = CreateNameString(field.name, ctxI); + + auto type = std::make_unique(); + + type->id = PandaTypeToAbcKitTypeId(field.type); + type->rank = field.type.GetRank(); + type->klass = nullptr; + aiField->type = type.get(); + ctxI->types.emplace_back(std::move(type)); + + if (field.metadata->GetValue().has_value()) { + auto abcval = std::make_unique(); + auto value = field.metadata->GetValue().value(); + auto newValue = new pandasm::ScalarValue (value); + abcval->impl = reinterpret_cast(newValue); + aiField->value = abcval.get(); + ctxI->values.emplace_back(std::move(abcval)); + } + + ai->fields.emplace_back(std::move(aiField)); + } + + module->at.emplace(recName, std::move(ai)); +} + +bool HasParentClass(const std::string &funcName) +{ + for (auto &sub: {"<#", ">#", "=#"}) { + if (funcName.find(sub) != std::string::npos) { + return true; + } + } + return false; +} + +void CreateMethod(const std::string &functionName, panda::pandasm::Function &function, + abckit_File *ctxI, std::unordered_map &classPrefixToClass) +{ + std::string moduleName = pandasm::GetOwnerName(functionName); + assert(ctxI->localModules.count(moduleName) != 0); + auto &m = ctxI->localModules[moduleName]; + + auto method = std::make_unique(); + method->m = m.get(); + method->impl = reinterpret_cast(&function); + + for (auto &anno_impl: function.metadata->GetAnnotations()) { + auto anno = std::make_unique(); + anno->name = anno_impl.GetName(); + + for (auto &anno_elem_impl: anno_impl.GetElements()) { + auto anno_elem = std::make_unique(); + anno_elem->ann = anno.get(); + anno_elem->name = anno_elem_impl.GetName(); + auto value = std::make_unique(); + value->impl = reinterpret_cast(anno_elem_impl.GetValue()); + anno_elem->value = std::move(value); + + anno->elements.emplace_back(std::move(anno_elem)); + } + anno->owner = method.get(); + method->annotations.emplace_back(std::move(anno)); + } + + if (HasParentClass(functionName)) { + auto classPrefix = GetClassPrefix(functionName); + assert(classPrefixToClass.count(classPrefix) != 0); + auto *c = classPrefixToClass[classPrefix]; + method->klass = c; + if (libabckit::IsCtor(functionName)) { + for (auto &anno : method->annotations) { + anno->owner = c; + c->annotations.emplace_back(std::move(anno)); + } + } + c->methods.emplace_back(std::move(method)); + } else { + m->methods.emplace_back(std::move(method)); + } +} + +void DumpHierarchy(abckit_File *ctxI) { + for (auto &[mName, m] : ctxI->localModules) { + LIBABCKIT_LOG(DEBUG) << mName << std::endl; + for (auto &[cName, c] : m->ct) { + LIBABCKIT_LOG(DEBUG) << " " << cName << std::endl; + for (auto &f : c->methods) { + LIBABCKIT_LOG(DEBUG) << " " << reinterpret_cast(f->impl)->name << std::endl; + } + } + for (auto &f : m->methods) { + LIBABCKIT_LOG(DEBUG) << " " << reinterpret_cast(f->impl)->name << std::endl; + } + } +} + +abckit_Module *ResolveUnfoundModule(abckit_Module *m, abckit_File *ctxI, size_t offset) +{ + auto literalArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + auto requestIdx = std::get(literalArr->literals_[offset].value_); + auto moduleName = std::get(literalArr->literals_[requestIdx + 1].value_); + if (moduleName.substr(0, 2) == "./") { + moduleName = moduleName.substr(2); + } + auto foundModule = TryFindModule(moduleName, ctxI); + if (foundModule == nullptr) { + auto md = std::make_unique(); + md->isExternal = true; + md->ctxI = ctxI; + md->moduleName = CreateNameString(moduleName, ctxI); + ctxI->externalModules.emplace(moduleName, std::move(md)); + foundModule = ctxI->externalModules[moduleName].get(); + } + if (m->md.at(requestIdx) == nullptr) { + m->md.at(requestIdx) = foundModule; + } + ASSERT(m->md.at(requestIdx) == foundModule); + return foundModule; +} + +void ResolveUnfoundModules(abckit_File *ctxI) +{ + for (auto &[name, m] : ctxI->localModules) { + if (std::find(m->md.begin(), m->md.end(), nullptr) == m->md.end()) { + continue; + } + for (auto &id : m->id) { + if (id->importedModule == nullptr) { + auto offset = id->payload.dyn.moduleRecordIndexOff; + auto absOffset = id->payload.dyn.isRegularImport ? m->impl.dyn.RegularImportsOffset + offset * 3 + 2 : + m->impl.dyn.NamespaceImportsOffset + offset * 2 + 1; + auto importedModule = ResolveUnfoundModule(m.get(), ctxI, absOffset); + id->importedModule = importedModule; + } + } + for (auto &ed : m->ed) { + if (ed->exportedModule == nullptr) { + auto offset = ed->payload.dyn.moduleRecordIndexOff; + auto absOffset = 0; + switch (ed->payload.dyn.kind) { + case abckit_DynamicExportKind_INDIRECT_EXPORT: { + absOffset = m->impl.dyn.IndirectExportsOffset + offset * 3 + 2; + break; + } + case abckit_DynamicExportKind_STAR_EXPORT: { + if (ed->payload.dyn.hasServiceImport) { + absOffset = m->impl.dyn.NamespaceImportsOffset + ed->payload.dyn.serviceNamespaceImportIdx * 2 + 1; + } else { + absOffset = m->impl.dyn.StarExportsOffset + offset; + } + break; + } + default: + UNREACHABLE(); + } + auto exportedModule = ResolveUnfoundModule(m.get(), ctxI, absOffset); + ed->exportedModule = exportedModule; + } + } + } +} + +void CreateWrappers(pandasm::Program *prog, abckit_File *ctxI) +{ + ctxI->program = reinterpret_cast(prog); + + // Collect modules + for (const auto &[recName, rec] : prog->record_table) { + LIBABCKIT_LOG(DEBUG) << "RECORD: " << recName << ' ' << rec.name << '\n'; + if (IsServiceRecord(recName) || IsAnnotationInterface(rec) || IsExternal(rec)) { + continue; + } + auto m = CreateModule(prog, &rec, ctxI); + ctxI->localModules.insert({rec.name, std::move(m)}); + } + + ResolveUnfoundModules(ctxI); + + // Collect annotation interfaces + for (auto &[recName, rec] : prog->record_table) { + if (!IsAnnotationInterface(rec)) { + continue; + } + LIBABCKIT_LOG(DEBUG) << "ANNOTATION: " << recName << ' ' << rec.name << '\n'; + CreateAnnotationInterface(ctxI, recName, rec, ctxI->localModules.begin()->second.get()); + } + + // Collect classes + std::unordered_map classPrefixToClass; + for (auto &[functionName, function] : prog->function_table) { + if (!libabckit::IsCtor(functionName)) { + continue; + } + CreateClass(functionName, function, ctxI, classPrefixToClass); + } + + // Collect methods + for (auto &[functionName, function] : prog->function_table) { + if (!libabckit::IsFunction(functionName)) { + continue; + } + CreateMethod(functionName, function, ctxI, classPrefixToClass); + } + + LIBABCKIT_LOG_DUMP(DumpHierarchy(ctxI), DEBUG); + + // Strings + for (auto &sImpl : prog->strings) { + auto s = std::make_unique(); + s->impl = sImpl; + ctxI->strings.insert({sImpl, std::move(s)}); + } +} +} + +namespace libabckit { + +typedef struct abckit_Graph abckit_Graph; + +typedef struct CtxIInternal { + panda::abc2program::Abc2ProgramDriver *driver = nullptr; +} CtxIInternal; + +abckit_File *OpenAbcDynamic(const char *path) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << path << '\n'; + auto *abc2program = new panda::abc2program::Abc2ProgramDriver(); + if (!abc2program->Compile(path)) { + LIBABCKIT_LOG(DEBUG) << "Failed to open " << path << "\n"; + delete abc2program; + return nullptr; + } + pandasm::Program &prog = const_cast(abc2program->GetProgram()); + auto ctxI = new abckit_File(); + ctxI->mode = Mode::DYNAMIC; + CreateWrappers(&prog, ctxI); + + auto pf = panda_file::File::Open(path); + if (pf == nullptr) { + LIBABCKIT_LOG(DEBUG) << "Failed to panda_file::File::Open\n"; + delete abc2program; + delete ctxI; + return nullptr; + } + + auto panda_file_version = pf->GetHeader()->version; + uint8_t *abckit_version = *reinterpret_cast(panda_file_version.data()); + + ctxI->version = new uint8_t[ABCKIT_VERSION_SIZE]; + std::copy(abckit_version, abckit_version + sizeof(uint8_t) * ABCKIT_VERSION_SIZE, ctxI->version); + + ctxI->internal = new CtxIInternal { abc2program }; + return ctxI; +} + +bool UpdateInsImms(pandasm::Program *program, ModuleUpdateData *updateData, const std::string &mainRecordName) +{ + for (auto &[name, func] : program->function_table) { + if (pandasm::GetOwnerName(name) != mainRecordName) { + continue; + } + for (size_t i = 0; i < func.ins.size(); i++) { + if (updateData->isRegularImportsChange) { + if (func.ins[i].opcode == pandasm::Opcode::LDEXTERNALMODULEVAR || + func.ins[i].opcode == pandasm::Opcode::WIDE_LDEXTERNALMODULEVAR) { + auto imm = static_cast(std::get(func.ins[i].imms[0])); + auto foundIdx = updateData->regularImportsIdxMap->find(imm); + if (foundIdx == updateData->regularImportsIdxMap->end()) { + LIBABCKIT_LOG(DEBUG) << "There is an instruction '" << func.ins[i].ToString() << "' with an unknown regular import index '" << std::hex << imm << "'\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return false; + } + func.ins[i].imms[0] = (long) foundIdx->second; + } + } + + if (updateData->isLocalExportsChange) { + auto op = func.ins[i].opcode; + if (op == pandasm::Opcode::LDLOCALMODULEVAR || op == pandasm::Opcode::WIDE_LDLOCALMODULEVAR || + op == pandasm::Opcode::STMODULEVAR || op == pandasm::Opcode::WIDE_STMODULEVAR) { + auto imm = static_cast(std::get(func.ins[i].imms[0])); + auto foundIdx = updateData->localExportsIdxMap->find(imm); + if (foundIdx == updateData->localExportsIdxMap->end()) { + LIBABCKIT_LOG(DEBUG) << "There is an instruction '" << func.ins[i].ToString() << "' with an unknown local export index '" << std::hex << imm << "'\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return false; + } + func.ins[i].imms[0] = (long) foundIdx->second; + } + } + } + } + return true; +} + +bool UpdateLitArrSectionPostAction(ModuleIterateData *data, std::pair res) +{ + bool *isChangeField {nullptr}; + size_t *offset {nullptr}; + if (data->isRegularImport.first) { + if (data->isRegularImport.second) { + ASSERT(data->payload->RegularImportsOffset == res.second); + isChangeField = &(data->updateData->isRegularImportsChange); + offset = &(data->payload->RegularImportsOffset); + } else { + offset = &(data->payload->NamespaceImportsOffset); + } + } else { + switch (data->kind) { + case abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT: { + isChangeField = &(data->updateData->isLocalExportsChange); + offset = &(data->payload->LocalExportsOffset); + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT: { + offset = &(data->payload->IndirectExportsOffset); + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT: { + offset = &(data->payload->StarExportsOffset); + break; + } + } + } + + auto prevNum = std::get(data->moduleLitArr->literals_[*offset - 1].value_); + auto newNum = std::get((*(data->updateData->newLiterals))[res.second - 1].value_); + if (prevNum != newNum && (isChangeField != nullptr)) { + *isChangeField = true; + } + return true; +} + +size_t IterateRequestIdxSectionBeforeUpdate(ModuleIterateData *data) +{ + auto *newLiterals = data->updateData->newLiterals; + size_t idx = 0; + while (idx < (data->payload->RegularImportsOffset - 1)) { + newLiterals->push_back(std::move(data->moduleLitArr->literals_[idx++])); + } + return idx; +} + +std::pair UpdateLitArrSection(ModuleIterateData *data, size_t idx, size_t fieldNum) +{ + auto *newLiterals = data->updateData->newLiterals; + auto *idxMap = data->isRegularImport.first ? data->updateData->regularImportsIdxMap : data->updateData->localExportsIdxMap; + + auto num = std::get(data->moduleLitArr->literals_[idx].value_); + newLiterals->push_back(std::move(data->moduleLitArr->literals_[idx++])); + auto newOffset = newLiterals->size(); + auto prevOffset = idx; + uint32_t oldIdx = 0; + uint32_t actualNumber = 0; + while(idx < prevOffset + num * fieldNum) { + if (data->moduleLitArr->literals_[idx].tag_ == panda_file::LiteralTag::NULLVALUE) { + for (size_t i = 0; i < fieldNum; i++) { + idx++; + } + oldIdx++; + continue; + } + if (idxMap != nullptr) { + idxMap->emplace(oldIdx, actualNumber); + } + actualNumber++; + oldIdx++; + for (size_t i = 0; i < fieldNum; i++) { + newLiterals->push_back(std::move(data->moduleLitArr->literals_[idx++])); + } + + } + if (actualNumber != num) { + (*newLiterals)[newOffset - 1].value_ = actualNumber; + } + return {idx, newOffset}; +} + +bool UpdateModuleLiteralArray(abckit_File *ctxI, const std::string &recName) +{ + auto program = reinterpret_cast(ctxI->program); + auto module = ctxI->localModules.find(recName); + if (module == ctxI->localModules.end()) { + LIBABCKIT_LOG(DEBUG) << "Can not find module with name '" << recName << "'\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return false; + } + auto moduleLitArr = reinterpret_cast(module->second->impl.dyn.moduleLiteralArray); + if (module->second->impl.dyn.absPaths) { + size_t idx = 1; + auto moduleBasePath = std::filesystem::path("./" + recName).remove_filename(); + while (idx < (module->second->impl.dyn.RegularImportsOffset - 1)) { + auto moduleAbsPath = std::get(moduleLitArr->literals_[idx].value_); + auto relativePath = std::filesystem::relative(std::filesystem::path(moduleAbsPath), moduleBasePath); + moduleLitArr->literals_[idx++].value_ = "./" + std::string(relativePath.c_str()); + } + module->second->impl.dyn.absPaths = false; + } + + bool modified = false; + for (const auto &lit : moduleLitArr->literals_) { + if (lit.tag_ == panda_file::LiteralTag::NULLVALUE) { + modified = true; + break; + } + } + if (!modified) { + return true; + } + + std::vector newLiterals; + std::unordered_map regularImportsIdxMap; + std::unordered_map localExportsIdxMap; + + ModuleUpdateData updateData; + updateData.newLiterals = &newLiterals; + updateData.regularImportsIdxMap = ®ularImportsIdxMap; + updateData.localExportsIdxMap = &localExportsIdxMap; + + ModuleIterateData iterData; + iterData.m = module->second.get(); + iterData.payload = &(module->second->impl.dyn); + iterData.moduleLitArr = moduleLitArr; + iterData.updateData = &updateData; + + if (!IterateModuleSections(&iterData, IterateRequestIdxSectionBeforeUpdate, UpdateLitArrSection, UpdateLitArrSectionPostAction)) { + return false; + } + + if (updateData.isRegularImportsChange || updateData.isLocalExportsChange) { + if (!UpdateInsImms(program, &updateData, recName)) { + return false; + } + } + + moduleLitArr->literals_ = std::move(newLiterals); + + LIBABCKIT_LOG_DUMP(DumpModuleArray(moduleLitArr, iterData.m->moduleName->impl), DEBUG); + return true; +} + +const panda_file::File *EmitDynamicProgram(abckit_File *ctxI, pandasm::Program *program, pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp, bool getFile, const char *path = nullptr) +{ + for (auto &[recName, rec] : program->record_table) { + if (IsServiceRecord(recName) || IsAnnotationInterface(rec) || IsExternal(rec)) { + continue; + } + if (!UpdateModuleLiteralArray(ctxI, recName)) { + return nullptr; + } + } + + const panda_file::File *pf = [&](){ + const panda_file::File *res {nullptr}; + if (!getFile) { + std::map *statp = nullptr; + if (!pandasm::AsmEmitter::Emit(path, *program, statp, mapsp, false)) { + LIBABCKIT_LOG(DEBUG) << "LIBABCKIT WriteAbcDynamic FAILURE\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + } + return res; + } + return pandasm::AsmEmitter::Emit(*program, mapsp, true).release(); + }(); + if (getFile && pf == nullptr) { + LIBABCKIT_LOG(DEBUG) << "LIBABCKIT WriteAbcDynamic FAILURE\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + return pf; +} + +void WriteAbcDynamic(abckit_File *ctxI, const char *path) +{ + auto program = reinterpret_cast(ctxI->program); + + pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = nullptr; + + EmitDynamicProgram(ctxI, program, mapsp, false, path); + if (statuses::GetLastError() != abckit_Status::abckit_Status_NO_ERROR) { + return; + } + + DestroyInspectContextDynamic(ctxI); + LIBABCKIT_LOG(DEBUG) << "LIBABCKIT WriteAbcDynamic SUCCESS\n"; +} + +void TransformClassDynamic(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data)) +{ + LIBABCKIT_LOG_FUNC + + auto ctxM = std::make_unique(); + ctxM->ctxI = c->m->ctxI; + + LIBABCKIT_LOG(DEBUG) << "before TransformClass: " << reinterpret_cast(c->impl.fn)->name << '\n'; + + cb(ctxM.get(), c, data); +} + +void TransformMethodDynamic(abckit_Method *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + + auto ctxM = std::make_unique(); + ctxM->ctxI = m->m->ctxI; + + LIBABCKIT_LOG(DEBUG) << "before TransformMethod: " << reinterpret_cast(m->impl)->name << '\n'; + + cb(ctxM.get(), m, data); +} + +void TransformModuleDynamic(abckit_Module *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Module *module, void *data)) +{ + LIBABCKIT_LOG_FUNC + + auto ctxM = std::make_unique(); + ctxM->ctxI = m->ctxI; + + LIBABCKIT_LOG(DEBUG) << "before TransformModule: " << m->moduleName << '\n'; + + cb(ctxM.get(), m, data); +} + +abckit_Graph *codeToGraphDynamic(abckit_File *ctxI, const abckit_Code *code) +{ + LIBABCKIT_LOG_FUNC + auto *fw = code->method; + auto *func = reinterpret_cast(fw->impl); + LIBABCKIT_LOG(DEBUG) << func->name << '\n'; + LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG); + + auto program = reinterpret_cast(ctxI->program); + + // Add strings to program + for (auto &[sImpl, s] : ctxI->strings) { + program->strings.insert(s->impl); + } + + auto *maps = new pandasm::AsmEmitter::PandaFileToPandaAsmMaps(); // FIXME + auto pf = EmitDynamicProgram(ctxI, program, maps, true); + if (pf == nullptr) { + return nullptr; + } + + uint32_t methodOffset = 0; + for (auto &[id, s] : maps->methods) { + if (s == func->name) { + methodOffset = id; + } + } + if (methodOffset == 0) { + LIBABCKIT_LOG(DEBUG) << "methodOffset == 0\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + auto *irInterface = + new abckit_IrInterface(maps->methods, maps->fields, maps->classes, maps->strings, maps->literalarrays); + + auto *wpf = new FileWrapper(reinterpret_cast(pf)); + auto [ctxG, error] = GraphWrapper::BuildGraphDynamic(wpf, irInterface, ctxI, methodOffset); + if (error != abckit_Status::abckit_Status_NO_ERROR) { + statuses::SetLastError(error); + return nullptr; + } + + ASSERT(ctxG->ctxI == ctxI); + ctxG->method = code->method; + + LIBABCKIT_LOG_DUMP(reinterpret_cast(code->method->impl)->DebugDump(), DEBUG); + + delete code; // not needed anymore, code wath translated to graph + delete maps; // not needed anymore, maps were copied to abckit_IrInterface + + return ctxG; +} + +abckit_Code *graphToCodeDynamic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + + auto func = reinterpret_cast(ctxG->method->impl); + LIBABCKIT_LOG(DEBUG) << "============================================ BEFORE CODEGEN: " << func->name << '\n'; + LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG); + + auto res = GraphWrapper::BuildCodeDynamic(ctxG, func->name); + auto error = std::get<1>(res); + if (error != abckit_Status::abckit_Status_NO_ERROR) { + statuses::SetLastError(error); + return nullptr; + } + auto code = std::get<0>(res); + + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "============================================ AFTER CODEGEN: " << func->name << '\n'; + LIBABCKIT_LOG_DUMP((reinterpret_cast(code->newCode))->DebugDump(), DEBUG); + + GraphWrapper::DestroyGraphDynamic(ctxG); + + return code; +} + +void DestroyGraphContextDynamic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + GraphWrapper::DestroyGraphDynamic(ctxG); +} + +void DestroyInspectContextDynamic(abckit_File *ctxI) +{ + LIBABCKIT_LOG_FUNC; + + for(auto& lit: ctxI->litvals) { + delete reinterpret_cast(lit->val); + } + + for(auto& val: ctxI->values) { + delete reinterpret_cast(val->impl); + } + + auto *CtxIInternal = reinterpret_cast(ctxI->internal); + delete CtxIInternal->driver; + delete CtxIInternal; + delete [] ctxI->version; + delete ctxI; +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_dynamic/abckit_dynamic.h b/libabckit/src/adapter_dynamic/abckit_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..2be6bf1788389c4795360b76cd7132e8e19caeb5 --- /dev/null +++ b/libabckit/src/adapter_dynamic/abckit_dynamic.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_DYNAMIC_ABCKIT_DYNAMIC_H +#define LIBABCKIT_SRC_ADAPTER_DYNAMIC_ABCKIT_DYNAMIC_H + +#include "libabckit/include/ir_core.h" +#include "libabckit/include/metadata.h" + +namespace libabckit { + +abckit_File *OpenAbcDynamic(const char *path); +void WriteAbcDynamic(abckit_File *ctx, const char *path); +void TransformMethodDynamic(abckit_Method *ctx, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Method *method, void *data)); +void TransformModuleDynamic(abckit_Module *ctx, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Module *module, void *data)); +void TransformClassDynamic(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data)); +abckit_Graph *codeToGraphDynamic(abckit_File *ctxI, const abckit_Code *code); +abckit_Code *graphToCodeDynamic(abckit_Graph *ctxG); +void DestroyGraphContextDynamic(abckit_Graph *ctxG); +void DestroyInspectContextDynamic(abckit_File *ctxI); + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_ADAPTER_DYNAMIC_ABCKIT_DYNAMIC_H diff --git a/libabckit/src/adapter_dynamic/helpers_dynamic.cpp b/libabckit/src/adapter_dynamic/helpers_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53bf7bf3be71f819698bda1bde67280224118e88 --- /dev/null +++ b/libabckit/src/adapter_dynamic/helpers_dynamic.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/adapter_dynamic/helpers_dynamic.h" +#include "assembler/assembly-program.h" + +using namespace panda; + +namespace libabckit { + +bool IsMain(const std::string &funcName) +{ + size_t dotPos = funcName.rfind("."); + assert(dotPos != std::string::npos); + if (funcName.substr(dotPos + 1) == "func_main_0") { + return true; + } + return false; +} + +bool IsFunction(const std::string &funcName) +{ + if (IsMain(funcName)) { + return true; + } + for (auto &sub: {"<#", ">#", "=#", "*#"}) { + if (funcName.find(sub) != std::string::npos) { + return true; + } + } + return false; +} + +bool IsCtor(const std::string &funcName) +{ + if (funcName.find("=#") != std::string::npos) { + return true; + } + return false; +} + +bool IsStatic(const std::string &funcName) +{ + if (IsMain(funcName)) { + return true; + } + if (funcName.find("<#") != std::string::npos) { + return true; + } + if (funcName.find("*#") != std::string::npos) { + return true; + } + return false; +} + +bool IsAnonymous(const std::string &funcName) +{ + if (IsMain(funcName)) { + return false; + } + size_t pos = funcName.rfind('#'); + assert(pos != std::string::npos); + std::string name = funcName.substr(pos + 1); + if (name.empty() || name.find('^') == 0) { + return true; + } + return false; +} + +std::string GetClassNameFromCtor(const std::string &ctorName, const abckit_LiteralArray *scopeNames) +{ + assert(IsCtor(ctorName)); + auto *litArr = reinterpret_cast(scopeNames); + auto className = ctorName.substr(ctorName.find("~") + 1); + className = className.substr(0, className.find("=#")); + if (className[0] != '@') { + return className; + } + size_t scopeIdx = stoi(className.substr(1)); + assert(litArr->literals_.size() % 2 == 0); + assert(scopeIdx < litArr->literals_.size()); + auto &lit = litArr->literals_[scopeIdx * 2 + 1]; + assert(lit.tag_ == panda_file::LiteralTag::STRING); + return std::get(lit.value_); +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_dynamic/helpers_dynamic.h b/libabckit/src/adapter_dynamic/helpers_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..b28b1ce6e205a6da62ed9a9a6d1abb25b70c2280 --- /dev/null +++ b/libabckit/src/adapter_dynamic/helpers_dynamic.h @@ -0,0 +1,35 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_DYNAMIC_HELPERS_DYNAMIC_H +#define LIBABCKIT_SRC_ADAPTER_DYNAMIC_HELPERS_DYNAMIC_H + +#include + +struct abckit_LiteralArray; + +namespace libabckit { + +bool IsMain(const std::string &funcName); +bool IsFunction(const std::string &funcName); +bool IsCtor(const std::string &funcName); +bool IsStatic(const std::string &funcName); +bool IsAnonymous(const std::string &funcName); + +std::string GetClassNameFromCtor(const std::string &ctorName, const abckit_LiteralArray *scopeNames); + +} + +#endif diff --git a/libabckit/src/adapter_dynamic/metadata_inspect_dynamic.cpp b/libabckit/src/adapter_dynamic/metadata_inspect_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..427feecc0f5a4a9c00a48a934a8c9181f2f2d768 --- /dev/null +++ b/libabckit/src/adapter_dynamic/metadata_inspect_dynamic.cpp @@ -0,0 +1,680 @@ +/** + * Copyright (c) 2024 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 "include/statuses.h" +#include "libabckit/include/metadata.h" +#include "libabckit/src/adapter_dynamic/metadata_inspect_dynamic.h" +#include "libabckit/src/adapter_dynamic/helpers_dynamic.h" +#include "libabckit/include/metadata.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/statuses_impl.h" + +#include "assembler/annotation.h" +#include "assembler/assembly-literals.h" +#include "assembler/assembly-program.h" +#include +#include +#include +#include + +namespace libabckit { + +using namespace panda; + +// ======================================== +// Module +// ======================================== + +void ModuleEnumerateClassesDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_Class *klass, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &[className, klass] : m->ct) { + if (!cb(klass.get(), data)) { + return; + } + } +} + +void ModuleEnumerateTopLevelMethodsDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &method : m->methods) { + if (!cb(method.get(), data)) { + return; + } + } +} + +void ModuleEnumerateAnnotationInterfacesDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_AnnotationInterface *ai, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &[atName, at] : m->at) { + if (!cb(at.get(), data)) { + return; + } + } +} + +void ModuleEnumerateAnonymousFunctionsDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + for (auto &method : m->methods) { + if (!MethodIsAnonymousDynamic(method.get())) { + continue; + } + if (!cb(method.get(), data)) { + return; + } + } +} + +// ======================================== +// Class +// ======================================== + +abckit_String *ClassGetNameDynamic(abckit_Class *klass) +{ + LIBABCKIT_LOG_FUNC + + auto *func = reinterpret_cast(klass->impl.fn); + + auto *scopesLitArr = klass->m->impl.dyn.scopeNamesLiteralArray; + auto name = GetClassNameFromCtor(func->name, scopesLitArr); + + auto &strings = klass->m->ctxI->strings; + if (strings.find(name) != strings.end()) { + return strings.at(name).get(); + } + + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +void ClassEnumerateMethodsDynamic(abckit_Class *klass, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &method : klass->methods) { + if (!cb(method.get(), data)) { + return; + } + } +} + +void ClassEnumerateAnnotationsDynamic(abckit_Class *klass, void *data, bool (*cb)(abckit_Annotation *anno, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &annotation : klass->annotations) { + if (!cb(annotation.get(), data)) { + return; + } + } +} + +// ======================================== +// Method +// ======================================== + +abckit_String *MethodGetNameDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *function = reinterpret_cast(method->impl); + auto name = function->name; + + size_t sharpPos = name.rfind('#'); + if (sharpPos != std::string::npos) { + name = name.substr(sharpPos + 1); + } else { + name = name.substr(name.rfind('.') + 1); + assert(name == "func_main_0"); + } + + auto &strings = method->m->ctxI->strings; + if (strings.find(name) != strings.end()) { + return strings.at(name).get(); + } + + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +abckit_Code *MethodGetCodeDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *code = new abckit_Code({method->impl, method}); // FIXME: arena + return code; +} + +abckit_Class *MethodGetParentClassDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + return method->klass; +} + +bool MethodIsStaticDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return IsStatic(func->name); +} + +bool MethodIsCtorDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return IsCtor(func->name); +} + +bool MethodIsAnonymousDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return IsAnonymous(func->name); +} + +void MethodEnumerateAnnotationsDynamic(abckit_Method *method, void *data, bool (*cb)(abckit_Annotation *anno, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &annotation : method->annotations) { + if (!cb(annotation.get(), data)) { + return; + } + } +} + +bool MethodIsNativeDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return (func->metadata->GetAccessFlags() & ACC_NATIVE) != 0x0; +} + +bool MethodIsAbstractDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return (func->metadata->GetAccessFlags() & ACC_ABSTRACT) != 0x0; +} + +bool MethodIsExternalDynamic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return func->metadata->IsForeign(); +} + +// ======================================== +// Annotation +// ======================================== + +void AnnotationEnumerateElementsDynamic(abckit_Annotation *anno, void *data, bool (*cb)(abckit_AnnotationElement *ae, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &elem : anno->elements) { + if (!cb(elem.get(), data)) { + return; + } + } +} + +abckit_String *AnnotationElementGetNameDynamic(abckit_AnnotationElement *ae) +{ + LIBABCKIT_LOG_FUNC + auto name = ae->name; + abckit_Module *module = nullptr; + if (std::holds_alternative(ae->ann->owner)) { + module = std::get(ae->ann->owner)->m; + } else if (std::holds_alternative(ae->ann->owner)) { + module = std::get(ae->ann->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + auto &strings = module->ctxI->strings; + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +abckit_AnnotationInterface *AnnotationGetInterfaceDynamic(abckit_Annotation *anno) +{ + LIBABCKIT_LOG_FUNC + auto recName = anno->name; + abckit_Module *module = nullptr; + if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } else if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + return module->at[recName].get(); +} + +abckit_String *AnnotationInterfaceGetNameDynamic(abckit_AnnotationInterface *ai) +{ + LIBABCKIT_LOG_FUNC + auto annotation = reinterpret_cast(ai->impl); + auto name = annotation->GetName(); + auto &strings = ai->m->ctxI->strings; + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +// ======================================== +// String +// ======================================== + +void StringToStringDynamic([[maybe_unused]] abckit_File *ctx, abckit_String *value, char *out, size_t *len) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << value->impl << '\n'; + if (out == nullptr) { + *len = value->impl.size() + 1; + } else { + std::strncpy(out, value->impl.c_str(), value->impl.size()); + out[value->impl.size()] = '\0'; + } +} + +// ======================================== +// ImportDescriptor +// ======================================== + +abckit_String *ImportDescriptorGetNameDynamic(abckit_ImportDescriptor *i) +{ + std::string name = [i](){ + const auto *moduleLitArr = i->importingModule->impl.dyn.moduleLiteralArray; + auto sectionOffset = i->payload.dyn.isRegularImport ? i->importingModule->impl.dyn.RegularImportsOffset : + i->importingModule->impl.dyn.NamespaceImportsOffset; + if (!i->payload.dyn.isRegularImport) { + return std::string("*"); + } + auto importNameOffset = sectionOffset + i->payload.dyn.moduleRecordIndexOff * 3 + 1; + return std::get(reinterpret_cast(moduleLitArr)->literals_[importNameOffset].value_); + }(); + auto &strings = i->importingModule->ctxI->strings; + if (strings.find(name) != strings.end()) { + return strings[name].get(); + } + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +abckit_String *ImportDescriptorGetAliasDynamic(abckit_ImportDescriptor *i) +{ + std::string name = [i](){ + const auto *moduleLitArr = i->importingModule->impl.dyn.moduleLiteralArray; + auto sectionOffset = i->payload.dyn.isRegularImport ? i->importingModule->impl.dyn.RegularImportsOffset : + i->importingModule->impl.dyn.NamespaceImportsOffset; + auto gap = i->payload.dyn.isRegularImport ? 3 : 2; + auto importNameOffset = sectionOffset + i->payload.dyn.moduleRecordIndexOff * gap; + return std::get(reinterpret_cast(moduleLitArr)->literals_[importNameOffset].value_); + }(); + auto &strings = i->importingModule->ctxI->strings; + if (strings.find(name) != strings.end()) { + return strings[name].get(); + } + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +// ======================================== +// ExportDescriptor +// ======================================== + +abckit_String *ExportDescriptorGetNameDynamic(abckit_ExportDescriptor *i) +{ + std::string name = [i](){ + const auto *moduleLitArr = i->exportingModule->impl.dyn.moduleLiteralArray; + size_t exportNameOffset; + switch (i->payload.dyn.kind) { + case abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT: { + exportNameOffset = i->exportingModule->impl.dyn.LocalExportsOffset + i->payload.dyn.moduleRecordIndexOff * 2 + 1; + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT: { + exportNameOffset = i->exportingModule->impl.dyn.IndirectExportsOffset + i->payload.dyn.moduleRecordIndexOff * 3 + 1; + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT: { + std::string res = "*"; + return res; + } + } + return std::get(reinterpret_cast(moduleLitArr)->literals_[exportNameOffset].value_); + }(); + auto &strings = i->exportingModule->ctxI->strings; + if (strings.find(name) != strings.end()) { + return strings[name].get(); + } + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +abckit_String *ExportDescriptorGetAliasDynamic(abckit_ExportDescriptor *i) +{ + std::string name = [i](){ + const auto *moduleLitArr = i->exportingModule->impl.dyn.moduleLiteralArray; + size_t exportNameOffset; + switch (i->payload.dyn.kind) { + case abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT: { + exportNameOffset = i->exportingModule->impl.dyn.LocalExportsOffset + i->payload.dyn.moduleRecordIndexOff * 2; + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT: { + exportNameOffset = i->exportingModule->impl.dyn.IndirectExportsOffset + i->payload.dyn.moduleRecordIndexOff * 3; + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT: { + if (!i->payload.dyn.hasServiceImport) { + std::string res = ""; + return res; + } + exportNameOffset = i->exportingModule->impl.dyn.LocalExportsOffset + i->payload.dyn.moduleRecordIndexOff * 2 + 1; + } + } + return std::get(reinterpret_cast(moduleLitArr)->literals_[exportNameOffset].value_); + }(); + auto &strings = i->exportingModule->ctxI->strings; + if (strings.find(name) != strings.end()) { + return strings[name].get(); + } + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +// ======================================== +// Literal +// ======================================== + +bool LiteralGetBoolDynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsBoolValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return false; + } + return std::get(literal->value_); +} + +uint8_t LiteralGetU8Dynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsByteValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value_); +} + +uint16_t LiteralGetU16Dynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsShortValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value_); +} + +uint32_t LiteralGetU32Dynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsIntegerValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value_); +} + +uint64_t LiteralGetU64Dynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsLongValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value_); +} + +float LiteralGetFloatDynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsFloatValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value_); +} + +double LiteralGetDoubleDynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsDoubleValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value_); +} + +abckit_String *LiteralGetStringDynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto s = std::make_unique(); + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsStringValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return nullptr; + } + + auto &strings = ctx->strings; + + auto val = std::get(literal->value_); + if (strings.find(val) != strings.end()) { + return strings[val].get(); + } + s->impl = val; + strings.insert({val, std::move(s)}); + + return strings[val].get(); +} + +abckit_LiteralTag LiteralGetTagDynamic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* litImpl = reinterpret_cast(lit->val); + switch (litImpl->tag_) { + case panda_file::LiteralTag::ARRAY_U1: + case panda_file::LiteralTag::BOOL: + return abckit_LiteralTag_BOOL; + case panda_file::LiteralTag::ARRAY_U8: + case panda_file::LiteralTag::ARRAY_I8: + return abckit_LiteralTag_BYTE; + case panda_file::LiteralTag::ARRAY_U16: + case panda_file::LiteralTag::ARRAY_I16: + return abckit_LiteralTag_SHORT; + case panda_file::LiteralTag::ARRAY_U32: + case panda_file::LiteralTag::ARRAY_I32: + case panda_file::LiteralTag::INTEGER: + return abckit_LiteralTag_INTEGER; + case panda_file::LiteralTag::ARRAY_U64: + case panda_file::LiteralTag::ARRAY_I64: + return abckit_LiteralTag_LONG; + case panda_file::LiteralTag::ARRAY_F32: + case panda_file::LiteralTag::FLOAT: + return abckit_LiteralTag_FLOAT; + case panda_file::LiteralTag::ARRAY_F64: + case panda_file::LiteralTag::DOUBLE: + return abckit_LiteralTag_DOUBLE; + case panda_file::LiteralTag::ARRAY_STRING: + case panda_file::LiteralTag::STRING: + return abckit_LiteralTag_STRING; + case panda_file::LiteralTag::NULLVALUE: + return abckit_LiteralTag_NULLVALUE; + case panda_file::LiteralTag::TAGVALUE: + return abckit_LiteralTag_TAGVALUE; + case panda_file::LiteralTag::METHOD: + case panda_file::LiteralTag::GETTER: + case panda_file::LiteralTag::SETTER: + case panda_file::LiteralTag::GENERATORMETHOD: + case panda_file::LiteralTag::ASYNCGENERATORMETHOD: + return abckit_LiteralTag_METHOD; + case panda_file::LiteralTag::LITERALARRAY: + return abckit_LiteralTag_LITERALARRAY; + default: + return abckit_LiteralTag_INVALID; + } +} + + +void LiteralArrayEnumerateElementsDynamic(abckit_File *ctx, abckit_LiteralArray *litArr, void *data, bool (*cb)(abckit_File *ctx, abckit_Literal *lit, void *data)) { + LIBABCKIT_LOG_FUNC + auto* arrImpl = reinterpret_cast(litArr); + + size_t size = arrImpl->literals_.size(); + if (size % 2 != 0) { + statuses::SetLastError(abckit_Status_TODO); + return; + } + + for (size_t idx = 1; idx < size; idx += 2) { + auto litImpl = arrImpl->literals_[idx]; + auto newLitImpl = new pandasm::LiteralArray::Literal(); + newLitImpl->tag_ = litImpl.tag_; + newLitImpl->value_ = litImpl.value_; + auto lit = std::make_unique(); + lit->val = reinterpret_cast(newLitImpl); + ctx->litvals.emplace_back(std::move(lit)); + if(!cb(ctx, ctx->litvals.back().get(), data)){ + return; + } + } +} + +// ======================================== +// Value +// ======================================== + +abckit_Type *ValueGetTypeDynamic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + auto* p_val = reinterpret_cast(value->impl); + auto type = std::make_unique(); + type->klass = nullptr; // TODO implement logic for classes + switch (p_val->GetType()) { + case pandasm::Value::Type::U1: + type->id = abckit_TypeId_U1; + break; + case pandasm::Value::Type::U8: + type->id = abckit_TypeId_U8; + break; + case pandasm::Value::Type::U16: + type->id = abckit_TypeId_U16; + break; + case pandasm::Value::Type::U32: + type->id = abckit_TypeId_U32; + break; + case pandasm::Value::Type::U64: + type->id = abckit_TypeId_U64; + break; + case pandasm::Value::Type::F64: + type->id = abckit_TypeId_F64; + break; + case pandasm::Value::Type::STRING: + type->id = abckit_TypeId_STRING; + break; + case pandasm::Value::Type::LITERALARRAY: + type->id = abckit_TypeId_LITERALARRAY; + break; + default: + return nullptr; + } + ctx->types.emplace_back(std::move(type)); + return ctx->types.back().get(); +} + +bool ValueGetU1Dynamic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeDynamic(ctx, value)->id != abckit_TypeId_U1) { + statuses::SetLastError(abckit_Status_TODO); + return false; + } + + auto* p_val = reinterpret_cast(value->impl); + return p_val->GetValue(); +} + +double ValueGetDoubleDynamic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeDynamic(ctx, value)->id != abckit_TypeId_F64) { + statuses::SetLastError(abckit_Status_TODO); + return false; + } + + auto* p_val = reinterpret_cast(value->impl); + return p_val->GetValue(); +} + +abckit_String *ValueGetStringDynamic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeDynamic(ctx, value)->id != abckit_TypeId_STRING) { + statuses::SetLastError(abckit_Status_TODO); + return nullptr; + } + + auto* p_val = reinterpret_cast(value->impl); + auto val_impl = p_val->GetValue(); + auto s = std::make_unique(); + s->impl = val_impl.c_str(); + ctx->strings.insert({val_impl, std::move(s)}); + return ctx->strings[val_impl].get(); +} + + +abckit_LiteralArray *ArrayValueGetLiteralArrayDynamic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeDynamic(ctx, value)->id != abckit_TypeId_LITERALARRAY) { + statuses::SetLastError(abckit_Status_TODO); + return nullptr; + } + + auto* p_val = reinterpret_cast(value->impl); + auto val_impl = p_val->GetValue(); + auto* prog = reinterpret_cast(ctx->program); + return reinterpret_cast(&(prog->literalarray_table[val_impl])); +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_dynamic/metadata_inspect_dynamic.h b/libabckit/src/adapter_dynamic/metadata_inspect_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..2c51fa0843da3c51813e6f23a6ea366636491622 --- /dev/null +++ b/libabckit/src/adapter_dynamic/metadata_inspect_dynamic.h @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_DYNAMIC_METADATA_INSPECT_DYNAMIC_H +#define LIBABCKIT_SRC_ADAPTER_DYNAMIC_METADATA_INSPECT_DYNAMIC_H + +#include "libabckit/include/metadata.h" + +#include + +namespace libabckit { + +// ======================================== +// Module +// ======================================== + +void ModuleEnumerateClassesDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_Class *klass, void *data)); +void ModuleEnumerateTopLevelMethodsDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)); +void ModuleEnumerateAnnotationInterfacesDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_AnnotationInterface *ai, void *data)); +void ModuleEnumerateAnonymousFunctionsDynamic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)); + +// ======================================== +// Class +// ======================================== + +abckit_String *ClassGetNameDynamic(abckit_Class *klass); +void ClassEnumerateMethodsDynamic(abckit_Class *klass, void *data, bool (*cb)(abckit_Method *method, void *data)); +void ClassEnumerateAnnotationsDynamic(abckit_Class *klass, void *data, bool (*cb)(abckit_Annotation *anno, void *data)); + +// ======================================== +// Method +// ======================================== + +abckit_String *MethodGetNameDynamic(abckit_Method *method); +void FileEnumerateTopLevelMethodsDynamic(abckit_File *ctxI, void *data, bool (*cb)(abckit_Method *method, void *data)); +abckit_Code *MethodGetCodeDynamic(abckit_Method *method); +abckit_Class *MethodGetParentClassDynamic(abckit_Method *method); +bool MethodIsStaticDynamic(abckit_Method *method); +bool MethodIsCtorDynamic(abckit_Method *method); +bool MethodIsAnonymousDynamic(abckit_Method *method); +void MethodEnumerateAnnotationsDynamic(abckit_Method *method, void *data, bool (*cb)(abckit_Annotation *anno, void *data)); +bool MethodIsNativeDynamic(abckit_Method *method); +bool MethodIsAbstractDynamic(abckit_Method *method); +bool MethodIsExternalDynamic(abckit_Method *method); + +// ======================================== +// Annotation +// ======================================== + +void AnnotationEnumerateElementsDynamic(abckit_Annotation *anno, void *data, bool (*cb)(abckit_AnnotationElement *ae, void *data)); +abckit_String *AnnotationElementGetNameDynamic(abckit_AnnotationElement *ae); +abckit_AnnotationInterface *AnnotationGetInterfaceDynamic(abckit_Annotation *anno); +abckit_String *AnnotationInterfaceGetNameDynamic(abckit_AnnotationInterface *ai); + +// ======================================== +// String +// ======================================== + +void StringToStringDynamic(abckit_File *ctx, abckit_String *value, char *out, size_t *len); + +abckit_String *CreateStringDynamic(abckit_ModifyContext *ctxM, const char *value); + +// ======================================== +// ImportDescriptor +// ======================================== + +abckit_String *ImportDescriptorGetNameDynamic(abckit_ImportDescriptor *i); +abckit_String *ImportDescriptorGetAliasDynamic(abckit_ImportDescriptor *i); + +// ======================================== +// ExportDescriptor +// ======================================== + +abckit_String *ExportDescriptorGetNameDynamic(abckit_ExportDescriptor *i); +abckit_String *ExportDescriptorGetAliasDynamic(abckit_ExportDescriptor *i); + +// ======================================== +// Literal +// ======================================== + +bool LiteralGetBoolDynamic(abckit_File *ctx, abckit_Literal *lit); +uint8_t LiteralGetU8Dynamic(abckit_File *ctx, abckit_Literal *lit); +uint16_t LiteralGetU16Dynamic(abckit_File *ctx, abckit_Literal *lit); +uint32_t LiteralGetU32Dynamic(abckit_File *ctx, abckit_Literal *lit); +uint64_t LiteralGetU64Dynamic(abckit_File *ctx, abckit_Literal *lit); +float LiteralGetFloatDynamic(abckit_File *ctx, abckit_Literal *lit); +double LiteralGetDoubleDynamic(abckit_File *ctx, abckit_Literal *lit); +abckit_String *LiteralGetStringDynamic(abckit_File *ctx, abckit_Literal *lit); +abckit_LiteralTag LiteralGetTagDynamic(abckit_File *ctx, abckit_Literal *lit); +void LiteralArrayEnumerateElementsDynamic(abckit_File *ctx, abckit_LiteralArray *litArr, void *data, bool (*cb)(abckit_File *ctx, abckit_Literal *lit, void *data)); + +// ======================================== +// Value +// ======================================== + +abckit_Type *ValueGetTypeDynamic(abckit_File *ctx, abckit_Value *value); +bool ValueGetU1Dynamic(abckit_File *ctx, abckit_Value *value); +double ValueGetDoubleDynamic(abckit_File *ctx, abckit_Value *value); +abckit_String *ValueGetStringDynamic(abckit_File *ctx, abckit_Value *value); +abckit_LiteralArray *ArrayValueGetLiteralArrayDynamic(abckit_File *ctx, abckit_Value *value); + +} // namespace libabckit + +#endif diff --git a/libabckit/src/adapter_dynamic/metadata_modify_dynamic.cpp b/libabckit/src/adapter_dynamic/metadata_modify_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91c5a3490d46cbec394368e5032187097ab54ed2 --- /dev/null +++ b/libabckit/src/adapter_dynamic/metadata_modify_dynamic.cpp @@ -0,0 +1,861 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/adapter_dynamic/metadata_modify_dynamic.h" +#include "assembly-function.h" +#include "assembly-record.h" +#include "include/statuses.h" +#include "libabckit/src/adapter_dynamic/metadata_inspect_dynamic.h" + +#include "libabckit/include/metadata.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/logger.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/metadata_modify_impl.h" +#include "assembler/annotation.h" +#include "assembler/assembly-literals.h" +#include "assembler/assembly-program.h" +#include "source_lang_enum.h" +#include "src/statuses_impl.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace libabckit { + +using namespace panda; + +abckit_String *CreateStringDynamic(abckit_ModifyContext *ctxM, const char *value) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "\"" << value << "\"" << '\n'; + auto *prog = reinterpret_cast(ctxM->ctxI->program); + prog->strings.insert(value); + auto &strings = ctxM->ctxI->strings; + + if (strings.find(value) != strings.end()) { + return strings.at(value).get(); + } + + auto s = std::make_unique(); + s->impl = value; + strings.insert({value, std::move(s)}); + return strings[value].get(); +} + +void MethodSetCodeDynamic(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code) { + LIBABCKIT_LOG_FUNC + auto *function = reinterpret_cast(method->impl); + auto *newFunction = reinterpret_cast(code->newCode); + function->ins = newFunction->ins; + function->catch_blocks = newFunction->catch_blocks; + function->regs_num = newFunction->regs_num; + + // update IC slot number info in annotation + function->slots_num = newFunction->slots_num; + static const std::string SLOT_NUMBER = "_ESSlotNumberAnnotation"; + static const std::string ELEMENT_NAME = "SlotNumber"; + size_t slotNumAnnoIndex = 0; + for (const auto &an : function->metadata->GetAnnotations()) { + if (an.GetName() == SLOT_NUMBER) { + pandasm::AnnotationElement ele(ELEMENT_NAME, std::make_unique( + pandasm::ScalarValue::Create(static_cast(function->slots_num)))); + function->metadata->SetOrAddAnnotationElementByIndex(slotNumAnnoIndex, 0, std::move(ele)); + break; + } + slotNumAnnoIndex++; + } + + delete newFunction; // not needed anymore + delete code; // not needed anymore +} + +abckit_Module *FileAddExternalModuleDynamic(abckit_File *ctx, + const struct abckit_ExternalModuleCreateParams *params) +{ + auto m = std::make_unique(); + m->ctxI = ctx; + + auto *prog = reinterpret_cast(ctx->program); + prog->strings.insert(params->name); + auto &strings = ctx->strings; + if (strings.find(params->name) != strings.end()) { + m->moduleName = strings.at(params->name).get(); + } else { + auto s = std::make_unique(); + s->impl = params->name; + strings.insert({params->name, std::move(s)}); + m->moduleName = strings[params->name].get(); + } + + m->isExternal = true; + auto modulePayload = abckit_ModulePayload(); + auto modulePayloadDyn = abckit_ModulePayloadDyn(); + modulePayloadDyn.absPaths = false; + modulePayload.dyn = modulePayloadDyn; + m->impl = modulePayload; + ctx->externalModules.insert({params->name, std::move(m)}); + return ctx->externalModules[params->name].get(); +} + +void ModuleRemoveImportDynamic(abckit_Module *m, abckit_ImportDescriptor *i) +{ + LIBABCKIT_LOG_FUNC + auto found = std::find_if(m->id.begin(), m->id.end(), [&](std::unique_ptr const& d) { + return d.get() == i; + }); + if (found == m->id.end()) { + LIBABCKIT_LOG(DEBUG) << "Can not find the import to delete\n"; + statuses::SetLastError(abckit_Status::abckit_Status_BAD_ARGUMENT); + return; + } + + auto idxOffset = i->payload.dyn.isRegularImport ? m->impl.dyn.RegularImportsOffset : m->impl.dyn.NamespaceImportsOffset; + auto gap = i->payload.dyn.isRegularImport ? 3 : 2; + (reinterpret_cast(m->impl.dyn.moduleLiteralArray))->literals_[idxOffset + i->payload.dyn.moduleRecordIndexOff * gap].tag_ = panda_file::LiteralTag::NULLVALUE; + + m->id.erase(found); +} + +void AddNewModuleRequest(abckit_Module *m, abckit_Module *newModule) +{ + auto *moduleLitArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + m->md.push_back(newModule); + auto requestsIdxNum = std::get(moduleLitArr->literals_[m->impl.dyn.ModuleRequestsOffset - 1].value_); + moduleLitArr->literals_[m->impl.dyn.ModuleRequestsOffset - 1].value_ = requestsIdxNum + 1; + auto literalModuleRequest = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, "./" + newModule->moduleName->impl}; + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->md.size(), std::move(literalModuleRequest)); + + m->impl.dyn.RegularImportsOffset = m->impl.dyn.RegularImportsOffset + 1; + m->impl.dyn.NamespaceImportsOffset = m->impl.dyn.NamespaceImportsOffset + 1; + m->impl.dyn.LocalExportsOffset = m->impl.dyn.LocalExportsOffset + 1; + m->impl.dyn.IndirectExportsOffset = m->impl.dyn.IndirectExportsOffset + 1; + m->impl.dyn.StarExportsOffset = m->impl.dyn.StarExportsOffset + 1; +} + +size_t AddNamespaceImportToModuleLiteralArray(abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params) +{ + auto literalLocalName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->alias)}; + auto *moduleLitArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + + ASSERT((params->module->isExternal && m->ctxI->externalModules.find(params->module->moduleName->impl) != m->ctxI->externalModules.end()) || + (!params->module->isExternal && m->ctxI->localModules.find(params->module->moduleName->impl) != m->ctxI->localModules.end())); + + auto found = std::find(m->md.begin(), m->md.end(), params->module); + uint16_t requestIdx; + if (found != m->md.end()) { + requestIdx = std::distance(m->md.begin(), found); + } else { + AddNewModuleRequest(m, params->module); + requestIdx = m->md.size() - 1; + } + + auto literalRequestIdx = pandasm::LiteralArray::Literal{panda_file::LiteralTag::METHODAFFILIATE, requestIdx}; + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.LocalExportsOffset - 1, std::move(literalRequestIdx)); + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.LocalExportsOffset - 1, std::move(literalLocalName)); + + auto namespaceImportsNum = std::get(moduleLitArr->literals_[m->impl.dyn.NamespaceImportsOffset - 1].value_); + moduleLitArr->literals_[m->impl.dyn.NamespaceImportsOffset - 1].value_ = namespaceImportsNum + 1; + m->impl.dyn.LocalExportsOffset = m->impl.dyn.LocalExportsOffset + 2; + m->impl.dyn.IndirectExportsOffset = m->impl.dyn.IndirectExportsOffset + 2; + m->impl.dyn.StarExportsOffset = m->impl.dyn.StarExportsOffset + 2; + + return namespaceImportsNum; +} + +size_t AddRegularImportToModuleLiteralArray(abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params) +{ + auto literalLocalName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->alias)}; + auto literalImportName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->name)}; + auto *moduleLitArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + + ASSERT((params->module->isExternal && m->ctxI->externalModules.find(params->module->moduleName->impl) != m->ctxI->externalModules.end()) || + (!params->module->isExternal && m->ctxI->localModules.find(params->module->moduleName->impl) != m->ctxI->localModules.end())); + + auto found = std::find(m->md.begin(), m->md.end(), params->module); + uint16_t requestIdx; + if (found != m->md.end()) { + requestIdx = std::distance(m->md.begin(), found); + } else { + AddNewModuleRequest(m, params->module); + requestIdx = m->md.size() - 1; + } + + auto literalRequestIdx = pandasm::LiteralArray::Literal{panda_file::LiteralTag::METHODAFFILIATE, requestIdx}; + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.NamespaceImportsOffset - 1, std::move(literalRequestIdx)); + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.NamespaceImportsOffset - 1, std::move(literalImportName)); + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.NamespaceImportsOffset - 1, std::move(literalLocalName)); + + auto regularImportsNum = std::get(moduleLitArr->literals_[m->impl.dyn.RegularImportsOffset - 1].value_); + moduleLitArr->literals_[m->impl.dyn.RegularImportsOffset - 1].value_ = regularImportsNum + 1; + m->impl.dyn.NamespaceImportsOffset = m->impl.dyn.NamespaceImportsOffset + 3; + m->impl.dyn.LocalExportsOffset = m->impl.dyn.LocalExportsOffset + 3; + m->impl.dyn.IndirectExportsOffset = m->impl.dyn.IndirectExportsOffset + 3; + m->impl.dyn.StarExportsOffset = m->impl.dyn.StarExportsOffset + 3; + + return regularImportsNum; +} + +size_t AddImportToModuleLiteralArray(abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params) +{ + return (std::strcmp(params->name, "*") == 0) ? AddNamespaceImportToModuleLiteralArray(m, params) + : AddRegularImportToModuleLiteralArray(m, params); +} + +abckit_ImportDescriptor *ModuleAddImportFromDynamicModuleDynamic( + abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params) +{ + auto id = std::make_unique(); + id->importingModule = m; + id->importedModule = params->module; + id->kind = abckit_ImportExportDescriptorKind::UNTYPED; + auto payloadDyn = abckit_DynamicImportDescriptorPayload(); + payloadDyn.isRegularImport = (std::strcmp(params->name, "*") == 0) ? false : true; + payloadDyn.moduleRecordIndexOff = AddImportToModuleLiteralArray(m, params); + auto payload = abckit_ImportDescriptorPayload(); + payload.dyn = payloadDyn; + id->payload = payload; + m->id.push_back(std::move(id)); + + return m->id[m->id.size() - 1].get(); +} + +size_t AddLocalExportToModuleLiteralArray(abckit_Module *m, const abckit_DynamicModuleExportCreateParams *params) +{ + auto literalLocalName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->alias)}; + auto literalExportName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->name)}; + auto *moduleLitArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.IndirectExportsOffset - 1, std::move(literalExportName)); + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.IndirectExportsOffset - 1, std::move(literalLocalName)); + + auto localExportsNum = std::get(moduleLitArr->literals_[m->impl.dyn.LocalExportsOffset - 1].value_); + moduleLitArr->literals_[m->impl.dyn.LocalExportsOffset - 1].value_ = localExportsNum + 1; + m->impl.dyn.StarExportsOffset = m->impl.dyn.IndirectExportsOffset + 2; + m->impl.dyn.StarExportsOffset = m->impl.dyn.StarExportsOffset + 2; + + return localExportsNum; +} + +size_t AddIndirectExportToModuleLiteralArray(abckit_Module *m, const abckit_DynamicModuleExportCreateParams *params) +{ + auto literalExportName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->alias)}; + auto literalImportName = pandasm::LiteralArray::Literal{panda_file::LiteralTag::STRING, std::string(params->name)}; + auto *moduleLitArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + + ASSERT((params->module->isExternal && m->ctxI->externalModules.find(params->module->moduleName->impl) != m->ctxI->externalModules.end()) || + (!params->module->isExternal && m->ctxI->localModules.find(params->module->moduleName->impl) != m->ctxI->localModules.end())); + + auto found = std::find(m->md.begin(), m->md.end(), params->module); + uint16_t requestIdx; + if (found != m->md.end()) { + requestIdx = std::distance(m->md.begin(), found); + } else { + AddNewModuleRequest(m, params->module); + requestIdx = m->md.size() - 1; + } + + auto literalRequestIdx = pandasm::LiteralArray::Literal{panda_file::LiteralTag::METHODAFFILIATE, requestIdx}; + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.StarExportsOffset - 1, std::move(literalRequestIdx)); + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.StarExportsOffset - 1, std::move(literalImportName)); + moduleLitArr->literals_.insert(moduleLitArr->literals_.begin() + m->impl.dyn.StarExportsOffset - 1, std::move(literalExportName)); + + auto indirectExportsNum = std::get(moduleLitArr->literals_[m->impl.dyn.IndirectExportsOffset - 1].value_); + moduleLitArr->literals_[m->impl.dyn.IndirectExportsOffset - 1].value_ = indirectExportsNum + 1; + m->impl.dyn.StarExportsOffset = m->impl.dyn.StarExportsOffset + 3; + + return indirectExportsNum; +} + +std::string GetServiceExportName(abckit_Module *m) +{ + auto maxNum = -1; + const auto *moduleLitArr = m->impl.dyn.moduleLiteralArray; + for (auto &ed : m->ed) { + if (ed->payload.dyn.hasServiceImport) { + auto exportNameOffset = m->impl.dyn.LocalExportsOffset + ed->payload.dyn.moduleRecordIndexOff * 2; + auto name = std::get(reinterpret_cast(moduleLitArr)->literals_[exportNameOffset].value_); + ASSERT(name.find("=ens") != std::string::npos); + auto serviceImportsNum = std::atoi(name.substr(4).c_str()); + if (serviceImportsNum > maxNum) { + maxNum = serviceImportsNum; + } + } + } + + return "=ens" + std::to_string(maxNum + 1); +} + +size_t AddStarExportToModuleLiteralArray(abckit_Module *m, const abckit_DynamicModuleExportCreateParams *params, + abckit_DynamicExportDescriptorPayload *payload) +{ + auto *moduleLitArr = reinterpret_cast(m->impl.dyn.moduleLiteralArray); + + ASSERT((params->module->isExternal && m->ctxI->externalModules.find(params->module->moduleName->impl) != m->ctxI->externalModules.end()) || + (!params->module->isExternal && m->ctxI->localModules.find(params->module->moduleName->impl) != m->ctxI->localModules.end())); + + auto found = std::find(m->md.begin(), m->md.end(), params->module); + uint16_t requestIdx; + if (found != m->md.end()) { + requestIdx = std::distance(m->md.begin(), found); + } else { + AddNewModuleRequest(m, params->module); + requestIdx = m->md.size() - 1; + } + + if (params->alias == nullptr) { + auto starExportsNum = std::get(moduleLitArr->literals_[m->impl.dyn.StarExportsOffset - 1].value_); + auto literalRequestIdx = pandasm::LiteralArray::Literal{panda_file::LiteralTag::METHODAFFILIATE, requestIdx}; + moduleLitArr->literals_.push_back(std::move(literalRequestIdx)); + moduleLitArr->literals_[m->impl.dyn.StarExportsOffset - 1].value_ = starExportsNum + 1; + return starExportsNum; + } + auto serviceName = GetServiceExportName(m); + abckit_DynamicModuleExportCreateParams params1; + params1.name = params->alias; + params1.alias = serviceName.c_str(); + auto localExpIdx = AddLocalExportToModuleLiteralArray(m, ¶ms1); + abckit_ImportFromDynamicModuleCreateParams params2; + params2.alias = serviceName.c_str(); + params2.module = params->module; + auto nsImpIdx = AddNamespaceImportToModuleLiteralArray(m, ¶ms2); + payload->hasServiceImport = true; + payload->serviceNamespaceImportIdx = nsImpIdx; + return localExpIdx; +} + +size_t AddExportToModuleLiteralArray(abckit_Module *m, const abckit_DynamicModuleExportCreateParams *params, + abckit_DynamicExportDescriptorPayload *payload, abckit_DynamicExportKind kind) +{ + switch(kind) { + case abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT: { + return AddStarExportToModuleLiteralArray(m, params, payload); + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT: { + return AddLocalExportToModuleLiteralArray(m, params); + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT: { + return AddIndirectExportToModuleLiteralArray(m, params); + } + } + UNREACHABLE(); +} + +abckit_ExportDescriptor *DynamicModuleAddExportDynamic(abckit_Module *m, + const abckit_DynamicModuleExportCreateParams *params) +{ + auto ed = std::make_unique(); + ed->exportingModule = m; + ed->exportedModule = params->module; + ed->kind = abckit_ImportExportDescriptorKind::UNTYPED; + auto payloadDyn = abckit_DynamicExportDescriptorPayload(); + if (std::strcmp(params->name, "*") == 0) { + payloadDyn.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT; + } else if (params->module == nullptr) { + payloadDyn.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT; + ed->exportedModule = m; + } else { + payloadDyn.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT; + } + + payloadDyn.hasServiceImport = false; + payloadDyn.moduleRecordIndexOff = AddExportToModuleLiteralArray(m, params, &payloadDyn, payloadDyn.kind); + auto payload = abckit_ExportDescriptorPayload(); + payload.dyn = payloadDyn; + ed->payload = payload; + m->ed.push_back(std::move(ed)); + return m->ed[m->ed.size() - 1].get(); +} + +void ModuleRemoveExportDynamic(abckit_Module *m, abckit_ExportDescriptor *i) +{ + LIBABCKIT_LOG_FUNC + auto found = std::find_if(m->ed.begin(), m->ed.end(), [&](std::unique_ptr const& d) { + return d.get() == i; + }); + if (found == m->ed.end()) { + LIBABCKIT_LOG(DEBUG) << "Can not find the export to delete\n"; + statuses::SetLastError(abckit_Status::abckit_Status_BAD_ARGUMENT); + return; + } + + auto idxOffset = 0;; + auto gap = 0; + switch (i->payload.dyn.kind) { + case abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT: { + idxOffset = m->impl.dyn.LocalExportsOffset; + gap = 2; + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT: { + idxOffset = m->impl.dyn.IndirectExportsOffset; + gap = 3; + break; + } + case abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT: { + idxOffset = m->impl.dyn.StarExportsOffset; + gap = 1; + } + } + (reinterpret_cast(m->impl.dyn.moduleLiteralArray))->literals_[idxOffset + i->payload.dyn.moduleRecordIndexOff * gap].tag_ = panda_file::LiteralTag::NULLVALUE; + + m->ed.erase(found); +} + +abckit_Literal *CreateLiteralBoolDynamic(abckit_ModifyContext *ctx, bool value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::BOOL; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU8Dynamic(abckit_ModifyContext *ctx, uint8_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::ARRAY_U8; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU16Dynamic(abckit_ModifyContext *ctx, uint16_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::ARRAY_U16; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU32Dynamic(abckit_ModifyContext *ctx, uint32_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::INTEGER; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU64Dynamic(abckit_ModifyContext *ctx, uint64_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::ARRAY_U64; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralFloatDynamic(abckit_ModifyContext *ctx, float value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::FLOAT; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralDoubleDynamic(abckit_ModifyContext *ctx, double value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::DOUBLE; + literal->value_ = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralStringDynamic(abckit_ModifyContext *ctx, const char* value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag_ = panda_file::LiteralTag::STRING; + literal->value_ = std::string(value); + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_LiteralArray *CreateLiteralArrayDynamic(abckit_ModifyContext *ctxM, abckit_Literal **value, size_t size) { + LIBABCKIT_LOG_FUNC + auto* prog = reinterpret_cast(ctxM->ctxI->program); + + std::vector std_lit_arr; + for(size_t i = 0; i < size; i++) { + auto lit = *reinterpret_cast(value[i]->val); + pandasm::LiteralArray::Literal tag_lit; + tag_lit.tag_ = panda_file::LiteralTag::TAGVALUE; + tag_lit.value_ = static_cast(lit.tag_); + std_lit_arr.emplace_back(tag_lit); + std_lit_arr.emplace_back(lit); + } + + std::srand(0); + uint32_t arrayOffset = 0; + while(prog->literalarray_table.find(std::to_string(arrayOffset)) != prog->literalarray_table.end()) { + LIBABCKIT_LOG(DEBUG) << "generating new arrayOffset\n"; + arrayOffset = rand() % 1000; + } + auto arrayName = std::to_string(arrayOffset); + + prog->literalarray_table.emplace(arrayName, pandasm::LiteralArray()); + pandasm::LiteralArray &arrImpl = prog->literalarray_table[arrayName]; + arrImpl.literals_ = std::move(std_lit_arr); + + return reinterpret_cast(&arrImpl); +} + +abckit_Value *CreateValueU1Dynamic(abckit_ModifyContext *ctx, bool value) { + LIBABCKIT_LOG_FUNC + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(value)); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_Value *CreateValueDoubleDynamic(abckit_ModifyContext *ctx, double value) { + LIBABCKIT_LOG_FUNC + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(value)); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_Value *CreateValueStringDynamic(abckit_ModifyContext *ctx, const char *value) { + LIBABCKIT_LOG_FUNC + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(std::string(value))); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_Value *CreateLiteralArrayValueDynamic(abckit_ModifyContext *ctx, abckit_Value **value, size_t size) { + LIBABCKIT_LOG_FUNC + std::vector lit_arr; + for(size_t i = 0; i < size; i++) { + switch(ValueGetTypeDynamic(ctx->ctxI, value[i])->id) { + case abckit_TypeId_U1: + lit_arr.emplace_back(CreateLiteralBoolDynamic(ctx, ValueGetU1Dynamic(ctx->ctxI, value[i]))); + break; + case abckit_TypeId_F64: + lit_arr.emplace_back(CreateLiteralDoubleDynamic(ctx, ValueGetDoubleDynamic(ctx->ctxI, value[i]))); + break; + case abckit_TypeId_STRING: + lit_arr.emplace_back(CreateLiteralStringDynamic(ctx, ValueGetStringDynamic(ctx->ctxI, value[i])->impl.c_str())); + break; + default: + break; + } + } + auto* abc_arr = CreateLiteralArrayDynamic(ctx, lit_arr.data(), lit_arr.size()); + auto* prog = reinterpret_cast(ctx->ctxI->program); + std::string arr_name; + for(auto& item : prog->literalarray_table) { + if(&item.second == reinterpret_cast(abc_arr)){ + arr_name = item.first; + break; + } + } + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(arr_name)); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_AnnotationInterface *ModuleAddAnnotationInterfaceDynamic( + abckit_ModifyContext *ctx, abckit_Module *m, const abckit_AnnotationInterfaceCreateParams *params) +{ + std::string name = params->name; + auto prog = reinterpret_cast(ctx->ctxI->program); + auto progRecord = pandasm::Record{name, prog->lang}; + prog->record_table.emplace(name, std::move(progRecord)); + pandasm::Record &record = prog->record_table.find(name)->second; + auto ai = std::make_unique(); + ai->m = m; + ai->impl = reinterpret_cast(&record); + return m->at.emplace(name, std::move(ai)).first->second.get(); +} + +abckit_Annotation *ClassAddAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Class *klass, const abckit_AnnotationCreateParams *params) +{ + auto ai = params->ai; + + auto progFunc = reinterpret_cast(klass->impl.fn); + auto str = AnnotationInterfaceGetNameDynamic(ai); + auto name = str->impl; + + std::vector vec; + vec.emplace_back(name); + + progFunc->metadata->AddAnnotations(vec); + + auto anno = std::make_unique(); + anno->owner = klass; + anno->name = name; + return klass->annotations.emplace_back(std::move(anno)).get(); +} + +void ClassRemoveAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Class *klass, abckit_Annotation *anno) +{ + auto progFunc = reinterpret_cast(klass->impl.fn); + + auto ai = AnnotationGetInterfaceDynamic(anno); + + auto str = AnnotationInterfaceGetNameDynamic(ai); + auto name = str->impl; + + progFunc->metadata->DeleteAnnotationByName(name); + auto& annotations = klass->annotations; + auto iter = std::find_if(annotations.begin(), annotations.end(), [&name](auto &annoIt){ + return name == annoIt.get()->name; + }); + annotations.erase(iter); +} + +abckit_Annotation *MethodAddAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Method *method, const abckit_AnnotationCreateParams *params) +{ + auto ai = params->ai; + + auto progFunc = reinterpret_cast(method->impl); + auto str = AnnotationInterfaceGetNameDynamic(ai); + auto name = str->impl; + + std::vector vec; + vec.emplace_back(name); + + progFunc->metadata->AddAnnotations(vec); + + auto anno = std::make_unique(); + anno->owner = method; + anno->name = name; + return method->annotations.emplace_back(std::move(anno)).get(); +} + +void MethodRemoveAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno) +{ + auto progFunc = reinterpret_cast(method->impl); + + auto ai = AnnotationGetInterfaceDynamic(anno); + + auto str = AnnotationInterfaceGetNameDynamic(ai); + auto name = str->impl; + + progFunc->metadata->DeleteAnnotationByName(name); + auto& annotations = method->annotations; + auto iter = std::find_if(annotations.begin(), annotations.end(), [&name](auto &annoIt){ + return name == annoIt.get()->name; + }); + annotations.erase(iter); +} + +abckit_AnnotationElement *AnnotationAddAnnotationElementDynamic(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params) +{ + auto valuePtr = params->value; + auto name = params->name; + + auto value = *valuePtr; + auto pandasmValue = *reinterpret_cast(value.impl); + auto abcValue = std::make_unique(std::move(value)); + + pandasm::AnnotationElement progAnnoElem (params->name, std::make_unique(std::move(pandasmValue))); + abcValue->impl = reinterpret_cast(progAnnoElem.GetValue()); + + auto annoElem = std::make_unique(); + annoElem->ann = anno; + annoElem->name = progAnnoElem.GetName(); + annoElem->value = std::move(abcValue); + + + if (std::holds_alternative(anno->owner)) { + auto progOwner = reinterpret_cast(std::get(anno->owner)->impl); + progOwner->metadata->AddAnnotationElementByName(name, std::move(progAnnoElem)); + } else if (std::holds_alternative(anno->owner)) { + auto progOwner = reinterpret_cast(std::get(anno->owner)->impl.fn); + progOwner->metadata->AddAnnotationElementByName(name, std::move(progAnnoElem)); + } + + return anno->elements.emplace_back(std::move(annoElem)).get(); +} + +void AnnotationRemoveAnnotationElementDynamic(abckit_ModifyContext *ctx, abckit_Annotation *anno, abckit_AnnotationElement *elem) +{ + auto name = elem->name; + + if (std::holds_alternative(anno->owner)) { + auto progOwner = reinterpret_cast(std::get(anno->owner)->impl); + progOwner->metadata->DeleteAnnotationElementByName(name); + } else if (std::holds_alternative(anno->owner)) { + auto progOwner = reinterpret_cast(std::get(anno->owner)->impl.fn); + progOwner->metadata->DeleteAnnotationElementByName(name); + } + + auto& annotationElementes = anno->elements; + auto iter = std::find_if(annotationElementes.begin(), annotationElementes.end(), [&name](auto &annoElemIt){ + return name == annoElemIt.get()->name; + }); + if (iter == annotationElementes.end()) { + statuses::SetLastError(abckit_Status_TODO); + return; + } + annotationElementes.erase(iter); +} + +std::string TypeToName(abckit_Type *type) +{ + if (type->id == abckit_TypeId_REFERENCE) { + auto str = ClassGetNameDynamic(type->klass); + if (str == nullptr) { + return ""; + } + return str->impl; + } + switch(type->id) { + case abckit_TypeId_VOID: + return "void"; + case abckit_TypeId_U1: + return "u1"; + case abckit_TypeId_U8: + return "u8"; + case abckit_TypeId_I8: + return "u8"; + case abckit_TypeId_U16: + return "u16"; + case abckit_TypeId_I16: + return "i16"; + case abckit_TypeId_U32: + return "u32"; + case abckit_TypeId_I32: + return "i32"; + case abckit_TypeId_U64: + return "u64"; + case abckit_TypeId_I64: + return "i64"; + case abckit_TypeId_F32: + return "f32"; + case abckit_TypeId_F64: + return "f64"; + case abckit_TypeId_ANY: + return "any"; + case abckit_TypeId_STRING: + return "panda.String"; + default: + return "invalid"; + } +} + +abckit_AnnotationInterfaceField *AnnotationInterfaceAddFieldDynamic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params) +{ + auto name = params->name; + auto type = params->type; + auto value = params->defaultValue; + + auto field = std::make_unique(); + field->ai = ai; + field->name = CreateStringDynamic(ctx, name); + field->type = type; + field->value = value; + + ai->fields.emplace_back(std::move(field)); + + auto record = reinterpret_cast(ai->impl); + + auto prog = reinterpret_cast(ctx->ctxI->program); + auto progField = pandasm::Field(prog->lang); + + progField.name = name; + std::string typeName; + progField.type = pandasm::Type(TypeToName(type), type->rank); + progField.metadata->SetValue(*reinterpret_cast(value->impl)); + record->field_list.emplace_back(std::move(progField)); + + return ai->fields.back().get(); +} + +void AnnotationInterfaceRemoveFieldDynamic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, abckit_AnnotationInterfaceField *field) +{ + auto str = field->name; + if (str == nullptr) { + statuses::SetLastError(abckit_Status_TODO); + return; + } + auto name = str->impl; + + auto record = reinterpret_cast(ai->impl); + + auto &fields = record->field_list; + + auto fieldsIter = std::find_if(fields.begin(), fields.end(), [&name](auto &field){ + return name == field.name; + }); + if (fieldsIter == fields.end()) { + statuses::SetLastError(abckit_Status_TODO); + return; + } + fields.erase(fieldsIter); + + auto& aiFields = ai->fields; + auto iter = std::find_if(aiFields.begin(), aiFields.end(), [&name](auto &field){ + return name == field.get()->name->impl; + }); + if (iter == aiFields.end()) { + statuses::SetLastError(abckit_Status_TODO); + return; + } + aiFields.erase(iter); +} + +} diff --git a/libabckit/src/adapter_dynamic/metadata_modify_dynamic.h b/libabckit/src/adapter_dynamic/metadata_modify_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..52f9b2752e3e3be019ae1089d1f85af2454d9fc6 --- /dev/null +++ b/libabckit/src/adapter_dynamic/metadata_modify_dynamic.h @@ -0,0 +1,63 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_DYNAMIC_METADATA_MODIFY_DYNAMIC_H +#define LIBABCKIT_SRC_ADAPTER_DYNAMIC_METADATA_MODIFY_DYNAMIC_H + +#include "libabckit/include/metadata.h" + +namespace libabckit { + +abckit_String *CreateStringDynamic(abckit_ModifyContext *ctxM, const char *value); +void MethodSetCodeDynamic(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code); +abckit_Module *FileAddExternalModuleDynamic(abckit_File *ctx, + const struct abckit_ExternalModuleCreateParams *params); +void ModuleRemoveImportDynamic(abckit_Module *m, abckit_ImportDescriptor *i); +abckit_ImportDescriptor *ModuleAddImportFromDynamicModuleDynamic( + abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params); +abckit_ExportDescriptor *DynamicModuleAddExportDynamic(abckit_Module *m, + const abckit_DynamicModuleExportCreateParams *params); +void ModuleRemoveExportDynamic(abckit_Module *m, abckit_ExportDescriptor *i); +abckit_Literal *CreateLiteralBoolDynamic(abckit_ModifyContext *ctx, bool value); +abckit_Literal *CreateLiteralU8Dynamic(abckit_ModifyContext *ctx, uint8_t value); +abckit_Literal *CreateLiteralU16Dynamic(abckit_ModifyContext *ctx, uint16_t value); +abckit_Literal *CreateLiteralU32Dynamic(abckit_ModifyContext *ctx, uint32_t value); +abckit_Literal *CreateLiteralU64Dynamic(abckit_ModifyContext *ctx, uint64_t value); +abckit_Literal *CreateLiteralFloatDynamic(abckit_ModifyContext *ctx, float value); +abckit_Literal *CreateLiteralDoubleDynamic(abckit_ModifyContext *ctx, double value); +abckit_Literal *CreateLiteralStringDynamic(abckit_ModifyContext *ctx, const char* value); +abckit_LiteralArray *CreateLiteralArrayDynamic(abckit_ModifyContext *ctxM, abckit_Literal **value, size_t size); + +abckit_Value *CreateValueU1Dynamic(abckit_ModifyContext *ctx, bool value); +abckit_Value *CreateValueDoubleDynamic(abckit_ModifyContext *ctx, double value); +abckit_Value *CreateValueStringDynamic(abckit_ModifyContext *ctx, const char *value); +abckit_Value *CreateLiteralArrayValueDynamic(abckit_ModifyContext *ctx, abckit_Value **value, size_t size); + +abckit_AnnotationInterface *ModuleAddAnnotationInterfaceDynamic(abckit_ModifyContext *ctx, abckit_Module *m, + const abckit_AnnotationInterfaceCreateParams *params); + +abckit_Annotation *ClassAddAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Class *klass, const abckit_AnnotationCreateParams *params); +void ClassRemoveAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Class *klass, abckit_Annotation *anno); +abckit_Annotation *MethodAddAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Method *method, const abckit_AnnotationCreateParams *params); +void MethodRemoveAnnotationDynamic(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno); +abckit_AnnotationElement *AnnotationAddAnnotationElementDynamic(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params); +void AnnotationRemoveAnnotationElementDynamic(abckit_ModifyContext *ctx, abckit_Annotation *anno, abckit_AnnotationElement *elem); +abckit_AnnotationInterfaceField *AnnotationInterfaceAddFieldDynamic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params); +void AnnotationInterfaceRemoveFieldDynamic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, abckit_AnnotationInterfaceField *field); +} + +#endif diff --git a/libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h b/libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..e0c8ab20ebeac0c3da8204dd206184f1a7f3072b --- /dev/null +++ b/libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_DYNAMIC_RUNTIME_ADAPTER_DYNAMIC_H +#define LIBABCKIT_SRC_ADAPTER_DYNAMIC_RUNTIME_ADAPTER_DYNAMIC_H + +#include "compiler/optimizer/ir/runtime_interface.h" +#include "libabckit/src/wrappers/abcfile_wrapper.h" + +namespace libabckit { + +using namespace ark; +using compiler::RuntimeInterface; + +class AbckitRuntimeAdapterDynamic : public RuntimeInterface { +public: + explicit AbckitRuntimeAdapterDynamic(const FileWrapper &abc_file) : abc_file_(abc_file) {} + + ~AbckitRuntimeAdapterDynamic() override = default; + + BinaryFilePtr GetBinaryFileForMethod([[maybe_unused]] MethodPtr method) const override + { + return const_cast(&abc_file_); + } + + uint32_t ResolveMethodIndex(MethodPtr parent_method, uint16_t index) const override + { + return abc_file_.ResolveOffsetByIndex(parent_method, index); + } + + MethodId GetMethodId(MethodPtr method) const override + { + return static_cast(reinterpret_cast(method)); + } + + size_t GetMethodTotalArgumentsCount(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // ASSERT(!mda.IsExternal()); + // panda_file::CodeDataAccessor cda(abc_file_, mda.GetCodeId().value()); + + // return cda.GetNumArgs(); + return abc_file_.GetMethodTotalArgumentsCount(method); + } + + size_t GetMethodArgumentsCount([[maybe_unused]] MethodPtr caller, MethodId id) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, panda_file::File::EntityId(id)); + // panda_file::ProtoDataAccessor pda(abc_file_, mda.GetProtoId()); + + // return pda.GetNumArgs(); + return abc_file_.GetMethodArgumentsCount(caller, id); + } + + size_t GetMethodRegistersCount(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // ASSERT(!mda.IsExternal()); + // panda_file::CodeDataAccessor cda(abc_file_, mda.GetCodeId().value()); + + // return cda.GetNumVregs(); + return abc_file_.GetMethodRegistersCount(method); + } + + const uint8_t *GetMethodCode(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // ASSERT(!mda.IsExternal()); + // panda_file::CodeDataAccessor cda(abc_file_, mda.GetCodeId().value()); + + // return cda.GetInstructions(); + return abc_file_.GetMethodCode(method); + } + + size_t GetMethodCodeSize(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // ASSERT(!mda.IsExternal()); + // panda_file::CodeDataAccessor cda(abc_file_, mda.GetCodeId().value()); + + // return cda.GetCodeSize(); + return abc_file_.GetMethodCodeSize(method); + } + + SourceLanguage GetMethodSourceLanguage(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // ASSERT(!mda.IsExternal()); + + // auto source_lang = mda.GetSourceLang(); + // ASSERT(source_lang.has_value()); + + // return static_cast(source_lang.value()); + return static_cast(abc_file_.GetMethodSourceLanguage(method)); + } + + size_t GetClassIdForMethod(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // return static_cast(mda.GetClassId().GetOffset()); + return abc_file_.GetClassIdForMethod(method); + } + + std::string GetClassNameFromMethod(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // auto string_data = abc_file_.GetStringData(mda.GetClassId()); + + // return std::string(reinterpret_cast(string_data.data)); + return abc_file_.GetClassNameFromMethod(method); + } + + std::string GetMethodName(MethodPtr method) const override + { + // panda_file::MethodDataAccessor mda(abc_file_, MethodCast(method)); + + // auto string_data = abc_file_.GetStringData(mda.GetNameId()); + + // return std::string(reinterpret_cast(string_data.data)); + return abc_file_.GetMethodName(method); + } + + std::string GetMethodFullName(MethodPtr method, bool /* with_signature */) const override + { + auto class_name = GetClassNameFromMethod(method); + auto method_name = GetMethodName(method); + + return class_name + "::" + method_name; + } + +private: + // static compiler::DataType::Type ToCompilerType(panda_file::Type type) + // { + // switch (type.GetId()) { + // case panda_file::Type::TypeId::VOID: + // return compiler::DataType::VOID; + // case panda_file::Type::TypeId::I32: + // return compiler::DataType::INT32; + // case panda_file::Type::TypeId::U32: + // return compiler::DataType::UINT32; + // case panda_file::Type::TypeId::I64: + // return compiler::DataType::INT64; + // case panda_file::Type::TypeId::U64: + // return compiler::DataType::UINT64; + // case panda_file::Type::TypeId::F64: + // return compiler::DataType::FLOAT64; + // case panda_file::Type::TypeId::REFERENCE: + // return compiler::DataType::REFERENCE; + // case panda_file::Type::TypeId::TAGGED: + // case panda_file::Type::TypeId::INVALID: + // return compiler::DataType::ANY; + // default: + // break; + // } + // UNREACHABLE(); + // } + + // static panda_file::File::EntityId MethodCast(RuntimeInterface::MethodPtr method) + // { + // return panda_file::File::EntityId(reinterpret_cast(method)); + // } + + const FileWrapper &abc_file_; +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_ADAPTER_DYNAMIC_RUNTIME_ADAPTER_DYNAMIC_H diff --git a/libabckit/src/adapter_dynamic/templates/BUILD.gn b/libabckit/src/adapter_dynamic/templates/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1e4d8e932f7072556be3c452327cd92066628aaf --- /dev/null +++ b/libabckit/src/adapter_dynamic/templates/BUILD.gn @@ -0,0 +1,22 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") + +ark_isa_gen("isa_gen_libabckit") { + sources = "$abckit_root/src/adapter_dynamic/templates" + requires = ["$abckit_root/scripts/inst_props_api.rb"] + template_files = ["inst_props_helpers_dynamic.inc.erb"] + destination = "$target_gen_dir/../generated" +} diff --git a/libabckit/src/adapter_dynamic/templates/inst_props_helpers_dynamic.inc.erb b/libabckit/src/adapter_dynamic/templates/inst_props_helpers_dynamic.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..da8d999542fdc03f6f827562d8b314243c6b159e --- /dev/null +++ b/libabckit/src/adapter_dynamic/templates/inst_props_helpers_dynamic.inc.erb @@ -0,0 +1,98 @@ +bool HasMethodIdOperandDynamic(abckit_IsaApiDynamicOpcode opcode) +{ + switch(opcode) { +% Panda::instructions.uniq{|i| i.mnemonic}.each_with_index do |inst, idx| +% res = Opcodes.find{|opc| opc.bc_opcode == inst.mnemonic} +% method_id_operand = inst.operands.find {|op| op.method_id?} +% if not res.nil? and not method_id_operand.nil? + case <%= res.abckit_opcode %>: +% end +% end + return true; + default: + return false; + } +} + +int GetMethodIdOperandIndexDynamic(abckit_IsaApiDynamicOpcode opcode) +{ + switch(opcode) { +% Panda::instructions.uniq{|i| i.mnemonic}.each_with_index do |inst, idx| +% res = Opcodes.find{|opc| opc.bc_opcode == inst.mnemonic} +% method_id_operand = inst.operands.find {|op| op.method_id?} +% if not res.nil? and not method_id_operand.nil? + case <%= res.abckit_opcode %>: + return <%= inst.operands.find_index(method_id_operand)%>; +% end +% end + default: + return -1; + } +} + +bool HasStringIdOperandDynamic(abckit_IsaApiDynamicOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiDynamicOpcode_LoadString: +% Panda::instructions.uniq{|i| i.mnemonic}.each_with_index do |inst, idx| +% res = Opcodes.find{|opc| opc.bc_opcode == inst.mnemonic } +% string_id_operand = inst.operands.find {|op| op.string_id?} +% if not res.nil? and not string_id_operand.nil? + case <%= res.abckit_opcode %>: +% end +% end + return true; + default: + return false; + } +} + +int GetStringIdOperandIndexDynamic(abckit_IsaApiDynamicOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiDynamicOpcode_LoadString: + return 0; +% Panda::instructions.uniq{|i| i.mnemonic}.each_with_index do |inst, idx| +% res = Opcodes.find{|opc| opc.bc_opcode == inst.mnemonic } +% string_id_operand = inst.operands.find {|op| op.string_id?} +% if not res.nil? and not string_id_operand.nil? + case <%= res.abckit_opcode %>: + return <%= inst.operands.find_index(string_id_operand) %>; +% end +% end + default: + return -1; + } +} + +bool HasLiteralArrayIdOperandDynamic(abckit_IsaApiDynamicOpcode opcode) +{ + switch(opcode) { +% Panda::instructions.uniq{|i| i.mnemonic}.each_with_index do |inst, idx| +% res = Opcodes.find{|opc| opc.bc_opcode == inst.mnemonic } +% litarr_id_operand = inst.operands.find {|op| op.literalarray_id?} +% if not res.nil? and not litarr_id_operand.nil? + case <%= res.abckit_opcode %>: +% end +% end + return true; + default: + return false; + } +} + +int GetLiteralArrayIdOperandIndexDynamic(abckit_IsaApiDynamicOpcode opcode) +{ + switch(opcode) { +% Panda::instructions.uniq{|i| i.mnemonic}.each_with_index do |inst, idx| +% res = Opcodes.find{|opc| opc.bc_opcode == inst.mnemonic && !inst.operands.find {|op| op.literalarray_id?}.nil? } +% litarr_id_operand = inst.operands.find {|op| op.literalarray_id?} +% if not res.nil? and not litarr_id_operand.nil? + case <%= res.abckit_opcode %>: + return <%= inst.operands.find_index(litarr_id_operand) %>; +% end +% end + default: + return -1; + } +} diff --git a/libabckit/src/adapter_static/BUILD.gn b/libabckit/src/adapter_static/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..0324d149d46c446b6eb445f2f1a65fa4a593b2bb --- /dev/null +++ b/libabckit/src/adapter_static/BUILD.gn @@ -0,0 +1,24 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ark_gen_file("get_intrinsic_id_static_inc") { + extra_dependencies = [ "$ark_root/runtime:arkruntime_gen_intrinsics_yaml" ] + template_file = "templates/get_intrinsic_id_static.inc.erb" + data = [ "$target_gen_dir/../../../static_core/runtime/intrinsics.yaml" ] + api = [ "$ark_root/runtime/templates/intrinsics.rb" ] + output_file = "$target_gen_dir/generated/get_intrinsic_id_static.inc" +} diff --git a/libabckit/src/adapter_static/abckit_static.cpp b/libabckit/src/adapter_static/abckit_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42d98e53ae970df075c0687c383784a61375abcf --- /dev/null +++ b/libabckit/src/adapter_static/abckit_static.cpp @@ -0,0 +1,480 @@ +/** + * Copyright (c) 2024 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 "abckit_static.h" +#include "inst.h" +#include "libabckit/src/adapter_static/helpers_static.h" +#include "libabckit/include/ir_core.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/statuses_impl.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/metadata_modify_impl.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/codegen/codegen_static.h" +#include "libabckit/src/wrappers/graph_wrapper/graph_wrapper.h" +#include "libabckit/src/adapter_static/runtime_adapter_static.h" +#include "libabckit/src/logger.h" +#include "libpandafile/file.h" + +#include "static_core/compiler/compiler_options.h" +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir_builder/ir_builder.h" + +#include "static_core/compiler/optimizer/optimizations/regalloc/reg_alloc_graph_coloring.h" +#include "static_core/compiler/optimizer/optimizations/cleanup.h" +#include "static_core/compiler/optimizer/optimizations/move_constants.h" +#include "static_core/compiler/optimizer/optimizations/regalloc/reg_alloc_resolver.h" +#include "static_core/compiler/optimizer/optimizations/lowering.h" +#include "static_core/bytecode_optimizer/check_resolver.h" +#include "static_core/bytecode_optimizer/reg_acc_alloc.h" +#include "static_core/bytecode_optimizer/reg_encoder.h" + +#include "static_core/abc2program/abc2program_driver.h" + +#include "static_core/assembler/assembly-emitter.h" +#include "static_core/assembler/mangling.h" + +#include +#include +#include +#include + +using namespace ark; + +namespace libabckit { + +[[maybe_unused]] static bool IsAbstract(pandasm::ItemMetadata *meta) +{ + uint32_t flags = meta->GetAccessFlags(); + return flags & ACC_ABSTRACT; +} + +abckit_String *CreateNameString(abckit_File *ctxI, std::string name) +{ + if (ctxI->strings.find(name) != ctxI->strings.end()) { + return ctxI->strings.at(name).get(); + } + + auto s = std::make_unique(); + s->impl = name; + ctxI->strings.insert({name, std::move(s)}); + return ctxI->strings[name].get(); +} + +static void CreateWrappers(pandasm::Program *prog, abckit_File *ctxI) +{ + std::unordered_set GlobalClassNames = {"ETSGLOBAL", "_GLOBAL"}; + static const std::string LambdaRecordKey = "LambdaObject"; + ctxI->program = reinterpret_cast(prog); + + // Collect modules + std::unordered_map> modulesMap; + for (auto &[recordName, record] : prog->recordTable) { + if (record.metadata->IsForeign()) { + // TODO: Create abckit_ImportDescriptor and abckit_ModuleDescriptor + continue; + } + + auto [moduleName, className] = ClassGetNames(recordName); + if (GlobalClassNames.find(className) != GlobalClassNames.end()) { + if (modulesMap.find(moduleName) != modulesMap.end()) { + LIBABCKIT_LOG(FATAL) << "Duplicated ETSGLOBAL for module: " << moduleName << '\n'; + } + + LIBABCKIT_LOG(DEBUG) << "Found module: '" << moduleName << "'\n"; + auto m = std::make_unique(); + m->ctxI = ctxI; + m->moduleName = CreateNameString(ctxI, moduleName); + modulesMap.insert({moduleName, std::move(m)}); + } + } + + // Collect classes + for (auto &[recordName, record] : prog->recordTable) { + if (record.metadata->IsForeign() || (recordName.find(LambdaRecordKey) != std::string::npos)) { + // TODO: find and fill abckit_ImportDescriptor + continue; + } + + // TODO: abckit_AnnotationInterface + + auto [moduleName, className] = ClassGetNames(recordName); + + if (GlobalClassNames.find(className) != GlobalClassNames.end()) { + continue; + } + + LIBABCKIT_LOG(DEBUG) << " Found class. module: '" << moduleName << "' class: '" << className << "'\n"; + assert(modulesMap.find(moduleName) != modulesMap.end()); + auto &classModule = modulesMap[moduleName]; + auto klass = std::make_unique(); + klass->m = classModule.get(); + abckit_ClassPayload classPayload; + classPayload.cl = reinterpret_cast(&record); + klass->impl = classPayload; + + classModule->ct.emplace(className, std::move(klass)); + } + + // Functions + for (auto &[functionName, function] : prog->functionTable) { + if (function.metadata->IsForeign() || (functionName.substr(0, LambdaRecordKey.size()) == LambdaRecordKey)) { + // TODO: find and fill abckit_ImportDescriptor + continue; + } + + if (IsAbstract(function.metadata.get())) { + // TODO: ? + continue; + } + + auto [moduleName, className] = FuncGetNames(functionName); + LIBABCKIT_LOG(DEBUG) << " Found function. module: '" << moduleName << "' class: '" << className << "' function: '" + << functionName << "'\n"; + assert(modulesMap.find(moduleName) != modulesMap.end()); + auto &functionModule = modulesMap[moduleName]; + auto method = std::make_unique(); + method->m = functionModule.get(); + method->impl = reinterpret_cast(&function); + + for (auto &anno_impl: function.metadata->GetAnnotations()) { + auto anno = std::make_unique(); + + for (auto &anno_elem_impl: anno_impl.GetElements()) { + auto anno_elem = std::make_unique(); + anno_elem->ann = anno.get(); + anno_elem->name = anno_elem_impl.GetName(); + auto value = std::make_unique(); + value->impl = reinterpret_cast(anno_elem_impl.GetValue()); + anno_elem->value = std::move(value); + + anno->elements.emplace_back(std::move(anno_elem)); + } + method->annotations.emplace_back(std::move(anno)); + } + + if (GlobalClassNames.find(className) != GlobalClassNames.end()) { + functionModule->methods.emplace_back(std::move(method)); + } else { + assert(functionModule->ct.find(className) != functionModule->ct.end()); + auto &klass = functionModule->ct[className]; + method->klass = klass.get(); + klass->methods.emplace_back(std::move(method)); + } + } + + // TODO: abckit_ExportDescriptor + // TODO: abckit_ModulePayload + + for (auto &[moduleName, module] : modulesMap) { + ctxI->localModules.insert({moduleName, std::move(module)}); + } + + // Strings + for (auto &sImpl : prog->strings) { + auto s = std::make_unique(); + s->impl = sImpl; + ctxI->strings.insert({sImpl, std::move(s)}); + } +} + +typedef struct CtxIInternal { + ark::abc2program::Abc2ProgramDriver *driver = nullptr; +} CtxIInternal; + +abckit_File *OpenAbcStatic(const char *path) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << path << '\n'; + auto *abc2program = new ark::abc2program::Abc2ProgramDriver(); + if (!abc2program->Compile(path)) { + LIBABCKIT_LOG(DEBUG) << "Failed to open " << path << "\n"; + delete abc2program; + return nullptr; + } + pandasm::Program &prog = abc2program->GetProgram(); + auto ctxI = new abckit_File(); + ctxI->mode = Mode::STATIC; + CreateWrappers(&prog, ctxI); + + auto pf = panda_file::File::Open(path); + if (pf == nullptr) { + LIBABCKIT_LOG(DEBUG) << "Failed to panda_file::File::Open\n"; + delete abc2program; + delete ctxI; + return nullptr; + } + + auto panda_file_version = pf->GetHeader()->version; + uint8_t *abckit_version = *reinterpret_cast(panda_file_version.data()); + + ctxI->version = new uint8_t[ABCKIT_VERSION_SIZE]; + std::copy(abckit_version, abckit_version + sizeof(uint8_t) * ABCKIT_VERSION_SIZE, ctxI->version); + + ctxI->internal = new CtxIInternal { abc2program }; + return ctxI; +} + +void DestroyInspectContextStatic(abckit_File *ctxI) +{ + auto *CtxIInternal = reinterpret_cast(ctxI->internal); + delete CtxIInternal->driver; + delete CtxIInternal; + delete [] ctxI->version; + delete ctxI; +} + +void WriteAbcStatic(abckit_File *ctxI, const char *path) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << path << '\n'; + + auto program = reinterpret_cast(ctxI->program); + + auto emitDebugInfo = false; + std::map *statp = nullptr; + ark::pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = nullptr; + + if (!pandasm::AsmEmitter::Emit(path, *program, statp, mapsp, emitDebugInfo)) { + LIBABCKIT_LOG(DEBUG) << "FAILURE\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return; + } + + DestroyInspectContextStatic(ctxI); + + return; +} + +void TransformClassStatic(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data)) +{ + LIBABCKIT_LOG_FUNC + + auto ctxM = std::make_unique(); + + ctxM->ctxI = c->m->ctxI; + + LIBABCKIT_LOG(DEBUG) << "before TransformClass: " << reinterpret_cast(c->impl.cl)->name << '\n'; + + cb(ctxM.get(), c, data); +} + +void TransformMethodStatic(abckit_Method *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + + auto ctxM = std::make_unique(); + + ctxM->ctxI = m->m->ctxI; + + LIBABCKIT_LOG(DEBUG) << "before TransformMethod: " << reinterpret_cast(m->impl)->name << '\n'; + + cb(ctxM.get(), m, data); +} + +struct CtxGInternal { + ArenaAllocator *allocator; + ArenaAllocator *localAllocator; + const abckit_IrInterface *irInterface; + AbckitRuntimeAdapterStatic *runtimeAdapter; +}; + +abckit_Graph *codeToGraphStatic(abckit_File *ctxI, abckit_Code *code) +{ + LIBABCKIT_LOG_FUNC + + ark::compiler::g_options.SetCompilerUseSafepoint(false); + auto *fw = code->method; + auto *func = reinterpret_cast(fw->impl); + LIBABCKIT_LOG(DEBUG) << func->name << '\n'; + LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG); + + auto program = reinterpret_cast(ctxI->program); + + // Add strings to program + for (auto &[sImpl, s] : ctxI->strings) { + program->strings.insert(s->impl); + } + + auto *maps = new pandasm::AsmEmitter::PandaFileToPandaAsmMaps(); // FIXME + auto pf = pandasm::AsmEmitter::Emit(*program, maps).release(); + if (pf == nullptr) { + LIBABCKIT_LOG(DEBUG) << "pf == nullptr\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + uint32_t methodOffset = 0; + auto funcFullName = pandasm::MangleFunctionName(func->name, func->params, func->returnType); + for (auto &[id, s] : maps->methods) { + if (s == funcFullName) { + methodOffset = id; + } + } + if (methodOffset == 0) { + LIBABCKIT_LOG(DEBUG) << "methodOffset == 0\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + auto *irInterface = + new abckit_IrInterface(maps->methods, maps->fields, maps->classes, maps->strings, maps->literalarrays); + + ArenaAllocator *allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER); + ArenaAllocator *localAllocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + AbckitRuntimeAdapterStatic *adapter = new AbckitRuntimeAdapterStatic(*pf); + + auto methodPtr = reinterpret_cast(methodOffset); // FIXME + auto graph = + allocator->New(allocator, localAllocator, Arch::NONE, methodPtr, adapter, /*osrMode*/ false, + /*parent*/ nullptr, /*isDynamic*/ false, /*bytecodeOpt*/ true); + if (graph == nullptr) { + LIBABCKIT_LOG(DEBUG) << "graph == nullptr\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + graph->SetLanguage(SourceLanguage::ETS); + graph->SetBCT(); +#ifndef NDEBUG + graph->SetLowLevelInstructionsEnabled(); +#endif + + // build map from pc to pandasm::ins (to re-build line-number info in BytecodeGen) + // BuildMapFromPcToIns(function, irInterface, graph, methodPtr); + + bool irBuilderRes = graph->RunPass(); + if (!irBuilderRes) { + LIBABCKIT_LOG(DEBUG) << "!irBuilderRes\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + graph->RunPass(); + graph->RunPass(false); + std::vector> instsToRemove; + for (auto bb : graph->GetBlocksRPO()) { + for ([[maybe_unused]] auto inst : bb->AllInsts()) { + if (inst->IsSaveState() || (inst->GetOpcode() == compiler::Opcode::SaveStateDeoptimize)) { + ASSERT(!inst->HasUsers()); + /* + * TODO(nsizov): find out why we still have non-movable + * SaveStates with no users + */ + instsToRemove.emplace_back(bb, inst); + } + } + } + for (auto &[bb, inst] : instsToRemove) { + bb->RemoveInst(inst); + } + CheckInvalidOpcodes(graph, false); + + auto ctxG = new abckit_Graph; + ctxG->ctxI = ctxI; + ctxG->method = code->method; + ctxG->irInterface = irInterface; + ctxG->impl = graph; + GraphWrapper::CreateGraphWrappers(ctxG); + + auto *ctxGInternal = new CtxGInternal {allocator, localAllocator, irInterface, adapter}; + ctxG->internal = ctxGInternal; + + delete code; // not needed anymore, code wath translated to graph + delete maps; // not needed anymore, maps were copied to abckit_IrInterface + + return ctxG; +} + +abckit_Code *graphToCodeStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + + auto method = ctxG->method; + auto *func = reinterpret_cast(method->impl); + + auto graph = ctxG->impl; + + graph->RemoveUnreachableBlocks(); + + CheckInvalidOpcodes(graph, false); + + LIBABCKIT_LOG(DEBUG) << "======================== BEFORE CODEGEN ========================\n"; + LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG); + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + + LIBABCKIT_LOG_DUMP(graph->Dump(&std::cerr), DEBUG); + + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + + ctxG->impl->InvalidateAnalysis(); + + graph->RunPass(); + + graph->RunPass(false); + + graph->RunPass(); + graph->RunPass(); + compiler::RegAllocResolver(graph).ResolveCatchPhis(); + + if (!graph->RunPass(compiler::VIRTUAL_FRAME_SIZE)) { + LIBABCKIT_LOG(DEBUG) << func->name << ": RegAllocGraphColoring failed!\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + if (!graph->RunPass()) { + LIBABCKIT_LOG(DEBUG) << func->name << ": RegEncoder failed!\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + auto *newFunc = new pandasm::Function("newCode", SourceLanguage::ETS); + auto code = new abckit_Code({reinterpret_cast(newFunc), method}); + if (!graph->RunPass(newFunc, ctxG->irInterface)) { + LIBABCKIT_LOG(DEBUG) << func->name << ": Code generation failed!\n"; + statuses::SetLastError(abckit_Status::abckit_Status_TODO); + return nullptr; + } + + newFunc->valueOfFirstParam = static_cast(graph->GetStackSlotsCount()) - 1L; + newFunc->regsNum = static_cast(newFunc->valueOfFirstParam + 1U); + + LIBABCKIT_LOG(DEBUG) << "======================== AFTER CODEGEN ========================\n"; + LIBABCKIT_LOG_DUMP(newFunc->DebugDump(), DEBUG); + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + + DestroyGraphContextStatic(ctxG); + return code; +} + +void DestroyGraphContextStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + auto *ctxGInternal = (CtxGInternal *)ctxG->internal; + // dirty hack to obtain PandaFile pointer + // TODO(mshimenkov): refactor it + auto *fileWrapper = reinterpret_cast(ctxGInternal->runtimeAdapter->GetBinaryFileForMethod(nullptr)); + delete fileWrapper; + delete ctxGInternal->runtimeAdapter; + delete ctxGInternal->irInterface; + delete ctxGInternal->localAllocator; + delete ctxGInternal->allocator; + delete ctxGInternal; + delete ctxG; +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_static/abckit_static.h b/libabckit/src/adapter_static/abckit_static.h new file mode 100644 index 0000000000000000000000000000000000000000..3a341bd0f002dda7c7a19d13cc8d71e2f7b992bf --- /dev/null +++ b/libabckit/src/adapter_static/abckit_static.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_STATIC_ABCKIT_STATIC_H +#define LIBABCKIT_SRC_ADAPTER_STATIC_ABCKIT_STATIC_H + +#include "libabckit/include/ir_core.h" +#include "libabckit/include/metadata.h" + + +namespace libabckit { + +abckit_File *OpenAbcStatic(const char *path); +void WriteAbcStatic(abckit_File *ctx, const char *path); +void TransformMethodStatic(abckit_Method *ctx, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Method *method, void *data)); +void TransformClassStatic(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data)); +abckit_Graph *codeToGraphStatic(abckit_File *ctxI, abckit_Code *code); +abckit_Code *graphToCodeStatic(abckit_Graph *ctxG); +void DestroyGraphContextStatic(abckit_Graph *ctxG); +void DestroyInspectContextStatic(abckit_File *ctxI); + +} // namespace libabckit + +#endif diff --git a/libabckit/src/adapter_static/helpers_static.cpp b/libabckit/src/adapter_static/helpers_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1161118b7e1c1b6de11cb339448d31344fd3036d --- /dev/null +++ b/libabckit/src/adapter_static/helpers_static.cpp @@ -0,0 +1,859 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/adapter_static/helpers_static.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/logger.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/wrappers/pandasm_wrapper.h" + +#include "static_core/assembler/assembly-program.h" +#include "static_core/assembler/mangling.h" +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir/basicblock.h" + +#include "bct_intrinsics_opcodes.inc" + +using namespace ark; + +namespace libabckit { + +std::tuple ClassGetNames(const std::string &fullName) +{ + static const std::string GlobalClassName= "ETSGLOBAL"; + std::string::size_type pos = fullName.rfind('.'); + if (pos == std::string::npos) { + return {".", fullName}; + } + if (pos < GlobalClassName.size()) { + return {fullName.substr(0, pos), fullName.substr(pos + 1)}; + } + auto rawModuleName = fullName.substr(pos - GlobalClassName.size(), GlobalClassName.size()); + if (rawModuleName == GlobalClassName) { + std::string::size_type pos2 = fullName.substr(0, pos).rfind('.'); + return {fullName.substr(0, pos2), fullName.substr(pos2 + 1)}; + } + return {fullName.substr(0, pos), fullName.substr(pos + 1)}; +} + +std::tuple FuncGetNames(const std::string &fullSig) +{ + auto fullName = fullSig.substr(0, fullSig.find(':')); + std::string::size_type pos = fullName.rfind('.'); + if (pos == std::string::npos) { + return {".", "ETSGLOBAL"}; + } + return ClassGetNames(fullName.substr(0, pos)); +} + +std::string FuncNameCropModule(const std::string &fullSig) +{ + auto fullName = fullSig.substr(0, fullSig.find(':')); + std::string::size_type dotPos = fullName.rfind('.'); + if (dotPos != std::string::npos) { + return fullSig.substr(dotPos + 1); + } + return fullSig; +} + +void CheckInvalidOpcodes(compiler::Graph *graph, bool isDynamic) +{ +#ifndef NDEBUG + for (auto *bb : graph->GetBlocksRPO()) { + for (auto *inst : bb->AllInsts()) { + bool isInvalid = isDynamic ? (GetDynamicOpcode(inst) == abckit_IsaApiDynamicOpcode_INVALID) : (GetStaticOpcode(inst) == abckit_IsaApiStaticOpcode_INVALID); + if (isInvalid) { + std::ostringstream out; + LIBABCKIT_LOG_DUMP(inst->DumpOpcode(&out), DEBUG); + LIBABCKIT_LOG(DEBUG) << "ASSERTION FAILED: Invalid opcode encountered: " << out.str() << std::endl; + assert(false); + } + } + } +#endif +} + +abckit_IsaApiStaticOpcode GetStaticOpcode(compiler::Inst *inst) +{ + auto opcode = inst->GetOpcode(); + switch (opcode) { + case compiler::Opcode::CallStatic: + return abckit_IsaApiStaticOpcode_CallStatic; + case compiler::Opcode::CallVirtual: + return abckit_IsaApiStaticOpcode_CallVirtual; + case compiler::Opcode::LoadStatic: + return abckit_IsaApiStaticOpcode_LoadStatic; + case compiler::Opcode::LoadString: + return abckit_IsaApiStaticOpcode_LoadString; + case compiler::Opcode::LoadObject: + return abckit_IsaApiStaticOpcode_LoadObject; + case compiler::Opcode::Sub: + return abckit_IsaApiStaticOpcode_Sub; + case compiler::Opcode::ReturnVoid: + return abckit_IsaApiStaticOpcode_ReturnVoid; + case compiler::Opcode::Parameter: + return abckit_IsaApiStaticOpcode_Parameter; + case compiler::Opcode::Constant: + return abckit_IsaApiStaticOpcode_Constant; + case compiler::Opcode::Cmp: + return abckit_IsaApiStaticOpcode_Cmp; + case compiler::Opcode::Cast: + return abckit_IsaApiStaticOpcode_Cast; + case compiler::Opcode::Return: + return abckit_IsaApiStaticOpcode_Return; + case compiler::Opcode::Add: + return abckit_IsaApiStaticOpcode_Add; + case compiler::Opcode::Mul: + return abckit_IsaApiStaticOpcode_Mul; + case compiler::Opcode::Mod: + return abckit_IsaApiStaticOpcode_Mod; + case compiler::Opcode::Div: + return abckit_IsaApiStaticOpcode_Div; + case compiler::Opcode::Neg: + return abckit_IsaApiStaticOpcode_Neg; + case compiler::Opcode::AddI: + return abckit_IsaApiStaticOpcode_AddI; + case compiler::Opcode::DivI: + return abckit_IsaApiStaticOpcode_DivI; + case compiler::Opcode::SubI: + return abckit_IsaApiStaticOpcode_SubI; + case compiler::Opcode::MulI: + return abckit_IsaApiStaticOpcode_MulI; + case compiler::Opcode::ModI: + return abckit_IsaApiStaticOpcode_ModI; + case compiler::Opcode::Shl: + return abckit_IsaApiStaticOpcode_Shl; + case compiler::Opcode::Shr: + return abckit_IsaApiStaticOpcode_Shr; + case compiler::Opcode::AShr: + return abckit_IsaApiStaticOpcode_AShr; + case compiler::Opcode::ShlI: + return abckit_IsaApiStaticOpcode_ShlI; + case compiler::Opcode::ShrI: + return abckit_IsaApiStaticOpcode_ShrI; + case compiler::Opcode::AShrI: + return abckit_IsaApiStaticOpcode_AShrI; + case compiler::Opcode::And: + return abckit_IsaApiStaticOpcode_And; + case compiler::Opcode::Or: + return abckit_IsaApiStaticOpcode_Or; + case compiler::Opcode::Xor: + return abckit_IsaApiStaticOpcode_Xor; + case compiler::Opcode::AndI: + return abckit_IsaApiStaticOpcode_AndI; + case compiler::Opcode::OrI: + return abckit_IsaApiStaticOpcode_OrI; + case compiler::Opcode::XorI: + return abckit_IsaApiStaticOpcode_XorI; + case compiler::Opcode::Not: + return abckit_IsaApiStaticOpcode_Not; + case compiler::Opcode::LenArray: + return abckit_IsaApiStaticOpcode_LenArray; + case compiler::Opcode::If: + return abckit_IsaApiStaticOpcode_If; + case compiler::Opcode::NullPtr: + return abckit_IsaApiStaticOpcode_NullPtr; + case compiler::Opcode::Phi: + return abckit_IsaApiStaticOpcode_Phi; + case compiler::Opcode::LoadUndefined: + return abckit_IsaApiStaticOpcode_LoadUndefined; + case compiler::Opcode::Try: + return abckit_IsaApiStaticOpcode_Try; + case compiler::Opcode::CatchPhi: + return abckit_IsaApiStaticOpcode_CatchPhi; + case compiler::Opcode::Intrinsic: + return GetStaticIntrinsicOpcode(inst->CastToIntrinsic()); + default: + LIBABCKIT_LOG(DEBUG) << "compiler->abckit INVALID\n"; + return abckit_IsaApiStaticOpcode_INVALID; + } + LIBABCKIT_UNREACHABLE +} + +abckit_IsaApiDynamicOpcode GetDynamicOpcode(compiler::Inst *inst) +{ + auto opcode = inst->GetOpcode(); + switch (opcode) { + case compiler::Opcode::LoadString: + return abckit_IsaApiDynamicOpcode_LoadString; + case compiler::Opcode::Parameter: + return abckit_IsaApiDynamicOpcode_Parameter; + case compiler::Opcode::Constant: + return abckit_IsaApiDynamicOpcode_Constant; + case compiler::Opcode::If: + return abckit_IsaApiDynamicOpcode_if; + case compiler::Opcode::Phi: + return abckit_IsaApiDynamicOpcode_Phi; + case compiler::Opcode::Try: + return abckit_IsaApiDynamicOpcode_Try; + case compiler::Opcode::CatchPhi: + return abckit_IsaApiDynamicOpcode_CatchPhi; + case compiler::Opcode::Intrinsic: + switch(inst->CastToIntrinsic()->GetIntrinsicId()) { + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STRING: + return abckit_IsaApiDynamicOpcode_LoadString; + default: + break; + } + return GetDynamicIntrinsicOpcode(inst->CastToIntrinsic()); + default: + LIBABCKIT_LOG(DEBUG) << "compiler->abckit INVALID\n"; + return abckit_IsaApiDynamicOpcode_INVALID; + } + LIBABCKIT_UNREACHABLE +} + +abckit_TypeId TypeToTypeId(compiler::DataType::Type type) +{ + LIBABCKIT_LOG(DEBUG) << "compiler->abckit\n"; + switch (type) { + case compiler::DataType::Type::REFERENCE: + return abckit_TypeId::abckit_TypeId_REFERENCE; + case compiler::DataType::Type::BOOL: + return abckit_TypeId::abckit_TypeId_U1; + case compiler::DataType::Type::UINT8: + return abckit_TypeId::abckit_TypeId_U8; + case compiler::DataType::Type::INT8: + return abckit_TypeId::abckit_TypeId_I8; + case compiler::DataType::Type::UINT16: + return abckit_TypeId::abckit_TypeId_U16; + case compiler::DataType::Type::INT16: + return abckit_TypeId::abckit_TypeId_I16; + case compiler::DataType::Type::UINT32: + return abckit_TypeId::abckit_TypeId_U32; + case compiler::DataType::Type::INT32: + return abckit_TypeId::abckit_TypeId_I32; + case compiler::DataType::Type::UINT64: + return abckit_TypeId::abckit_TypeId_U64; + case compiler::DataType::Type::INT64: + return abckit_TypeId::abckit_TypeId_I64; + case compiler::DataType::Type::FLOAT32: + return abckit_TypeId::abckit_TypeId_F32; + case compiler::DataType::Type::FLOAT64: + return abckit_TypeId::abckit_TypeId_F64; + case compiler::DataType::Type::ANY: + return abckit_TypeId::abckit_TypeId_ANY; + case compiler::DataType::Type::VOID: + return abckit_TypeId::abckit_TypeId_VOID; + case compiler::DataType::Type::POINTER: + case compiler::DataType::Type::NO_TYPE: + default: + LIBABCKIT_LOG(DEBUG) << "compiler->abckit INVALID\n"; + return abckit_TypeId::abckit_TypeId_INVALID; + } + LIBABCKIT_UNREACHABLE +} + +compiler::DataType::Type TypeIdToType(abckit_TypeId typeId) +{ + LIBABCKIT_LOG(DEBUG) << "abckit->compiler\n"; + switch (typeId) { + case abckit_TypeId::abckit_TypeId_REFERENCE: + return compiler::DataType::Type::REFERENCE; + case abckit_TypeId::abckit_TypeId_U1: + return compiler::DataType::Type::BOOL; + case abckit_TypeId::abckit_TypeId_U8: + return compiler::DataType::Type::UINT8; + case abckit_TypeId::abckit_TypeId_I8: + return compiler::DataType::Type::INT8; + case abckit_TypeId::abckit_TypeId_U16: + return compiler::DataType::Type::UINT16; + case abckit_TypeId::abckit_TypeId_I16: + return compiler::DataType::Type::INT16; + case abckit_TypeId::abckit_TypeId_U32: + return compiler::DataType::Type::UINT32; + case abckit_TypeId::abckit_TypeId_I32: + return compiler::DataType::Type::INT32; + case abckit_TypeId::abckit_TypeId_U64: + return compiler::DataType::Type::UINT64; + case abckit_TypeId::abckit_TypeId_I64: + return compiler::DataType::Type::INT64; + case abckit_TypeId::abckit_TypeId_F32: + return compiler::DataType::Type::FLOAT32; + case abckit_TypeId::abckit_TypeId_F64: + return compiler::DataType::Type::FLOAT64; + case abckit_TypeId::abckit_TypeId_ANY: + return compiler::DataType::Type::ANY; + case abckit_TypeId::abckit_TypeId_VOID: + return compiler::DataType::Type::VOID; + case abckit_TypeId::abckit_TypeId_INVALID: + default: + LIBABCKIT_LOG(DEBUG) << "abckit->compiler INVALID\n"; + return compiler::DataType::Type::NO_TYPE; + } + LIBABCKIT_UNREACHABLE +} + +ark::compiler::ConditionCode CcToCc(abckit_IsaApiDynamicConditionCode cc) +{ + LIBABCKIT_LOG(DEBUG) << "abckit->compiler\n"; + switch (cc) { + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_EQ: + return ark::compiler::ConditionCode::CC_EQ; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_NE: + return ark::compiler::ConditionCode::CC_NE; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_LT: + return ark::compiler::ConditionCode::CC_LT; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_LE: + return ark::compiler::ConditionCode::CC_LE; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_GT: + return ark::compiler::ConditionCode::CC_GT; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_GE: + return ark::compiler::ConditionCode::CC_GE; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_B: + return ark::compiler::ConditionCode::CC_B; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_BE: + return ark::compiler::ConditionCode::CC_BE; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_A: + return ark::compiler::ConditionCode::CC_A; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_AE: + return ark::compiler::ConditionCode::CC_AE; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_TST_EQ: + return ark::compiler::ConditionCode::CC_TST_EQ; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_TST_NE: + return ark::compiler::ConditionCode::CC_TST_NE; + case abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_NONE: + break; + } + LIBABCKIT_LOG(DEBUG) << "abckit->compiler CcToCc INVALID\n"; + LIBABCKIT_UNREACHABLE +} + +ark::compiler::ConditionCode CcToCc(abckit_IsaApiStaticConditionCode cc) +{ + LIBABCKIT_LOG(DEBUG) << "abckit->compiler\n"; + switch (cc) { + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_EQ: + return ark::compiler::ConditionCode::CC_EQ; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_NE: + return ark::compiler::ConditionCode::CC_NE; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_LT: + return ark::compiler::ConditionCode::CC_LT; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_LE: + return ark::compiler::ConditionCode::CC_LE; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_GT: + return ark::compiler::ConditionCode::CC_GT; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_GE: + return ark::compiler::ConditionCode::CC_GE; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_B: + return ark::compiler::ConditionCode::CC_B; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_BE: + return ark::compiler::ConditionCode::CC_BE; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_A: + return ark::compiler::ConditionCode::CC_A; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_AE: + return ark::compiler::ConditionCode::CC_AE; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_TST_EQ: + return ark::compiler::ConditionCode::CC_TST_EQ; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_TST_NE: + return ark::compiler::ConditionCode::CC_TST_NE; + case abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_NONE: + break; + } + LIBABCKIT_LOG(DEBUG) << "abckit->compiler CcToCc INVALID\n"; + LIBABCKIT_UNREACHABLE +} + +// abckit_IsaApiDynamicConditionCode CcToDynamicCc(ark::compiler::ConditionCode cc); +// abckit_IsaApiStaticConditionCode CcToStaticCc(ark::compiler::ConditionCode cc); + +abckit_IsaApiDynamicConditionCode CcToDynamicCc(ark::compiler::ConditionCode cc) +{ + LIBABCKIT_LOG(DEBUG) << "abckit->compiler\n"; + switch (cc) { + case ark::compiler::ConditionCode::CC_EQ: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_EQ; + case ark::compiler::ConditionCode::CC_NE: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_NE; + case ark::compiler::ConditionCode::CC_LT: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_LT; + case ark::compiler::ConditionCode::CC_LE: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_LE; + case ark::compiler::ConditionCode::CC_GT: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_GT; + case ark::compiler::ConditionCode::CC_GE: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_GE; + case ark::compiler::ConditionCode::CC_B: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_B; + case ark::compiler::ConditionCode::CC_BE: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_BE; + case ark::compiler::ConditionCode::CC_A: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_A; + case ark::compiler::ConditionCode::CC_AE: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_AE; + case ark::compiler::ConditionCode::CC_TST_EQ: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_TST_EQ; + case ark::compiler::ConditionCode::CC_TST_NE: + return abckit_IsaApiDynamicConditionCode::abckit_IsaApiDynamicConditionCode_CC_TST_NE; + default: + break; + } + LIBABCKIT_LOG(DEBUG) << "compiler->abckit CcToDynamicCc INVALID\n"; + LIBABCKIT_UNREACHABLE +} + +abckit_IsaApiStaticConditionCode CcToStaticCc(ark::compiler::ConditionCode cc) +{ + LIBABCKIT_LOG(DEBUG) << "abckit->compiler\n"; + switch (cc) { + case ark::compiler::ConditionCode::CC_EQ: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_EQ; + case ark::compiler::ConditionCode::CC_NE: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_NE; + case ark::compiler::ConditionCode::CC_LT: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_LT; + case ark::compiler::ConditionCode::CC_LE: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_LE; + case ark::compiler::ConditionCode::CC_GT: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_GT; + case ark::compiler::ConditionCode::CC_GE: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_GE; + case ark::compiler::ConditionCode::CC_B: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_B; + case ark::compiler::ConditionCode::CC_BE: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_BE; + case ark::compiler::ConditionCode::CC_A: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_A; + case ark::compiler::ConditionCode::CC_AE: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_AE; + case ark::compiler::ConditionCode::CC_TST_EQ: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_TST_EQ; + case ark::compiler::ConditionCode::CC_TST_NE: + return abckit_IsaApiStaticConditionCode::abckit_IsaApiStaticConditionCode_CC_TST_NE; + default: + break; + } + LIBABCKIT_LOG(DEBUG) << "compiler->abckit CcToStaticCc INVALID\n"; + LIBABCKIT_UNREACHABLE +} + +void SetLastError(abckit_Status err) { + LIBABCKIT_LOG(DEBUG) << "error code: " << err << std::endl; + statuses::SetLastError(err); +} + +uint32_t GetClassOffset(abckit_Graph *ctxG, abckit_Class *klass) +{ + assert(ctxG->ctxI->mode == Mode::STATIC); + + auto *rec = reinterpret_cast(klass->impl.cl); + LIBABCKIT_LOG(DEBUG) << "className: " << rec->name << "\n"; + + uint32_t classOffset = 0; + for (auto &[id, s] : ctxG->irInterface->classes) { + if (s == rec->name) { + classOffset = id; + } + } + if (classOffset == 0) { + LIBABCKIT_LOG(DEBUG) << "classOffset == 0\n"; + LIBABCKIT_UNREACHABLE + } + LIBABCKIT_LOG(DEBUG) << "classOffset: " << classOffset << "\n"; + return classOffset; +} + +uint32_t GetMethodOffset(abckit_Graph *ctxG, abckit_Method *method) +{ + + std::string funcName = "__ABCKIT_INVALID__"; + if(method->m->ctxI->mode == Mode::DYNAMIC) { + auto *func = PandasmWrapper::GetWrappedFunction(method->impl); + funcName = func->name; + delete func; + } else { + auto *func = reinterpret_cast(method->impl); + funcName = func->name; + } + + assert(funcName != "__ABCKIT_INVALID__"); + LIBABCKIT_LOG(DEBUG) << "methodName: " << funcName << "\n"; + + uint32_t methodOffset = 0; + for (auto &[id, s] : ctxG->irInterface->methods) { + if (pandasm::DeMangleName(s) == funcName) { + methodOffset = id; + } + } + if (methodOffset == 0) { + LIBABCKIT_LOG(DEBUG) << "methodOffset == 0\n"; + LIBABCKIT_UNREACHABLE + } + LIBABCKIT_LOG(DEBUG) << "methodOffset: " << methodOffset << "\n"; + return methodOffset; +} + +uint32_t GetStringOffset(abckit_Graph *ctxG, abckit_String *string) +{ + uint32_t stringOffset = 0; + for(auto &[id, s] : ctxG->irInterface->strings) { + if (s == string->impl) { + stringOffset = id; + } + } + + if (stringOffset == 0) { + // Newly created string + std::srand(0); + do { + LIBABCKIT_LOG(DEBUG) << "generating new stringOffset\n"; + stringOffset = rand() % 1000; + } while(ctxG->irInterface->strings.find(stringOffset) != ctxG->irInterface->strings.end()); + // insert new string id + ctxG->irInterface->strings.insert({stringOffset, string->impl}); + } + + LIBABCKIT_LOG(DEBUG) << "stringOffset: " << stringOffset << "\n"; + return stringOffset; +} + +uint32_t GetLiteralArrayOffset(abckit_Graph *ctxG, abckit_LiteralArray *arr) +{ + std::string arrName = "__ABCKIT_INVALID__"; + if (ctxG->ctxI->mode == Mode::DYNAMIC) { + auto litarrTable = PandasmWrapper::GetUnwrappedLiteralArrayTable(ctxG->ctxI->program); + for(auto &[id, s] : litarrTable) { + if (s == arr) { + arrName = id; + } + } + } else { + auto* prog = reinterpret_cast(ctxG->ctxI->program); + for(auto &[id, s] : prog->literalarrayTable) { + if (&s == reinterpret_cast(arr)) { + arrName = id; + } + } + } + assert(arrName != "__ABCKIT_INVALID__"); + + uint32_t arrayOffset = 0; + for(auto &[id, s] : ctxG->irInterface->literalarrays) { + if (s == arrName) { + arrayOffset = id; + } + } + + if (arrayOffset == 0) { + // Newly created literal array + std::srand(0); + do { + LIBABCKIT_LOG(DEBUG) << "generating new arrayOffset\n"; + arrayOffset = rand() % 1000; + } while(ctxG->irInterface->literalarrays.find(arrayOffset) != ctxG->irInterface->literalarrays.end()); + // insert new literal array + ctxG->irInterface->literalarrays.insert({arrayOffset, arrName}); + } + + return arrayOffset; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, compiler::IntrinsicInst::IntrinsicId intrinsicId) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {2U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input1->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {3U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input1->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input2->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrinsic_id = intrinsicId; + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsic_id); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {2U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input1->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, compiler::DataType::Type retType, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(retType, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XFF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XFF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XFF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, uint64_t imm1, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XFF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm1); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XFF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm1); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0, + uint64_t imm1, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrinsic_id = intrinsicId; + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsic_id); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {2U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input1->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm1); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {4U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(acc->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input1->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input2->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1, uint64_t imm2, + abckit_Inst *input0, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm0); + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm1); + intrImpl->AddImm(ctxG->impl->GetAllocator(), imm2); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {5U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(acc->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input1->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input2->impl, compiler::DataType::ANY); + intrImpl->AppendInputAndType(input3->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args, + compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {argCount+1}; + intrImpl->ReserveInputs(argCount+1); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + for (size_t index = 0; index < argCount; ++index) { + abckit_Inst *input = va_arg(args, abckit_Inst *); + intrImpl->AppendInputAndType(input->impl, compiler::DataType::ANY); + } + intrImpl->AppendInputAndType(acc->impl, compiler::DataType::ANY); + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), argCount); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, size_t argCount, std::va_list args, + compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC) +{ + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, intrinsicId); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {argCount}; + intrImpl->ReserveInputs(argCount); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + for (size_t index = 0; index < argCount; ++index) { + abckit_Inst *input = va_arg(args, abckit_Inst *); + intrImpl->AppendInputAndType(input->impl, compiler::DataType::ANY); + } + if (hasIC) { + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + } + intrImpl->AddImm(ctxG->impl->GetAllocator(), argCount); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_static/helpers_static.h b/libabckit/src/adapter_static/helpers_static.h new file mode 100644 index 0000000000000000000000000000000000000000..9d46298d597b565cc7198e19fa4d3ae325977e8b --- /dev/null +++ b/libabckit/src/adapter_static/helpers_static.h @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_STATIC_HELPERS_STATIC_H +#define LIBABCKIT_SRC_ADAPTER_STATIC_HELPERS_STATIC_H + +#include "libabckit/include/abckit.h" +#include "libabckit/include/ir_core.h" +#include "libabckit/include/isa/isa_dynamic.h" +#include "libabckit/include/isa/isa_static.h" +#include "static_core/compiler/optimizer/ir/inst.h" + +#include +#include + +// #include "statuses.h" +// #include "ir_impl.h" + +struct VerificationStatus { + enum abckit_Status statuses; + static const int PASS = 0; + static const int INCORRECT_STATE = 1; + static const int BAD_IDX_TYPE = 2; + static const int BAD_ARR_TYPE = 3; +}; +typedef const int verification_status; + +namespace libabckit { + +std::tuple ClassGetNames(const std::string &fullName); +std::tuple FuncGetNames(const std::string &fullSig); +std::string FuncNameCropModule(const std::string &fullSig); + +void CheckInvalidOpcodes(ark::compiler::Graph *ctxG, bool isDynamic); + +abckit_IsaApiStaticOpcode GetStaticOpcode(ark::compiler::Inst *inst); +abckit_IsaApiDynamicOpcode GetDynamicOpcode(ark::compiler::Inst *inst); +abckit_TypeId TypeToTypeId(ark::compiler::DataType::Type type); +ark::compiler::DataType::Type TypeIdToType(abckit_TypeId typeId); +ark::compiler::ConditionCode CcToCc(abckit_IsaApiDynamicConditionCode cc); +ark::compiler::ConditionCode CcToCc(abckit_IsaApiStaticConditionCode cc); +abckit_IsaApiDynamicConditionCode CcToDynamicCc(ark::compiler::ConditionCode cc); +abckit_IsaApiStaticConditionCode CcToStaticCc(ark::compiler::ConditionCode cc); +void SetLastError(abckit_Status err); + +uint32_t GetClassOffset(abckit_Graph *ctxG, abckit_Class *klass); +uint32_t GetMethodOffset(abckit_Graph *ctxG, abckit_Method *method); +uint32_t GetStringOffset(abckit_Graph *ctxG, abckit_String *string); +uint32_t GetLiteralArrayOffset(abckit_Graph *ctxG, abckit_LiteralArray *arr); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, ark::compiler::DataType::Type retType, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2, + ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0, + ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, uint64_t imm1, + ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0, + uint64_t imm1, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1, uint64_t imm2, + abckit_Inst *input0, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); + +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args, + ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); +abckit_Inst *CreateDynInst(abckit_Graph *ctxG, size_t argCount, std::va_list args, + ark::compiler::IntrinsicInst::IntrinsicId intrinsicId, bool hasIC = true); + +} + +#endif diff --git a/libabckit/src/adapter_static/ir_static.cpp b/libabckit/src/adapter_static/ir_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98c46b21e9dfd4c72539f63a89add2806fd470d1 --- /dev/null +++ b/libabckit/src/adapter_static/ir_static.cpp @@ -0,0 +1,3789 @@ +/** + * Copyright (c) 2024 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 "ir_static.h" + +#include "datatype.h" +#include "include/ir_core.h" +#include "libabckit/src/adapter_static/helpers_static.h" + +#include "libabckit/include/metadata.h" +#include "libabckit/src/statuses_impl.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/ir_impl.h" + +#include "static_core/assembler/assembly-program.h" +#include "static_core/assembler/mangling.h" + +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir/basicblock.h" +#include "static_core/compiler/optimizer/ir/inst.h" +#include "static_core/compiler/optimizer/analysis/loop_analyzer.h" + +#include "bct_intrinsics_opcodes.inc" + + +#include + +using namespace ark; + +namespace libabckit { + +#include "inst_props_helpers_dynamic.inc" + +// helpers for getting inst operand's info +// for dynamic insts helpers are autogenerated by inst_props_helpers_dynamic.inc.erb +static bool HasMethodIdOperandStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_InitObject: + case abckit_IsaApiStaticOpcode_CallStatic: + case abckit_IsaApiStaticOpcode_CallVirtual: + return true; + default: + return false; + } +} + +static int GetMethodIdOperandIndexStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_InitObject: + case abckit_IsaApiStaticOpcode_CallStatic: + case abckit_IsaApiStaticOpcode_CallVirtual: + return 0; + default: + return false; + } +} + +static bool HasStringIdOperandStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_LoadString: + return true; + default: + return false; + } +} + +static int GetStringIdOperandIndexStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_LoadString: + return 0; + default: + return false; + } +} + +static bool HasLiteralArrayIdOperandStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_LoadConstArray: + return true; + default: + return false; + } +} + +static int GetLiteralArrayIdOperandIndexStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_LoadConstArray: + return 0; + default: + return false; + } +} + +[[maybe_unused]] static bool HasTypeIdOperandStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_NewArray: + case abckit_IsaApiStaticOpcode_NewObject: + case abckit_IsaApiStaticOpcode_CheckCast: + case abckit_IsaApiStaticOpcode_IsInstance: + return true; + default: + return false; + } +} + +[[maybe_unused]] static int GetTypeIdOperandIndexStatic(abckit_IsaApiStaticOpcode opcode) +{ + switch(opcode) { + case abckit_IsaApiStaticOpcode_NewArray: + case abckit_IsaApiStaticOpcode_NewObject: + case abckit_IsaApiStaticOpcode_CheckCast: + case abckit_IsaApiStaticOpcode_IsInstance: + return 0; + default: + return -1; + } +} + + +// ======================================== +// Api for Graph manipulation +// ======================================== + +uint32_t GgetNumberOfBasicBlocksStatic(abckit_Graph *ctx) { + LIBABCKIT_LOG_FUNC + if(ctx == nullptr) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return 0; + } + return ctx->impl->GetVectorBlocks().size(); +} + +abckit_BasicBlock *GgetBasicBlockStatic(abckit_Graph *ctx, uint32_t id) { + LIBABCKIT_LOG_FUNC + if(ctx == nullptr) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto *bb_impl = ctx->impl->GetVectorBlocks()[id]; + return ctx->implToBB.at(bb_impl); +} + +abckit_Inst *GgetParameterStatic(abckit_Graph *ctx, uint32_t index) { + LIBABCKIT_LOG_FUNC + if(ctx == nullptr) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto list = ctx->impl->GetParameters(); + auto ins = list.begin(); + if(index == 0) { + return ctx->implToInst.at(*ins); + } + for(uint32_t i = 0; i <= index; i++) { + ++ins; + } + + return ctx->implToInst.at(*ins); +} + +void GinsertTryCatchStatic(abckit_BasicBlock *tryFirstBB, abckit_BasicBlock *tryLastBB, + abckit_BasicBlock *catchBeginBB, abckit_BasicBlock *catchEndBB) +{ + LIBABCKIT_LOG_FUNC + + // TODO(nsizov): check input for dominance tryFirstBB -> tryLastBB + // and catchBeginBB -> catchEndBB + + if (BBisStartStatic(tryFirstBB) || BBisEndStatic(tryFirstBB)) { + LIBABCKIT_LOG(DEBUG) << "tryFirstBB cannot be niether 'start' nor 'end' block"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + if (BBisStartStatic(tryLastBB) || BBisEndStatic(tryLastBB)) { + LIBABCKIT_LOG(DEBUG) << "tryLastBB cannot be niether 'start' nor 'end' block"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + abckit_Graph *ctxG = tryFirstBB->ctxG; + + // TODO(nsizov): implement for static mode as well + if (ctxG->ctxI->mode != Mode::DYNAMIC) { + libabckit::statuses::SetLastError(abckit_Status_WRONG_MODE); + return; + } + + if ((ctxG != tryLastBB->ctxG) || (ctxG != catchBeginBB->ctxG) || (ctxG != catchEndBB->ctxG)) { + LIBABCKIT_LOG(DEBUG) << "All BB's must be in the same graph"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + abckit_BasicBlock *tryBeginBB = BBcreateEmptyStatic(ctxG); + tryBeginBB->impl->SetTryBegin(true); + tryBeginBB->impl->SetTryId(tryBeginBB->impl->GetId()); + ctxG->impl->AppendTryBeginBlock(tryBeginBB->impl); + abckit_Inst *tryInst = IcreateTryStatic(ctxG); + BBaddInstFrontStatic(tryBeginBB, tryInst); + + abckit_BasicBlock *tryEndBB = BBcreateEmptyStatic(ctxG); + tryEndBB->impl->SetTryEnd(true); + tryEndBB->impl->SetTryId(tryBeginBB->impl->GetTryId()); + // TODO(nsizov): FIXME, calculate guest pc for new created blocks (abckit-wise problem) + tryEndBB->impl->SetGuestPc(0x1b); + tryInst->impl->CastToTry()->SetTryEndBlock(tryEndBB->impl); + // TODO(nsizov): FIXME, set proper typeid for catch blocks (abckit-wise problem) + tryInst->impl->CastToTry()->AppendCatchTypeId(0, 1); + + catchBeginBB->impl->SetCatchBegin(true); + if (catchBeginBB != catchEndBB) { + catchEndBB->impl->SetCatchEnd(true); + } + + std::unordered_set visited; + std::queue toVisit; + + // A data to pass into visitors traverse + struct VisitorData { + abckit_BasicBlock *tryBegin; + abckit_BasicBlock *tryEnd; + std::unordered_set *visited; + std::queue *toVisit; + } VisitorData { tryBeginBB, tryEndBB, &visited, &toVisit }; + + BBvisitPredBlocksStatic(tryFirstBB, &VisitorData, [](abckit_BasicBlock *curBasicBlock, + abckit_BasicBlock *predBasicBlock, + void *data) { + abckit_BasicBlock *tryBeginBB = static_cast(data)->tryBegin; + + predBasicBlock->impl->ReplaceSucc(curBasicBlock->impl, tryBeginBB->impl); + curBasicBlock->impl->RemovePred(predBasicBlock->impl); + }); + + BBconnectBlocksStatic(tryBeginBB, tryFirstBB, true); + BBconnectBlocksStatic(tryBeginBB, catchBeginBB, false); + + BBvisitPredBlocksStatic(tryLastBB, &VisitorData, [](abckit_BasicBlock *curBasicBlock, + abckit_BasicBlock *predBasicBlock, + void *data) { + abckit_BasicBlock *tryEndBB = static_cast(data)->tryEnd; + + predBasicBlock->impl->ReplaceSucc(curBasicBlock->impl, tryEndBB->impl); + curBasicBlock->impl->RemovePred(predBasicBlock->impl); + }); + + toVisit.push(tryBeginBB); + + while(!toVisit.empty()) { + abckit_BasicBlock* curBB = toVisit.front(); + toVisit.pop(); + visited.insert(curBB); + curBB->impl->SetTry(true); + curBB->impl->SetTryId(tryBeginBB->impl->GetTryId()); + BBvisitSuccBlocksStatic(curBB, &VisitorData, [](abckit_BasicBlock *curBasicBlock, + abckit_BasicBlock *succBasicBlock, + void *data) { + if (succBasicBlock->impl->IsTryEnd() || succBasicBlock->impl->IsCatchBegin() || succBasicBlock->impl->IsEndBlock()) { + return; + } + + auto *visited = static_cast(data)->visited; + auto *toVisit = static_cast(data)->toVisit; + + auto it = visited->find(succBasicBlock); + if (it == visited->end()) { + toVisit->push(succBasicBlock); + } + }); + } + + visited.erase(visited.begin(), visited.end()); + std::queue().swap(toVisit); + + while(!toVisit.empty()) { + abckit_BasicBlock* curBB = toVisit.front(); + toVisit.pop(); + visited.insert(curBB); + curBB->impl->SetCatch(true); + curBB->impl->SetTryId(tryBeginBB->impl->GetTryId()); + BBvisitSuccBlocksStatic(curBB, &VisitorData, [](abckit_BasicBlock *curBasicBlock, + abckit_BasicBlock *succBasicBlock, + void *data) { + if (succBasicBlock->impl->IsCatchEnd() || succBasicBlock->impl->IsTry()) { + return; + } + + auto *visited = static_cast(data)->visited; + auto *toVisit = static_cast(data)->toVisit; + + auto it = visited->find(succBasicBlock); + if (it == visited->end()) { + toVisit->push(succBasicBlock); + } + }); + } + + BBconnectBlocksStatic(tryEndBB, tryLastBB, true); + BBconnectBlocksStatic(tryEndBB, catchBeginBB, false); + BBconnectBlocksStatic(catchEndBB, tryLastBB, true); +} + +abckit_BasicBlock *GgetStartBasicBlockStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + compiler::BasicBlock *bbImpl = ctxG->impl->GetStartBlock(); + auto *bb = ctxG->implToBB.at(bbImpl); + + return bb; +} + +abckit_BasicBlock *GgetEndBasicBlockStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + compiler::BasicBlock *bbImpl = ctxG->impl->GetEndBlock(); + auto *bb = ctxG->implToBB.at(bbImpl); + + return bb; +} + +void IdumpStatic(abckit_Inst *inst, [[maybe_unused]] int fd) +{ + LIBABCKIT_LOG_FUNC + std::stringstream ss; + LIBABCKIT_LOG_DUMP(inst->impl->Dump(&ss), DEBUG); + // write(fd, ss.str().data(), ss.str().size()); +} + +void GdumpStatic(abckit_Graph *ctxG, int fd) +{ + LIBABCKIT_LOG_FUNC + std::stringstream ss; + LIBABCKIT_LOG_DUMP(ctxG->impl->Dump(&ss), DEBUG); + // write(fd, ss.str().data(), ss.str().size()); +} + +void GrunPassRemoveUnreachableBlocksStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + ctxG->impl->RemoveUnreachableBlocks(); +} + +void GvisitBlocksRPOStatic(abckit_Graph *ctxG, void *data, void (*cb)(abckit_BasicBlock *bb, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(ctxG, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + std::stringstream ss; + for (auto *bbImpl : ctxG->impl->GetBlocksRPO()) { + auto *bb = ctxG->implToBB.at(bbImpl); + cb(bb, data); + } +} + +// ======================================== +// Api for basic block manipulation +// ======================================== + +void BBvisitSuccBlocksStatic(abckit_BasicBlock *curBasicBlock, void *data, + void (*cb)(abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, + void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(curBasicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + + auto *ctxG = curBasicBlock->ctxG; + auto *bbImpl = curBasicBlock->impl; + auto succImpls = bbImpl->GetSuccsBlocks(); + for (auto *succImpl : succImpls) { + auto *succ = ctxG->implToBB.at(succImpl); + cb(curBasicBlock, succ, data); + } +} + +void BBvisitPredBlocksStatic(abckit_BasicBlock *curBasicBlock, void *data, + void (*cb)(abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, + void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(curBasicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + auto *ctxG = curBasicBlock->ctxG; + auto *bbImpl = curBasicBlock->impl; + auto predImpls = bbImpl->GetPredsBlocks(); + for (auto *predImpl : predImpls) { + auto *pred = ctxG->implToBB.at(predImpl); + cb(curBasicBlock, pred, data); + } +} + +abckit_BasicBlock *BBcreateEmptyStatic(abckit_Graph *ctxG) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + + auto* bb_impl = ctxG->impl->CreateEmptyBlock(0U); + auto *bb = ctxG->impl->GetLocalAllocator()->New(); + bb->ctxG = ctxG; + bb->impl = bb_impl; + ctxG->implToBB.insert({bb_impl, bb}); + return bb; +} + +void BBaddInstFrontStatic(abckit_BasicBlock *basicBlock, abckit_Inst *inst) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(inst, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(basicBlock->ctxG, inst->ctxG); + + if(inst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + basicBlock->impl->PrependInst(inst->impl); +} + +abckit_BasicBlock *BBsplitBlockAfterInstructionStatic(abckit_Inst *inst, bool makeEdge) { + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + auto* bb_impl = inst->impl->GetBasicBlock(); + auto* new_bb_impl = bb_impl->SplitBlockAfterInstruction(inst->impl, makeEdge); + + auto *bb = inst->ctxG->impl->GetLocalAllocator()->New(); + bb->ctxG = inst->ctxG; + bb->impl = new_bb_impl; + inst->ctxG->implToBB.insert({new_bb_impl, bb}); + return bb; +} + +void BBaddInstBackStatic(abckit_BasicBlock *basicBlock, abckit_Inst *inst) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(inst, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(basicBlock->ctxG, inst->ctxG); + + if(inst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + basicBlock->impl->AppendInst(inst->impl); +} + +abckit_Inst *BBgetLastInstStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr); + + auto *bb = basicBlock->impl; + auto *inst = bb->GetLastInst(); + if (inst == nullptr) { + return nullptr; + } + return basicBlock->ctxG->implToInst.at(inst); +} + +abckit_Graph *BBgetGraphStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr); + + return basicBlock->ctxG; +} + +abckit_Inst *BBgetFirstInstStatic(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr); + + auto *bbImpl = basicBlock->impl; + + compiler::Inst *instImpl = bbImpl->GetFirstPhi(); + if (instImpl == nullptr) { + instImpl = bbImpl->GetFirstInst(); + } + if (instImpl == nullptr) { + return nullptr; + } + + auto *inst = basicBlock->ctxG->implToInst.at(instImpl); + return inst; +} + +void BBconnectBlocksStatic(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool connectViaTrueEdge) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(bb1, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(bb2, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(bb1->ctxG, bb2->ctxG); + + bb1->impl->AddSucc(bb2->impl, !connectViaTrueEdge); +} + +void BBdisconnectBlocksStatic(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(bb1, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(bb2, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(bb1->ctxG, bb2->ctxG); + + if(bb1->impl == nullptr || bb2->impl == nullptr) { + return; + } + bb1->impl->RemoveSucc(bb2->impl); + bb2->impl->RemovePred(bb1->impl); +} + +void BBclearStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + basicBlock->impl->Clear(); +} + +abckit_BasicBlock *BBgetSuccBlockStatic(abckit_BasicBlock *basicBlock, int32_t index) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr); + if(index >= (int) basicBlock->impl->GetSuccsBlocks().size()) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto* succ_impl = basicBlock->impl->GetSuccsBlocks()[index]; + + return basicBlock->ctxG->implToBB.at(succ_impl); +} + +uint64_t BBgetSuccBlockCountStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, 0); + + return basicBlock->impl->GetSuccsBlocks().size(); +} + +uint32_t BBgetIdStatic([[maybe_unused]] abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, 0); + + return basicBlock->impl->GetId(); +} + +abckit_BasicBlock *BBgetPredBlockStatic(abckit_BasicBlock *basicBlock, int32_t index) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr); + + if(index >= (int) basicBlock->impl->GetPredsBlocks().size()) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto* pred_impl = basicBlock->impl->GetPredsBlocks()[index]; + + return basicBlock->ctxG->implToBB.at(pred_impl); +} + +uint64_t BBgetPredBlockCountStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, 0); + + return basicBlock->impl->GetPredsBlocks().size(); +} + +bool BBisStartStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsStartBlock(); +} + +bool BBisEndStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsEndBlock(); +} + +uint32_t BBgetNumberOfInstructionsStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, 0); + + return basicBlock->impl->CountInsts(); +} + +bool BBisLoopHeadStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsLoopHeader(); +} + +bool BBisLoopPreheadStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsLoopPreHeader(); +} + +bool BBisTryBeginStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsTryBegin(); +} + +bool BBisTryStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsTry(); +} + +bool BBisTryEndStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsTry(); +} + +bool BBisCatchBeginStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsTryBegin(); +} + +bool BBisCatchStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + + return basicBlock->impl->IsTry(); +} + +void BBdumpStatic(abckit_BasicBlock *basicBlock, int fd) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + + std::stringstream ss; + LIBABCKIT_LOG_DUMP(basicBlock->impl->Dump(&ss), DEBUG); + // write(fd, ss.str().data(), ss.str().size()); +} + +bool BBcheckDominanceStatic(abckit_BasicBlock *basicBlock, abckit_BasicBlock *dominator) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, false); + LIBABCKIT_BAD_ARGUMENT(dominator, false); + + LIBABCKIT_WRONG_CTX(basicBlock->ctxG, dominator->ctxG, false); + + return dominator->impl->IsDominate(basicBlock->impl); +} + +abckit_BasicBlock *BBgetImmediateDominatorStatic(abckit_BasicBlock *basicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr); + + auto *bb = basicBlock->impl->GetDominator(); + return basicBlock->ctxG->implToBB.at(bb); +} + +void BBvisitDominatedBlocksStatic(abckit_BasicBlock *basicBlock, void *data, + void (*cb)(abckit_BasicBlock *basicBlock, abckit_BasicBlock *dominatedBasicBlock, + void *data)) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + for (auto *bbImpl : basicBlock->impl->GetDominatedBlocks()) { + auto *bb = basicBlock->ctxG->implToBB.at(bbImpl); + cb(basicBlock, bb, data); + } +} + +void BBsetSuccBlockStatic(abckit_BasicBlock *basicBlock, abckit_BasicBlock *succBlock, int32_t index) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(succBlock, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(basicBlock->ctxG, succBlock->ctxG); + + auto& bbs = basicBlock->impl->GetSuccsBlocks(); + if(index > (int)bbs.size() || index < 0) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + if(index == (int)bbs.size()) { + bbs.emplace_back(succBlock->impl); + } else { + auto it = std::find(bbs.begin(), bbs.end(), bbs[index]); + bbs.insert(it, succBlock->impl); + } + + succBlock->impl->GetPredsBlocks().emplace_back(basicBlock->impl); +} + +void BBsetPredBlockStatic(abckit_BasicBlock *basicBlock, abckit_BasicBlock *predBlock, int32_t index) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(predBlock, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(basicBlock->ctxG, predBlock->ctxG); + + auto& bbs = basicBlock->impl->GetPredsBlocks(); + if(index > (int)bbs.size() || index < 0) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + if(index == (int)bbs.size()) { + bbs.emplace_back(predBlock->impl); + } else { + auto it = std::find(bbs.begin(), bbs.end(), bbs[index]); + bbs.insert(it, predBlock->impl); + } + + predBlock->impl->GetSuccsBlocks().emplace_back(basicBlock->impl); +} + +void BBsetPredBlocksStatic(abckit_BasicBlock *basicBlock, size_t argCount, va_list args) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + if(argCount < 0) { + LIBABCKIT_LOG(DEBUG) << "bad argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + for (size_t i = 0; i < argCount; ++i) { + auto* arg = va_arg(args, abckit_BasicBlock *); + if(arg == nullptr) { + LIBABCKIT_LOG(DEBUG) << "nullptr argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + LIBABCKIT_WRONG_CTX_VOID(basicBlock->ctxG, arg->ctxG); + arg->impl->AddSucc(basicBlock->impl); + } + va_end(args); +} + +void BBsetSuccBlocksStatic(abckit_BasicBlock *basicBlock, size_t argCount, va_list args) { + LIBABCKIT_BAD_ARGUMENT(basicBlock, LIBABCKIT_RETURN_VOID); + if(argCount < 0) { + LIBABCKIT_LOG(DEBUG) << "bad argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + for (size_t i = 0; i < argCount; ++i) { + auto* arg = va_arg(args, abckit_BasicBlock *); + if(arg == nullptr) { + LIBABCKIT_LOG(DEBUG) << "nullptr argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + LIBABCKIT_WRONG_CTX_VOID(basicBlock->ctxG, arg->ctxG); + basicBlock->impl->AddSucc(arg->impl); + } + va_end(args); +} + +abckit_BasicBlock *BBgetTrueBranchStatic(abckit_BasicBlock *curBasicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(curBasicBlock, nullptr); + + auto* tb = curBasicBlock->impl->GetTrueSuccessor(); + if(tb == nullptr) { + return nullptr; + } + + return curBasicBlock->ctxG->implToBB.at(tb); +} + +abckit_BasicBlock *BBgetFalseBranchStatic(abckit_BasicBlock *curBasicBlock) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(curBasicBlock, nullptr); + + auto* fb = curBasicBlock->impl->GetFalseSuccessor(); + if(fb == nullptr) { + return nullptr; + } + + return curBasicBlock->ctxG->implToBB.at(fb); +} + +abckit_Inst *BBcreatePhiStatic(abckit_BasicBlock *bb, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + + LIBABCKIT_LOG(DEBUG) << argCount << '\n'; + if (argCount < 1) { + LIBABCKIT_LOG(DEBUG) << "not enough inputs\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + std::vector inputs; + + for (size_t index = 0; index < argCount; ++index) { + abckit_Inst *input = va_arg(args, abckit_Inst *); + LIBABCKIT_BAD_ARGUMENT(input, nullptr); + inputs.emplace_back(input); + } + + compiler::DataType::Type type = inputs[0]->impl->GetType(); + if (bb->ctxG->ctxI->mode == Mode::DYNAMIC) { + type = compiler::DataType::ANY; + } + + for (auto *inst : inputs) { + if (bb->ctxG->ctxI->mode == Mode::DYNAMIC) { + if (inst->impl->GetType() != compiler::DataType::INT64 && + inst->impl->GetType() != compiler::DataType::ANY) { + LIBABCKIT_LOG(DEBUG) << "inconsistent input types\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + } + else { + if (type != inst->impl->GetType()) { + LIBABCKIT_LOG(DEBUG) << "inconsistent input types\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + } + } + + auto phiImpl = bb->ctxG->impl->CreateInstPhi(type, 0); + bb->impl->AppendPhi(phiImpl); + auto *phi = bb->ctxG->impl->GetLocalAllocator()->New(); + phi->ctxG = bb->ctxG; + phi->impl = phiImpl; + bb->ctxG->implToInst.insert({phiImpl, phi}); + + for (auto *inst : inputs) { + phiImpl->AppendInput(inst->impl); + } + + return phi; +} + +// ======================================== +// Api for instruction manipulation +// ======================================== + +abckit_Inst *IcreateCallStaticStatic(abckit_Graph *ctxG, abckit_Method *inputMethod, size_t argCount, + va_list argp) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "argCount: " << argCount << "\n"; + auto *func = reinterpret_cast(inputMethod->impl); + size_t paramCount = func->GetParamsNum(); + auto methodOffset = GetMethodOffset(ctxG, inputMethod); + auto methodPtr = reinterpret_cast(methodOffset); + + auto callImpl = ctxG->impl->CreateInstCallStatic(ctxG->impl->GetRuntime()->GetMethodReturnType(methodPtr), 0, + methodOffset, methodPtr); + callImpl->ClearFlag(compiler::inst_flags::REQUIRE_STATE); + callImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), paramCount); + for (size_t i = 0; i < argCount; i++) { + LIBABCKIT_LOG(DEBUG) << "append arg " << i << '\n'; + auto *inst = va_arg(argp, abckit_Inst *); + callImpl->AppendInputAndType(inst->impl, inst->impl->GetType()); + } + va_end(argp); + + auto *call = ctxG->impl->GetLocalAllocator()->New(); + call->ctxG = ctxG; + call->impl = callImpl; + ctxG->implToInst.insert({callImpl, call}); + return call; +} + +abckit_Inst *IcreateCallVirtualStatic(abckit_Graph *ctxG, abckit_Inst *inputObj, abckit_Method *inputMethod, size_t argCount, + va_list argp) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "argCount: " << argCount << "\n"; + auto *func = reinterpret_cast(inputMethod->impl); + size_t paramCount = func->GetParamsNum(); + auto methodOffset = GetMethodOffset(ctxG, inputMethod); + auto methodPtr = reinterpret_cast(methodOffset); + + auto callImpl = ctxG->impl->CreateInstCallVirtual(ctxG->impl->GetRuntime()->GetMethodReturnType(methodPtr), 0, + methodOffset, methodPtr); + callImpl->ClearFlag(compiler::inst_flags::REQUIRE_STATE); + callImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), paramCount+1); + callImpl->AppendInputAndType(inputObj->impl, compiler::DataType::REFERENCE); + for (size_t i = 0; i < argCount; i++) { + LIBABCKIT_LOG(DEBUG) << "append arg " << i << '\n'; + auto *inst = va_arg(argp, abckit_Inst *); + callImpl->AppendInputAndType(inst->impl, inst->impl->GetType()); + } + va_end(argp); + + auto *call = ctxG->impl->GetLocalAllocator()->New(); + call->ctxG = ctxG; + call->impl = callImpl; + ctxG->implToInst.insert({callImpl, call}); + return call; +} + +abckit_Inst *IcreateLoadStringStatic(abckit_Graph *ctxG, abckit_String* str) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << GetStringOffset(ctxG, str) << '\n'; + auto intrinsicId = compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STRING; + auto dataType = ctxG->ctxI->mode == Mode::DYNAMIC ? compiler::DataType::ANY : compiler::DataType::REFERENCE; + auto loadStringImpl = ctxG->impl->CreateInstIntrinsic(dataType, 0, intrinsicId); + auto *loadString = ctxG->impl->GetLocalAllocator()->New(); + loadStringImpl->AddImm(ctxG->impl->GetAllocator(), GetStringOffset(ctxG, str)); + loadString->ctxG = ctxG; + loadString->impl = loadStringImpl; + ctxG->implToInst.insert({loadStringImpl, loadString}); + return loadString; +} + +abckit_Inst *IcreateCmpStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + if (input0->impl->GetType() != input1->impl->GetType()) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto cmpImpl = ctxG->impl->CreateInstCmp(compiler::DataType::INT32, 0, input0->impl, input1->impl, input0->impl->GetType()); + + auto *cmp = ctxG->impl->GetLocalAllocator()->New(); + + cmp->ctxG = ctxG; + cmp->impl = cmpImpl; + ctxG->implToInst.insert({cmpImpl, cmp}); + + return cmp; +} + +abckit_Inst *GcreateConstantI64Static(abckit_Graph *ctxG, int64_t value) +{ + LIBABCKIT_LOG_FUNC + if (ctxG == nullptr) { + LIBABCKIT_LOG(DEBUG) << "nullptr argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto constantI64Impl = ctxG->impl->FindOrCreateConstant(value); + + auto *constantI64 = ctxG->impl->GetLocalAllocator()->New(); + + constantI64->ctxG = ctxG; + constantI64->impl = constantI64Impl; + ctxG->implToInst.insert({constantI64Impl, constantI64}); + + return constantI64; +} + +abckit_Inst *GcreateConstantI32Static(abckit_Graph *ctxG, int32_t value) +{ + LIBABCKIT_LOG_FUNC + if (ctxG == nullptr) { + LIBABCKIT_LOG(DEBUG) << "nullptr argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto constantI32Impl = ctxG->impl->FindOrCreateConstant(value); + + auto *constantI32 = ctxG->impl->GetLocalAllocator()->New(); + + constantI32->ctxG = ctxG; + constantI32->impl = constantI32Impl; + ctxG->implToInst.insert({constantI32Impl, constantI32}); + + return constantI32; +} + +abckit_Inst *GcreateConstantU64Static(abckit_Graph *ctxG, uint64_t value) +{ + LIBABCKIT_LOG_FUNC + if (ctxG == nullptr) { + LIBABCKIT_LOG(DEBUG) << "nullptr argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto constantU64Impl = ctxG->impl->FindOrCreateConstant(value); + auto *constantU64 = ctxG->impl->GetLocalAllocator()->New(); + + constantU64->ctxG = ctxG; + constantU64->impl = constantU64Impl; + ctxG->implToInst.insert({constantU64Impl, constantU64}); + + return constantU64; +} + +abckit_Inst *GcreateConstantF64Static(abckit_Graph *ctxG, double value) +{ + LIBABCKIT_LOG_FUNC + // check inputs are valid + if (ctxG == nullptr) { + LIBABCKIT_LOG(DEBUG) << "nullptr argument\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto constantF64Impl = ctxG->impl->FindOrCreateConstant(value); + auto *constantF64 = ctxG->impl->GetLocalAllocator()->New(); + + constantF64->ctxG = ctxG; + constantF64->impl = constantF64Impl; + ctxG->implToInst.insert({constantF64Impl, constantF64}); + + return constantF64; +} + +abckit_Inst *IcreateNegStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + + auto negImpl = ctxG->impl->CreateInstNeg(input0->impl->GetType(), 0, input0->impl); + auto *neg = ctxG->impl->GetLocalAllocator()->New(); + neg->ctxG = ctxG; + neg->impl = negImpl; + ctxG->implToInst.insert({negImpl, neg}); + return neg; +} + +abckit_Inst *IcreateAddStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + auto addImpl = ctxG->impl->CreateInstAdd(input0->impl->GetType(), 0, input0->impl, input1->impl); + auto *add = ctxG->impl->GetLocalAllocator()->New(); + add->ctxG = ctxG; + add->impl = addImpl; + ctxG->implToInst.insert({addImpl, add}); + return add; +} + +void IremoveStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + auto bbImpl = inst->impl->GetBasicBlock(); + LIBABCKIT_BAD_ARGUMENT(bbImpl, LIBABCKIT_RETURN_VOID); + + bbImpl->RemoveInst(inst->impl); +} + +uint32_t IgetIdStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + auto id = inst->impl->GetId(); + LIBABCKIT_LOG(DEBUG) << id << '\n'; + return id; +} + +abckit_Inst *IcreateSubStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + auto subImpl = ctxG->impl->CreateInstSub(input0->impl->GetType(), 0, input0->impl, input1->impl); + auto *sub = ctxG->impl->GetLocalAllocator()->New(); + sub->ctxG = ctxG; + sub->impl = subImpl; + ctxG->implToInst.insert({subImpl, sub}); + return sub; +} + +abckit_Inst *IcreateMulStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + auto mulImpl = ctxG->impl->CreateInstMul(input0->impl->GetType(), 0, input0->impl, input1->impl); + auto *mul = ctxG->impl->GetLocalAllocator()->New(); + mul->ctxG = ctxG; + mul->impl = mulImpl; + ctxG->implToInst.insert({mulImpl, mul}); + return mul; +} + +abckit_Inst *IcreateDivStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + auto divImpl = ctxG->impl->CreateInstDiv(input0->impl->GetType(), 0, input0->impl, input1->impl); + auto *div = ctxG->impl->GetLocalAllocator()->New(); + div->ctxG = ctxG; + div->impl = divImpl; + ctxG->implToInst.insert({divImpl, div}); + return div; +} + +abckit_Inst *IcreateModStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + auto modImpl = ctxG->impl->CreateInstMod(input0->impl->GetType(), 0, input0->impl, input1->impl); + auto *mod = ctxG->impl->GetLocalAllocator()->New(); + mod->ctxG = ctxG; + mod->impl = modImpl; + ctxG->implToInst.insert({modImpl, mod}); + return mod; +} + +abckit_Inst *IcreateEqualsStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::BOOL, compiler::INVALID_PC, + compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_EQUALS); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {2U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, input0->impl->GetType()); + intrImpl->AppendInputAndType(input1->impl, input1->impl->GetType()); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateAddIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto addIImpl = ctxG->impl->CreateInstAddI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *addI = ctxG->impl->GetLocalAllocator()->New(); + addI->ctxG = ctxG; + addI->impl = addIImpl; + ctxG->implToInst.insert({addIImpl, addI}); + return addI; +} + +abckit_Inst *IcreateSubIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto subIImpl = ctxG->impl->CreateInstSubI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *subI = ctxG->impl->GetLocalAllocator()->New(); + subI->ctxG = ctxG; + subI->impl = subIImpl; + ctxG->implToInst.insert({subIImpl, subI}); + return subI; +} + +abckit_Inst *IcreateMulIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto mulIImpl = ctxG->impl->CreateInstMulI(compiler::DataType::INT32, 0, input0->impl, imm); + auto mulI = ctxG->impl->GetLocalAllocator()->New(); + mulI->ctxG = ctxG; + mulI->impl = mulIImpl; + ctxG->implToInst.insert({mulIImpl, mulI}); + return mulI; +} + +abckit_Inst *IcreateDivIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto divIImpl = ctxG->impl->CreateInstDivI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *divI = ctxG->impl->GetLocalAllocator()->New(); + divI->ctxG = ctxG; + divI->impl = divIImpl; + ctxG->implToInst.insert({divIImpl, divI}); + return divI; +} + +abckit_Inst *IcreateModIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto modIImpl = ctxG->impl->CreateInstModI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *modI = ctxG->impl->GetLocalAllocator()->New(); + modI->ctxG = ctxG; + modI->impl = modIImpl; + ctxG->implToInst.insert({modIImpl, modI}); + return modI; +} + +abckit_Inst *IcreateShlStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + auto shlImpl = ctxG->impl->CreateInstShl(compiler::DataType::INT64, 0, input0->impl, input1->impl); + auto *shl = ctxG->impl->GetLocalAllocator()->New(); + shl->ctxG = ctxG; + shl->impl = shlImpl; + ctxG->implToInst.insert({shlImpl, shl}); + return shl; +} + +abckit_Inst *IcreateShrStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + auto shrImpl = ctxG->impl->CreateInstShr(compiler::DataType::INT64, 0, input0->impl, input1->impl); + auto *shr = ctxG->impl->GetLocalAllocator()->New(); + shr->ctxG = ctxG; + shr->impl = shrImpl; + ctxG->implToInst.insert({shrImpl, shr}); + return shr; +} + +abckit_Inst *IcreateAShrStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + auto aShrImpl = ctxG->impl->CreateInstAShr(compiler::DataType::INT64, 0, input0->impl, input1->impl); + auto *aShr = ctxG->impl->GetLocalAllocator()->New(); + aShr->ctxG = ctxG; + aShr->impl = aShrImpl; + ctxG->implToInst.insert({aShrImpl, aShr}); + return aShr; +} + +abckit_Inst *IcreateShlIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto shlIImpl = ctxG->impl->CreateInstShlI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *shlI = ctxG->impl->GetLocalAllocator()->New(); + shlI->ctxG = ctxG; + shlI->impl = shlIImpl; + ctxG->implToInst.insert({shlIImpl, shlI}); + return shlI; +} + +abckit_Inst *IcreateShrIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto shrIImpl = ctxG->impl->CreateInstShrI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *shrI = ctxG->impl->GetLocalAllocator()->New(); + shrI->ctxG = ctxG; + shrI->impl = shrIImpl; + ctxG->implToInst.insert({shrIImpl, shrI}); + return shrI; +} + +abckit_Inst *IcreateAShrIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto aShrIImpl = ctxG->impl->CreateInstAShrI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *aShrI = ctxG->impl->GetLocalAllocator()->New(); + aShrI->ctxG = ctxG; + aShrI->impl = aShrIImpl; + ctxG->implToInst.insert({aShrIImpl, aShrI}); + return aShrI; +} + +abckit_Inst *IcreateNotStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + auto notImpl = ctxG->impl->CreateInstNot(compiler::DataType::INT64, 0, input0->impl); + auto *notInst = ctxG->impl->GetLocalAllocator()->New(); + notInst->ctxG = ctxG; + notInst->impl = notImpl; + ctxG->implToInst.insert({notImpl, notInst}); + return notInst; +} + +abckit_Inst *IcreateOrStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + auto orImpl = ctxG->impl->CreateInstOr(compiler::DataType::INT64, 0, input0->impl, input1->impl); + auto *orInst = ctxG->impl->GetLocalAllocator()->New(); + orInst->ctxG = ctxG; + orInst->impl = orImpl; + ctxG->implToInst.insert({orImpl, orInst}); + return orInst; +} + +abckit_Inst *IcreateXorStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + auto xorImpl = ctxG->impl->CreateInstXor(compiler::DataType::INT64, 0, input0->impl, input1->impl); + auto *xorInst = ctxG->impl->GetLocalAllocator()->New(); + xorInst->ctxG = ctxG; + xorInst->impl = xorImpl; + ctxG->implToInst.insert({xorImpl, xorInst}); + return xorInst; +} + +abckit_Inst *IcreateAndStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + auto andImpl = ctxG->impl->CreateInstAnd(compiler::DataType::INT64, 0, input0->impl, input1->impl); + auto *andInst = ctxG->impl->GetLocalAllocator()->New(); + andInst->ctxG = ctxG; + andInst->impl = andImpl; + ctxG->implToInst.insert({andImpl, andInst}); + return andInst; +} + +abckit_Inst *IcreateOrIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto orIImpl = ctxG->impl->CreateInstOrI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *orIInst = ctxG->impl->GetLocalAllocator()->New(); + orIInst->ctxG = ctxG; + orIInst->impl = orIImpl; + ctxG->implToInst.insert({orIImpl, orIInst}); + return orIInst; +} + +abckit_Inst *IcreateXorIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto xorIImpl = ctxG->impl->CreateInstXorI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *xorIInst = ctxG->impl->GetLocalAllocator()->New(); + xorIInst->ctxG = ctxG; + xorIInst->impl = xorIImpl; + ctxG->implToInst.insert({xorIImpl, xorIInst}); + return xorIInst; +} + +abckit_Inst *IcreateAndIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + auto andIImpl = ctxG->impl->CreateInstAndI(compiler::DataType::INT32, 0, input0->impl, imm); + auto *andIInst = ctxG->impl->GetLocalAllocator()->New(); + andIInst->ctxG = ctxG; + andIInst->impl = andIImpl; + ctxG->implToInst.insert({andIImpl, andIInst}); + return andIInst; +} + +abckit_LiteralArray *IgetLiteralArrayStatic(abckit_Inst *inst) { + LIBABCKIT_LOG_FUNC + size_t idx = 0; + if (inst->ctxG->ctxI->mode == Mode::DYNAMIC) { + auto inst_opcode = GetDynamicOpcode(inst->impl); + if(!HasLiteralArrayIdOperandDynamic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + idx = GetLiteralArrayIdOperandIndexDynamic(inst_opcode); + } else if (inst->ctxG->ctxI->mode == Mode::STATIC) { + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasLiteralArrayIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + idx = GetLiteralArrayIdOperandIndexStatic(inst_opcode); + } else { + LIBABCKIT_UNREACHABLE + } + auto& imms = inst->impl->CastToIntrinsic()->GetImms(); + assert(imms.size() == 2); + auto arr_name = inst->ctxG->irInterface->literalarrays.at(imms[idx]); + auto* prog = reinterpret_cast(inst->ctxG->ctxI->program); + auto* arr_impl = &(prog->literalarrayTable.at(arr_name)); + return reinterpret_cast(arr_impl); +} + +void IsetLiteralArrayStatic(abckit_Inst *inst, abckit_LiteralArray *la) { + LIBABCKIT_LOG_FUNC + size_t idx = 0; + if (inst->ctxG->ctxI->mode == Mode::DYNAMIC) { + auto inst_opcode = GetDynamicOpcode(inst->impl); + if(!HasLiteralArrayIdOperandDynamic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + idx = GetLiteralArrayIdOperandIndexDynamic(inst_opcode); + } else if (inst->ctxG->ctxI->mode == Mode::STATIC) { + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasLiteralArrayIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + idx = GetLiteralArrayIdOperandIndexStatic(inst_opcode); + } else { + LIBABCKIT_UNREACHABLE + } + + auto& imms = inst->impl->CastToIntrinsic()->GetImms(); + assert(imms.size() == 2); + imms[idx] = GetLiteralArrayOffset(inst->ctxG, la); +} + +abckit_String *IgetStringStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + size_t idx = 0; + if (inst->ctxG->ctxI->mode == Mode::DYNAMIC) { + auto inst_opcode = GetDynamicOpcode(inst->impl); + std::cerr << "AAAAAAAAAAAAAAAAAA\n"; + if(!HasStringIdOperandDynamic(inst_opcode)) { + std::cerr << "OOOOOOOOOOOOOOOOOOOOOO\n"; + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + idx = GetStringIdOperandIndexDynamic(inst_opcode); + } else if (inst->ctxG->ctxI->mode == Mode::STATIC) { + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasStringIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + idx = GetStringIdOperandIndexStatic(inst_opcode); + } else { + LIBABCKIT_UNREACHABLE + } + + auto& imms = inst->impl->CastToIntrinsic()->GetImms(); + auto str_name = inst->ctxG->irInterface->strings.at(imms[idx]); + auto str_impl = inst->ctxG->ctxI->strings.at(str_name).get(); + return str_impl; +} + +void IsetStringStatic(abckit_Inst *inst, abckit_String *str) +{ + LIBABCKIT_LOG_FUNC + size_t idx = 0; + if (inst->ctxG->ctxI->mode == Mode::DYNAMIC) { + auto inst_opcode = GetDynamicOpcode(inst->impl); + if(!HasStringIdOperandDynamic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + idx = GetStringIdOperandIndexDynamic(inst_opcode); + } else if (inst->ctxG->ctxI->mode == Mode::STATIC) { + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasStringIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + idx = GetStringIdOperandIndexStatic(inst_opcode); + } else { + LIBABCKIT_UNREACHABLE + } + + auto& imms = inst->impl->CastToIntrinsic()->GetImms(); + imms[idx] = GetStringOffset(inst->ctxG, str); +} + +abckit_IsaApiStaticOpcode IgetOpcodeStaticStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + auto opc = inst->impl->GetOpcode(); + if (opc == compiler::Opcode::Intrinsic) { + return GetStaticIntrinsicOpcode(inst->impl->CastToIntrinsic()); + } + return GetStaticOpcode(inst->impl); +} + +abckit_IsaApiDynamicOpcode IgetOpcodeDynamicStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + auto opc = inst->impl->GetOpcode(); + if (opc == compiler::Opcode::Intrinsic) { + switch(inst->impl->CastToIntrinsic()->GetIntrinsicId()) { + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STRING: + return abckit_IsaApiDynamicOpcode_LoadString; + default: + break; + } + return GetDynamicIntrinsicOpcode(inst->impl->CastToIntrinsic()); + } + return GetDynamicOpcode(inst->impl); +} + +abckit_Inst *IgetNextStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + auto *nextInstImpl = inst->impl->GetNext(); + if (nextInstImpl == nullptr) { + return nullptr; + } + auto *nextInst = inst->ctxG->implToInst.at(nextInstImpl); + return nextInst; +} + +abckit_Inst *IgetPrevStatic(abckit_Inst *inst) { + LIBABCKIT_LOG_FUNC + auto *nextInstImpl = inst->impl->GetPrev(); + if (nextInstImpl == nullptr) { + return nullptr; + } + auto *nextInst = inst->ctxG->implToInst.at(nextInstImpl); + return nextInst; +} + +void IinsertAfterStatic(abckit_Inst *inst, abckit_Inst *refInst) { + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(inst, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(refInst, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(inst->ctxG, refInst->ctxG); + + auto* bb = IgetBasicBlockStatic(refInst); + LIBABCKIT_BAD_ARGUMENT(bb, LIBABCKIT_RETURN_VOID); + + if(inst->impl->IsConst() || refInst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + bb->impl->InsertAfter(inst->impl, refInst->impl); +} + +void IinsertBeforeStatic(abckit_Inst *inst, abckit_Inst *refInst) { + + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(inst, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(refInst, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_WRONG_CTX_VOID(inst->ctxG, refInst->ctxG); + + auto* bb = IgetBasicBlockStatic(refInst); + LIBABCKIT_BAD_ARGUMENT(bb, LIBABCKIT_RETURN_VOID); + + if(inst->impl->IsConst() || refInst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + bb->impl->InsertBefore(inst->impl, refInst->impl); +} + +bool IcheckDominanceStatic(abckit_Inst *inst, abckit_Inst *dominator) { + LIBABCKIT_LOG_FUNC + + LIBABCKIT_WRONG_CTX(inst->ctxG, dominator->ctxG, false); + + return inst->impl->IsDominate(dominator->impl); +} + +void IvisitUsersStatic(abckit_Inst *inst, void *data, void (*cb)(abckit_Inst *inst, abckit_Inst *user, void *data)) { + + LIBABCKIT_LOG_FUNC + + auto* user = inst->impl->GetFirstUser(); + + while(user != nullptr) { + auto *user_inst = inst->ctxG->implToInst.at(user->GetInst()); + cb(inst, user_inst, data); + user = user->GetNext(); + } +} + +uint32_t IgetUserCountStatic(abckit_Inst *inst) { + LIBABCKIT_LOG_FUNC + uint32_t count = 0; + + auto* user = inst->impl->GetFirstUser(); + + while(user != nullptr) { + count++; + user = user->GetNext(); + } + return count; +} + +void IvisitInputsStatic(abckit_Inst *inst, void *data, + void (*cb)(abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data)) { + LIBABCKIT_LOG_FUNC + for(size_t i = 0; i < inst->impl->GetInputsCount(); i++) { + auto *inputImpl = inst->impl->GetInput(i).GetInst(); + auto *input = inst->ctxG->implToInst.at(inputImpl); + cb(inst, input, i, data); + } +} + +uint64_t IgetInputCountStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + return inst->impl->GetInputsCount(); +} + +abckit_Inst *IgetInputStatic(abckit_Inst *inst, size_t index) +{ + LIBABCKIT_LOG_FUNC + if (inst->impl->GetInputsCount() <= index) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto *inputImpl = inst->impl->GetInput(index).GetInst(); + auto *input = inst->ctxG->implToInst.at(inputImpl); + return input; +} + +void IsetInputStatic(abckit_Inst *inst, abckit_Inst *input, int32_t index) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << index << '\n'; + LIBABCKIT_LOG(DEBUG) << inst->impl->GetInputs().size() << '\n'; + inst->impl->SetInput(index, input->impl); +} + +void IsetInputsStatic(abckit_Inst *inst, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << argCount << '\n'; + LIBABCKIT_LOG(DEBUG) << inst->impl->GetInputs().size() << '\n'; + for (size_t index = 0; index < argCount; ++index) { + abckit_Inst *input = va_arg(args, abckit_Inst *); + inst->impl->SetInput(index, input->impl); + } +} + +void IappendInputStatic(abckit_Inst *inst, abckit_Inst *input) +{ + LIBABCKIT_LOG_FUNC + // TOOD: support other insts + if (!inst->impl->IsPhi()) { + LIBABCKIT_LOG(DEBUG) << "Currently IappendInputStatic is supported only for phi node"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + inst->impl->AppendInput(input->impl); +} + +// Type helpers + +static abckit_Type *CreateGeneralType(abckit_File *ctxI, abckit_TypeId typeId, abckit_Class *klass) +{ + auto type = std::make_unique(); + type->id = typeId; + type->klass = klass; + ctxI->types.emplace_back(std::move(type)); + return ctxI->types.back().get(); +} + +abckit_Type *IgetTypeStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + abckit_TypeId typeId = TypeToTypeId(inst->impl->GetType()); + abckit_Class *klass = nullptr; + if (typeId != abckit_TypeId_REFERENCE) { + return CreateGeneralType(inst->ctxG->ctxI, typeId, klass); + } + // Add get of abckit_TypeId_REFERENCE NOTE(ymolokanov) + return CreateGeneralType(inst->ctxG->ctxI, typeId, klass); +} + +abckit_TypeId IgetTargetTypeStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + if (inst->impl->GetOpcode() != compiler::Opcode::Cast) { + LIBABCKIT_LOG(DEBUG) << "Instruction is not a cast\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return abckit_TypeId::abckit_TypeId_INVALID; + } + + return TypeToTypeId(static_cast(inst->impl)->GetType()); +} + +void IsetTargetTypeStatic(abckit_Inst *inst, abckit_TypeId type) +{ + LIBABCKIT_LOG_FUNC + if (inst->impl->GetOpcode() != compiler::Opcode::Cast) { + LIBABCKIT_LOG(DEBUG) << "Instruction is not a cast\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + inst->impl->SetType(TypeIdToType(type)); +} + +bool IcheckIsCallStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + //TODO(nsizov): Handle intrinsic calls + return inst->impl->IsCall(); +} + +abckit_BasicBlock *IgetBasicBlockStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + auto *ctxG = inst->ctxG; + auto *implBB = inst->impl->GetBasicBlock(); + auto it = ctxG->implToBB.find(implBB); + if (it != ctxG->implToBB.end()) { + return it->second; + } + return nullptr; +} + +abckit_Method *IgetMethodStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + auto *ctxG = inst->ctxG; + + compiler::RuntimeInterface::MethodPtr methodPtr = 0; + if (inst->impl->IsCall()) { + auto *callInst = static_cast(inst->impl); + methodPtr = callInst->GetCallMethod(); + } else if (inst->impl->IsIntrinsic()) { + size_t idx = 0; + if (inst->ctxG->ctxI->mode == Mode::DYNAMIC) { + auto inst_opcode = GetDynamicOpcode(inst->impl); + if(!HasMethodIdOperandDynamic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + idx = GetMethodIdOperandIndexDynamic(inst_opcode); + } else if (inst->ctxG->ctxI->mode == Mode::STATIC) { + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasMethodIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + idx = GetMethodIdOperandIndexStatic(inst_opcode); + } else { + LIBABCKIT_UNREACHABLE + } + + auto *intrinsic = inst->impl->CastToIntrinsic(); + methodPtr = reinterpret_cast(intrinsic->GetImm(idx)); + } else { + LIBABCKIT_LOG(DEBUG) << "Instruction is not a call or intrinsic\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto it = ctxG->ptrToMethod.find(reinterpret_cast(methodPtr)); + if (it == ctxG->ptrToMethod.end()) { + LIBABCKIT_LOG(DEBUG) << "No requested call exists in current graph context\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + return it->second; +} + +void IsetMethodStatic(abckit_Inst *inst, abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *ctxG = inst->ctxG; + + auto methodOffset = GetMethodOffset(ctxG, method); + + if (inst->impl->IsCall()) { + auto *callInst = static_cast(inst->impl); + callInst->SetCallMethodId(methodOffset); + } else if (inst->impl->IsIntrinsic()) { + size_t idx = 0; + if (inst->ctxG->ctxI->mode == Mode::DYNAMIC) { + auto inst_opcode = GetDynamicOpcode(inst->impl); + if(!HasMethodIdOperandDynamic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + idx = GetMethodIdOperandIndexDynamic(inst_opcode); + } else if (inst->ctxG->ctxI->mode == Mode::STATIC) { + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasMethodIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + idx = GetMethodIdOperandIndexStatic(inst_opcode); + } else { + LIBABCKIT_UNREACHABLE + } + + auto *intrinsic = inst->impl->CastToIntrinsic(); + intrinsic->SetImm(idx, methodOffset); + } else { + LIBABCKIT_LOG(DEBUG) << "Instruction is not a call or intrinsic\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + auto it = ctxG->ptrToMethod.find(methodOffset); + if (it == ctxG->ptrToMethod.end()) { + LIBABCKIT_LOG(DEBUG) << "No requested call exists in current graph context\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } +} + +void IsetClassStatic(abckit_Inst *inst, abckit_Class *klass) +{ + LIBABCKIT_LOG_FUNC + auto *ctxG = inst->ctxG; + auto *intrinsic = inst->impl->CastToIntrinsic(); + auto inst_opcode = GetStaticOpcode(inst->impl); + if(!HasTypeIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + size_t idx = GetTypeIdOperandIndexStatic(inst_opcode); + auto klassOffset = GetClassOffset(ctxG, klass); + intrinsic->SetImm(idx, klassOffset); +} + +abckit_Class *IgetClassStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + auto *ctxG = inst->ctxG; + auto *intrinsic = inst->impl->CastToIntrinsic(); + auto inst_opcode = IgetOpcodeStaticStatic(inst); + if(!HasTypeIdOperandStatic(inst_opcode)) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + size_t idx = GetTypeIdOperandIndexStatic(inst_opcode); + auto classPtr = reinterpret_cast(intrinsic->GetImm(idx)); + + auto it = ctxG->ptrToClass.find(reinterpret_cast(classPtr)); + if (it == ctxG->ptrToClass.end()) { + LIBABCKIT_LOG(DEBUG) << "No requested class exists in current graph context\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + return it->second; +} + + +abckit_Inst *IcreateLoadArrayStatic(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_TypeId return_type_id) { + + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "IcreateLoadArrayStatic" << '\n'; + + if (return_type_id == abckit_TypeId_INVALID || + ctxG->ctxI->mode != Mode::STATIC || + arrayRef->impl->GetType() != compiler::DataType::REFERENCE || + (idx->impl->GetType() != compiler::DataType::INT32 && + idx->impl->GetType() != compiler::DataType::INT64)) { + + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + // ARRAY VERIFICATION!!! + + auto intrinsicId = compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_ARRAY; + auto dataType = TypeIdToType(return_type_id); + auto loadArrayImpl = ctxG->impl->CreateInstIntrinsic(dataType, 0, intrinsicId); + auto *loadArray = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {2U}; + + loadArrayImpl->ReserveInputs(args_count); + loadArrayImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + loadArrayImpl->AppendInputAndType(arrayRef->impl, compiler::DataType::REFERENCE); + loadArrayImpl->AppendInputAndType(idx->impl, compiler::DataType::INT64); + + loadArray->ctxG = ctxG; + loadArray->impl = loadArrayImpl; + ctxG->implToInst.insert({loadArrayImpl, loadArray}); + + return loadArray; +} + +abckit_Inst *IcreateStoreArrayBody(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id, bool is_wide) { + + if (value_type_id == abckit_TypeId_INVALID || + ctxG->ctxI->mode != Mode::STATIC || + arrayRef->impl->GetType() != compiler::DataType::REFERENCE) { + + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + // ARRAY VERIFICATION!!! :() + auto dataType = TypeIdToType(value_type_id); + + auto intrinsicId = compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_ARRAY; + auto storeArrayImpl = ctxG->impl->CreateInstIntrinsic(dataType, 0, intrinsicId); + auto *storeArray = ctxG->impl->GetLocalAllocator()->New(); // + size_t args_count {3U}; + + storeArrayImpl->ReserveInputs(args_count); + storeArrayImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + storeArrayImpl->AppendInputAndType(arrayRef->impl, compiler::DataType::REFERENCE); + if (is_wide) + storeArrayImpl->AppendInputAndType(idx->impl, compiler::DataType::INT64); + else + storeArrayImpl->AppendInputAndType(idx->impl, compiler::DataType::INT32); + + storeArrayImpl->AppendInputAndType(value->impl, dataType); + + storeArray->ctxG = ctxG; // + storeArray->impl = storeArrayImpl; // + ctxG->implToInst.insert({storeArrayImpl, storeArray}); // + + return storeArray; +} + +abckit_Inst *IcreateStoreArrayStatic(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id) { + + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "IcreateStoreArrayStatic" << '\n'; + + if (idx->impl->GetType() != compiler::DataType::INT32) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + return IcreateStoreArrayBody(ctxG, arrayRef, idx, value, value_type_id, false); +} + +abckit_Inst *IcreateStoreArrayWideStatic(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id) { + + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "IcreateStoreArrayWideStatic" << '\n'; + + if (idx->impl->GetType() != compiler::DataType::INT32 && + idx->impl->GetType() != compiler::DataType::INT64) { + + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + return IcreateStoreArrayBody(ctxG, arrayRef, idx, value, value_type_id, true); +} + +abckit_Inst *IcreateLenArrayStatic(abckit_Graph *ctxG, abckit_Inst *arr) { + + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "IcreateLenArrayStatic" << '\n'; + + if (ctxG->ctxI->mode != Mode::STATIC || + arr->impl->GetType() != compiler::DataType::REFERENCE) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto lenArrayImpl = ctxG->impl->CreateInstLenArray(compiler::DataType::INT32, 0, arr->impl); + auto *lenArray = ctxG->impl->GetLocalAllocator()->New(); + + lenArray->ctxG = ctxG; + lenArray->impl = lenArrayImpl; + ctxG->implToInst.insert({lenArrayImpl, lenArray}); + return lenArray; +} + +abckit_Inst *IcreateLoadConstArrayStatic(abckit_Graph *ctx, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_LOG_FUNC + + return CreateDynInst(ctx, GetLiteralArrayOffset(ctx, literalArray), compiler::DataType::REFERENCE, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_LOAD_CONST_ARRAY, false); +} + +abckit_Inst *IcreateCheckCastStatic(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType) +{ + LIBABCKIT_LOG_FUNC + + if (targetType->id != abckit_TypeId::abckit_TypeId_REFERENCE || targetType->klass == nullptr) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto intrImpl = ctx->impl->CreateInstIntrinsic(compiler::DataType::REFERENCE, 0, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_CHECK_CAST); + auto *intr = ctx->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctx->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(inputObj->impl, inputObj->impl->GetType()); + intrImpl->AddImm(ctx->impl->GetAllocator(), GetClassOffset(ctx, targetType->klass)); + intr->ctxG = ctx; + intr->impl = intrImpl; + ctx->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateIsInstanceStatic(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType) +{ + LIBABCKIT_LOG_FUNC + + if (targetType->id != abckit_TypeId::abckit_TypeId_REFERENCE || targetType->klass == nullptr) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + auto intrImpl = ctx->impl->CreateInstIntrinsic(compiler::DataType::INT32, 0, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_IS_INSTANCE); + auto *intr = ctx->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctx->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(inputObj->impl, inputObj->impl->GetType()); + intrImpl->AddImm(ctx->impl->GetAllocator(), GetClassOffset(ctx, targetType->klass)); + intr->ctxG = ctx; + intr->impl = intrImpl; + ctx->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateLoadUndefinedStatic(abckit_Graph *ctx) +{ + auto instImpl = ctx->impl->CreateInstLoadUndefined(compiler::DataType::REFERENCE); + auto *cast = ctx->impl->GetLocalAllocator()->New(); + cast->ctxG = ctx; + cast->impl = instImpl; + ctx->implToInst.insert({instImpl, cast}); + return cast; +} + +abckit_Inst *IcreateCastStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId target_type_id) { + if (target_type_id <= abckit_TypeId_INVALID || target_type_id > abckit_TypeId_REFERENCE) { + LIBABCKIT_LOG(DEBUG) << "Bad cast destination type\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto instImpl = ctxG->impl->CreateInstCast(TypeIdToType(target_type_id), 0, input0->impl, input0->impl->GetType()); + auto *cast = ctxG->impl->GetLocalAllocator()->New(); + cast->ctxG = ctxG; + cast->impl = instImpl; + ctxG->implToInst.insert({instImpl, cast}); + return cast; +} + +abckit_Inst *IcreateIsUndefinedStatic(abckit_Graph *ctx, abckit_Inst *inputObj) +{ + LIBABCKIT_LOG_FUNC + auto intrImpl = ctx->impl->CreateInstIntrinsic(compiler::DataType::BOOL, 0, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_IS_UNDEFINED); + auto *intr = ctx->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctx->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(inputObj->impl, inputObj->impl->GetType()); + intr->ctxG = ctx; + intr->impl = intrImpl; + ctx->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateReturnStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + auto instImpl = ctxG->impl->CreateInstReturn(input0->impl->GetType(), compiler::INVALID_PC, input0->impl); + auto *ret = ctxG->impl->GetLocalAllocator()->New(); + ret->ctxG = ctxG; + ret->impl = instImpl; + ctxG->implToInst.insert({instImpl, ret}); + return ret; +} + +abckit_Inst *IcreateReturnVoidStatic(abckit_Graph *ctxG) +{ + auto instImpl = ctxG->impl->CreateInstReturnVoid(); + auto *ret = ctxG->impl->GetLocalAllocator()->New(); + ret->ctxG = ctxG; + ret->impl = instImpl; + ctxG->implToInst.insert({instImpl, ret}); + return ret; +} + +abckit_Inst *IcreateThrowStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::REFERENCE, + 0, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_THROW); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {1U}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + intrImpl->AppendInputAndType(input0->impl, compiler::DataType::REFERENCE); + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateCatchPhiStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args) +{ + auto type = ctxG->ctxI->mode == Mode::STATIC ? compiler::DataType::REFERENCE : compiler::DataType::ANY; + auto *instImpl = ctxG->impl->CreateInstCatchPhi(type, 0); + if (argCount == 0) { + instImpl->SetIsAcc(); + } + auto *catchPhi = ctxG->impl->GetLocalAllocator()->New(); + catchPhi->ctxG = ctxG; + catchPhi->impl = instImpl; + ctxG->implToInst.insert({instImpl, catchPhi}); + return catchPhi; +} + +abckit_Inst *GcreateNullPtrStatic(abckit_Graph *ctxG) +{ + auto instImpl = ctxG->impl->CreateInstNullPtr(compiler::DataType::REFERENCE); + auto *inst = ctxG->impl->GetLocalAllocator()->New(); + inst->ctxG = ctxG; + inst->impl = instImpl; + ctxG->implToInst.insert({instImpl, inst}); + ctxG->impl->GetStartBlock()->AppendInst(instImpl); + return inst; +} + +int64_t IgetConstantValueI64Static(abckit_Inst *inst) +{ + if (!inst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction" << '\n'; + } + if (inst->impl->GetType() != compiler::DataType::INT64 && inst->impl->GetType() != compiler::DataType::UINT64) { + LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n'; + } + return static_cast(inst->impl)->GetInt64Value(); +} + +uint64_t IgetConstantValueU64Static(abckit_Inst *inst) +{ + if (!inst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction" << '\n'; + SetLastError(abckit_Status_BAD_ARGUMENT); + } + if (inst->impl->GetType() != compiler::DataType::INT64 && inst->impl->GetType() != compiler::DataType::UINT64) { + LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n'; + SetLastError(abckit_Status_BAD_ARGUMENT); + } + return static_cast(inst->impl)->GetInt64Value(); +} + +double IgetConstantValueF64Static(abckit_Inst *inst) +{ + if (!inst->impl->IsConst()) { + LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction" << '\n'; + SetLastError(abckit_Status_BAD_ARGUMENT); + } + if (inst->impl->GetType() != compiler::DataType::FLOAT64) { + LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n'; + SetLastError(abckit_Status_BAD_ARGUMENT); + } + return static_cast(inst->impl)->GetDoubleValue(); +} + +uint64_t IgetImmediateStatic(abckit_Inst *inst, size_t idx) +{ + LIBABCKIT_LOG_FUNC + + if (IgetImmediateCountStatic(inst) <= idx) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return 0; + } + + if (inst->impl->IsBinaryImmInst()) { + return (static_cast(inst->impl))->GetImm(); + } else if (inst->impl->GetOpcode() == compiler::Opcode::Intrinsic) { + return inst->impl->CastToIntrinsic()->GetImm(idx); + } else { + SetLastError(abckit_Status_BAD_ARGUMENT); + return 0; + } +} + +void IsetImmediateStatic(abckit_Inst *inst, size_t idx, uint64_t imm) +{ + LIBABCKIT_LOG_FUNC + + if (IgetImmediateCountStatic(inst) <= idx) { + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + if (inst->impl->IsBinaryImmInst()) { + (static_cast(inst->impl))->SetImm(imm); + return; + } else if (inst->impl->GetOpcode() == compiler::Opcode::Intrinsic) { + inst->impl->CastToIntrinsic()->SetImm(idx, imm); + return; + } else { + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } +} + +uint64_t IgetImmediateCountStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + if (inst->impl->IsBinaryImmInst()) { + return 1; + } else if (inst->impl->GetOpcode() == compiler::Opcode::Intrinsic) { + return inst->impl->CastToIntrinsic()->GetImms().size(); + } else { + return 0; + } +} + +abckit_Inst *IcreateIfStaticStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_IsaApiStaticConditionCode cc) +{ + LIBABCKIT_LOG_FUNC + auto instImpl = ctxG->impl->CreateInstIf(compiler::DataType::NO_TYPE, 0, input0->impl, + input1->impl, input0->impl->GetType(), CcToCc(cc), ctxG->impl->GetMethod()); + auto *ret = ctxG->impl->GetLocalAllocator()->New(); + ret->ctxG = ctxG; + ret->impl = instImpl; + ctxG->implToInst.insert({instImpl, ret}); + return ret; +} + +abckit_Inst *IcreateIfDynamicStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_IsaApiDynamicConditionCode cc) +{ + LIBABCKIT_LOG_FUNC + auto instImpl = ctxG->impl->CreateInstIf(compiler::DataType::NO_TYPE, 0, input0->impl, + input1->impl, input0->impl->GetType(), CcToCc(cc), ctxG->impl->GetMethod()); + auto *ret = ctxG->impl->GetLocalAllocator()->New(); + ret->ctxG = ctxG; + ret->impl = instImpl; + ctxG->implToInst.insert({instImpl, ret}); + return ret; +} + +abckit_Inst *IcreateTryStatic(abckit_Graph *ctx) +{ + LIBABCKIT_LOG_FUNC + auto instImpl = ctx->impl->CreateInstTry(); + auto *ret = ctx->impl->GetLocalAllocator()->New(); + ret->ctxG = ctx; + ret->impl = instImpl; + ctx->implToInst.insert({instImpl, ret}); + return ret; +} + +abckit_Module *IgetModuleStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + if (!inst->impl->IsIntrinsic()) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto intrInst = inst->impl->CastToIntrinsic(); + auto opcode = GetDynamicIntrinsicOpcode(intrInst); + if (opcode != abckit_IsaApiDynamicOpcode_getmodulenamespace && opcode != abckit_IsaApiDynamicOpcode_wide_getmodulenamespace) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + return inst->ctxG->method->m->md[intrInst->GetImm(0)]; +} + +uint64_t GetModuleIndex(abckit_Graph *ctxG, abckit_Module *md) +{ + uint64_t imm = 0; + for (auto m : ctxG->method->m->md) { + if (m == md) { + break; + } + imm++; + } + if (imm == ctxG->method->m->md.size()) { + LIBABCKIT_LOG(DEBUG) << "Can not find module descriptor for module with name '" << md->moduleName->impl << "'\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return 0; + } + return imm; +} + +void IsetModuleStatic(abckit_Inst *inst, abckit_Module *md) +{ + LIBABCKIT_LOG_FUNC + + if (!inst->impl->IsIntrinsic()) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + auto intrInst = inst->impl->CastToIntrinsic(); + auto opcode = GetDynamicIntrinsicOpcode(intrInst); + if (opcode != abckit_IsaApiDynamicOpcode_getmodulenamespace && opcode != abckit_IsaApiDynamicOpcode_wide_getmodulenamespace) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + uint64_t imm = GetModuleIndex(inst->ctxG, md); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return; + } + intrInst->SetImm(0, imm); +} + +abckit_ImportDescriptor *GetImportDescriptorDynamic(abckit_Inst *inst, uint64_t idx) +{ + auto *module = inst->ctxG->method->m; + for (size_t i = 0; i < module->id.size(); i++) { + if (!module->id[i]->payload.dyn.isRegularImport) { + continue; + } + if (module->id[i]->payload.dyn.moduleRecordIndexOff == idx) { + return module->id[i].get(); + } + } + UNREACHABLE(); +} + +abckit_ImportDescriptor *IgetImportDescriptorStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + if (!inst->impl->IsIntrinsic()) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto intrInst = inst->impl->CastToIntrinsic(); + auto opcode = GetDynamicIntrinsicOpcode(intrInst); + if (opcode != abckit_IsaApiDynamicOpcode_ldexternalmodulevar && opcode != abckit_IsaApiDynamicOpcode_wide_ldexternalmodulevar) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + switch (inst->ctxG->ctxI->mode) { + case Mode::DYNAMIC: + return GetImportDescriptorDynamic(inst, intrInst->GetImm(0)); + case Mode::STATIC: + LIBABCKIT_UNREACHABLE + default: + LIBABCKIT_UNREACHABLE + } + + return nullptr; +} + +uint32_t GetImportDescriptorIdxDynamic(abckit_Graph *ctxG, abckit_ImportDescriptor *id) +{ + abckit_Module *m = ctxG->method->m; + auto found = std::find_if(m->id.begin(), m->id.end(), [&](std::unique_ptr const& d) { + return d.get() == id; + }); + if (found == m->id.end()) { + LIBABCKIT_LOG(DEBUG) << "Can not find the import in module imports\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return 0; + } + return (*found)->payload.dyn.moduleRecordIndexOff; +} + +void IsetImportDescriptorStatic(abckit_Inst *inst, abckit_ImportDescriptor *id) +{ + LIBABCKIT_LOG_FUNC + + if (!inst->impl->IsIntrinsic()) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + auto intrInst = inst->impl->CastToIntrinsic(); + auto opcode = GetDynamicIntrinsicOpcode(intrInst); + if (opcode != abckit_IsaApiDynamicOpcode_ldexternalmodulevar && opcode != abckit_IsaApiDynamicOpcode_wide_ldexternalmodulevar) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + uint32_t imm = 0; + switch (inst->ctxG->ctxI->mode) { + case Mode::DYNAMIC: + imm = GetImportDescriptorIdxDynamic(inst->ctxG, id); + break; + case Mode::STATIC: + LIBABCKIT_UNREACHABLE + default: + LIBABCKIT_UNREACHABLE + } + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return; + } + intrInst->SetImm(0, imm); +} + +abckit_ExportDescriptor *GetExportDescriptorDynamic(abckit_Inst *inst, uint64_t idx) +{ + auto *module = inst->ctxG->method->m; + for (size_t i = 0; i < module->ed.size(); i++) { + if (module->ed[i]->payload.dyn.kind != abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT) { + continue; + } + if (module->ed[i]->payload.dyn.moduleRecordIndexOff == idx) { + return module->ed[i].get(); + } + } + UNREACHABLE(); +} + +abckit_ExportDescriptor *IgetExportDescriptorStatic(abckit_Inst *inst) +{ + LIBABCKIT_LOG_FUNC + + if (!inst->impl->IsIntrinsic()) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + auto intrInst = inst->impl->CastToIntrinsic(); + auto opcode = GetDynamicIntrinsicOpcode(intrInst); + if (opcode != abckit_IsaApiDynamicOpcode_ldlocalmodulevar && opcode != abckit_IsaApiDynamicOpcode_wide_ldlocalmodulevar && + opcode != abckit_IsaApiDynamicOpcode_stmodulevar && opcode != abckit_IsaApiDynamicOpcode_wide_stmodulevar) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + switch (inst->ctxG->ctxI->mode) { + case Mode::DYNAMIC: + return GetExportDescriptorDynamic(inst, intrInst->GetImm(0)); + case Mode::STATIC: + LIBABCKIT_UNREACHABLE + default: + LIBABCKIT_UNREACHABLE + } + + return nullptr; +} + +uint32_t GetExportDescriptorIdxDynamic(abckit_Graph *ctxG, abckit_ExportDescriptor *ed) +{ + abckit_Module *m = ctxG->method->m; + auto found = std::find_if(m->ed.begin(), m->ed.end(), [&](std::unique_ptr const& d) { + return d.get() == ed; + }); + if (found == m->ed.end()) { + LIBABCKIT_LOG(DEBUG) << "Can not find the import in module imports\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return 0; + } + return (*found)->payload.dyn.moduleRecordIndexOff; +} + +void IsetExportDescriptorStatic(abckit_Inst *inst, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_LOG_FUNC + + if (!inst->impl->IsIntrinsic()) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + auto intrInst = inst->impl->CastToIntrinsic(); + auto opcode = GetDynamicIntrinsicOpcode(intrInst); + if (opcode != abckit_IsaApiDynamicOpcode_ldlocalmodulevar && opcode != abckit_IsaApiDynamicOpcode_wide_ldlocalmodulevar && + opcode != abckit_IsaApiDynamicOpcode_stmodulevar && opcode != abckit_IsaApiDynamicOpcode_wide_stmodulevar) { + LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + uint32_t imm = 0; + switch (inst->ctxG->ctxI->mode) { + case Mode::DYNAMIC: + imm = GetExportDescriptorIdxDynamic(inst->ctxG, ed); + break; + case Mode::STATIC: + LIBABCKIT_UNREACHABLE + default: + LIBABCKIT_UNREACHABLE + } + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return; + } + intrInst->SetImm(0, imm); +} + +abckit_IsaApiStaticConditionCode IgetConditionCodeStaticStatic(abckit_Inst *inst) +{ + return CcToStaticCc(inst->impl->CastToIf()->GetCc()); +} + +abckit_IsaApiDynamicConditionCode IgetConditionCodeDynamicStatic(abckit_Inst *inst) +{ + return CcToDynamicCc(inst->impl->CastToIf()->GetCc()); +} + +void IsetConditionCodeStaticStatic(abckit_Inst *inst, abckit_IsaApiStaticConditionCode cc) +{ + inst->impl->CastToIf()->SetCc(CcToCc(cc)); +} + +void IsetConditionCodeDynamicStatic(abckit_Inst *inst, abckit_IsaApiDynamicConditionCode cc) +{ + inst->impl->CastToIf()->SetCc(CcToCc(cc)); +} + +abckit_Inst *IcreateDynCallthis0Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLTHIS0_IMM8_V8); +} + +abckit_Inst *IcreateDynCallthis1Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLTHIS1_IMM8_V8_V8); +} + +abckit_Inst *IcreateDynCallarg0Static(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLARG0_IMM8); +} + +abckit_Inst *IcreateDynCallarg1Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLARG1_IMM8_V8); +} + +abckit_Inst *IcreateDynTryldglobalbynameStatic(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_TRYLDGLOBALBYNAME_IMM8_ID16); +} + +abckit_Inst *IcreateDynLdobjbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_LDOBJBYNAME_IMM8_ID16); +} + +abckit_Inst *IcreateDynNewobjrangeStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_NEWOBJRANGE_IMM16_IMM8_V8); +} + +abckit_Inst *IcreateDynDefinefuncStatic(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetMethodOffset(ctxG, method), imm0, compiler::IntrinsicInst::IntrinsicId::DYN_DEFINEFUNC_IMM16_ID16_IMM8); +} + +abckit_Inst *IcreateDynNegStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_NEG_IMM8); +} + +abckit_Inst *IcreateDynAdd2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ADD2_IMM8_V8); +} + +abckit_Inst *IcreateDynSub2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_SUB2_IMM8_V8); +} + +abckit_Inst *IcreateDynMul2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_MUL2_IMM8_V8); +} + +abckit_Inst *IcreateDynDiv2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_DIV2_IMM8_V8); +} + +abckit_Inst *IcreateDynMod2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_MOD2_IMM8_V8); +} + +abckit_Inst *IcreateDynExpStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_EXP_IMM8_V8); +} + +abckit_Inst *IcreateDynShl2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_SHL2_IMM8_V8); +} + +abckit_Inst *IcreateDynShr2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_SHR2_IMM8_V8); +} + +abckit_Inst *IcreateDynAshr2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ASHR2_IMM8_V8); +} + +abckit_Inst *IcreateDynNotStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_NOT_IMM8); +} + + +abckit_Inst *IcreateDynOr2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_OR2_IMM8_V8); +} + +abckit_Inst *IcreateDynXor2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_XOR2_IMM8_V8); +} + +abckit_Inst *IcreateDynAnd2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_AND2_IMM8_V8); +} + +abckit_Inst *IcreateDynIncStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_INC_IMM8); +} + +abckit_Inst *IcreateDynDecStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_DEC_IMM8); +} + +abckit_Inst *IcreateDynEqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_EQ_IMM8_V8); +} + +abckit_Inst *IcreateDynNoteqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_NOTEQ_IMM8_V8); +} + +abckit_Inst *IcreateDynLessStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_LESS_IMM8_V8); +} + +abckit_Inst *IcreateDynLesseqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_LESSEQ_IMM8_V8); +} + +abckit_Inst *IcreateDynGreaterStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_GREATER_IMM8_V8); +} + +abckit_Inst *IcreateDynGreatereqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_GREATEREQ_IMM8_V8); +} + +abckit_Inst *IcreateDynStrictnoteqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_STRICTNOTEQ_IMM8_V8); +} + +abckit_Inst *IcreateDynStricteqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_STRICTEQ_IMM8_V8); +} + +abckit_Inst *IcreateDynIstrueStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_ISTRUE); +} + +abckit_Inst *IcreateDynIsfalseStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_ISFALSE); +} + +abckit_Inst *IcreateDynTonumberStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_TONUMBER_IMM8); +} + +abckit_Inst *IcreateDynTonumericStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_TONUMERIC_IMM8); +} + +abckit_Inst *IcreateDynThrowStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_PREF_NONE); +} + +abckit_Inst *IcreateDynThrowNotexistsStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_NOTEXISTS_PREF_NONE); +} + +abckit_Inst *IcreateDynThrowPatternnoncoercibleStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_PATTERNNONCOERCIBLE_PREF_NONE); +} + +abckit_Inst *IcreateDynThrowDeletesuperpropertyStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_DELETESUPERPROPERTY_PREF_NONE); +} + +abckit_Inst *IcreateDynThrowConstassignmentStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_CONSTASSIGNMENT_PREF_V8); +} + +abckit_Inst *IcreateDynThrowIfnotobjectStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_IFNOTOBJECT_PREF_V8); +} + +abckit_Inst *IcreateDynThrowUndefinedifholeStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_UNDEFINEDIFHOLE_PREF_V8_V8); +} + +abckit_Inst *IcreateDynThrowIfsupernotcorrectcallStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8, false); +} + +abckit_Inst *IcreateDynThrowUndefinedifholewithnameStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16, false); +} + +abckit_Inst *IcreateDynCallruntimeCreateprivatepropertyStatic(abckit_Graph *ctxG, uint64_t imm0, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, GetLiteralArrayOffset(ctxG, literalArray), compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_CREATEPRIVATEPROPERTY_PREF_IMM16_ID16, false); +} + +abckit_Inst *IcreateDynDefineclasswithbufferStatic(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0) { + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetMethodOffset(ctxG, method), GetLiteralArrayOffset(ctxG, literalArray), imm0, input0, compiler::IntrinsicInst::IntrinsicId::DYN_DEFINECLASSWITHBUFFER_IMM16_ID16_ID16_IMM16_V8); +} + +abckit_Inst *IcreateDynCallruntimeDefinesendableclassStatic(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetMethodOffset(ctxG, method), GetLiteralArrayOffset(ctxG, literalArray), imm0, input0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_DEFINESENDABLECLASS_PREF_IMM16_ID16_ID16_IMM16_V8); +} + +abckit_Inst *IcreateDynLdnanStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDNAN); +} + +abckit_Inst *IcreateDynLdinfinityStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDINFINITY); +} + +abckit_Inst *IcreateDynLdundefinedStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDUNDEFINED); +} + +abckit_Inst *IcreateDynLdnullStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDNULL); +} + +abckit_Inst *IcreateDynLdsymbolStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDSYMBOL); +} + +abckit_Inst *IcreateDynLdglobalStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDGLOBAL); +} + +abckit_Inst *IcreateDynLdtrueStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDTRUE); +} + +abckit_Inst *IcreateDynLdfalseStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDFALSE); +} + +abckit_Inst *IcreateDynLdholeStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDHOLE); +} + +abckit_Inst *IcreateDynLdfunctionStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDFUNCTION); +} + +abckit_Inst *IcreateDynLdnewtargetStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDNEWTARGET); +} + +abckit_Inst *IcreateDynLdthisStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_LDTHIS); +} + +abckit_Inst *IcreateDynTypeofStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_TYPEOF_IMM16); +} + +abckit_Inst *IcreateDynIsinStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ISIN_IMM8_V8); +} + +abckit_Inst *IcreateDynInstanceofStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_INSTANCEOF_IMM8_V8); +} + +abckit_Inst *IcreateDynReturnStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_RETURN); +} + +abckit_Inst *IcreateDynReturnundefinedStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_RETURNUNDEFINED); +} + +abckit_Inst *IcreateDynStownbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STOWNBYNAME_IMM16_ID16_V8); +} + +abckit_Inst *IcreateDynStownbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_STOWNBYVALUE_IMM8_V8_V8); +} + +abckit_Inst *IcreateDynStownbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_STOWNBYINDEX_IMM16_V8_IMM16); +} + +abckit_Inst *IcreateDynWideStownbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_STOWNBYINDEX_PREF_V8_IMM32, false); +} + +abckit_Inst *IcreateDynStownbyvaluewithnamesetStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_STOWNBYVALUEWITHNAMESET_IMM16_V8_V8); +} + +abckit_Inst *IcreateDynStownbynamewithnamesetStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STOWNBYNAMEWITHNAMESET_IMM8_ID16_V8); +} + +abckit_Inst *IcreateDynCreateemptyobjectStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEEMPTYOBJECT); +} + +abckit_Inst *IcreateDynStobjbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_STOBJBYVALUE_IMM16_V8_V8); +} + +abckit_Inst *IcreateDynStobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_STOBJBYINDEX_IMM8_V8_IMM16); +} + +abckit_Inst *IcreateDynWideStobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_STOBJBYINDEX_PREF_V8_IMM32, false); +} + +abckit_Inst *IcreateDynStobjbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STOBJBYNAME_IMM16_ID16_V8); +} + +abckit_Inst *IcreateDynPoplexenvStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_POPLEXENV); +} + +abckit_Inst *IcreateDynGetunmappedargsStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_GETUNMAPPEDARGS); +} + +abckit_Inst *IcreateDynAsyncfunctionenterStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_ASYNCFUNCTIONENTER); +} + +abckit_Inst *IcreateDynDebuggerStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_DEBUGGER); +} + +abckit_Inst *IcreateDynCreateemptyarrayStatic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEEMPTYARRAY_IMM16); +} + +abckit_Inst *IcreateDynGetpropiteratorStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_GETPROPITERATOR); +} + +abckit_Inst *IcreateDynGetiteratorStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_GETITERATOR_IMM16); +} + +abckit_Inst *IcreateDynCloseiteratorStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, compiler::IntrinsicInst::IntrinsicId::DYN_CLOSEITERATOR_IMM16_V8); +} + +abckit_Inst *IcreateDynGetasynciteratorStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_GETASYNCITERATOR_IMM8); +} + +abckit_Inst *IcreateDynCreategeneratorobjStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEGENERATOROBJ_V8); +} + +abckit_Inst *IcreateDynCreateasyncgeneratorobjStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEASYNCGENERATOROBJ_V8); +} + +abckit_Inst *IcreateDynCallruntimeNotifyconcurrentresultStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_NOTIFYCONCURRENTRESULT_PREF_NONE); +} + +abckit_Inst *IcreateDynCallruntimeTopropertykeyStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_TOPROPERTYKEY_PREF_NONE); +} + +abckit_Inst *IcreateDynResumegeneratorStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_RESUMEGENERATOR); +} + +abckit_Inst *IcreateDynGetresumemodeStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_GETRESUMEMODE); +} + +abckit_Inst *IcreateDynGettemplateobjectStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_GETTEMPLATEOBJECT_IMM8); +} + +abckit_Inst *IcreateDynGetnextpropnameStatic(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, compiler::IntrinsicInst::IntrinsicId::DYN_GETNEXTPROPNAME_V8); +} + +abckit_Inst *IcreateDynLdthisbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_LDTHISBYVALUE_IMM16); +} + +abckit_Inst *IcreateDynDynamicimportStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_DYNAMICIMPORT); +} + +//* Binary instructions *// + +abckit_Inst *IcreateDynCreateiterresultobjStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEITERRESULTOBJ_V8_V8); +} + +abckit_Inst *IcreateDynNewobjapplyStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_NEWOBJAPPLY_IMM16_V8); +} + +abckit_Inst *IcreateDynCallruntimeCallinitStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_CALLINIT_PREF_IMM8_V8); +} + +abckit_Inst *IcreateDynSupercallspreadStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_SUPERCALLSPREAD_IMM8_V8); +} + +abckit_Inst *IcreateDynDelobjpropStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_DELOBJPROP_V8); +} + +abckit_Inst *IcreateDynSuspendgeneratorStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_SUSPENDGENERATOR_V8); +} + +abckit_Inst *IcreateDynAsyncfunctionawaituncaughtStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ASYNCFUNCTIONAWAITUNCAUGHT_V8); +} + +abckit_Inst *IcreateDynCopydatapropertiesStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_COPYDATAPROPERTIES_V8); +} + +abckit_Inst *IcreateDynSetobjectwithprotoStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_SETOBJECTWITHPROTO_IMM16_V8); +} + +abckit_Inst *IcreateDynLdobjbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_LDOBJBYVALUE_IMM16_V8); +} + +abckit_Inst *IcreateDynLdsuperbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_LDSUPERBYVALUE_IMM16_V8); +} + +abckit_Inst *IcreateDynAsyncfunctionresolveStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ASYNCFUNCTIONRESOLVE_V8); +} + +abckit_Inst *IcreateDynAsyncfunctionrejectStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ASYNCFUNCTIONREJECT_V8); +} + +abckit_Inst *IcreateDynStthisbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_STTHISBYVALUE_IMM8_V8); +} + +abckit_Inst *IcreateDynAsyncgeneratorrejectStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, compiler::IntrinsicInst::IntrinsicId::DYN_ASYNCGENERATORREJECT_V8); +} + +//* Ternary instructions *// + +abckit_Inst *IcreateDynCallargs2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLARGS2_IMM8_V8_V8); +} + +abckit_Inst *IcreateDynApplyStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_APPLY_IMM8_V8_V8); +} + +abckit_Inst *IcreateDynStarrayspreadStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_STARRAYSPREAD_V8_V8); +} + +abckit_Inst *IcreateDynStsuperbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_STSUPERBYVALUE_IMM16_V8_V8); +} + +abckit_Inst *IcreateDynAsyncgeneratorresolveStatic(abckit_Graph *ctxG, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, input2, compiler::IntrinsicInst::IntrinsicId::DYN_ASYNCGENERATORRESOLVE_V8_V8_V8); +} + +abckit_Inst *IcreateDynCallruntimeDefinefieldbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_DEFINEFIELDBYVALUE_PREF_IMM8_V8_V8); +} + +abckit_Inst *IcreateDynDefinefieldbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_DEFINEFIELDBYNAME_IMM8_ID16_V8); +} + +abckit_Inst *IcreateDynStsuperbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STSUPERBYNAME_IMM16_ID16_V8); +} + +abckit_Inst *IcreateDynCreateobjectwithexcludedkeysStatic(abckit_Graph *ctxG, uint64_t imm0, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8); +} + +abckit_Inst *IcreateDynWideCreateobjectwithexcludedkeysStatic(abckit_Graph *ctxG, uint64_t imm0, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8, false); +} + +abckit_Inst *IcreateDynCallruntimeDefinefieldbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, + uint64_t imm0, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_DEFINEFIELDBYINDEX_PREF_IMM8_IMM32_V8); +} + +abckit_Inst *IcreateDynCallthisrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLTHISRANGE_IMM8_IMM8_V8); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {argCount + 2}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + for (size_t index = 0; index < argCount + 1; ++index) { + abckit_Inst *input = va_arg(args, abckit_Inst *); + intrImpl->AppendInputAndType(input->impl, compiler::DataType::ANY); + } + intrImpl->AppendInputAndType(acc->impl, compiler::DataType::ANY); + intrImpl->AddImm(ctxG->impl->GetAllocator(), 0XF); + intrImpl->AddImm(ctxG->impl->GetAllocator(), argCount); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateDynWideCallthisrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + auto intrImpl = ctxG->impl->CreateInstIntrinsic(compiler::DataType::ANY, 0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_CALLTHISRANGE_PREF_IMM16_V8); + auto *intr = ctxG->impl->GetLocalAllocator()->New(); + size_t args_count {argCount + 2}; + intrImpl->ReserveInputs(args_count); + intrImpl->AllocateInputTypes(ctxG->impl->GetAllocator(), args_count); + for (size_t index = 0; index < argCount + 1; ++index) { + abckit_Inst *input = va_arg(args, abckit_Inst *); + intrImpl->AppendInputAndType(input->impl, compiler::DataType::ANY); + } + intrImpl->AppendInputAndType(acc->impl, compiler::DataType::ANY); + intrImpl->AddImm(ctxG->impl->GetAllocator(), argCount); + intr->ctxG = ctxG; + intr->impl = intrImpl; + ctxG->implToInst.insert({intrImpl, intr}); + return intr; +} + +abckit_Inst *IcreateDynSupercallarrowrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_SUPERCALLARROWRANGE_IMM8_IMM8_V8); +} + +abckit_Inst *IcreateDynCallrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRANGE_IMM8_IMM8_V8); +} + +abckit_Inst *IcreateDynWideCallrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_CALLRANGE_PREF_IMM16_V8, false); +} + +abckit_Inst *IcreateDynWideSupercallarrowrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8, false); +} + +abckit_Inst *IcreateDynStprivatepropertyStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8); +} +abckit_Inst *IcreateDynCallruntimeDefineprivatepropertyStatic(abckit_Graph *ctxG, abckit_Inst *acc, + uint64_t imm0, uint64_t imm1, abckit_Inst *input0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8); +} + +abckit_Inst *IcreateDynCreateregexpwithliteralStatic(abckit_Graph *ctxG, abckit_String *string, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetStringOffset(ctxG, string), imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CREATEREGEXPWITHLITERAL_IMM16_ID16_IMM8); +} + +abckit_Inst *IcreateDynCreatearraywithbufferStatic(abckit_Graph *ctxG, abckit_LiteralArray *literalArray) { + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetLiteralArrayOffset(ctxG, literalArray), compiler::IntrinsicInst::IntrinsicId::DYN_CREATEARRAYWITHBUFFER_IMM16_ID16); +} + +abckit_Inst *IcreateDynCreateobjectwithbufferStatic(abckit_Graph *ctxG, abckit_LiteralArray *literalArray) { + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetLiteralArrayOffset(ctxG, literalArray), compiler::IntrinsicInst::IntrinsicId::DYN_CREATEOBJECTWITHBUFFER_IMM16_ID16); +} + +abckit_Inst *IcreateDynCallargs3Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, input2, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLARGS3_IMM8_V8_V8_V8); +} + +abckit_Inst *IcreateDynCallthis2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, input2, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLTHIS2_IMM8_V8_V8_V8); +} + +abckit_Inst *IcreateDynCallthis3Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2, abckit_Inst *input3) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, input0, input1, input2, input3, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLTHIS3_IMM8_V8_V8_V8_V8); +} + +abckit_Inst *IcreateDynDefinegettersetterbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, input0, input1, input2, input3, compiler::IntrinsicInst::IntrinsicId::DYN_DEFINEGETTERSETTERBYVALUE_V8_V8_V8_V8); +} + +abckit_Inst *IcreateDynStlexvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_STLEXVAR_IMM8_IMM8); +} + +abckit_Inst *IcreateDynWideStlexvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_STLEXVAR_PREF_IMM16_IMM16, false); +} + +abckit_Inst *IcreateDynTestinStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_TESTIN_IMM8_IMM16_IMM16); +} + +abckit_Inst *IcreateDynLdprivatepropertyStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_LDPRIVATEPROPERTY_IMM8_IMM16_IMM16); +} + +abckit_Inst *IcreateDynLdlexvarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_LDLEXVAR_IMM8_IMM8); +} +abckit_Inst *IcreateDynWideLdlexvarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_LDLEXVAR_PREF_IMM16_IMM16, false); +} + +abckit_Inst *IcreateDynStconsttoglobalrecordStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STCONSTTOGLOBALRECORD_IMM16_ID16); +} + +abckit_Inst *IcreateDynSttoglobalrecordStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STTOGLOBALRECORD_IMM16_ID16); +} + +abckit_Inst *IcreateDynStthisbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STTHISBYNAME_IMM16_ID16); +} + +abckit_Inst *IcreateDynTrystglobalbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_TRYSTGLOBALBYNAME_IMM16_ID16); +} + +abckit_Inst *IcreateDynStglobalvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_STGLOBALVAR_IMM16_ID16); +} + +abckit_Inst *IcreateDynLdsuperbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_LDSUPERBYNAME_IMM16_ID16); +} + +abckit_Inst *IcreateDynWideStpatchvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0){ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_STPATCHVAR_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynSetgeneratorstateStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0){ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_SETGENERATORSTATE_IMM8); +} + +abckit_Inst *IcreateDynLdobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0){ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_LDOBJBYINDEX_IMM16_IMM16); +} + +abckit_Inst *IcreateDynWideLdobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0){ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_LDOBJBYINDEX_PREF_IMM32, false); +} + +abckit_Inst *IcreateDynSupercallthisrangeStatic(abckit_Graph *ctxG, size_t argCount , std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_SUPERCALLTHISRANGE_IMM8_IMM8_V8); +} + +abckit_Inst *IcreateDynWideSupercallthisrangeStatic(abckit_Graph *ctxG, size_t argCount , std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8, false); +} + +abckit_Inst *IcreateDynWideNewobjrangeStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, argCount, args, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_NEWOBJRANGE_PREF_IMM16_V8, false); +} + +abckit_Inst *IcreateDynWideLdpatchvarStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_LDPATCHVAR_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynNewlexenvStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_NEWLEXENV_IMM8); +} + +abckit_Inst *IcreateDynWideNewlexenvStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_NEWLEXENV_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynNewlexenvwithnameStatic(abckit_Graph *ctxG, uint64_t imm0, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetLiteralArrayOffset(ctxG, literalArray), compiler::IntrinsicInst::IntrinsicId::DYN_NEWLEXENVWITHNAME_IMM8_ID16, false); +} + +abckit_Inst *IcreateDynWideNewlexenvwithnameStatic(abckit_Graph *ctxG, uint64_t imm0, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_LOG_FUNC + + return CreateDynInst(ctxG, GetLiteralArrayOffset(ctxG, literalArray), compiler::IntrinsicInst::IntrinsicId::DYN_NEWLEXENVWITHNAME_IMM8_ID16, false); +} + +abckit_Inst *IcreateDynCopyrestargsStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_COPYRESTARGS_IMM8); +} + +abckit_Inst *IcreateDynWideCopyrestargsStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_COPYRESTARGS_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynCallruntimeLdsendableclassStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_LDSENDABLECLASS_PREF_IMM16); +} + +abckit_Inst *IcreateDynCallruntimeLdsendableexternalmodulevarStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_LDSENDABLEEXTERNALMODULEVAR_PREF_IMM8); +} + +abckit_Inst *IcreateDynCallruntimeWideldsendableexternalmodulevarStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_WIDELDSENDABLEEXTERNALMODULEVAR_PREF_IMM16); +} + +abckit_Inst *IcreateDynCallruntimeNewsendableenvStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_NEWSENDABLEENV_PREF_IMM8); +} + +abckit_Inst *IcreateDynCallruntimeWidenewsendableenvStatic(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_WIDENEWSENDABLEENV_PREF_IMM16); +} + +abckit_Inst *IcreateDynCallruntimeStsendablevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_STSENDABLEVAR_PREF_IMM4_IMM4); +} + +abckit_Inst *IcreateDynCallruntimeWidestsendablevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_WIDESTSENDABLEVAR_PREF_IMM16_IMM16); +} + +abckit_Inst *IcreateDynCallruntimeLdsendablevarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_LDSENDABLEVAR_PREF_IMM4_IMM4); +} + +abckit_Inst *IcreateDynCallruntimeWideldsendablevarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, imm0, imm1, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_WIDELDSENDABLEVAR_PREF_IMM16_IMM16); +} + +abckit_Inst *IcreateDynCallruntimeIstrueStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_ISTRUE_PREF_IMM8); +} + +abckit_Inst *IcreateDynCallruntimeIsfalseStatic(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, acc, compiler::IntrinsicInst::IntrinsicId::DYN_CALLRUNTIME_ISFALSE_PREF_IMM8); +} + +abckit_Inst *IcreateDynLdglobalvarStatic(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_LDGLOBALVAR_IMM16_ID16); +} + +abckit_Inst *IcreateDynLdbigintStatic(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_LDBIGINT_ID16); +} + +abckit_Inst *IcreateDynLdthisbynameStatic(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_LOG_FUNC + return CreateDynInst(ctxG, GetStringOffset(ctxG, string), compiler::IntrinsicInst::IntrinsicId::DYN_LDTHISBYNAME_IMM16_ID16); +} + +abckit_Inst *IcreateDynIfStatic(abckit_Graph *ctxG, abckit_Inst *input, abckit_IsaApiDynamicConditionCode cc) +{ + LIBABCKIT_LOG_FUNC + + if (!((cc == abckit_IsaApiDynamicConditionCode_CC_NE) || (cc == abckit_IsaApiDynamicConditionCode_CC_EQ))) { + SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "IcreateDynIf works only with CC_NE and CC_EQ condidion codes\n"; + return nullptr; + } + + auto constZeroImpl = ctxG->impl->FindOrCreateConstant(0L); + auto *constZeroI = ctxG->impl->GetLocalAllocator()->New(); + constZeroI->ctxG = ctxG; + constZeroI->impl = constZeroImpl; + ctxG->implToInst.insert({constZeroImpl, constZeroI}); + + return IcreateIfDynamicStatic(ctxG, input, constZeroI, cc); +} + +abckit_Inst *IcreateDynGetmodulenamespaceStatic(abckit_Graph *ctxG, abckit_Module *md) +{ + LIBABCKIT_LOG_FUNC + + uint64_t imm = GetModuleIndex(ctxG, md); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, imm, compiler::IntrinsicInst::IntrinsicId::DYN_GETMODULENAMESPACE_IMM8, false); +} + +abckit_Inst *IcreateDynWideGetmodulenamespaceStatic(abckit_Graph *ctxG, abckit_Module *md) +{ + LIBABCKIT_LOG_FUNC + + uint64_t imm = GetModuleIndex(ctxG, md); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, imm, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_GETMODULENAMESPACE_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynLdexternalmodulevarStatic(abckit_Graph *ctxG, abckit_ImportDescriptor *id) +{ + LIBABCKIT_LOG_FUNC + + uint32_t imm = GetImportDescriptorIdxDynamic(ctxG, id); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, imm, compiler::IntrinsicInst::IntrinsicId::DYN_LDEXTERNALMODULEVAR_IMM8, false); +} + +abckit_Inst *IcreateDynWideLdexternalmodulevarStatic(abckit_Graph *ctxG, abckit_ImportDescriptor *id) +{ + LIBABCKIT_LOG_FUNC + + uint32_t imm = GetImportDescriptorIdxDynamic(ctxG, id); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, imm, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_LDEXTERNALMODULEVAR_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynLdlocalmodulevarStatic(abckit_Graph *ctxG, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_LOG_FUNC + + uint32_t imm = GetExportDescriptorIdxDynamic(ctxG, ed); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, imm, compiler::IntrinsicInst::IntrinsicId::DYN_LDLOCALMODULEVAR_IMM8, false); +} + +abckit_Inst *IcreateDynWideLdlocalmodulevarStatic(abckit_Graph *ctxG, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_LOG_FUNC + + uint32_t imm = GetExportDescriptorIdxDynamic(ctxG, ed); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, imm, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_LDLOCALMODULEVAR_PREF_IMM16, false); +} + + +abckit_Inst *IcreateDynStmodulevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_LOG_FUNC + + uint32_t imm = GetExportDescriptorIdxDynamic(ctxG, ed); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, acc, imm, compiler::IntrinsicInst::IntrinsicId::DYN_STMODULEVAR_IMM8, false); +} + +abckit_Inst *IcreateDynWideStmodulevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_LOG_FUNC + + uint32_t imm = GetExportDescriptorIdxDynamic(ctxG, ed); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctxG, acc, imm, compiler::IntrinsicInst::IntrinsicId::DYN_WIDE_STMODULEVAR_PREF_IMM16, false); +} + +abckit_Inst *IcreateDynDefinemethodStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0) +{ + LIBABCKIT_LOG_FUNC + auto methodOffset = GetMethodOffset(ctxG, method); + return CreateDynInst(ctxG, acc, methodOffset, imm0, compiler::IntrinsicInst::IntrinsicId::DYN_DEFINEMETHOD_IMM16_ID16_IMM8, true); +} + +abckit_Inst *IcreateNewArrayStatic(abckit_Graph *ctx, abckit_Class *inputClass, abckit_Inst *inputSize) +{ + LIBABCKIT_LOG_FUNC + + return CreateDynInst(ctx, GetClassOffset(ctx, inputClass), compiler::DataType::REFERENCE, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_NEW_ARRAY, false); +} + +abckit_Inst *IcreateNewObjectStatic(abckit_Graph *ctx, abckit_Class *inputClass) +{ + LIBABCKIT_LOG_FUNC + + auto typeId = GetClassOffset(ctx, inputClass); + if (statuses::GetLastError() != abckit_Status_NO_ERROR) { + return nullptr; + } + return CreateDynInst(ctx, typeId, compiler::DataType::REFERENCE, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_NEW_OBJECT, false); +} + +constexpr size_t MAX_NUM_SHORT_CALL_ARGS = 2; +constexpr size_t MAX_NUM_NON_RANGE_ARGS = 4; + +abckit_Inst *IcreateInitObjectStatic(abckit_Graph *ctx, abckit_Method *inputMethod, size_t argCount, + va_list argp) +{ + LIBABCKIT_LOG_FUNC + + auto func = reinterpret_cast(inputMethod->impl); + auto constrName = pandasm::MangleFunctionName(func->name, func->params, func->returnType); + uint64_t methodId; + bool found = false; + for (const auto &[offset, name] : ctx->irInterface->methods) { + if (name == constrName) { + methodId = offset; + found = true; + break; + } + } + + if (!found) { + LIBABCKIT_LOG(DEBUG) << "Can not find method id for '" << constrName << "'\n"; + SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + abckit_Inst *inst {nullptr}; + if (argCount > MAX_NUM_NON_RANGE_ARGS) { + inst = CreateDynInst(ctx, methodId, ark::compiler::DataType::REFERENCE, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_INIT_OBJECT_RANGE, false); + } else if (argCount > MAX_NUM_SHORT_CALL_ARGS) { + inst = CreateDynInst(ctx, methodId, ark::compiler::DataType::REFERENCE, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_INIT_OBJECT, false); + } else { + inst = CreateDynInst(ctx, methodId, ark::compiler::DataType::REFERENCE, compiler::IntrinsicInst::IntrinsicId::INTRINSIC_BCT_INIT_OBJECT_SHORT, false); + } + + inst->impl->CastToIntrinsic()->AllocateInputTypes(ctx->impl->GetAllocator(), argCount); + for (size_t i = 0; i < argCount; i++) { + auto *arg = va_arg(argp, abckit_Inst *); + inst->impl->CastToIntrinsic()->AppendInputAndType(arg->impl, arg->impl->GetType()); + } + va_end(argp); + + return inst; +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_static/ir_static.h b/libabckit/src/adapter_static/ir_static.h new file mode 100644 index 0000000000000000000000000000000000000000..1fdb8c29ee023f78abb982d703837da98c01299d --- /dev/null +++ b/libabckit/src/adapter_static/ir_static.h @@ -0,0 +1,476 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_STATIC_IR_STATIC_H +#define LIBABCKIT_SRC_ADAPTER_STATIC_IR_STATIC_H + +#include "libabckit/include/metadata.h" +#include "libabckit/include/ir_core.h" +#include "libabckit/include/isa/isa_dynamic.h" +#include "libabckit/include/isa/isa_static.h" + +#include +#include + +namespace libabckit { + +// ======================================== +// Api for Graph manipulation +// ======================================== + +abckit_BasicBlock *GgetStartBasicBlockStatic(abckit_Graph *ctx); +abckit_BasicBlock *GgetEndBasicBlockStatic(abckit_Graph *ctx); +abckit_BasicBlock *GgetBasicBlockStatic(abckit_Graph *ctx, uint32_t id); +abckit_Inst *GgetParameterStatic(abckit_Graph *ctx, uint32_t index); +void GinsertTryCatchStatic(abckit_BasicBlock *tryFirstBB, abckit_BasicBlock *tryLastBB, + abckit_BasicBlock *catchBeginBB, abckit_BasicBlock *catchEndBB); +uint32_t GgetNumberOfBasicBlocksStatic(abckit_Graph *ctx); +void GdumpStatic(abckit_Graph *ctxG, int fd); +void GrunPassRemoveUnreachableBlocksStatic(abckit_Graph *ctxG); +void IdumpStatic(abckit_Inst *inst, int fd); +void GvisitBlocksRPOStatic(abckit_Graph *ctx, void *data, void (*cb)(abckit_BasicBlock *bb, void *data)); + +// ======================================== +// Api for basic block manipulation +// ======================================== + +void BBvisitSuccBlocksStatic(abckit_BasicBlock *curBasicBlock, void *data, + void (*cb)(abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, + void *data)); +void BBvisitPredBlocksStatic(abckit_BasicBlock *curBasicBlock, void *data, + void (*cb)(abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, + void *data)); +void BBvisitDominatedBlocksStatic(abckit_BasicBlock *basicBlock, void *data, + void (*cb)(abckit_BasicBlock *basicBlock, abckit_BasicBlock *dominatedBasicBlock, + void *data)); +abckit_Inst *BBgetFirstInstStatic(abckit_BasicBlock *basicBlock); +abckit_Inst *BBgetLastInstStatic(abckit_BasicBlock *basicBlock); +abckit_Graph *BBgetGraphStatic(abckit_BasicBlock *basicBlock); +abckit_BasicBlock *BBgetTrueBranchStatic(abckit_BasicBlock *curBasicBlock); +abckit_BasicBlock *BBgetFalseBranchStatic(abckit_BasicBlock *curBasicBlock); +abckit_BasicBlock *BBcreateEmptyStatic(abckit_Graph *ctx); +abckit_BasicBlock *BBgetSuccBlockStatic(abckit_BasicBlock *basicBlock, int32_t index); +abckit_BasicBlock *BBgetPredBlockStatic(abckit_BasicBlock *basicBlock, int32_t index); +abckit_BasicBlock *BBgetImmediateDominatorStatic(abckit_BasicBlock *basicBlock); +uint64_t BBgetSuccBlockCountStatic(abckit_BasicBlock *basicBlock); +uint64_t BBgetPredBlockCountStatic(abckit_BasicBlock *basicBlock); +uint32_t BBgetIdStatic(abckit_BasicBlock *basicBlock); +uint32_t BBgetNumberOfInstructionsStatic(abckit_BasicBlock *basicBlock); +abckit_BasicBlock *BBsplitBlockAfterInstructionStatic(abckit_Inst *inst, bool makeEdge); +void BBclearStatic(abckit_BasicBlock *basicBlock); +void BBconnectBlocksStatic(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool connectViaTrueEdge); +void BBdisconnectBlocksStatic(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2); +void BBaddInstFrontStatic(abckit_BasicBlock *basicBlock, abckit_Inst *inst); +void BBaddInstBackStatic(abckit_BasicBlock *basicBlock, abckit_Inst *inst); +void BBdumpStatic(abckit_BasicBlock *basicBlock, int fd); +void BBsetPredBlocksStatic(abckit_BasicBlock *basicBlock, size_t argCount, va_list args); +void BBsetSuccBlocksStatic(abckit_BasicBlock *basicBlock, size_t argCount, va_list args); +void BBsetSuccBlockStatic(abckit_BasicBlock *basicBlock, abckit_BasicBlock *succBlock, int32_t index); +void BBsetPredBlockStatic(abckit_BasicBlock *basicBlock, abckit_BasicBlock *predBlock, int32_t index); +bool BBisStartStatic(abckit_BasicBlock *basicBlock); +bool BBisEndStatic(abckit_BasicBlock *basicBlock); +bool BBisLoopHeadStatic(abckit_BasicBlock *basicBlock); +bool BBisLoopPreheadStatic(abckit_BasicBlock *basicBlock); +bool BBisTryBeginStatic(abckit_BasicBlock *basicBlock); +bool BBisTryStatic(abckit_BasicBlock *basicBlock); +bool BBisTryEndStatic(abckit_BasicBlock *basicBlock); +bool BBisCatchBeginStatic(abckit_BasicBlock *basicBlock); +bool BBisCatchStatic(abckit_BasicBlock *basicBlock); +bool BBcheckDominanceStatic(abckit_BasicBlock *basicBlock, abckit_BasicBlock *dominator); +abckit_Inst *BBcreatePhiStatic(abckit_BasicBlock *bb, size_t argCount, std::va_list args); + +// ======================================== +// Api for instruction manipulation +// ======================================== + +abckit_Inst *IcreateCallStaticStatic(abckit_Graph *ctx, abckit_Method *inputMethod, size_t argCount, + va_list argp); +abckit_Inst *IcreateCallVirtualStatic(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Method *inputMethod, size_t argCount, + va_list argp); +abckit_Inst *IcreateLoadStringStatic(abckit_Graph *ctx, abckit_String* str); +abckit_Inst *GcreateConstantI32Static(abckit_Graph *ctxG, int32_t value); +abckit_Inst *GcreateConstantI64Static(abckit_Graph *ctxG, int64_t value); +abckit_Inst *GcreateConstantU64Static(abckit_Graph *ctxG, uint64_t value); +abckit_Inst *GcreateConstantF64Static(abckit_Graph *ctxG, double value); + +abckit_Inst *IcreateCmpStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateNegStatic(abckit_Graph *ctxG, abckit_Inst *input0); + +abckit_Inst *IcreateAddStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateSubStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateMulStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDivStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateModStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateEqualsStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); + +abckit_Inst *IcreateAddIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateSubIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateMulIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateDivIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateModIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); + +abckit_Inst *IcreateShlStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateShrStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateAShrStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); + +abckit_Inst *IcreateShlIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateShrIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateAShrIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); + +abckit_Inst *IcreateNotStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateOrStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateXorStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateAndStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); + +abckit_Inst *IcreateOrIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateXorIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); +abckit_Inst *IcreateAndIStatic(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm); + +abckit_Inst *IcreateLoadArrayStatic(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_TypeId return_type_id); +abckit_Inst *IcreateStoreArrayStatic(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id); +abckit_Inst *IcreateStoreArrayWideStatic(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id); +abckit_Inst *IcreateLenArrayStatic(abckit_Graph *ctxG, abckit_Inst *arr); +abckit_Inst *IcreateLoadConstArrayStatic(abckit_Graph *ctxG, abckit_LiteralArray *literaArray); + +abckit_Inst *IcreateCheckCastStatic(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType); +abckit_Inst *IcreateIsInstanceStatic(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType); +abckit_Inst *IcreateLoadUndefinedStatic(abckit_Graph *ctx); +abckit_Inst *IcreateCastStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId target_type_id); +abckit_Inst *IcreateIsUndefinedStatic(abckit_Graph *ctx, abckit_Inst *inputObj); + +abckit_Inst *IcreateThrowStatic(abckit_Graph *ctxG, abckit_Inst *acc); + + +abckit_Inst *IcreateReturnStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateReturnVoidStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateCatchPhiStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args); +abckit_Inst *GcreateNullPtrStatic(abckit_Graph *ctxG); + +int64_t IgetConstantValueI64Static(abckit_Inst *inst); +uint64_t IgetConstantValueU64Static(abckit_Inst *inst); +double IgetConstantValueF64Static(abckit_Inst *inst); +abckit_LiteralArray *IgetLiteralArrayStatic(abckit_Inst *inst); +void IsetLiteralArrayStatic(abckit_Inst *inst, abckit_LiteralArray *la); +abckit_String *IgetStringStatic(abckit_Inst *inst); +void IsetStringStatic(abckit_Inst *inst, abckit_String *str); + +abckit_Inst *IcreateDynCallthis0Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynCallthis1Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1); +abckit_Inst *IcreateDynCallarg0Static(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynCallarg1Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynTryldglobalbynameStatic(abckit_Graph *ctxG, abckit_String *string); +abckit_Inst *IcreateDynLdobjbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string); +abckit_Inst *IcreateDynNewobjrangeStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args); + +abckit_Inst *IcreateDynDefinefuncStatic(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm0); + +abckit_Inst *IcreateDynNegStatic(abckit_Graph *ctxG, abckit_Inst *acc); + +abckit_Inst *IcreateDynAdd2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynSub2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynMul2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynDiv2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynMod2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynExpStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); + +abckit_Inst *IcreateDynShl2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynShr2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynAshr2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); + +abckit_Inst *IcreateDynNotStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynOr2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynXor2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynAnd2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); + +abckit_Inst *IcreateDynIncStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynDecStatic(abckit_Graph *ctxG, abckit_Inst *acc); + +abckit_Inst *IcreateDynEqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynNoteqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynLessStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynLesseqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynGreaterStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynGreatereqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynStrictnoteqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynStricteqStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); + +abckit_Inst *IcreateDynIstrueStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynIsfalseStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynTonumberStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynTonumericStatic(abckit_Graph *ctxG, abckit_Inst *acc); + +abckit_Inst *IcreateDynThrowStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynThrowNotexistsStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynThrowPatternnoncoercibleStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynThrowDeletesuperpropertyStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynThrowConstassignmentStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateDynThrowIfnotobjectStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateDynThrowUndefinedifholeStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDynThrowIfsupernotcorrectcallStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0); +abckit_Inst *IcreateDynThrowUndefinedifholewithnameStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string); + +abckit_Inst *IcreateDynLdnanStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdinfinityStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdundefinedStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdnullStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdsymbolStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdglobalStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdtrueStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdfalseStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdholeStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdfunctionStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdnewtargetStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynLdthisStatic(abckit_Graph *ctxG); + +abckit_Inst *IcreateDynTypeofStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynIsinStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynInstanceofStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynReturnStatic(abckit_Graph *ctxG, abckit_Inst* acc); +abckit_Inst *IcreateDynReturnundefinedStatic(abckit_Graph *ctxG); + +abckit_Inst *IcreateDynStownbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, abckit_Inst *input0); +abckit_Inst *IcreateDynStownbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDynStownbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0); +abckit_Inst *IcreateDynWideStownbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0); +abckit_Inst *IcreateDynStownbynamewithnamesetStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, abckit_Inst *input1); +abckit_Inst *IcreateDynStownbyvaluewithnamesetStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDynStobjbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDynStobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0); +abckit_Inst *IcreateDynWideStobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, uint64_t imm0); +abckit_Inst *IcreateDynStobjbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, abckit_Inst *input0); + +abckit_Inst *IcreateDynCreateemptyobjectStatic(abckit_Graph *ctxG); + +abckit_Inst *IcreateDynPoplexenvStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynGetunmappedargsStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynAsyncfunctionenterStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynDebuggerStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynGetpropiteratorStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynGetiteratorStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynCloseiteratorStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateDynGetasynciteratorStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynLdprivatepropertyStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1); +abckit_Inst *IcreateDynStprivatepropertyStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1, abckit_Inst *input0); +abckit_Inst *IcreateDynTestinStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynDefinefieldbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0); +abckit_Inst *IcreateDynCreateemptyarrayStatic(abckit_Graph *ctxG); +abckit_Inst *IcreateDynCreategeneratorobjStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateDynCreateiterresultobjStatic(abckit_Graph *ctxG, abckit_Inst *input0, + abckit_Inst *input1); +abckit_Inst *IcreateDynCreateobjectwithexcludedkeysStatic(abckit_Graph *ctxG, uint64_t imm0, + abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDynWideCreateobjectwithexcludedkeysStatic(abckit_Graph *ctxG, uint64_t imm0, + abckit_Inst *input0, abckit_Inst *input1); + +abckit_Inst *IcreateDynCreateregexpwithliteralStatic(abckit_Graph *ctxG, abckit_String *string, + uint64_t imm0); +abckit_Inst *IcreateDynDefineclasswithbufferStatic(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0); +abckit_Inst *IcreateDynNewobjapplyStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynWideNewobjrangeStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynNewlexenvStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynWideNewlexenvStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynNewlexenvwithnameStatic(abckit_Graph *ctxG, uint64_t imm0, abckit_LiteralArray *literalArray); +abckit_Inst *IcreateDynWideNewlexenvwithnameStatic(abckit_Graph *ctxG, uint64_t imm0, abckit_LiteralArray *literalArray); + +abckit_Inst *IcreateDynCreateasyncgeneratorobjStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateDynAsyncgeneratorresolveStatic(abckit_Graph *ctxG, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2); +abckit_Inst *IcreateDynCallruntimeNotifyconcurrentresultStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynCallruntimeDefinefieldbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1); +abckit_Inst *IcreateDynCallruntimeDefinefieldbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, + uint64_t imm0, abckit_Inst *input0); +abckit_Inst *IcreateDynCallruntimeTopropertykeyStatic(abckit_Graph *ctxG, abckit_Inst *acc); + +abckit_Inst *IcreateDynCallruntimeDefineprivatepropertyStatic(abckit_Graph *ctxG, abckit_Inst *acc, + uint64_t imm0, uint64_t imm1, abckit_Inst *input0); +abckit_Inst *IcreateDynCallruntimeCallinitStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); + +abckit_Inst *IcreateDynCallruntimeDefinesendableclassStatic(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0); +abckit_Inst *IcreateDynCallruntimeLdsendableclassStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynCallruntimeLdsendableexternalmodulevarStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynCallruntimeWideldsendableexternalmodulevarStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynCallruntimeNewsendableenvStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynCallruntimeWidenewsendableenvStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynCallruntimeStsendablevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynCallruntimeWidestsendablevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynCallruntimeLdsendablevarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynCallruntimeWideldsendablevarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynCallruntimeIstrueStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynCallruntimeIsfalseStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynCallruntimeCreateprivatepropertyStatic(abckit_Graph *ctxG, uint64_t imm0, + abckit_LiteralArray *literalArray); +abckit_Inst *IcreateDynCallruntimeDefinesendableclassStatic(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0); +abckit_Inst *IcreateDynCallargs2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1); +abckit_Inst *IcreateDynCallargs3Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2); +abckit_Inst *IcreateDynCallrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynWideCallrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynSupercallspreadStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynApplyStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1); +abckit_Inst *IcreateDynCallthis2Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2); +abckit_Inst *IcreateDynCallthis3Static(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2, abckit_Inst *input3); +abckit_Inst *IcreateDynCallthisrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynWideCallthisrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynSupercallthisrangeStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynWideSupercallthisrangeStatic(abckit_Graph *ctxG, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynSupercallarrowrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynWideSupercallarrowrangeStatic(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, std::va_list args); +abckit_Inst *IcreateDynDefinegettersetterbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3); + +abckit_Inst *IcreateDynResumegeneratorStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynGetresumemodeStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynGettemplateobjectStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynGetnextpropnameStatic(abckit_Graph *ctxG, abckit_Inst *input0); +abckit_Inst *IcreateDynDelobjpropStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynSuspendgeneratorStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynAsyncfunctionawaituncaughtStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0); +abckit_Inst *IcreateDynCopydatapropertiesStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynStarrayspreadStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1); +abckit_Inst *IcreateDynSetobjectwithprotoStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynLdobjbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynLdsuperbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynStsuperbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1); +abckit_Inst *IcreateDynLdobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0); +abckit_Inst *IcreateDynWideLdobjbyindexStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0); +abckit_Inst *IcreateDynAsyncfunctionresolveStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynAsyncfunctionrejectStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynCopyrestargsStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynWideCopyrestargsStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynLdlexvarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynWideLdlexvarStatic(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynStlexvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1); +abckit_Inst *IcreateDynWideStlexvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1); + +abckit_Inst *IcreateDynTrystglobalbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string); +abckit_Inst *IcreateDynLdglobalvarStatic(abckit_Graph *ctxG, abckit_String *string); +abckit_Inst *IcreateDynStglobalvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string); +abckit_Inst *IcreateDynLdsuperbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string); +abckit_Inst *IcreateDynStsuperbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0); + +abckit_Inst *IcreateDynStconsttoglobalrecordStatic(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string); +abckit_Inst *IcreateDynSttoglobalrecordStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string); +abckit_Inst *IcreateDynLdbigintStatic(abckit_Graph *ctxG, abckit_String *string); +abckit_Inst *IcreateDynLdthisbynameStatic(abckit_Graph *ctxG, abckit_String *string); +abckit_Inst *IcreateDynStthisbynameStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string); +abckit_Inst *IcreateDynLdthisbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynStthisbyvalueStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynWideLdpatchvarStatic(abckit_Graph *ctxG, uint64_t imm0); +abckit_Inst *IcreateDynWideStpatchvarStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0); +abckit_Inst *IcreateDynDynamicimportStatic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynAsyncgeneratorrejectStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynSetgeneratorstateStatic(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0); + +abckit_Inst *IcreateDynGetmodulenamespaceStatic(abckit_Graph *ctxG, abckit_Module *md); +abckit_Inst *IcreateDynWideGetmodulenamespaceStatic(abckit_Graph *ctxG, abckit_Module *md); +abckit_Inst *IcreateDynLdexternalmodulevarStatic(abckit_Graph *ctxG, abckit_ImportDescriptor *id); +abckit_Inst *IcreateDynWideLdexternalmodulevarStatic(abckit_Graph *ctxG, abckit_ImportDescriptor *id); +abckit_Inst *IcreateDynLdlocalmodulevarStatic(abckit_Graph *ctxG, abckit_ExportDescriptor *ed); +abckit_Inst *IcreateDynWideLdlocalmodulevarStatic(abckit_Graph *ctxG, abckit_ExportDescriptor *ed); +abckit_Inst *IcreateDynStmodulevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_ExportDescriptor *ed); +abckit_Inst *IcreateDynWideStmodulevarStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_ExportDescriptor *ed); +abckit_Inst *IcreateDynCreatearraywithbufferStatic(abckit_Graph *ctxG, abckit_LiteralArray *literalArray); +abckit_Inst *IcreateDynCreateobjectwithbufferStatic(abckit_Graph *ctxG, abckit_LiteralArray *literalArray); + +abckit_Inst *IcreateDynDefinemethodStatic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0); + +void IremoveStatic(abckit_Inst *inst); +uint32_t IgetIdStatic(abckit_Inst *inst); +abckit_IsaApiStaticOpcode IgetOpcodeStaticStatic(abckit_Inst *inst); +abckit_IsaApiDynamicOpcode IgetOpcodeDynamicStatic(abckit_Inst *inst); + +abckit_Inst *IgetNextStatic(abckit_Inst *instnext); +abckit_Inst *IgetPrevStatic(abckit_Inst *instprev); +void IinsertAfterStatic(abckit_Inst *inst, abckit_Inst *next); +void IinsertBeforeStatic(abckit_Inst *inst, abckit_Inst *prev); +abckit_BasicBlock *IgetBasicBlockStatic(abckit_Inst *instprev); +bool IcheckDominanceStatic(abckit_Inst *inst, abckit_Inst *dominator); +void IvisitUsersStatic(abckit_Inst *inst, void *data, void (*cb)(abckit_Inst *inst, abckit_Inst *user, void *data)); +void IvisitInputsStatic(abckit_Inst *inst, void *data, + void (*cb)(abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data)); +uint32_t IgetUserCountStatic(abckit_Inst *inst); +void IsetImmediateStatic(abckit_Inst *inst, size_t idx, uint64_t imm); + +uint64_t IgetInputCountStatic(abckit_Inst *inst); +abckit_Inst *IgetInputStatic(abckit_Inst *inst, size_t index); +void IsetInputStatic(abckit_Inst *inst, abckit_Inst *input, int32_t index); +void IsetInputsStatic(abckit_Inst *inst, size_t argCount, std::va_list args); +void IappendInputStatic(abckit_Inst *inst, abckit_Inst *input); +abckit_Type *IgetTypeStatic(abckit_Inst *inst); +abckit_TypeId IgetTargetTypeStatic(abckit_Inst *inst); +void IsetTargetTypeStatic(abckit_Inst *inst, abckit_TypeId t); +abckit_Method *IgetMethodStatic(abckit_Inst *inst); +void IsetCallMethodStatic(abckit_Inst *inst, abckit_Method *method); +void IsetMethodStatic(abckit_Inst *inst, abckit_Method *method); +void IsetClassStatic(abckit_Inst *inst, abckit_Class *klass); +abckit_Class *IgetClassStatic(abckit_Inst *inst); +uint64_t IgetImmediateStatic(abckit_Inst *inst, size_t idx); +uint64_t IgetImmediateCountStatic(abckit_Inst *inst); +abckit_Inst *IcreateIfStaticStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_IsaApiStaticConditionCode cc); +abckit_Inst *IcreateIfDynamicStatic(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_IsaApiDynamicConditionCode cc); +abckit_Inst *IcreateTryStatic(abckit_Graph *ctx); +abckit_BasicBlock *IgetBasicBlockStatic(abckit_Inst *inst); +abckit_Module *IgetModuleStatic(abckit_Inst *inst); +void IsetModuleStatic(abckit_Inst *inst, abckit_Module *md); +abckit_ImportDescriptor *IgetImportDescriptorStatic(abckit_Inst *inst); +void IsetImportDescriptorStatic(abckit_Inst *inst, abckit_ImportDescriptor *id); +abckit_ExportDescriptor *IgetExportDescriptorStatic(abckit_Inst *inst); +void IsetExportDescriptorStatic(abckit_Inst *inst, abckit_ExportDescriptor *id); +abckit_IsaApiStaticConditionCode IgetConditionCodeStaticStatic(abckit_Inst *inst); +abckit_IsaApiDynamicConditionCode IgetConditionCodeDynamicStatic(abckit_Inst *inst); +void IsetConditionCodeStaticStatic(abckit_Inst *inst, abckit_IsaApiStaticConditionCode cc); +void IsetConditionCodeDynamicStatic(abckit_Inst *inst, abckit_IsaApiDynamicConditionCode cc); + +abckit_Inst *IcreateDynCallarg0Dynamic(abckit_Graph *ctxG, abckit_Inst *acc); +abckit_Inst *IcreateDynCallarg1Dynamic(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0); +abckit_Inst *IcreateDynIfStatic(abckit_Graph *ctxG, abckit_Inst *input, abckit_IsaApiDynamicConditionCode cc); + +abckit_Inst *IcreateNewArrayStatic(abckit_Graph *ctx, abckit_Class *inputClass, abckit_Inst *inputSize); + +abckit_Inst *IcreateNewObjectStatic(abckit_Graph *ctx, abckit_Class *inputClass); +abckit_Inst *IcreateInitObjectStatic(abckit_Graph *ctx, abckit_Method *inputMethod, size_t argCount, + va_list argp); + +bool IcheckIsCallStatic(abckit_Inst *inst); + +} // namespace libabckit + +#endif diff --git a/libabckit/src/adapter_static/metadata_inspect_static.cpp b/libabckit/src/adapter_static/metadata_inspect_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a8f0e9195c36b84f6b8c35aef2882f121ba4b14 --- /dev/null +++ b/libabckit/src/adapter_static/metadata_inspect_static.cpp @@ -0,0 +1,586 @@ +/** + * Copyright (c) 2024 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 "helpers_static.h" +#include "metadata_inspect_static.h" +#include "assembler/annotation.h" +#include "libabckit/include/statuses.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/metadata_inspect_impl.h" + +#include "modifiers.h" +#include "static_core/assembler/assembly-program.h" +#include "static_core/assembler/mangling.h" + +#include +#include + +using namespace ark; + +namespace libabckit { + +// ======================================== +// File +// ======================================== + +abckit_File_Version FileGetVersionStatic(abckit_File *ctx) +{ + LIBABCKIT_LOG_FUNC + return ctx->version; +} + +// ======================================== +// Module +// ======================================== + +void ModuleEnumerateClassesStatic(abckit_Module *m, void *data, bool (*cb)(abckit_Class *klass, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &[className, klass] : m->ct) { + if (!cb(klass.get(), data)) { + return; + } + } +} + +void ModuleEnumerateTopLevelMethodsStatic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &method : m->methods) { + if (!cb(method.get(), data)) { + return; + } + } +} + +void ModuleEnumerateAnnotationInterfacesStatic(abckit_Module *m, void *data, bool (*cb)(abckit_AnnotationInterface *ai, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &[atName, at] : m->at) { + if (!cb(at.get(), data)) { + return; + } + } +} + +void ModuleEnumerateAnonymousFunctionsStatic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &method : m->methods) { + if (!MethodIsAnonymousStatic(method.get())) { + continue; + } + if (!cb(method.get(), data)) { + return; + } + } +} + +// ======================================== +// Class +// ======================================== + +abckit_String *ClassGetNameStatic(abckit_Class *klass) +{ + LIBABCKIT_LOG_FUNC + auto *record = reinterpret_cast(klass->impl.cl); + auto [moduleName, className] = ClassGetNames(record->name); + auto &strings = klass->m->ctxI->strings; + + if (strings.find(className) != strings.end()) { + return strings.at(className).get(); + } + + auto s = std::make_unique(); + s->impl = className; + strings.insert({className, std::move(s)}); + return strings[className].get(); +} + +void ClassEnumerateMethodsStatic(abckit_Class *klass, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &method : klass->methods) { + if (!cb(method.get(), data)) { + return; + } + } +} + +void ClassEnumerateAnnotationsStatic(abckit_Class *klass, void *data, bool (*cb)(abckit_Annotation *anno, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &annotation : klass->annotations) { + if (!cb(annotation.get(), data)) { + return; + } + } +} + +// ======================================== +// Method +// ======================================== +abckit_String *MethodGetNameStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *function = reinterpret_cast(method->impl); + + auto [moduleName, className] = FuncGetNames(function->name); + auto methodName = pandasm::MangleFunctionName(function->name, function->params, function->returnType); + auto croppedName = FuncNameCropModule(methodName); + + auto &strings = method->m->ctxI->strings; + if (strings.find(croppedName) != strings.end()) { + return strings.at(croppedName).get(); + } + + auto s = std::make_unique(); + s->impl = croppedName; + strings.insert({croppedName, std::move(s)}); + return strings[croppedName].get(); +} + +abckit_Code *MethodGetCodeStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *code = new abckit_Code({method->impl, method}); // FIXME: arena + return code; +} + +abckit_Class *MethodGetParentClassStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + return method->klass; +} + +bool MethodIsStaticStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return (func->metadata->GetAccessFlags() & ACC_STATIC) != 0x0; +} + +bool MethodIsCtorStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + size_t pos = func->name.rfind('.'); + assert(pos != std::string::npos); + std::string name = func->name.substr(pos + 1); + return name == "_ctor_"; // FIXME(ivagin) +} + +bool MethodIsAnonymousStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + size_t pos = func->name.rfind('.'); + assert(pos != std::string::npos); + std::string name = func->name.substr(pos + 1); + if (name.find("lambda$invoke$") == 0) { + return true; + } + return false; +} + +bool MethodIsNativeStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return (func->metadata->GetAccessFlags() & ACC_NATIVE) != 0x0; +} + +bool MethodIsAbstractStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return (func->metadata->GetAccessFlags() & ACC_ABSTRACT) != 0x0; +} + +bool MethodIsExternalStatic(abckit_Method *method) +{ + LIBABCKIT_LOG_FUNC + auto *func = reinterpret_cast(method->impl); + return func->metadata->IsForeign(); +} + +void MethodEnumerateAnnotationsStatic(abckit_Method *method, void *data, bool (*cb)(abckit_Annotation *anno, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &annotation : method->annotations) { + if (!cb(annotation.get(), data)) { + return; + } + } +} + +// ======================================== +// Annotation +// ======================================== + +void AnnotationEnumerateElementsStatic(abckit_Annotation *anno, void *data, bool (*cb)(abckit_AnnotationElement *ae, void *data)) +{ + LIBABCKIT_LOG_FUNC + for (auto &elem : anno->elements) { + if (!cb(elem.get(), data)) { + return; + } + } +} + +abckit_String *AnnotationElementGetNameStatic(abckit_AnnotationElement *ae) +{ + LIBABCKIT_LOG_FUNC + auto name = ae->name; + + abckit_Module *module = nullptr; + if (std::holds_alternative(ae->ann->owner)) { + module = std::get(ae->ann->owner)->m; + } else if (std::holds_alternative(ae->ann->owner)) { + module = std::get(ae->ann->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + auto &strings = module->ctxI->strings; + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +abckit_AnnotationInterface *AnnotationGetInterfaceStatic(abckit_Annotation *anno) +{ + LIBABCKIT_LOG_FUNC + auto recName = anno->name; + + abckit_Module *module = nullptr; + if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } else if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + return module->at[recName].get(); +} + +abckit_String *AnnotationInterfaceGetNameStatic(abckit_AnnotationInterface *ai) +{ + LIBABCKIT_LOG_FUNC + auto annotation = reinterpret_cast(ai->impl); + auto name = annotation->GetName(); + auto &strings = ai->m->ctxI->strings; + auto s = std::make_unique(); + s->impl = name; + strings.insert({name, std::move(s)}); + return strings[name].get(); +} + +// ======================================== +// String +// ======================================== + +void StringToStringStatic([[maybe_unused]] abckit_File *ctx, abckit_String *value, char *out, size_t *len) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << value->impl << '\n'; + if (out == nullptr) { + *len = value->impl.size() + 1; + } else { + std::strncpy(out, value->impl.c_str(), value->impl.size()); + } +} + +// ======================================== +// ImportDescriptor +// ======================================== + +abckit_String *ImportDescriptorGetNameStatic(abckit_ImportDescriptor *i) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_String *ImportDescriptorGetAliasStatic(abckit_ImportDescriptor *i) +{ + LIBABCKIT_UNIMPLEMENTED +} + +// ======================================== +// ExportDescriptor +// ======================================== + +abckit_String *ExportDescriptorGetNameStatic(abckit_ExportDescriptor *i) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_String *ExportDescriptorGetAliasStatic(abckit_ExportDescriptor *i) +{ + LIBABCKIT_UNIMPLEMENTED +} + +// ======================================== +// Literal +// ======================================== + +bool LiteralGetBoolStatic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsBoolValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return false; + } + return std::get(literal->value); +} + +uint8_t LiteralGetU8Static(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsByteValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value); +} + +uint16_t LiteralGetU16Static(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsShortValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value); +} + +uint32_t LiteralGetU32Static(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsIntegerValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value); +} + +uint64_t LiteralGetU64Static(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsLongValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value); +} + +float LiteralGetFloatStatic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsFloatValue()) { + std::cout << (uint32_t) literal->tag << std::endl; + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value); +} + +double LiteralGetDoubleStatic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsDoubleValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return 0; + } + return std::get(literal->value); +} + +abckit_String *LiteralGetStringStatic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto s = std::make_unique(); + auto* literal = reinterpret_cast(lit->val); + if(!literal->IsStringValue()) { + statuses::SetLastError(abckit_Status_WRONG_LITERAL_TYPE); + return nullptr; + } + + auto &strings = ctx->strings; + + auto val = std::get(literal->value); + if (strings.find(val) != strings.end()) { + return strings[val].get(); + } + s->impl = val; + strings.insert({val, std::move(s)}); + + return strings[val].get(); +} + +abckit_LiteralTag LiteralGetTagStatic(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_LOG_FUNC + auto* litImpl = reinterpret_cast(lit->val); + switch (litImpl->tag) { + case panda_file::LiteralTag::ARRAY_U1: + case panda_file::LiteralTag::BOOL: + return abckit_LiteralTag_BOOL; + case panda_file::LiteralTag::ARRAY_U8: + case panda_file::LiteralTag::ARRAY_I8: + return abckit_LiteralTag_BYTE; + case panda_file::LiteralTag::ARRAY_U16: + case panda_file::LiteralTag::ARRAY_I16: + return abckit_LiteralTag_SHORT; + case panda_file::LiteralTag::ARRAY_U32: + case panda_file::LiteralTag::ARRAY_I32: + case panda_file::LiteralTag::INTEGER: + return abckit_LiteralTag_INTEGER; + case panda_file::LiteralTag::ARRAY_U64: + case panda_file::LiteralTag::ARRAY_I64: + return abckit_LiteralTag_LONG; + case panda_file::LiteralTag::ARRAY_F32: + case panda_file::LiteralTag::FLOAT: + return abckit_LiteralTag_FLOAT; + case panda_file::LiteralTag::ARRAY_F64: + case panda_file::LiteralTag::DOUBLE: + return abckit_LiteralTag_DOUBLE; + case panda_file::LiteralTag::ARRAY_STRING: + case panda_file::LiteralTag::STRING: + return abckit_LiteralTag_STRING; + case panda_file::LiteralTag::NULLVALUE: + return abckit_LiteralTag_NULLVALUE; + case panda_file::LiteralTag::TAGVALUE: + return abckit_LiteralTag_TAGVALUE; + case panda_file::LiteralTag::METHOD: + case panda_file::LiteralTag::GENERATORMETHOD: + case panda_file::LiteralTag::ASYNCGENERATORMETHOD: + return abckit_LiteralTag_METHOD; + default: + return abckit_LiteralTag_INVALID; + } +} + + +void LiteralArrayEnumerateElementsStatic(abckit_File *ctx, abckit_LiteralArray *litArr, void *data, bool (*cb)(abckit_File *ctx, abckit_Literal *lit, void *data)) { + LIBABCKIT_LOG_FUNC + auto* arrImpl = reinterpret_cast(litArr); + + size_t size = arrImpl->literals.size(); + + for (size_t idx = 1; idx < size; idx++) { + auto litImpl = arrImpl->literals[idx]; + auto newLitImpl = new pandasm::LiteralArray::Literal(); + newLitImpl->tag = litImpl.tag; + newLitImpl->value = litImpl.value; + auto lit = std::make_unique(); + lit->val = reinterpret_cast(newLitImpl); + ctx->litvals.emplace_back(std::move(lit)); + if(!cb(ctx, ctx->litvals.back().get(), data)){ + return; + } + } +} + + +// ======================================== +// Value +// ======================================== + +abckit_Type *ValueGetTypeStatic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + auto* p_val = reinterpret_cast(value->impl); + auto type = std::make_unique(); + type->klass = nullptr; // TODO implement logic for classes + switch (p_val->GetType()) { + case pandasm::Value::Type::U1: + type->id = abckit_TypeId_U1; + break; + case pandasm::Value::Type::U8: + type->id = abckit_TypeId_U8; + break; + case pandasm::Value::Type::U16: + type->id = abckit_TypeId_U16; + break; + case pandasm::Value::Type::U32: + type->id = abckit_TypeId_U32; + break; + case pandasm::Value::Type::U64: + type->id = abckit_TypeId_U64; + break; + case pandasm::Value::Type::F64: + type->id = abckit_TypeId_F64; + break; + case pandasm::Value::Type::STRING: + type->id = abckit_TypeId_STRING; + break; + default: + return nullptr; + } + ctx->types.emplace_back(std::move(type)); + return ctx->types.back().get(); +} + +bool ValueGetU1Static(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeStatic(ctx, value)->id != abckit_TypeId_U1) { + statuses::SetLastError(abckit_Status_TODO); + return false; + } + + auto* p_val = reinterpret_cast(value->impl); + return p_val->GetValue(); +} + +double ValueGetDoubleStatic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeStatic(ctx, value)->id != abckit_TypeId_F64) { + statuses::SetLastError(abckit_Status_TODO); + return false; + } + + auto* p_val = reinterpret_cast(value->impl); + return p_val->GetValue(); +} + +abckit_String *ValueGetStringStatic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + if(ValueGetTypeStatic(ctx, value)->id != abckit_TypeId_STRING) { + statuses::SetLastError(abckit_Status_TODO); + return nullptr; + } + + auto* p_val = reinterpret_cast(value->impl); + auto val_impl = p_val->GetValue(); + auto s = std::make_unique(); + s->impl = val_impl.c_str(); + ctx->strings.insert({val_impl, std::move(s)}); + return ctx->strings[val_impl].get(); +} + + +abckit_LiteralArray *ArrayValueGetLiteralArrayStatic(abckit_File *ctx, abckit_Value *value) { + LIBABCKIT_LOG_FUNC + statuses::SetLastError(abckit_Status_TODO); + return nullptr; +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_static/metadata_inspect_static.h b/libabckit/src/adapter_static/metadata_inspect_static.h new file mode 100644 index 0000000000000000000000000000000000000000..cc477e4f9e2f1229bf451461af2d38de91ab74f5 --- /dev/null +++ b/libabckit/src/adapter_static/metadata_inspect_static.h @@ -0,0 +1,120 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_STATIC_METADATA_INSPECT_STATIC_H +#define LIBABCKIT_SRC_ADAPTER_STATIC_METADATA_INSPECT_STATIC_H + +#include "libabckit/include/metadata.h" + +#include + +namespace libabckit { + +// ======================================== +// File +// ======================================== + +abckit_File_Version FileGetVersionStatic(abckit_File *ctx); + +// ======================================== +// Module +// ======================================== + +void ModuleEnumerateClassesStatic(abckit_Module *m, void *data, bool (*cb)(abckit_Class *klass, void *data)); +void ModuleEnumerateTopLevelMethodsStatic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)); +void ModuleEnumerateAnnotationInterfacesStatic(abckit_Module *m, void *data, bool (*cb)(abckit_AnnotationInterface *ai, void *data)); +void ModuleEnumerateAnonymousFunctionsStatic(abckit_Module *m, void *data, bool (*cb)(abckit_Method *method, void *data)); + +// ======================================== +// Class +// ======================================== + +abckit_String *ClassGetNameStatic(abckit_Class *klass); +void ClassEnumerateMethodsStatic(abckit_Class *klass, void *data, bool (*cb)(abckit_Method *method, void *data)); +void ClassEnumerateAnnotationsStatic(abckit_Class *klass, void *data, bool (*cb)(abckit_Annotation *anno, void *data)); + +// ======================================== +// Method +// ======================================== + +abckit_String *MethodGetNameStatic(abckit_Method *method); +abckit_Code *MethodGetCodeStatic(abckit_Method *method); +abckit_Class *MethodGetParentClassStatic(abckit_Method *method); +bool MethodIsStaticStatic(abckit_Method *method); +bool MethodIsCtorStatic(abckit_Method *method); +bool MethodIsAnonymousStatic(abckit_Method *method); +void MethodEnumerateAnnotationsStatic(abckit_Method *method, void *data, bool (*cb)(abckit_Annotation *anno, void *data)); +bool MethodIsNativeStatic(abckit_Method *method); +bool MethodIsExternalStatic(abckit_Method *method); +bool MethodIsAbstractStatic(abckit_Method *method); + +// ======================================== +// Annotation +// ======================================== + +void AnnotationEnumerateElementsStatic(abckit_Annotation *anno, void *data, bool (*cb)(abckit_AnnotationElement *ae, void *data)); +abckit_String *AnnotationElementGetNameStatic(abckit_AnnotationElement *ae); +abckit_AnnotationInterface *AnnotationGetInterfaceStatic(abckit_Annotation *anno); +abckit_String *AnnotationInterfaceGetNameStatic(abckit_AnnotationInterface *ai); + +// ======================================== +// String +// ======================================== + +void StringToStringStatic(abckit_File *ctx, abckit_String *value, char *out, size_t *len); + +// ======================================== +// ImportDescriptor +// ======================================== + +abckit_String *ImportDescriptorGetNameStatic(abckit_ImportDescriptor *i); +abckit_String *ImportDescriptorGetAliasStatic(abckit_ImportDescriptor *i); + + +// ======================================== +// ImportDescriptor +// ======================================== + +abckit_String *ExportDescriptorGetNameStatic(abckit_ExportDescriptor *i); +abckit_String *ExportDescriptorGetAliasStatic(abckit_ExportDescriptor *i); + +// ======================================== +// Literal +// ======================================== + +bool LiteralGetBoolStatic(abckit_File *ctx, abckit_Literal *lit); +uint8_t LiteralGetU8Static(abckit_File *ctx, abckit_Literal *lit); +uint16_t LiteralGetU16Static(abckit_File *ctx, abckit_Literal *lit); +uint32_t LiteralGetU32Static(abckit_File *ctx, abckit_Literal *lit); +uint64_t LiteralGetU64Static(abckit_File *ctx, abckit_Literal *lit); +float LiteralGetFloatStatic(abckit_File *ctx, abckit_Literal *lit); +double LiteralGetDoubleStatic(abckit_File *ctx, abckit_Literal *lit); +abckit_String *LiteralGetStringStatic(abckit_File *ctx, abckit_Literal *lit); +abckit_LiteralTag LiteralGetTagStatic(abckit_File *ctx, abckit_Literal *lit); +void LiteralArrayEnumerateElementsStatic(abckit_File *ctx, abckit_LiteralArray *litArr, void *data, bool (*cb)(abckit_File *ctx, abckit_Literal *lit, void *data)); + +// ======================================== +// Value +// ======================================== + +abckit_Type *ValueGetTypeStatic(abckit_File *ctx, abckit_Value *value); +bool ValueGetU1Static(abckit_File *ctx, abckit_Value *value); +double ValueGetDoubleStatic(abckit_File *ctx, abckit_Value *value); +abckit_String *ValueGetStringStatic(abckit_File *ctx, abckit_Value *value); +abckit_LiteralArray *ArrayValueGetLiteralArrayStatic(abckit_File *ctx, abckit_Value *value); + +} // namespace libabckit + +#endif diff --git a/libabckit/src/adapter_static/metadata_modify_static.cpp b/libabckit/src/adapter_static/metadata_modify_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5604fbf1d8051c889dd8e1d6c1405ddacb8ef900 --- /dev/null +++ b/libabckit/src/adapter_static/metadata_modify_static.cpp @@ -0,0 +1,348 @@ +/** + * Copyright (c) 2024 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 "metadata_modify_static.h" +#include "assembly-type.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/metadata_modify_impl.h" + +#include "macros.h" +#include "src/adapter_static/metadata_inspect_static.h" +#include "static_core/assembler/assembly-program.h" +#include "static_core/assembler/assembly-emitter.h" + +#include +#include +#include + +using namespace ark; + +namespace libabckit { + +// ======================================== +// Create / Update +// ======================================== +abckit_String *CreateStringStatic(abckit_ModifyContext *ctxM, const char *value) +{ + LIBABCKIT_LOG_FUNC + LIBABCKIT_LOG(DEBUG) << "\"" << value << "\"" << '\n'; + auto *prog = reinterpret_cast(ctxM->ctxI->program); + prog->strings.insert(value); + auto &strings = ctxM->ctxI->strings; + + if (strings.find(value) != strings.end()) { + return strings.at(value).get(); + } + + auto s = std::make_unique(); + s->impl = value; + strings.insert({value, std::move(s)}); + return strings[value].get(); +} + +void MethodSetCodeStatic(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code) { + LIBABCKIT_LOG_FUNC + auto *function = reinterpret_cast(method->impl); + auto *newFunction = reinterpret_cast(code->newCode); + function->ins = newFunction->ins; + function->catchBlocks = newFunction->catchBlocks; + function->regsNum = newFunction->regsNum; + function->valueOfFirstParam = newFunction->valueOfFirstParam; + + delete newFunction; // not needed anymore + delete code; // not needed anymore +} + +void ModuleRemoveImportStatic(abckit_Module *m, abckit_ImportDescriptor *i) +{ + LIBABCKIT_UNIMPLEMENTED +} + +void ModuleRemoveExportStatic(abckit_Module *m, abckit_ExportDescriptor *i) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_AnnotationInterface *ModuleAddAnnotationInterfaceStatic( + abckit_ModifyContext *ctx, abckit_Module *m, const abckit_AnnotationInterfaceCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_Annotation *ClassAddAnnotationStatic(abckit_ModifyContext *ctx, abckit_Class *klass, const abckit_AnnotationCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +void ClassRemoveAnnotationStatic(abckit_ModifyContext *ctx, abckit_Class *klass, abckit_Annotation *anno) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_Annotation *MethodAddAnnotationStatic(abckit_ModifyContext *ctx, abckit_Method *method, + const abckit_AnnotationCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +void MethodRemoveAnnotationStatic(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_AnnotationElement *AnnotationAddAnnotationElementStatic(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +void AnnotationRemoveAnnotationElementStatic(abckit_ModifyContext *ctx, abckit_Annotation *anno, abckit_AnnotationElement *elem) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_AnnotationInterfaceField *AnnotationInterfaceAddFieldStatic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +void AnnotationInterfaceRemoveFieldStatic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, abckit_AnnotationInterfaceField *field) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_ImportDescriptor *ModuleAddImportFromDynamicModuleStatic(abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_ExportDescriptor *DynamicModuleAddExportStatic(abckit_Module *m, const abckit_DynamicModuleExportCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_Module *FileAddExternalModuleStatic(abckit_File *ctx, + const struct abckit_ExternalModuleCreateParams *params) +{ + LIBABCKIT_UNIMPLEMENTED +} + +abckit_Literal *CreateLiteralBoolStatic(abckit_ModifyContext *ctx, bool value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::ARRAY_U1; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU8Static(abckit_ModifyContext *ctx, uint8_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::ARRAY_U8; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU16Static(abckit_ModifyContext *ctx, uint16_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::ARRAY_U16; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU32Static(abckit_ModifyContext *ctx, uint32_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::ARRAY_U32; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralU64Static(abckit_ModifyContext *ctx, uint64_t value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::ARRAY_U64; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralFloatStatic(abckit_ModifyContext *ctx, float value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::FLOAT; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralDoubleStatic(abckit_ModifyContext *ctx, double value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::DOUBLE; + literal->value = value; + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_Literal *CreateLiteralStringStatic(abckit_ModifyContext *ctx, const char* value) { + LIBABCKIT_LOG_FUNC + auto* literal = new pandasm::LiteralArray::Literal(); + + literal->tag = panda_file::LiteralTag::STRING; + literal->value = std::string(value); + auto abclit = std::make_unique(); + + abclit->val = reinterpret_cast(literal); + ctx->ctxI->litvals.emplace_back(std::move(abclit)); + return ctx->ctxI->litvals.back().get(); +} + +abckit_LiteralArray *CreateLiteralArrayStatic(abckit_ModifyContext *ctxM, abckit_Literal **value, size_t size) { + LIBABCKIT_LOG_FUNC + auto* prog = reinterpret_cast(ctxM->ctxI->program); + + switch (LiteralGetTagStatic(ctxM->ctxI, value[0])) { + + case abckit_LiteralTag_BOOL: + prog->arrayTypes.emplace(pandasm::Type("u1", 1)); + break; + case abckit_LiteralTag_BYTE: + prog->arrayTypes.emplace(pandasm::Type("u8", 1)); + break; + case abckit_LiteralTag_SHORT: + prog->arrayTypes.emplace(pandasm::Type("u16", 1)); + break; + case abckit_LiteralTag_INTEGER: + prog->arrayTypes.emplace(pandasm::Type("u32", 1)); + break; + case abckit_LiteralTag_LONG: + prog->arrayTypes.emplace(pandasm::Type("u64", 1)); + break; + case abckit_LiteralTag_FLOAT: + prog->arrayTypes.emplace(pandasm::Type("f32", 1)); + break; + case abckit_LiteralTag_DOUBLE: + prog->arrayTypes.emplace(pandasm::Type("f64", 1)); + break; + case abckit_LiteralTag_STRING: + prog->arrayTypes.emplace(pandasm::Type("reference", 1)); + break; + default: + UNREACHABLE(); + } + + auto lit = *reinterpret_cast(value[0]->val); + pandasm::LiteralArray::Literal tag_lit; + tag_lit.tag = panda_file::LiteralTag::TAGVALUE; + tag_lit.value = static_cast(lit.tag); + std::vector std_lit_arr; + std_lit_arr.emplace_back(tag_lit); + + pandasm::LiteralArray::Literal len; + len.tag = panda_file::LiteralTag::INTEGER; + len.value = static_cast(size); + std_lit_arr.emplace_back(len); + + prog->arrayTypes.emplace(pandasm::Type("u32", 1)); + for(size_t i = 0; i < size; i++) { + auto lit = *reinterpret_cast(value[i]->val); + std_lit_arr.emplace_back(lit); + } + + std::srand(0); + uint32_t arrayOffset = 0; + while(prog->literalarrayTable.find(std::to_string(arrayOffset)) != prog->literalarrayTable.end()) { + LIBABCKIT_LOG(DEBUG) << "generating new arrayOffset\n"; + arrayOffset = rand() % 1000; + } + auto arrayName = std::to_string(arrayOffset); + + prog->literalarrayTable.emplace(arrayName, pandasm::LiteralArray()); + pandasm::LiteralArray &arrImpl = prog->literalarrayTable[arrayName]; + arrImpl.literals = std::move(std_lit_arr); + + return reinterpret_cast(&arrImpl); +} + +abckit_Value *CreateValueU1Static(abckit_ModifyContext *ctx, bool value) { + LIBABCKIT_LOG_FUNC + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(value)); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_Value *CreateValueDoubleStatic(abckit_ModifyContext *ctx, double value) { + LIBABCKIT_LOG_FUNC + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(value)); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_Value *CreateValueStringStatic(abckit_ModifyContext *ctx, const char *value) { + LIBABCKIT_LOG_FUNC + auto* pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create(std::string(value))); + auto abcval = std::make_unique(); + abcval->impl = reinterpret_cast(pval); + ctx->ctxI->values.emplace_back(std::move(abcval)); + return ctx->ctxI->values.back().get(); +} + +abckit_Value *CreateLiteralArrayValueStatic(abckit_ModifyContext *ctx, abckit_Value **value, size_t size) { + LIBABCKIT_LOG_FUNC + statuses::SetLastError(abckit_Status_TODO); + return nullptr; +} + +} // namespace libabckit diff --git a/libabckit/src/adapter_static/metadata_modify_static.h b/libabckit/src/adapter_static/metadata_modify_static.h new file mode 100644 index 0000000000000000000000000000000000000000..8eb04f35fab6d5c1ba5928ae239f569dd30aa08b --- /dev/null +++ b/libabckit/src/adapter_static/metadata_modify_static.h @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_STATIC_METADATA_MODIFY_STATIC_H +#define LIBABCKIT_SRC_ADAPTER_STATIC_METADATA_MODIFY_STATIC_H + +#include "libabckit/include/metadata.h" + +#include + +namespace libabckit { + +// ======================================== +// Create / Update +// ======================================== + +abckit_String *CreateStringStatic(abckit_ModifyContext *ctxM, const char *value); + +void MethodSetCodeStatic(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code); + +abckit_Module *FileAddExternalModuleStatic(abckit_File *ctx, + const struct abckit_ExternalModuleCreateParams *params); +void ModuleRemoveImportStatic(abckit_Module *m, abckit_ImportDescriptor *i); +void ModuleRemoveExportStatic(abckit_Module *m, abckit_ExportDescriptor *i); +abckit_AnnotationInterface *ModuleAddAnnotationInterfaceStatic( + abckit_ModifyContext *ctx, abckit_Module *m, const abckit_AnnotationInterfaceCreateParams *params); +abckit_Annotation *ClassAddAnnotationStatic(abckit_ModifyContext *ctx, abckit_Class *klass, const abckit_AnnotationCreateParams *params); +void ClassRemoveAnnotationStatic(abckit_ModifyContext *ctx, abckit_Class *klass, abckit_Annotation *anno); +abckit_Annotation *MethodAddAnnotationStatic(abckit_ModifyContext *ctx, abckit_Method *method, const abckit_AnnotationCreateParams *params); +void MethodRemoveAnnotationStatic(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno); +abckit_AnnotationElement *AnnotationAddAnnotationElementStatic(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params); +void AnnotationRemoveAnnotationElementStatic(abckit_ModifyContext *ctx, abckit_Annotation *anno, abckit_AnnotationElement *elem); +abckit_AnnotationInterfaceField *AnnotationInterfaceAddFieldStatic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params); +void AnnotationInterfaceRemoveFieldStatic(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, abckit_AnnotationInterfaceField *field); +abckit_ImportDescriptor *ModuleAddImportFromDynamicModuleStatic(abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params); +abckit_ExportDescriptor *DynamicModuleAddExportStatic(abckit_Module *m, const abckit_DynamicModuleExportCreateParams *params); + + +abckit_Literal *CreateLiteralBoolStatic(abckit_ModifyContext *ctx, bool value); +abckit_Literal *CreateLiteralU8Static(abckit_ModifyContext *ctx, uint8_t value); +abckit_Literal *CreateLiteralU16Static(abckit_ModifyContext *ctx, uint16_t value); +abckit_Literal *CreateLiteralU32Static(abckit_ModifyContext *ctx, uint32_t value); +abckit_Literal *CreateLiteralU64Static(abckit_ModifyContext *ctx, uint64_t value); +abckit_Literal *CreateLiteralFloatStatic(abckit_ModifyContext *ctx, float value); +abckit_Literal *CreateLiteralDoubleStatic(abckit_ModifyContext *ctx, double value); +abckit_Literal *CreateLiteralStringStatic(abckit_ModifyContext *ctx, const char* value); +abckit_LiteralArray *CreateLiteralArrayStatic(abckit_ModifyContext *ctxM, abckit_Literal **value, size_t size); + +abckit_Value *CreateValueU1Static(abckit_ModifyContext *ctx, bool value); +abckit_Value *CreateValueDoubleStatic(abckit_ModifyContext *ctx, double value); +abckit_Value *CreateValueStringStatic(abckit_ModifyContext *ctx, const char *value); +abckit_Value *CreateLiteralArrayValueStatic(abckit_ModifyContext *ctx, abckit_Value **value, size_t size); +} + +#endif diff --git a/libabckit/src/adapter_static/runtime_adapter_static.cpp b/libabckit/src/adapter_static/runtime_adapter_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4927223526dc04603cd7f69ec731f9247d061d1 --- /dev/null +++ b/libabckit/src/adapter_static/runtime_adapter_static.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 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 "runtime_adapter_static.h" +#include "static_core/runtime/include/method.h" + +namespace ark { + +bool AbckitRuntimeAdapterStatic::IsEqual(panda_file::MethodDataAccessor mda, + std::initializer_list shorties, + std::initializer_list refTypes) +{ + bool equal = true; + auto shortyIt = shorties.begin(); + auto refTypeIt = refTypes.begin(); + auto &pf = mda.GetPandaFile(); + + auto visitType = [&equal, &shorties, &shortyIt, &refTypes, &refTypeIt, &pf](panda_file::Type type, + panda_file::File::EntityId classId) { + if (!equal) { + return; + } + if (shortyIt == shorties.end() || *shortyIt++ != type.GetId()) { + equal = false; + return; + } + if (type.IsReference() && + (refTypeIt == refTypes.end() || *refTypeIt++ != utf::Mutf8AsCString(pf.GetStringData(classId).data))) { + equal = false; + } + }; + mda.EnumerateTypesInProto(visitType, true); // true for skipThis + return equal && shortyIt == shorties.end() && refTypeIt == refTypes.end(); +} + +#include "generated/get_intrinsic_id_static.inc" + +} // namespace ark diff --git a/libabckit/src/adapter_static/runtime_adapter_static.h b/libabckit/src/adapter_static/runtime_adapter_static.h new file mode 100644 index 0000000000000000000000000000000000000000..0d1847e17628fcba25405fb7dd175dd1c2a98775 --- /dev/null +++ b/libabckit/src/adapter_static/runtime_adapter_static.h @@ -0,0 +1,472 @@ +/* + * Copyright (c) 2023-2024 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. + */ + +#ifndef LIBABCKIT_SRC_ADAPTER_STATIC_RUNTIME_ADAPTER_STATIC_H +#define LIBABCKIT_SRC_ADAPTER_STATIC_RUNTIME_ADAPTER_STATIC_H + +#include "static_core/compiler/optimizer/ir/runtime_interface.h" +#include "static_core/libpandafile/bytecode_instruction.h" +#include "static_core/libpandafile/class_data_accessor-inl.h" +#include "static_core/libpandafile/code_data_accessor.h" +#include "static_core/libpandafile/field_data_accessor.h" +#include "static_core/libpandafile/file.h" +#include "static_core/libpandafile/file_items.h" +#include "static_core/libpandafile/method_data_accessor.h" +#include "static_core/libpandafile/proto_data_accessor.h" +#include "static_core/libpandafile/proto_data_accessor-inl.h" +#include "static_core/libpandafile/type_helper.h" + +namespace ark { +using compiler::RuntimeInterface; + +class AbckitRuntimeAdapterStatic : public RuntimeInterface { +public: + explicit AbckitRuntimeAdapterStatic(const panda_file::File &abcFile) : abcFile_(abcFile) {} + ~AbckitRuntimeAdapterStatic() override = default; + NO_COPY_SEMANTIC(AbckitRuntimeAdapterStatic); + NO_MOVE_SEMANTIC(AbckitRuntimeAdapterStatic); + + BinaryFilePtr GetBinaryFileForMethod([[maybe_unused]] MethodPtr method) const override + { + return const_cast(&abcFile_); + } + + MethodId ResolveMethodIndex(MethodPtr parentMethod, MethodIndex index) const override + { + return abcFile_.ResolveMethodIndex(MethodCast(parentMethod), index).GetOffset(); + } + + FieldId ResolveFieldIndex(MethodPtr parentMethod, FieldIndex index) const override + { + return abcFile_.ResolveFieldIndex(MethodCast(parentMethod), index).GetOffset(); + } + + IdType ResolveTypeIndex(MethodPtr parentMethod, TypeIndex index) const override + { + return abcFile_.ResolveClassIndex(MethodCast(parentMethod), index).GetOffset(); + } + + MethodPtr GetMethodById([[maybe_unused]] MethodPtr caller, MethodId id) const override + { + return reinterpret_cast(id); + } + + MethodId GetMethodId(MethodPtr method) const override + { + return static_cast(reinterpret_cast(method)); + } + + compiler::DataType::Type GetMethodReturnType(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + panda_file::ProtoDataAccessor pda(abcFile_, mda.GetProtoId()); + + return ToCompilerType(panda_file::GetEffectiveType(pda.GetReturnType())); + } + + IdType GetMethodReturnTypeId(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + panda_file::ProtoDataAccessor pda(abcFile_, mda.GetProtoId()); + + return pda.GetReferenceType(0).GetOffset(); + } + + compiler::DataType::Type GetMethodTotalArgumentType(MethodPtr method, size_t index) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + if (!mda.IsStatic()) { + if (index == 0) { + return ToCompilerType( + panda_file::GetEffectiveType(panda_file::Type(panda_file::Type::TypeId::REFERENCE))); + } + --index; + } + + panda_file::ProtoDataAccessor pda(abcFile_, mda.GetProtoId()); + return ToCompilerType(panda_file::GetEffectiveType(pda.GetArgType(index))); + } + + compiler::DataType::Type GetMethodArgumentType([[maybe_unused]] MethodPtr caller, MethodId id, + size_t index) const override + { + panda_file::MethodDataAccessor mda(abcFile_, panda_file::File::EntityId(id)); + panda_file::ProtoDataAccessor pda(abcFile_, mda.GetProtoId()); + + return ToCompilerType(panda_file::GetEffectiveType(pda.GetArgType(index))); + } + + size_t GetMethodTotalArgumentsCount(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative()); + panda_file::CodeDataAccessor cda(abcFile_, mda.GetCodeId().value()); + + return cda.GetNumArgs(); + } + + size_t GetMethodArgumentsCount([[maybe_unused]] MethodPtr caller, MethodId id) const override + { + panda_file::MethodDataAccessor mda(abcFile_, panda_file::File::EntityId(id)); + panda_file::ProtoDataAccessor pda(abcFile_, mda.GetProtoId()); + + return pda.GetNumArgs(); + } + + compiler::DataType::Type GetMethodReturnType(MethodPtr caller, MethodId id) const override + { + return GetMethodReturnType(GetMethodById(caller, id)); + } + + size_t GetMethodRegistersCount(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative()); + panda_file::CodeDataAccessor cda(abcFile_, mda.GetCodeId().value()); + + return cda.GetNumVregs(); + } + + const uint8_t *GetMethodCode(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative()); + panda_file::CodeDataAccessor cda(abcFile_, mda.GetCodeId().value()); + + return cda.GetInstructions(); + } + + size_t GetMethodCodeSize(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative()); + panda_file::CodeDataAccessor cda(abcFile_, mda.GetCodeId().value()); + + return cda.GetCodeSize(); + } + + SourceLanguage GetMethodSourceLanguage(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + ASSERT(!mda.IsExternal() && !mda.IsAbstract() && !mda.IsNative()); + + auto sourceLang = mda.GetSourceLang(); + ASSERT(sourceLang.has_value()); + + return static_cast(sourceLang.value()); + } + + size_t GetClassIdForField([[maybe_unused]] MethodPtr method, size_t fieldId) const override + { + panda_file::FieldDataAccessor fda(abcFile_, panda_file::File::EntityId(fieldId)); + + return static_cast(fda.GetClassId().GetOffset()); + } + + ClassPtr GetClassForField(FieldPtr field) const override + { + panda_file::FieldDataAccessor fda(abcFile_, FieldCast(field)); + + return reinterpret_cast(fda.GetClassId().GetOffset()); + } + + size_t GetClassIdForMethod(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + return static_cast(mda.GetClassId().GetOffset()); + } + + size_t GetClassIdForMethod([[maybe_unused]] MethodPtr caller, size_t methodId) const override + { + panda_file::MethodDataAccessor mda(abcFile_, panda_file::File::EntityId(methodId)); + + return static_cast(mda.GetClassId().GetOffset()); + } + + bool IsMethodExternal([[maybe_unused]] MethodPtr caller, MethodPtr callee) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(callee)); + + return mda.IsExternal(); + } + + bool IsMethodIntrinsic([[maybe_unused]] MethodPtr method) const override + { + return false; + } + + bool IsMethodIntrinsic([[maybe_unused]] MethodPtr caller, MethodId id) const override + { + return GetIntrinsicId(GetMethodById(caller, id)) != IntrinsicId::INVALID; + } + + IntrinsicId GetIntrinsicId([[maybe_unused]] MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + auto className = GetClassNameFromMethod(method); + auto methodName = GetMethodName(method); + return GetIntrinsicId(className, methodName, mda); + } + + bool IsMethodStatic(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + return mda.IsStatic(); + } + + bool IsMethodStatic([[maybe_unused]] MethodPtr caller, MethodId id) const override + { + panda_file::MethodDataAccessor mda(abcFile_, panda_file::File::EntityId(id)); + + return mda.IsStatic(); + } + + // return true if the method is Native with exception + bool HasNativeException([[maybe_unused]] MethodPtr method) const override + { + return false; + } + + std::string GetClassNameFromMethod(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + return mda.GetClassName(); + } + + std::string GetClassName(ClassPtr cls) const override + { + auto stringData = abcFile_.GetStringData(ClassCast(cls)); + + return panda_file::ClassDataAccessor::DemangledName(stringData); + } + + std::string GetMethodName(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + auto stringData = abcFile_.GetStringData(mda.GetNameId()); + + return std::string(reinterpret_cast(stringData.data)); + } + + bool IsConstructor(MethodPtr method, SourceLanguage lang) override + { + return GetMethodName(method) == panda_file::GetCtorName(lang); + } + + std::string GetMethodFullName(MethodPtr method, bool /* with_signature */) const override + { + auto className = GetClassNameFromMethod(method); + auto methodName = GetMethodName(method); + + return className + "::" + methodName; + } + + ClassPtr GetClass(MethodPtr method) const override + { + panda_file::MethodDataAccessor mda(abcFile_, MethodCast(method)); + + return reinterpret_cast(mda.GetClassId().GetOffset()); + } + + std::string GetBytecodeString(MethodPtr method, uintptr_t pc) const override + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + BytecodeInstruction inst(GetMethodCode(method) + pc); + std::stringstream ss; + + ss << inst; + return ss.str(); + } + + bool IsArrayClass([[maybe_unused]] MethodPtr method, IdType id) const override + { + panda_file::File::EntityId cid(id); + + return panda_file::IsArrayDescriptor(abcFile_.GetStringData(cid).data); + } + + FieldPtr ResolveField([[maybe_unused]] MethodPtr method, size_t id, [[maybe_unused]] bool allowExternal, + uint32_t * /* class_id */) override + { + return reinterpret_cast(id); + } + + compiler::DataType::Type GetFieldType(FieldPtr field) const override + { + panda_file::FieldDataAccessor fda(abcFile_, FieldCast(field)); + + return ToCompilerType(panda_file::Type::GetTypeFromFieldEncoding(fda.GetType())); + } + + compiler::DataType::Type GetFieldTypeById([[maybe_unused]] MethodPtr parentMethod, IdType id) const override + { + panda_file::FieldDataAccessor fda(abcFile_, panda_file::File::EntityId(id)); + + return ToCompilerType(panda_file::Type::GetTypeFromFieldEncoding(fda.GetType())); + } + + IdType GetFieldValueTypeId([[maybe_unused]] MethodPtr method, IdType id) const override + { + auto typeId = panda_file::FieldDataAccessor::GetTypeId(abcFile_, panda_file::File::EntityId(id)); + return typeId.GetOffset(); + } + + bool IsFieldVolatile(FieldPtr field) const override + { + panda_file::FieldDataAccessor fda(abcFile_, FieldCast(field)); + + if (!fda.IsExternal()) { + return fda.IsVolatile(); + } + + auto fieldId = panda_file::File::EntityId(); + + if (abcFile_.IsExternal(fda.GetClassId())) { + // If the field is external and class of the field is also external + // assume that field is volatile + return true; + } + + auto classId = panda_file::ClassDataAccessor(abcFile_, fda.GetClassId()).GetSuperClassId(); +#ifndef NDEBUG + auto visitedClasses = std::unordered_set {classId}; +#endif + while (classId.IsValid() && !abcFile_.IsExternal(classId)) { + auto cda = panda_file::ClassDataAccessor(abcFile_, classId); + cda.EnumerateFields([&fieldId, &fda](panda_file::FieldDataAccessor &fieldDataAccessor) { + auto &pf = fda.GetPandaFile(); + auto fieldType = panda_file::Type::GetTypeFromFieldEncoding(fda.GetType()); + if (fda.GetType() != fieldDataAccessor.GetType()) { + return; + } + + if (pf.GetStringData(fda.GetNameId()) != pf.GetStringData(fieldDataAccessor.GetNameId())) { + return; + } + + if (fieldType.IsReference()) { + if (pf.GetStringData(panda_file::File::EntityId(fda.GetType())) != + pf.GetStringData(panda_file::File::EntityId(fieldDataAccessor.GetType()))) { + return; + } + } + + fieldId = fieldDataAccessor.GetFieldId(); + }); + + classId = cda.GetSuperClassId(); +#ifndef NDEBUG + ASSERT_PRINT(visitedClasses.count(classId) == 0, "Class hierarchy is incorrect"); + visitedClasses.insert(classId); +#endif + } + + if (!fieldId.IsValid()) { + // If we cannot find field (for example it's in the class that located in other panda file) + // assume that field is volatile + return true; + } + ASSERT(fieldId.IsValid()); + panda_file::FieldDataAccessor fieldDa(abcFile_, fieldId); + return fieldDa.IsVolatile(); + } + + ClassPtr ResolveType([[maybe_unused]] MethodPtr method, size_t id) const override + { + return reinterpret_cast(id); + } + + std::string GetFieldName(FieldPtr field) const override + { + panda_file::FieldDataAccessor fda(abcFile_, FieldCast(field)); + auto stringData = abcFile_.GetStringData(fda.GetNameId()); + return utf::Mutf8AsCString(stringData.data); + } + +private: + static compiler::DataType::Type ToCompilerType(panda_file::Type type) + { + switch (type.GetId()) { + case panda_file::Type::TypeId::VOID: + return compiler::DataType::VOID; + case panda_file::Type::TypeId::U1: + return compiler::DataType::BOOL; + case panda_file::Type::TypeId::I8: + return compiler::DataType::INT8; + case panda_file::Type::TypeId::U8: + return compiler::DataType::UINT8; + case panda_file::Type::TypeId::I16: + return compiler::DataType::INT16; + case panda_file::Type::TypeId::U16: + return compiler::DataType::UINT16; + case panda_file::Type::TypeId::I32: + return compiler::DataType::INT32; + case panda_file::Type::TypeId::U32: + return compiler::DataType::UINT32; + case panda_file::Type::TypeId::I64: + return compiler::DataType::INT64; + case panda_file::Type::TypeId::U64: + return compiler::DataType::UINT64; + case panda_file::Type::TypeId::F32: + return compiler::DataType::FLOAT32; + case panda_file::Type::TypeId::F64: + return compiler::DataType::FLOAT64; + case panda_file::Type::TypeId::REFERENCE: + return compiler::DataType::REFERENCE; + case panda_file::Type::TypeId::TAGGED: + case panda_file::Type::TypeId::INVALID: + return compiler::DataType::ANY; + default: + break; + } + UNREACHABLE(); + } + + static panda_file::File::EntityId MethodCast(RuntimeInterface::MethodPtr method) + { + return panda_file::File::EntityId(reinterpret_cast(method)); + } + + static panda_file::File::EntityId ClassCast(RuntimeInterface::ClassPtr cls) + { + return panda_file::File::EntityId(reinterpret_cast(cls)); + } + + static panda_file::File::EntityId FieldCast(RuntimeInterface::FieldPtr field) + { + return panda_file::File::EntityId(reinterpret_cast(field)); + } + + static IntrinsicId GetIntrinsicId(std::string_view className, std::string_view methodName, + panda_file::MethodDataAccessor mda); + + static bool IsEqual(panda_file::MethodDataAccessor mda, std::initializer_list shorties, + std::initializer_list refTypes); + + const panda_file::File &abcFile_; +}; +} // namespace ark + +#endif //LIBABCKIT_SRC_ADAPTER_STATIC_RUNTIME_ADAPTER_STATIC_H diff --git a/libabckit/src/adapter_static/templates/get_intrinsic_id_static.inc.erb b/libabckit/src/adapter_static/templates/get_intrinsic_id_static.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..137d71e32ef8121b701d5c608614f4350d53180f --- /dev/null +++ b/libabckit/src/adapter_static/templates/get_intrinsic_id_static.inc.erb @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +// NOLINTNEXTLINE(readability-function-size) +compiler::RuntimeInterface::IntrinsicId AbckitRuntimeAdapterStatic::GetIntrinsicId([[maybe_unused]] std::string_view className, + [[maybe_unused]] std::string_view methodName, [[maybe_unused]] panda_file::MethodDataAccessor mda) { +% Runtime::intrinsics.select{ |i| i.static && !i.signature.stackrange && !i.is_stub && !i.compiler_only && i.has_impl? && i.need_nullcheck.empty? }.group_by(&:class_name).each do |clazz, intrinsics| + if (className == "<%= clazz %>") { +% intrinsics.each do |intrinsic| + if (methodName == "<%= intrinsic.method_name %>") { +% types = [intrinsic.signature.ret] + intrinsic.signature.args +% shorty = types.map { |t| "panda_file::Type::TypeId::" + get_shorty_type(t) }.join(", ") +% refTypes = types.select { |t| object_type?(t) }.map { |t| get_object_descriptor(t).inspect }.join(", ") + if (IsEqual(mda, {<%= shorty %>}, {<%= refTypes %>})) { + return compiler::RuntimeInterface::IntrinsicId::INTRINSIC_<%= intrinsic.enum_name %>; + } + return compiler::RuntimeInterface::IntrinsicId::INVALID; + } +% end + return compiler::RuntimeInterface::IntrinsicId::INVALID; + } +% end + return compiler::RuntimeInterface::IntrinsicId::INVALID; +} diff --git a/libabckit/src/bct_compiler_intrinsics.yaml b/libabckit/src/bct_compiler_intrinsics.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf1952f061244c59b0937821a53e6369047ecbec --- /dev/null +++ b/libabckit/src/bct_compiler_intrinsics.yaml @@ -0,0 +1,734 @@ +# Copyright (c) 2023-2024 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. + +intrinsics: +- name: BCTLoadConstArray + space: bct + class_name: "LoadConstArray" + method_name: "lda.const" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ literalarray_id ] + clear_flags: [ "require_state", "call", "heap_inv", "acc_write", "acc_read" ] + set_flags: ["load"] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadString + space: bct + class_name: "LoadString" + method_name: "lda.str" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ string_id ] + clear_flags: [ "require_state", "call", "heap_inv", "acc_read", "no_dce", "barrier" ] + set_flags: ["load"] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTCheckCast + space: bct + class_name: "CheckCast" + method_name: "checkcast" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, type_id ] + clear_flags: [ "require_state", "call", "heap_inv", "acc_write", "barrier" ] + set_flags: ["load", "no_dst"] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTIsInstance + space: bct + class_name: "IsInstance" + method_name: "isinstance" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: i32 + args: [ ref, type_id ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "can_throw", "no_dce", "no_hoist", "no_cse"] + set_flags: [] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTThrow + space: bct + class_name: "Throw" + method_name: "throw" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref ] + clear_flags: [ "require_state", "call", "heap_inv", "runtime_call", "acc_read", "acc_write" ] + set_flags: ["cf", "terminator", "no_dst"] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTNewArray + space: bct + class_name: "NewArray" + method_name: "newarr" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ i32, type_id ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "acc_read", "acc_write" ] + set_flags: [ "alloc", "mem_barrier" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTNewObject + space: bct + class_name: "NewObject" + method_name: "newobj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ type_id ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "acc_read", "acc_write" ] + set_flags: [ "alloc", "mem_barrier" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTInitObjectShort + space: bct + class_name: "InitObject" + method_name: "initobj.short" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ none, none, method_id ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "alloc" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTInitObject + space: bct + class_name: "InitObject" + method_name: "initobj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ none, none, none, none, method_id ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "alloc" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTInitObjectRange + space: bct + class_name: "InitObject" + method_name: "initobj.range" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ none, method_id ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "alloc" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadObject + space: bct + class_name: "LoadObject" + method_name: "ldobj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: b32 + args: [ ref, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadObjectWide + space: bct + class_name: "LoadObject" + method_name: "ldobj.64" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: b64 + args: [ ref, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadObjectObject + space: bct + class_name: "LoadObject" + method_name: "ldobj.obj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ ref, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreObject + space: bct + class_name: "StoreObject" + method_name: "stobj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, b32, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreObjectWide + space: bct + class_name: "StoreObject" + method_name: "stobj.64" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, b64, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreObjectObject + space: bct + class_name: "StoreObject" + method_name: "stobj.obj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, ref, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadStatic + space: bct + class_name: "LoadStatic" + method_name: "ldstatic" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: b32 + args: [ field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadStaticWide + space: bct + class_name: "LoadStatic" + method_name: "ldstatic.64" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: b64 + args: [ field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadStaticObject + space: bct + class_name: "LoadStatic" + method_name: "ldstatic.obj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_read"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreStatic + space: bct + class_name: "StoreStatic" + method_name: "ststatic" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ b32, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreStaticWide + space: bct + class_name: "StoreStatic" + method_name: "ststatic.64" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ b64, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreStaticObject + space: bct + class_name: "StoreStatic" + method_name: "ststatic.obj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, field_id ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreArray + space: bct + class_name: "StoreArray" + method_name: "starr" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, i32, i32 ] + clear_flags: [ "can_throw", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreArrayWide + space: bct + class_name: "StoreArray" + method_name: "starr.64" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, i32, i64 ] + clear_flags: [ "can_throw", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTStoreArrayObject + space: bct + class_name: "StoreArray" + method_name: "starr.obj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: none + args: [ ref, i32, ref ] + clear_flags: [ "can_throw", "require_state", "call", "runtime_call", "heap_inv", "barrier", "acc_write"] + set_flags: [ "store", "no_dst" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadArray + space: bct + class_name: "LoadArray" + method_name: "ldarr" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: i32 + args: [ i32, ref ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadArrayWide + space: bct + class_name: "LoadArray" + method_name: "ldarr.64" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: i64 + args: [ i32, ref ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTLoadArrayObject + space: bct + class_name: "LoadArray" + method_name: "ldarr.obj" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: ref + args: [ i32, ref ] + clear_flags: [ "can_throw", "no_dce", "require_state", "call", "runtime_call", "heap_inv", "barrier"] + set_flags: [ "load" ] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + + +- name: BCTEquals + space: bct + class_name: "Equals" + method_name: "ets.equals" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: i32 + args: [ ref, ref ] + clear_flags: ["acc_read", "require_state", "can_throw", "heap_inv", "no_dce", "no_cse", "no_hoist"] + set_flags: ["commutative"] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +- name: BCTIsUndefined + space: bct + class_name: "IsUndefined" + method_name: "ets.isundefined" + compiler_only: true + private: false + static: true + safepoint_after_call: false + signature: + ret: u1 + args: [ ref ] + clear_flags: [ "require_state", "call", "heap_inv", "barrier", "can_throw", "no_dce", "no_hoist", "no_cse"] + set_flags: [] + is_stub: false + additional_temps: 0 + codegen_arch: [] + need_nullcheck: [] + is_fastpath: false + need_param_locations: false + +# - name: BCTLaunchShort +# space: bct +# class_name: "Lanch" +# method_name: "launch.short" +# compiler_only: true +# private: false +# static: true +# safepoint_after_call: false +# signature: +# ret: top +# args: [ top, top, method_id ] +# clear_flags: [ "require_state", "heap_inv" ] +# set_flags: [ "alloc", "mem_barrier" ] +# is_stub: false +# additional_temps: 0 +# codegen_arch: [] +# need_nullcheck: [] +# is_fastpath: false +# need_param_locations: false + +# - name: BCTLaunch +# space: bct +# class_name: "Lanch" +# method_name: "launch" +# compiler_only: true +# private: false +# static: true +# safepoint_after_call: false +# signature: +# ret: top +# args: [ top, top, top, top, method_id ] +# clear_flags: [ "require_state", "heap_inv" ] +# set_flags: [ "alloc", "mem_barrier" ] +# is_stub: false +# additional_temps: 0 +# codegen_arch: [] +# need_nullcheck: [] +# is_fastpath: false +# need_param_locations: false + +# - name: BCTLaunchRange +# space: bct +# class_name: "Lanch" +# method_name: "launch.range" +# compiler_only: true +# private: false +# static: true +# safepoint_after_call: false +# signature: +# ret: top +# args: [ top, method_id ] +# clear_flags: [ "require_state", "heap_inv" ] +# set_flags: [ "alloc", "mem_barrier" ] +# is_stub: false +# additional_temps: 0 +# codegen_arch: [] +# need_nullcheck: [] +# is_fastpath: false +# need_param_locations: false + +# - name: BCTLaunchVirtShort +# space: bct +# class_name: "LanchVirt" +# method_name: "launch.virt.short" +# compiler_only: true +# private: false +# static: true +# safepoint_after_call: false +# signature: +# ret: top +# args: [ top, top, method_id ] +# clear_flags: [ "require_state", "heap_inv" ] +# set_flags: [ "alloc", "mem_barrier" ] +# is_stub: false +# additional_temps: 0 +# codegen_arch: [] +# need_nullcheck: [] +# is_fastpath: false +# need_param_locations: false + +# - name: BCTLaunchVirt +# space: bct +# class_name: "LanchVirt" +# method_name: "launch.virt" +# compiler_only: true +# private: false +# static: true +# safepoint_after_call: false +# signature: +# ret: top +# args: [ top, top, top, top, method_id ] +# clear_flags: [ "require_state", "heap_inv" ] +# set_flags: [ "alloc", "mem_barrier" ] +# is_stub: false +# additional_temps: 0 +# codegen_arch: [] +# need_nullcheck: [] +# is_fastpath: false +# need_param_locations: false + +# - name: BCTLaunchVirtRange +# space: bct +# class_name: "LanchVirt" +# method_name: "launch.virt.range" +# compiler_only: true +# private: false +# static: true +# safepoint_after_call: false +# signature: +# ret: top +# args: [ top, method_id ] +# clear_flags: [ "require_state", "heap_inv" ] +# set_flags: [ "alloc", "mem_barrier" ] +# is_stub: false +# additional_temps: 0 +# codegen_arch: [] +# need_nullcheck: [] +# is_fastpath: false +# need_param_locations: false \ No newline at end of file diff --git a/libabckit/src/codegen/BUILD.gn b/libabckit/src/codegen/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..2e1974272d6d98695521e0e5e06b97c288bb427c --- /dev/null +++ b/libabckit/src/codegen/BUILD.gn @@ -0,0 +1,209 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ark_gen("ark_gen_libabckit") { + data = [ "../bct_compiler_intrinsics.yaml", + "$isa_gen_dir/isa.yaml" ] + template_files = [ + "insn_selection_static.h.erb", + "insn_selection_static.cpp.erb" + ] + sources = "templates" + api = [ + "$ark_root/compiler/optimizer/templates/intrinsics/compiler_intrinsics.rb", + "$ark_root/isa/isapi.rb" + ] + extra_dependencies = [ "$ark_root/isa:isa_combine", + "$ark_root/runtime:arkruntime_gen_intrinsics_yaml"] + requires = [ "$ark_root/libpandabase/utils.rb", + "codegen_static_isapi.rb", + "$ark_root/assembler/asm_isapi.rb" ] + destination = "$target_gen_dir/generated" +} + +ark_gen_file("codegen_visitors_static_inc") { + extra_dependencies = [ "$ark_root:concat_plugins_yamls" ] + template_file = "templates/codegen_visitors_static.inc.erb" + data = [ ark_plugin_options_yaml, + "../bct_compiler_intrinsics.yaml" ] + api = [ "$ark_root/templates/plugin_options.rb", + "$ark_root/compiler/optimizer/templates/intrinsics/compiler_intrinsics.rb" ] + output_file = "$target_gen_dir/generated/tmp/codegen_visitors_static.inc" +} + +runtime_intrinsics_gen_dir = get_label_info("$ark_root/runtime:arkruntime_gen_intrinsics_yaml(${host_toolchain})", "target_gen_dir") +ark_gen("ark_gen_libabckit") { + data = [ "$runtime_intrinsics_gen_dir/bct_intrinsics.yaml", + ark_plugin_options_yaml ] + template_files = [ + "codegen_intrinsics_static.cpp.erb" + ] + sources = "templates" + api = [ + "$ark_root/compiler/optimizer/templates/intrinsics/compiler_intrinsics.rb", + "$ark_root/templates/plugin_options.rb" + ] + extra_dependencies = [ "$ark_root:concat_plugins_yamls", + "../../:concat_bct_intrinsics_yaml" ] + requires = [ "$ark_root/libpandabase/utils.rb" ] + destination = "$target_gen_dir/generated/tmp" +} + +ets_codegen_visitors_dir = "$ark_root/plugins/ets/bytecode_optimizer/visitors" +copy("ets_codegen_intrinsics_inc_copy") { + sources = [ "$ets_codegen_visitors_dir/ets_codegen_intrinsics.inc" ] + outputs = [ "$target_gen_dir/generated/tmp/ets_codegen_intrinsics.inc" ] +} +copy("ets_codegen_visitors_inc_copy") { + sources = [ "$ets_codegen_visitors_dir/codegen_visitors.inc" ] + outputs = [ "$target_gen_dir/generated/tmp/codegen_visitors.inc" ] +} +ets_codegen_intrinsics_gen_target = "$ark_root/plugins/ets:isa_gen_ets_bytecodeopt_ets_codegen_intrinsics_gen_inc" +ets_codegen_gen_dir = get_label_info("$ets_codegen_intrinsics_gen_target", "target_gen_dir") +copy("ets_codegen_intrinsics_gen_copy") { + deps = [ "$ets_codegen_intrinsics_gen_target" ] + sources = [ "$ets_codegen_gen_dir/ets_codegen_intrinsics_gen.inc" ] + outputs = [ "$target_gen_dir/generated/tmp/ets_codegen_intrinsics_gen.inc" ] +} + +action("fix_static_codegen_plugin_files") { + deps = [ ":ark_gen_libabckit_codegen_intrinsics_static_cpp", + ":ets_codegen_intrinsics_inc_copy", + ":codegen_visitors_static_inc", + ":ets_codegen_visitors_inc_copy", + ":ets_codegen_intrinsics_gen_copy" + ] + script = "./../../scripts/fix_static_codegen_plugin_files.sh" + args = [ rebase_path("$target_gen_dir/generated"), + rebase_path("$target_gen_dir/generated/tmp/codegen_intrinsics_static.cpp"), + rebase_path("$target_gen_dir/generated/tmp/codegen_visitors_static.inc"), + rebase_path("$target_gen_dir/generated/tmp/ets_codegen_intrinsics.inc"), + rebase_path("$target_gen_dir/generated/tmp/codegen_visitors.inc"), + rebase_path("$target_gen_dir/generated/tmp/ets_codegen_intrinsics_gen.inc") + ] + outputs = [ "$target_gen_dir/generated/codegen_intrinsics_static.cpp", + "$target_gen_dir/generated/codegen_visitors_static.inc", + "$target_gen_dir/generated/ets_codegen_intrinsics.inc", + "$target_gen_dir/generated/codegen_visitors.inc", + "$target_gen_dir/generated/ets_codegen_intrinsics_gen.inc" + ] +} + +ark_gen_file("codegen_call_intrinsics_static_inc") { + extra_dependencies = [ + "$ark_root/runtime:arkruntime_gen_intrinsics_yaml", + "$ark_root:concat_plugins_yamls", + "../../:concat_bct_intrinsics_yaml" + ] + template_file = "templates/codegen_call_intrinsics_static.inc.erb" + data = [ "$runtime_intrinsics_gen_dir/bct_intrinsics.yaml", + ark_plugin_options_yaml + ] + api = [ "$ark_root/runtime/templates/intrinsics.rb", + "$ark_root/templates/plugin_options.rb" + ] + output_file = "$target_gen_dir/generated/codegen_call_intrinsics_static.inc" +} + +ohos_source_set("libabckit_codegen_static_source_set") { + sources = [ + "codegen_static.cpp", + ] + + bco_gen_dir = get_label_info("$ark_root/bytecode_optimizer:libarktsbytecodeopt(${host_toolchain})", "target_gen_dir") + ins_create_wrapper_dyn_dir = get_label_info("$ark_root/../libabckit/src/wrappers:isa_gen_libabckit_ins_create_wrapper_api_inc", "target_gen_dir") + include_dirs = [ + "$target_gen_dir", + "$ins_create_wrapper_dyn_dir", + "$ark_root", # this target should not include headers from dynamic runtime, so static_core must be listed first + "$ark_root/..", + "$bco_gen_dir" + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/:ark_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/compiler:arkcompiler_public_config", + "$ark_root/bytecode_optimizer:bytecodeopt_public_config", + "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/runtime:arkruntime_public_config" + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/libpandafile:libarktsfile", + "$ark_root/libpandabase:libarktsbase", + "$ark_root/compiler:libarktscompiler", + ":ark_gen_libabckit_insn_selection_static_cpp", + ":ark_gen_libabckit_insn_selection_static_h", + ":ark_gen_libabckit_codegen_intrinsics_static_cpp", + ":fix_static_codegen_plugin_files", + ":codegen_call_intrinsics_static_inc" + ] +} + +ohos_source_set("libabckit_codegen_dynamic_source_set") { + sources = [ + "codegen_dynamic.cpp", + "ic_slot_allocator.cpp" + ] + + intrinsics_gen_dir = get_label_info("$ark_root/../libabckit/src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_enum_inl", "target_gen_dir") + insn_selection_dyn_dir = get_label_info("$ark_root/../libabckit/src/codegen/templates_dynamic:isa_gen_libabckit_insn_selection_dynamic_h", "target_gen_dir") + ins_create_wrapper_dyn_dir = get_label_info("$ark_root/../libabckit/src/wrappers:isa_gen_libabckit_ins_create_wrapper_api_inc", "target_gen_dir") + include_dirs = [ + "$ark_root/compiler", + "$ark_root/runtime", + "$target_gen_dir", + "$intrinsics_gen_dir/../generated", + "$insn_selection_dyn_dir/..", + "$ins_create_wrapper_dyn_dir", + "$ark_root", + "$ark_root/.." + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/:ark_config", + "$ark_root/runtime:arkruntime_public_config", + "$ark_root/compiler:arkcompiler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config" + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/compiler:libarktscompiler", + "templates_dynamic:isa_gen_libabckit_insn_selection_dynamic_cpp", + "templates_dynamic:isa_gen_libabckit_insn_selection_dynamic_h", + "templates_dynamic:isa_gen_libabckit_check_width_dynamic_cpp", + "templates_dynamic:isa_gen_libabckit_check_width_dynamic_h", + "templates_dynamic:isa_gen_libabckit_generate_ecma_inl", + "templates_dynamic:isa_gen_libabckit_ic_info_h", + "../templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_inl", + "templates_dynamic:codegen_visitors_dyn_inc" + ] +} + diff --git a/libabckit/src/codegen/codegen_dynamic.cpp b/libabckit/src/codegen/codegen_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f57ce39c88bbfa08cb1a7a62d24046607e7ef9d0 --- /dev/null +++ b/libabckit/src/codegen/codegen_dynamic.cpp @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2024 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 "libabckit/src/codegen/codegen_dynamic.h" +#include "libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h" +#include "generated/generate_ecma.inl" +#include "static_core/runtime/include/coretypes/tagged_value.h" + +namespace libabckit { + +void DoLda(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(PandasmWrapper::Create_LDA_Wrapper(reg)); + } +} + +void DoSta(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(PandasmWrapper::Create_STA_Wrapper(reg)); + } +} + +void CodeGenDynamic::AppendCatchBlock(uint32_t type_id, const compiler::BasicBlock *try_begin, + const compiler::BasicBlock *try_end, const compiler::BasicBlock *catch_begin, + const compiler::BasicBlock *catch_end) +{ + auto cb = FunctionWrapper::CatchBlockWrapper(); + if (type_id != 0) { + cb.exceptionRecord = ir_interface_->GetTypeIdByOffset(type_id); + } + cb.tryBeginLabel = LabelName(try_begin->GetId()); + cb.tryEndLabel = "end_" + LabelName(try_end->GetId()); + cb.catchBeginLabel = LabelName(catch_begin->GetId()); + cb.catchEndLabel = + catch_end == nullptr ? cb.catchBeginLabel : "end_" + LabelName(catch_end->GetId()); + catch_blocks_.emplace_back(cb); +} + +void CodeGenDynamic::VisitTryBegin(const compiler::BasicBlock *bb) +{ + ASSERT(bb->IsTryBegin()); + auto try_inst = GetTryBeginInst(bb); + auto try_end = try_inst->GetTryEndBlock(); + ASSERT(try_end != nullptr && try_end->IsTryEnd()); + + bb->EnumerateCatchHandlers([&, bb, try_end](BasicBlock *catch_handler, size_t type_id) { + AppendCatchBlock(type_id, bb, try_end, catch_handler); + return true; + }); +} + +bool CodeGenDynamic::RunImpl() +{ + Reserve(function_->ins.size()); + // int32_t insn_order = 0; + if (!GetGraph()->GetTryBeginBlocks().empty()) { + // Workaround for AOT and JIT + result_.emplace_back(PandasmWrapper::Create_NOP_Wrapper()); + } + for (auto *bb : GetGraph()->GetBlocksLinearOrder()) { + EmitLabel(LabelName(bb->GetId())); + if (bb->IsTryEnd() || bb->IsCatchEnd()) { + auto label = "end_" + LabelName(bb->GetId()); + EmitLabel(label); + } + for (const auto &inst : bb->AllInsts()) { + auto start = GetResult().size(); + VisitInstruction(inst); + if (!GetStatus()) { + return false; + } + auto end = GetResult().size(); + ASSERT(end >= start); + for (auto i = start; i < end; ++i) { + AddLineNumber(inst, i); + AddColumnNumber(inst, i); + } + } + if (bb->NeedsJump()) { + EmitJump(bb); + } + } + if (!GetStatus()) { + return false; + } + // Visit try-blocks in order they were declared + for (auto *bb : GetGraph()->GetTryBeginBlocks()) { + VisitTryBegin(bb); + } + function_->ins = std::move(GetResult()); + function_->catchBlocks = catch_blocks_; + return true; +} + +void CodeGenDynamic::EmitJump(const BasicBlock *bb) +{ + BasicBlock *suc_bb = nullptr; + ASSERT(bb != nullptr); + + if (bb->GetLastInst() == nullptr) { + ASSERT(bb->IsEmpty()); + suc_bb = bb->GetSuccsBlocks()[0]; + result_.push_back(PandasmWrapper::Create_JMP_Wrapper(LabelName(suc_bb->GetId()))); + return; + } + + ASSERT(bb->GetLastInst() != nullptr); + switch (bb->GetLastInst()->GetOpcode()) { + case Opcode::If: + case Opcode::IfImm: + ASSERT(bb->GetSuccsBlocks().size() == compiler::MAX_SUCCS_NUM); + suc_bb = bb->GetFalseSuccessor(); + break; + default: + suc_bb = bb->GetSuccsBlocks()[0]; + break; + } + result_.push_back(PandasmWrapper::Create_JMP_Wrapper(LabelName(suc_bb->GetId()))); +} + +void CodeGenDynamic::AddLineNumber(const Inst *inst, const size_t idx) +{ + // if (ir_interface_ != nullptr && idx < result_.size()) { + // auto ln = ir_interface_->GetLineNumberByPc(inst->GetPc()); + // result_[idx].ins_debug.SetLineNumber(ln); + // } +} + +void CodeGenDynamic::AddColumnNumber(const Inst *inst, const uint32_t idx) +{ + // if (ir_interface_ != nullptr && idx < result_.size()) { + // auto cn = ir_interface_->GetLineNumberByPc(inst->GetPc()); + // result_[idx].ins_debug.SetColumnNumber(cn); + // } +} + +void CodeGenDynamic::EncodeSpillFillData(const compiler::SpillFillData &sf) +{ + if (sf.SrcType() != compiler::LocationType::REGISTER || sf.DstType() != compiler::LocationType::REGISTER) { + std::cerr << "EncodeSpillFillData with unknown move type, src_type: " + << static_cast(sf.SrcType()) + << " dst_type: " << static_cast(sf.DstType()); + success_ = false; + UNREACHABLE(); + return; + } + ASSERT(sf.GetType() != compiler::DataType::NO_TYPE); + ASSERT(sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG); + + if (sf.SrcValue() == sf.DstValue()) { + return; + } + + result_.emplace_back(PandasmWrapper::Create_MOV_Wrapper(sf.DstValue(), sf.SrcValue())); + return; +} + +void CodeGenDynamic::VisitSpillFill(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + for (auto sf : inst->CastToSpillFill()->GetSpillFills()) { + enc->EncodeSpillFillData(sf); + } +} + +template +bool HasUserPredicate(Inst *inst, UnaryPred p) +{ + bool found = false; + for (auto const &u : inst->GetUsers()) { + if (p(u.GetInst())) { + found = true; + break; + } + } + return found; +} + +void CodeGenDynamic::VisitConstant(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + auto type = inst->GetType(); + + InsWrapper movi; + movi.regs.emplace_back(inst->GetDstReg()); + switch (type) { + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + enc->result_.emplace_back(PandasmWrapper::Create_LDAI_Wrapper(inst->CastToConstant()->GetInt64Value())); + DoSta(inst->GetDstReg(), enc->result_); + break; + case compiler::DataType::FLOAT64: + enc->result_.emplace_back(PandasmWrapper::Create_FLDAI_Wrapper(inst->CastToConstant()->GetDoubleValue())); + DoSta(inst->GetDstReg(), enc->result_); + break; + case compiler::DataType::INT32: + case compiler::DataType::UINT32: + enc->result_.emplace_back(PandasmWrapper::Create_LDAI_Wrapper(inst->CastToConstant()->GetInt32Value())); + DoSta(inst->GetDstReg(), enc->result_); + break; + default: + UNREACHABLE(); + std::cerr << "VisitConstant with unknown type" << type; + enc->success_ = false; + } +} + +void CodeGenDynamic::EncodeSta(compiler::Register reg, compiler::DataType::Type type) +{ + std::string opc; + switch (type) { + case compiler::DataType::ANY: + opc = "STA"; + break; + default: + UNREACHABLE(); + std::cerr << "EncodeSta with unknown type" << type; + success_ = false; + } + InsWrapper sta; + sta.opcode = opc; + sta.regs.emplace_back(reg); + + result_.emplace_back(sta); +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenDynamic::VisitIf(GraphVisitor *v, Inst *instBase) +{ + auto inst = instBase->CastToIf(); + + size_t notZeroConstIdx = 1; + if (IsZeroConstant(inst->GetInput(0).GetInst())) { + notZeroConstIdx = 1; + } else if (IsZeroConstant(inst->GetInput(1).GetInst())) { + notZeroConstIdx = 0; + } else { + UNREACHABLE(); + } + + auto enc = static_cast(v); + DoLda(inst->GetSrcReg(notZeroConstIdx), enc->result_); + auto label = LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + switch (inst->GetCc()) { + case compiler::CC_NE: + enc->result_.emplace_back(PandasmWrapper::Create_JNEZ_Wrapper(label)); + return; + case compiler::CC_EQ: + enc->result_.emplace_back(PandasmWrapper::Create_JEQZ_Wrapper(label)); + return; + default: + UNREACHABLE(); + } +} + +void CodeGenDynamic::VisitIfImm(GraphVisitor *v, Inst *instBase) +{ + auto inst = instBase->CastToIfImm(); + auto imm = inst->GetImm(); + if (imm == 0) { + IfImmZero(v, instBase); + return; + } +} + +void CodeGenDynamic::IfImmZero(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIfImm(); + DoLda(inst->GetSrcReg(0), enc->result_); + auto label = LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + switch (inst->GetCc()) { + case compiler::CC_EQ: + enc->result_.emplace_back(PandasmWrapper::Create_JEQZ_Wrapper(label)); + return; + case compiler::CC_NE: + enc->result_.emplace_back(PandasmWrapper::Create_JNEZ_Wrapper(label)); + return; + default: + UNREACHABLE(); + } +} + +void CodeGenDynamic::VisitLoadString(GraphVisitor *v, Inst *instBase) +{ + UNREACHABLE(); +} + +void CodeGenDynamic::VisitLoadStringIntrinsic(GraphVisitor *v, Inst *instBase) +{ + InsWrapper ins; + auto enc = static_cast(v); + auto inst = instBase->CastToIntrinsic(); + enc->result_.emplace_back(PandasmWrapper::Create_LDA_STR_Wrapper(enc->ir_interface_->GetStringIdByOffset(inst->GetImm(0)))); + if (inst->GetDstReg() != compiler::ACC_REG_ID) { + enc->result_.emplace_back(PandasmWrapper::Create_STA_Wrapper(inst->GetDstReg())); + } +} + +void CodeGenDynamic::VisitReturn(GraphVisitor *v, Inst *instBase) +{ + InsWrapper ins; + auto enc = static_cast(v); + auto inst = instBase->CastToReturn(); + switch (inst->GetType()) { + case compiler::DataType::ANY: { +#if defined(PANDA_WITH_ECMASCRIPT) + auto test_arg = IsEcmaConstTemplate(inst->GetInput(0).GetInst()); + if (test_arg.has_value() && test_arg->IsUndefined()) { + enc->result_.emplace_back(PandasmWrapper::Create_RETURNUNDEFINED_Wrapper()); + break; + } +#endif + DoLda(inst->GetSrcReg(0), enc->result_); + enc->result_.emplace_back(PandasmWrapper::Create_RETURN_Wrapper()); + break; + } + default: + std::cerr + << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed"; + enc->success_ = false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenDynamic::VisitIntrinsic(GraphVisitor *visitor, Inst *instBase) +{ + ASSERT(instBase->IsIntrinsic()); + if (instBase->CastToIntrinsic()->GetIntrinsicId() == compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STRING) { + VisitLoadStringIntrinsic(visitor, instBase); + return; + } + VisitEcma(visitor, instBase); +} + +void CodeGenDynamic::VisitCatchPhi(GraphVisitor *visitor, Inst *inst) +{ + // The Acc register stores the exception object. + // Create an STA instruction if the exception is used later in virtual registers. + if (inst->CastToCatchPhi()->IsAcc()) { + bool hasRealUsers = false; + for (auto &user : inst->GetUsers()) { + if (!user.GetInst()->IsSaveState()) { + hasRealUsers = true; + break; + } + } + if (hasRealUsers) { + auto enc = static_cast(visitor); + DoSta(inst->GetDstReg(), enc->result_); + } + } +} + +#include "generated/insn_selection_dynamic.cpp" +} // namespace libabckit diff --git a/libabckit/src/codegen/codegen_dynamic.h b/libabckit/src/codegen/codegen_dynamic.h new file mode 100644 index 0000000000000000000000000000000000000000..5a4cd9644aee5bd772f81e0c099bb184346f3b5d --- /dev/null +++ b/libabckit/src/codegen/codegen_dynamic.h @@ -0,0 +1,148 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_CODEGEN_CODEGEN_DYNAMIC_H +#define LIBABCKIT_SRC_CODEGEN_CODEGEN_DYNAMIC_H + +#include "static_core/compiler/optimizer/pass.h" +#include "static_core/compiler/optimizer/ir/basicblock.h" +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir/graph_visitor.h" +#include "static_core/compiler/optimizer/ir/constants.h" +#include "static_core/compiler/optimizer/ir/inst.h" +#include "libabckit/src/codegen/common.h" +#include "libabckit/src/wrappers/pandasm_wrapper.h" +#include "libabckit/src/ir_impl.h" + +namespace libabckit { + +using namespace ark; + +using compiler::BasicBlock; +using compiler::Inst; +using compiler::Opcode; + +void DoLda(compiler::Register reg, std::vector &result); +void DoSta(compiler::Register reg, std::vector &result); + +class CodeGenDynamic : public compiler::Optimization, public compiler::GraphVisitor { +public: + explicit CodeGenDynamic(compiler::Graph *graph, FunctionWrapper *function, const abckit_IrInterface *irInterface) + : compiler::Optimization(graph), function_(function), ir_interface_(irInterface) + { + } + ~CodeGenDynamic() override = default; + bool RunImpl() override; + const char *GetPassName() const override + { + return "CodeGenDynamic"; + } + std::vector GetEncodedInstructions() const + { + return res_; + } + + void Reserve(size_t res_size = 0) + { + if (res_size > 0) { + result_.reserve(res_size); + } + } + + bool GetStatus() const + { + return success_; + } + + const std::vector &GetResult() const + { + return result_; + } + + std::vector &&GetResult() + { + return std::move(result_); + } + + static std::string LabelName(uint32_t id) + { + return "label_" + std::to_string(id); + } + + void EmitLabel(const std::string label) + { + InsWrapper l; + l.label = label; + l.setLabel = true; + result_.emplace_back(l); + } + + void EmitJump(const BasicBlock *bb); + + void EncodeSpillFillData(const compiler::SpillFillData &sf); + void EncodeSta(compiler::Register reg, compiler::DataType::Type type); + void AddLineNumber(const Inst *inst, const size_t idx); + void AddColumnNumber(const Inst *inst, const uint32_t idx); + + const ArenaVector &GetBlocksToVisit() const override + { + return GetGraph()->GetBlocksRPO(); + } + static void VisitSpillFill(GraphVisitor *visitor, Inst *inst); + static void VisitConstant(GraphVisitor *visitor, Inst *inst); + static void VisitCatchPhi(GraphVisitor *visitor, Inst *inst); + + static void VisitIf(GraphVisitor *v, Inst *inst_base); + static void VisitIfImm(GraphVisitor *v, Inst *inst_base); + static void IfImmZero(GraphVisitor *v, Inst *inst_base); + static void VisitIntrinsic(GraphVisitor *visitor, Inst *inst_base); + static void VisitLoadString(GraphVisitor *v, Inst *inst_base); + static void VisitLoadStringIntrinsic(GraphVisitor *v, Inst *inst_base); + static void VisitReturn(GraphVisitor *v, Inst *inst_base); + + static void VisitEcma(GraphVisitor *v, Inst *inst_base); + +#include "generated/codegen_visitors_dyn.inc" + +#include "generated/insn_selection_dynamic.h" + + void VisitDefault(Inst *inst) override + { + std::cerr << "Opcode " << compiler::GetOpcodeString(inst->GetOpcode()) + << " not yet implemented in codegen\n"; + success_ = false; + } + +#include "compiler/optimizer/ir/visitor.inc" + +private: + void AppendCatchBlock(uint32_t type_id, const compiler::BasicBlock *try_begin, const compiler::BasicBlock *try_end, + const compiler::BasicBlock *catch_begin, const compiler::BasicBlock *catch_end = nullptr); + void VisitTryBegin(const compiler::BasicBlock *bb); + +private: + FunctionWrapper *function_; + const abckit_IrInterface *ir_interface_; + + std::vector res_; + std::vector catch_blocks_; + + bool success_ {true}; + std::vector result_; +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_CODEGEN_CODEGEN_DYNAMIC_H diff --git a/libabckit/src/codegen/codegen_static.cpp b/libabckit/src/codegen/codegen_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9c60b686037b7cbda8e671b62f37196577f3b3a --- /dev/null +++ b/libabckit/src/codegen/codegen_static.cpp @@ -0,0 +1,1533 @@ +/* + * Copyright (c) 2023-2024 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 "libabckit/src/codegen/codegen_static.h" +#include "static_core/runtime/include/coretypes/tagged_value.h" +namespace ark { +#include +} + +namespace libabckit { + +uint8_t AccReadIndex(const compiler::Inst *inst) +{ + // Calls can have accumulator at any position, return false for them + ASSERT(!inst->IsCall()); + + if (inst->IsIntrinsic() && inst->IsAccRead()) { + ASSERT(inst->GetInputsCount() >= 1U); + return inst->GetInputsCount() - 1L; + } + + return 0U; +} + +// This method is used by bytecode optimizer's codegen. +bool CanConvertToIncI(const compiler::BinaryImmOperation *binop) +{ + ASSERT(binop->GetBasicBlock()->GetGraph()->IsRegAllocApplied()); + ASSERT(binop->GetOpcode() == compiler::Opcode::AddI || binop->GetOpcode() == compiler::Opcode::SubI); + + // IncI works on the same register. + if (binop->GetSrcReg(0U) != binop->GetDstReg()) { + return false; + } + + // IncI cannot write accumulator. + if (binop->GetSrcReg(0U) == compiler::ACC_REG_ID) { + return false; + } + + // IncI users cannot read from accumulator. + // While Addi/SubI stores the output in accumulator, IncI works directly on registers. + for (const auto &user : binop->GetUsers()) { + const auto *uinst = user.GetInst(); + + if (uinst->IsCall()) { + continue; + } + + const uint8_t index = AccReadIndex(uinst); + if (uinst->GetInput(index).GetInst() == binop && uinst->GetSrcReg(index) == compiler::ACC_REG_ID) { + return false; + } + } + + constexpr uint64_t BITMASK = 0xffffffff; + // Define min and max values of i4 type. + // NOLINTNEXTLINE(readability-identifier-naming) + constexpr int32_t min = -8; + // NOLINTNEXTLINE(readability-identifier-naming) + constexpr int32_t max = 7; + + int32_t imm = binop->GetImm() & BITMASK; + // Note: subi 3 is the same as inci v2, -3. + if (binop->GetOpcode() == compiler::Opcode::SubI) { + imm = -imm; + } + + // IncI works only with 4 bits immediates. + return imm >= min && imm <= max; +} + +void DoLdaObj(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_LDA_OBJ(reg)); + } +} + +void DoLda(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_LDA(reg)); + } +} + +void DoLda64(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_LDA_64(reg)); + } +} + +void DoStaObj(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_STA_OBJ(reg)); + } +} + +void DoSta(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_STA(reg)); + } +} + +void DoSta64(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_STA_64(reg)); + } +} + +void DoSta(compiler::DataType::Type type, compiler::Register reg, std::vector &result) +{ + if (compiler::DataType::Is64Bits(type, Arch::NONE)) { + DoSta64(reg, result); + } else { + DoSta(reg, result); + } +} + +void DoLdaDyn(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_LDA_DYN(reg)); + } +} + +void DoStaDyn(compiler::Register reg, std::vector &result) +{ + if (reg != compiler::ACC_REG_ID) { + result.emplace_back(pandasm::Create_STA_DYN(reg)); + } +} + +void CodeGenStatic::AppendCatchBlock(uint32_t typeId, const compiler::BasicBlock *tryBegin, + const compiler::BasicBlock *tryEnd, const compiler::BasicBlock *catchBegin, + const compiler::BasicBlock *catchEnd) +{ + auto cb = pandasm::Function::CatchBlock(); + if (typeId != 0U) { + cb.exceptionRecord = irInterface_->GetTypeIdByOffset(typeId); + // cb.exceptionRecord = ""; + } + cb.tryBeginLabel = CodeGenStatic::LabelName(tryBegin->GetId()); + cb.tryEndLabel = "end_" + CodeGenStatic::LabelName(tryEnd->GetId()); + cb.catchBeginLabel = CodeGenStatic::LabelName(catchBegin->GetId()); + cb.catchEndLabel = catchEnd == nullptr ? cb.catchBeginLabel : "end_" + CodeGenStatic::LabelName(catchEnd->GetId()); + catchBlocks_.emplace_back(cb); +} + +void CodeGenStatic::VisitTryBegin(const compiler::BasicBlock *bb) +{ + ASSERT(bb->IsTryBegin()); + auto tryInst = GetTryBeginInst(bb); + auto tryEnd = tryInst->GetTryEndBlock(); + ASSERT(tryEnd != nullptr && tryEnd->IsTryEnd()); + + bb->EnumerateCatchHandlers([&, bb, tryEnd](BasicBlock *catchHandler, size_t typeId) { + AppendCatchBlock(typeId, bb, tryEnd, catchHandler); + return true; + }); +} + +void CodeGenStatic::AddLineAndColumnNumber(const compiler::Inst *inst, size_t idx) +{ + AddLineNumber(inst, idx); +} + +bool CodeGenStatic::RunImpl() +{ + Reserve(function_->ins.size()); + for (auto *bb : GetGraph()->GetBlocksLinearOrder()) { + EmitLabel(CodeGenStatic::LabelName(bb->GetId())); + if (bb->IsTryEnd() || bb->IsCatchEnd()) { + auto label = "end_" + CodeGenStatic::LabelName(bb->GetId()); + EmitLabel(label); + } + for (const auto &inst : bb->AllInsts()) { + auto start = GetResult().size(); + VisitInstruction(inst); + if (!GetStatus()) { + return false; + } + auto end = GetResult().size(); + ASSERT(end >= start); + for (auto i = start; i < end; ++i) { + AddLineAndColumnNumber(inst, i); + } + } + if (bb->NeedsJump()) { + EmitJump(bb); + } + } + if (!GetStatus()) { + return false; + } + // Visit try-blocks in order they were declared + for (auto *bb : GetGraph()->GetTryBeginBlocks()) { + VisitTryBegin(bb); + } + function_->ins = std::move(GetResult()); + function_->catchBlocks = catchBlocks_; + return true; +} + +void CodeGenStatic::EmitJump(const BasicBlock *bb) +{ + BasicBlock *sucBb = nullptr; + ASSERT(bb != nullptr); + + if (bb->GetLastInst() == nullptr) { + ASSERT(bb->IsEmpty()); + sucBb = bb->GetSuccsBlocks()[0U]; + result_.push_back(pandasm::Create_JMP(CodeGenStatic::LabelName(sucBb->GetId()))); + return; + } + + ASSERT(bb->GetLastInst() != nullptr); + switch (bb->GetLastInst()->GetOpcode()) { + case Opcode::If: + case Opcode::IfImm: + ASSERT(bb->GetSuccsBlocks().size() == compiler::MAX_SUCCS_NUM); + sucBb = bb->GetFalseSuccessor(); + break; + default: + sucBb = bb->GetSuccsBlocks()[0U]; + break; + } + result_.push_back(pandasm::Create_JMP(CodeGenStatic::LabelName(sucBb->GetId()))); +} + +void CodeGenStatic::AddLineNumber(const Inst *inst, const size_t idx) +{ + // TODO + // if (irInterface_ != nullptr && idx < result_.size()) { + // auto ln = irInterface_->GetLineNumberByPc(inst->GetPc()); + // result_[idx].insDebug.SetLineNumber(ln); + // } +} + +void CodeGenStatic::AddColumnNumber(const Inst *inst, const uint32_t idx) +{ + // TODO + // if (irInterface_ != nullptr && idx < result_.size()) { + // auto cn = irInterface_->GetColumnNumberByPc(inst->GetPc()); + // result_[idx].insDebug.SetColumnNumber(cn); + // } +} + +void CodeGenStatic::EncodeSpillFillData(const compiler::SpillFillData &sf) +{ + if (sf.SrcType() != compiler::LocationType::REGISTER || sf.DstType() != compiler::LocationType::REGISTER) { + std::cerr << "EncodeSpillFillData with unknown move type, src_type: " + << static_cast(sf.SrcType()) + << " dst_type: " << static_cast(sf.DstType()) + << std::endl; + success_ = false; + UNREACHABLE(); + return; + } + ASSERT(sf.GetType() != compiler::DataType::NO_TYPE); + ASSERT(sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG); + + if (sf.SrcValue() == sf.DstValue()) { + return; + } + + pandasm::Ins move; + switch (sf.GetType()) { + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: + move = pandasm::Create_MOV_64(sf.DstValue(), sf.SrcValue()); + break; + case compiler::DataType::REFERENCE: + move = pandasm::Create_MOV_OBJ(sf.DstValue(), sf.SrcValue()); + break; + default: + move = pandasm::Create_MOV(sf.DstValue(), sf.SrcValue()); + } + result_.emplace_back(move); +} + +void CodeGenStatic::VisitSpillFill(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + for (auto sf : inst->CastToSpillFill()->GetSpillFills()) { + enc->EncodeSpillFillData(sf); + } +} + +template +bool HasUserPredicate(Inst *inst, UnaryPred p) +{ + bool found = false; + for (auto const &u : inst->GetUsers()) { + if (p(u.GetInst())) { + found = true; + break; + } + } + return found; +} + +static void VisitConstant32(CodeGenStatic *enc, compiler::Inst *inst, std::vector &res) +{ + auto type = inst->GetType(); + ASSERT(compiler::DataType::Is32Bits(type, Arch::NONE)); + + pandasm::Ins movi; + auto dstReg = inst->GetDstReg(); + movi.regs.emplace_back(inst->GetDstReg()); + + switch (type) { + case compiler::DataType::BOOL: + case compiler::DataType::INT8: + case compiler::DataType::UINT8: + case compiler::DataType::INT16: + case compiler::DataType::UINT16: + case compiler::DataType::INT32: + case compiler::DataType::UINT32: + if (dstReg == compiler::ACC_REG_ID) { + pandasm::Ins ldai = pandasm::Create_LDAI(inst->CastToConstant()->GetInt32Value()); + res.emplace_back(ldai); + } else { + movi = pandasm::Create_MOVI(dstReg, inst->CastToConstant()->GetInt32Value()); + res.emplace_back(movi); + } + break; + case compiler::DataType::FLOAT32: + if (dstReg == compiler::ACC_REG_ID) { + pandasm::Ins ldai = pandasm::Create_FLDAI(inst->CastToConstant()->GetFloatValue()); + res.emplace_back(ldai); + } else { + movi = pandasm::Create_FMOVI(dstReg, inst->CastToConstant()->GetFloatValue()); + res.emplace_back(movi); + } + break; + default: + UNREACHABLE(); + } +} + +static void VisitConstant64(CodeGenStatic *enc, compiler::Inst *inst, std::vector &res) +{ + auto type = inst->GetType(); + ASSERT(compiler::DataType::Is64Bits(type, Arch::NONE)); + + pandasm::Ins movi; + auto dstReg = inst->GetDstReg(); + movi.regs.emplace_back(inst->GetDstReg()); + + switch (type) { + case compiler::DataType::INT64: + case compiler::DataType::UINT64:\ + if (dstReg == compiler::ACC_REG_ID) { + pandasm::Ins ldai = pandasm::Create_LDAI_64(inst->CastToConstant()->GetInt64Value()); + res.emplace_back(ldai); + } else { + movi = pandasm::Create_MOVI_64(dstReg, inst->CastToConstant()->GetInt64Value()); + res.emplace_back(movi); + } + break; + case compiler::DataType::FLOAT64: + if (dstReg == compiler::ACC_REG_ID) { + pandasm::Ins ldai = pandasm::Create_FLDAI_64(inst->CastToConstant()->GetDoubleValue()); + res.emplace_back(ldai); + } else { + movi = pandasm::Create_FMOVI_64(dstReg, inst->CastToConstant()->GetDoubleValue()); + res.emplace_back(movi); + } + break; + default: + UNREACHABLE(); + } +} + +void CodeGenStatic::VisitConstant(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + auto type = inst->GetType(); + + switch (type) { + case compiler::DataType::BOOL: + case compiler::DataType::INT8: + case compiler::DataType::UINT8: + case compiler::DataType::INT16: + case compiler::DataType::UINT16: + case compiler::DataType::INT32: + case compiler::DataType::UINT32: + case compiler::DataType::FLOAT32: + VisitConstant32(enc, inst, enc->result_); + break; + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: + VisitConstant64(enc, inst, enc->result_); + break; + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + UNREACHABLE(); + std::cerr << "VisitConstant with unknown type" << type << std::endl; + enc->success_ = false; + } +} + +void CodeGenStatic::EncodeSta(compiler::Register reg, compiler::DataType::Type type) +{ + pandasm::Opcode opc; + switch (type) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: + case compiler::DataType::FLOAT32: + opc = pandasm::Opcode::STA; + break; + case compiler::DataType::UINT64: + case compiler::DataType::INT64: + case compiler::DataType::FLOAT64: + opc = pandasm::Opcode::STA_64; + break; + case compiler::DataType::ANY: + opc = pandasm::Opcode::STA_DYN; + break; + case compiler::DataType::REFERENCE: + opc = pandasm::Opcode::STA_OBJ; + break; + default: + UNREACHABLE(); + std::cerr << "EncodeSta with unknown type" << type << std::endl; + success_ = false; + } + pandasm::Ins sta; + sta.opcode = opc; + sta.regs.emplace_back(reg); + + result_.emplace_back(sta); +} + +static pandasm::Opcode ChooseCallOpcode(compiler::Opcode op, size_t nargs) +{ + ASSERT(op == compiler::Opcode::CallStatic || op == compiler::Opcode::CallVirtual || + op == compiler::Opcode::Intrinsic); + if (nargs > MAX_NUM_NON_RANGE_ARGS) { + switch (op) { + case compiler::Opcode::CallStatic: + return pandasm::Opcode::CALL_RANGE; + case compiler::Opcode::CallVirtual: + return pandasm::Opcode::CALL_VIRT_RANGE; + case compiler::Opcode::Intrinsic: + return pandasm::Opcode::INITOBJ_RANGE; + default: + UNREACHABLE(); + } + } else if (nargs > MAX_NUM_SHORT_CALL_ARGS) { + switch (op) { + case compiler::Opcode::CallStatic: + return pandasm::Opcode::CALL; + case compiler::Opcode::CallVirtual: + return pandasm::Opcode::CALL_VIRT; + case compiler::Opcode::Intrinsic: + return pandasm::Opcode::INITOBJ; + default: + UNREACHABLE(); + } + } + switch (op) { + case compiler::Opcode::CallStatic: + return pandasm::Opcode::CALL_SHORT; + case compiler::Opcode::CallVirtual: + return pandasm::Opcode::CALL_VIRT_SHORT; + case compiler::Opcode::Intrinsic: + return pandasm::Opcode::INITOBJ_SHORT; + default: + UNREACHABLE(); + } +} + +static pandasm::Opcode ChooseCallAccOpcode(pandasm::Opcode op) +{ + switch (op) { + case pandasm::Opcode::CALL_SHORT: + return pandasm::Opcode::CALL_ACC_SHORT; + case pandasm::Opcode::CALL: + return pandasm::Opcode::CALL_ACC; + case pandasm::Opcode::CALL_VIRT_SHORT: + return pandasm::Opcode::CALL_VIRT_ACC_SHORT; + case pandasm::Opcode::CALL_VIRT: + return pandasm::Opcode::CALL_VIRT_ACC; + default: + return pandasm::Opcode::INVALID; + } +} + +static ark::compiler::CallInst *CastToCall(ark::compiler::Inst *inst) +{ + switch (inst->GetOpcode()) { + case compiler::Opcode::CallStatic: + return inst->CastToCallStatic(); + case compiler::Opcode::CallVirtual: + return inst->CastToCallVirtual(); + default: + UNREACHABLE(); + } +} + +void CodeGenStatic::CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId) +{ + auto op = inst->GetOpcode(); + ASSERT(op == compiler::Opcode::CallStatic || op == compiler::Opcode::CallVirtual || + op == compiler::Opcode::Intrinsic); + auto *enc = static_cast(visitor); + auto sfCount = inst->GetInputsCount() - (inst->RequireState() ? 1U : 0U); + size_t start = 0U; + auto nargs = sfCount; + pandasm::Ins ins; + + ins.opcode = ChooseCallOpcode(op, nargs); + + if (nargs > MAX_NUM_NON_RANGE_ARGS) { +#ifndef NDEBUG + auto startReg = inst->GetSrcReg(start); + ASSERT(startReg <= MAX_8_BIT_REG); + for (auto i = start; i < sfCount; ++i) { + auto reg = inst->GetSrcReg(i); + ASSERT(reg - startReg == static_cast(i - start)); // check 'range-ness' of registers + } +#endif // !NDEBUG + ins.regs.emplace_back(inst->GetSrcReg(start)); + } else { + for (size_t i = start; i < sfCount; ++i) { + auto reg = inst->GetSrcReg(i); + ASSERT(reg < NUM_COMPACTLY_ENCODED_REGS || reg == compiler::ACC_REG_ID); + if (reg == compiler::ACC_REG_ID) { + ASSERT(inst->IsCallOrIntrinsic()); + ins.imms.emplace_back(static_cast(i)); + ins.opcode = ChooseCallAccOpcode(ins.opcode); + } else { + ins.regs.emplace_back(reg); + } + } + } + ins.ids.emplace_back(std::move(methodId)); + enc->result_.emplace_back(ins); + if (inst->GetDstReg() != compiler::INVALID_REG && inst->GetDstReg() != compiler::ACC_REG_ID) { + enc->EncodeSta(inst->GetDstReg(), inst->GetType()); + } +} + +void CodeGenStatic::CallHandler(GraphVisitor *visitor, Inst *inst) +{ + auto *enc = static_cast(visitor); + uint32_t methodOffset = 0; + if (inst->IsIntrinsic()) { + ASSERT(IsBCTInitObject(inst->CastToIntrinsic()->GetIntrinsicId())); + methodOffset = inst->CastToIntrinsic()->GetImm(0); + } else { + methodOffset = CastToCall(inst)->GetCallMethodId(); + } + CallHandler(visitor, inst, enc->irInterface_->GetMethodIdByOffset(methodOffset)); +} + +void CodeGenStatic::VisitCallStatic(GraphVisitor *visitor, Inst *inst) +{ + CallHandler(visitor, inst); +} + +void CodeGenStatic::VisitCallVirtual(GraphVisitor *visitor, Inst *inst) +{ + CallHandler(visitor, inst); +} + +static void VisitIf32(CodeGenStatic *enc, compiler::IfInst *inst, std::vector &res, bool &success) +{ + ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE)); + + DoLda(inst->GetSrcReg(0U), res); + + compiler::Register src = inst->GetSrcReg(1); + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQ(src, label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNE(src, label)); + break; + } + case compiler::CC_LT: { + res.emplace_back(pandasm::Create_JLT(src, label)); + break; + } + case compiler::CC_LE: { + res.emplace_back(pandasm::Create_JLE(src, label)); + break; + } + case compiler::CC_GT: { + res.emplace_back(pandasm::Create_JGT(src, label)); + break; + } + case compiler::CC_GE: { + res.emplace_back(pandasm::Create_JGE(src, label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +static void VisitIf64Signed(CodeGenStatic *enc, compiler::IfInst *inst, std::vector &res, bool &success) +{ + ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE)); + ASSERT(IsTypeSigned(inst->GetInputType(0U))); + + DoLda64(inst->GetSrcReg(0U), res); + + res.emplace_back(pandasm::Create_CMP_64(inst->GetSrcReg(1U))); + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQZ(label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNEZ(label)); + break; + } + case compiler::CC_LT: { + res.emplace_back(pandasm::Create_JLTZ(label)); + break; + } + case compiler::CC_LE: { + res.emplace_back(pandasm::Create_JLEZ(label)); + break; + } + case compiler::CC_GT: { + res.emplace_back(pandasm::Create_JGTZ(label)); + break; + } + case compiler::CC_GE: { + res.emplace_back(pandasm::Create_JGEZ(label)); + break; + } + default: + std::cerr << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +static void VisitIf64Unsigned(CodeGenStatic *enc, compiler::IfInst *inst, std::vector &res, bool &success) +{ + ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE)); + ASSERT(!IsTypeSigned(inst->GetInputType(0U))); + + DoLda64(inst->GetSrcReg(0U), res); + + res.emplace_back(pandasm::Create_UCMP_64(inst->GetSrcReg(1U))); + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQZ(label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNEZ(label)); + break; + } + case compiler::CC_LT: { + res.emplace_back(pandasm::Create_JLTZ(label)); + break; + } + case compiler::CC_LE: { + res.emplace_back(pandasm::Create_JLEZ(label)); + break; + } + case compiler::CC_GT: { + res.emplace_back(pandasm::Create_JGTZ(label)); + break; + } + case compiler::CC_GE: { + res.emplace_back(pandasm::Create_JGEZ(label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +static void VisitIfRef([[maybe_unused]] CodeGenStatic *enc, compiler::IfInst *inst, std::vector &res, + bool &success) +{ + ASSERT(IsReference(inst->GetInputType(0U))); + + DoLdaObj(inst->GetSrcReg(0U), res); + + compiler::Register src = inst->GetSrcReg(1); + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQ_OBJ(src, label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNE_OBJ(src, label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::VisitIf(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIf(); + switch (inst->GetInputType(0U)) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: { + VisitIf32(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::INT64: { + VisitIf64Signed(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::UINT64: { + VisitIf64Unsigned(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::REFERENCE: { + VisitIfRef(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +void CodeGenStatic::VisitIfImm(GraphVisitor *v, Inst *instBase) +{ + auto inst = instBase->CastToIfImm(); + auto imm = inst->GetImm(); + if (imm == 0U) { + IfImmZero(v, instBase); + return; + } + IfImmNonZero(v, instBase); +} + +static void IfImmZero32(CodeGenStatic *enc, compiler::IfImmInst *inst, std::vector &res, bool &success) +{ + ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE)); + + DoLda(inst->GetSrcReg(0U), res); + + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQZ(label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNEZ(label)); + break; + } + case compiler::CC_LT: { + res.emplace_back(pandasm::Create_JLTZ(label)); + break; + } + case compiler::CC_LE: { + res.emplace_back(pandasm::Create_JLEZ(label)); + break; + } + case compiler::CC_GT: { + res.emplace_back(pandasm::Create_JGTZ(label)); + break; + } + case compiler::CC_GE: { + res.emplace_back(pandasm::Create_JGEZ(label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +static void IfImmZeroRef(CodeGenStatic *enc, compiler::IfImmInst *inst, std::vector &res, bool &success) +{ + ASSERT(IsReference(inst->GetInputType(0U))); + + + DoLdaObj(inst->GetSrcReg(0U), res); + + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQZ_OBJ(label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNEZ_OBJ(label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::IfImmZero(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIfImm(); + switch (inst->GetInputType(0U)) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: { + IfImmZero32(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::INT64: + case compiler::DataType::UINT64: { + IfImm64(v, instBase); + break; + } + case compiler::DataType::REFERENCE: { + IfImmZeroRef(enc, inst, enc->result_, enc->success_); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +static void IfImmNonZero32(CodeGenStatic *enc, compiler::IfImmInst *inst, std::vector &res, bool &success) +{ + ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE)); + + res.emplace_back(pandasm::Create_LDAI(inst->GetImm())); + + compiler::Register src = inst->GetSrcReg(0); + std::string label = CodeGenStatic::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + res.emplace_back(pandasm::Create_JEQ(src, label)); + break; + } + case compiler::CC_NE: { + res.emplace_back(pandasm::Create_JNE(src, label)); + break; + } + case compiler::CC_LT: { + res.emplace_back(pandasm::Create_JLT(src, label)); + break; + } + case compiler::CC_LE: { + res.emplace_back(pandasm::Create_JLE(src, label)); + break; + } + case compiler::CC_GT: { + res.emplace_back(pandasm::Create_JGT(src, label)); + break; + } + case compiler::CC_GE: { + res.emplace_back(pandasm::Create_JGE(src, label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::IfImmNonZero(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIfImm(); + switch (inst->GetInputType(0U)) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: { + IfImmNonZero32(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::INT64: + case compiler::DataType::UINT64: { + IfImm64(v, instBase); + break; + } + case compiler::DataType::REFERENCE: { + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + std::cerr + << "VisitIfImm does not support non-zero imm of type reference, as no pandasm matches"; + enc->success_ = false; + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::IfImm64(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIfImm(); + + enc->result_.emplace_back(pandasm::Create_LDAI_64(inst->GetImm())); + + std::string label = LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()); + + switch (inst->GetInputType(0U)) { + case compiler::DataType::INT64: { + enc->result_.emplace_back(pandasm::Create_CMP_64(inst->GetSrcReg(0U))); + break; + } + case compiler::DataType::UINT64: { + enc->result_.emplace_back(pandasm::Create_UCMP_64(inst->GetSrcReg(0U))); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + return; + } + + switch (inst->GetCc()) { + case compiler::CC_EQ: { + enc->result_.emplace_back(pandasm::Create_JEQZ(label)); + break; + } + case compiler::CC_NE: { + enc->result_.emplace_back(pandasm::Create_JNEZ(label)); + break; + } + case compiler::CC_LT: { + enc->result_.emplace_back(pandasm::Create_JGTZ(label)); + break; + } + case compiler::CC_LE: { + enc->result_.emplace_back(pandasm::Create_JGEZ(label)); + break; + } + case compiler::CC_GT: { + enc->result_.emplace_back(pandasm::Create_JLTZ(label)); + break; + } + case compiler::CC_GE: { + enc->result_.emplace_back(pandasm::Create_JLEZ(label)); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + return; + } +} + +static void CastAccDownFromI32(compiler::DataType::Type type, std::vector &res) +{ + auto sizeBits = compiler::DataType::GetTypeSize(type, Arch::NONE); + if (compiler::DataType::IsTypeSigned(type)) { + auto shift = compiler::WORD_SIZE - sizeBits; + res.emplace_back(pandasm::Create_SHLI(shift)); + res.emplace_back(pandasm::Create_ASHRI(shift)); + } else { + auto andMask = (1U << sizeBits) - 1U; + res.emplace_back(pandasm::Create_ANDI(andMask)); + } +} + +static void VisitCastFromI32([[maybe_unused]] CodeGenStatic *enc, compiler::CastInst *inst, + std::vector &res, bool &success) +{ + ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE)); + + if (inst->GetType() == compiler::DataType::UINT32) { + return; + } + DoLda(inst->GetSrcReg(0U), res); + + switch (inst->GetType()) { + case compiler::DataType::FLOAT32: { + res.emplace_back(pandasm::Create_I32TOF32()); + break; + } + case compiler::DataType::FLOAT64: { + res.emplace_back(pandasm::Create_I32TOF64()); + break; + } + case compiler::DataType::INT64: { + res.emplace_back(pandasm::Create_I32TOI64()); + break; + } + case compiler::DataType::INT16: + case compiler::DataType::UINT16: + case compiler::DataType::INT8: + case compiler::DataType::UINT8: { + CastAccDownFromI32(inst->GetType(), res); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + return; + } + DoSta(inst->GetType(), inst->GetDstReg(), res); +} + +static void VisitCastFromU32([[maybe_unused]] CodeGenStatic *enc, compiler::CastInst *inst, + std::vector &res, bool &success) +{ + ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE)); + + if (inst->GetType() == compiler::DataType::INT32) { + return; + } + DoLda(inst->GetSrcReg(0U), res); + + switch (inst->GetType()) { + case compiler::DataType::FLOAT32: { + res.emplace_back(pandasm::Create_U32TOF32()); + break; + } + case compiler::DataType::FLOAT64: { + res.emplace_back(pandasm::Create_U32TOF64()); + break; + } + case compiler::DataType::INT64: { + res.emplace_back(pandasm::Create_U32TOI64()); + break; + } + case compiler::DataType::INT16: + case compiler::DataType::UINT16: + case compiler::DataType::INT8: + case compiler::DataType::UINT8: { + CastAccDownFromI32(inst->GetType(), res); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + return; + } + DoSta(inst->GetType(), inst->GetDstReg(), res); +} + +static void VisitCastFromI64([[maybe_unused]] CodeGenStatic *enc, compiler::CastInst *inst, + std::vector &res, bool &success) +{ + ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE)); + constexpr int64_t ANDI_32 = 0xffffffff; + + DoLda64(inst->GetSrcReg(0U), res); + + switch (inst->GetType()) { + case compiler::DataType::INT32: { + res.emplace_back(pandasm::Create_I64TOI32()); + break; + } + case compiler::DataType::UINT32: { + res.emplace_back(pandasm::Create_ANDI(ANDI_32)); + break; + } + case compiler::DataType::FLOAT32: { + res.emplace_back(pandasm::Create_I64TOF32()); + break; + } + case compiler::DataType::FLOAT64: { + res.emplace_back(pandasm::Create_I64TOF64()); + break; + } + case compiler::DataType::INT16: + case compiler::DataType::UINT16: + case compiler::DataType::INT8: + case compiler::DataType::UINT8: { + res.emplace_back(pandasm::Create_I64TOI32()); + CastAccDownFromI32(inst->GetType(), res); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + return; + } + DoSta(inst->GetType(), inst->GetDstReg(), res); +} + +static void VisitCastFromF32([[maybe_unused]] CodeGenStatic *enc, compiler::CastInst *inst, + std::vector &res, bool &success) +{ + ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE)); + ASSERT(IsFloatType(inst->GetInputType(0U))); + + constexpr int64_t ANDI_32 = 0xffffffff; + + DoLda(inst->GetSrcReg(0U), res); + + switch (inst->GetType()) { + case compiler::DataType::FLOAT64: { + res.emplace_back(pandasm::Create_F32TOF64()); + break; + } + case compiler::DataType::INT64: { + res.emplace_back(pandasm::Create_F32TOI64()); + break; + } + case compiler::DataType::UINT64: { + res.emplace_back(pandasm::Create_F32TOU64()); + break; + } + case compiler::DataType::INT32: { + res.emplace_back(pandasm::Create_F32TOI32()); + break; + } + case compiler::DataType::UINT32: { + res.emplace_back(pandasm::Create_F32TOU32()); + res.emplace_back(pandasm::Create_ANDI(ANDI_32)); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + return; + } + DoSta(inst->GetType(), inst->GetDstReg(), res); +} + +static void VisitCastFromF64([[maybe_unused]] CodeGenStatic *enc, compiler::CastInst *inst, + std::vector &res, bool &success) +{ + ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE)); + ASSERT(IsFloatType(inst->GetInputType(0U))); + + constexpr int64_t ANDI_32 = 0xffffffff; + + DoLda64(inst->GetSrcReg(0U), res); + + switch (inst->GetType()) { + case compiler::DataType::FLOAT32: { + res.emplace_back(pandasm::Create_F64TOF32()); + break; + } + case compiler::DataType::INT64: { + res.emplace_back(pandasm::Create_F64TOI64()); + break; + } + case compiler::DataType::INT32: { + res.emplace_back(pandasm::Create_F64TOI32()); + break; + } + case compiler::DataType::UINT32: { + res.emplace_back(pandasm::Create_F64TOI64()); + res.emplace_back(pandasm::Create_ANDI(ANDI_32)); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + success = false; + return; + } + DoSta(inst->GetType(), inst->GetDstReg(), res); +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::VisitCast(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToCast(); + switch (inst->GetInputType(0U)) { + case compiler::DataType::INT32: { + VisitCastFromI32(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::UINT32: { + VisitCastFromU32(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::INT64: { + VisitCastFromI64(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::FLOAT32: { + VisitCastFromF32(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::FLOAT64: { + VisitCastFromF64(enc, inst, enc->result_, enc->success_); + break; + } + case compiler::DataType::REFERENCE: { + switch (inst->GetType()) { + case compiler::DataType::ANY: { + UNREACHABLE(); + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +void CodeGenStatic::VisitReturn(GraphVisitor *v, Inst *instBase) +{ + pandasm::Ins ins; + auto enc = static_cast(v); + auto inst = instBase->CastToReturn(); + switch (inst->GetType()) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: + case compiler::DataType::FLOAT32: { + DoLda(inst->GetSrcReg(0U), enc->result_); + enc->result_.emplace_back(pandasm::Create_RETURN()); + break; + } + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: { + DoLda64(inst->GetSrcReg(0U), enc->result_); + enc->result_.emplace_back(pandasm::Create_RETURN_64()); + break; + } + case compiler::DataType::REFERENCE: { + DoLdaObj(inst->GetSrcReg(0U), enc->result_); + enc->result_.emplace_back(pandasm::Create_RETURN_OBJ()); + break; + } + case compiler::DataType::VOID: { + enc->result_.emplace_back(pandasm::Create_RETURN_VOID()); + break; + } + case compiler::DataType::ANY: { + UNREACHABLE(); + break; + } + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::VisitStoreObjectIntrinsic(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + const compiler::IntrinsicInst *inst = instBase->CastToIntrinsic(); + + compiler::Register vd = inst->GetSrcReg(0U); + compiler::Register vs = inst->GetSrcReg(1U); + std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetImm(0)); + + bool isAccType = (vs == compiler::ACC_REG_ID); + + switch (inst->GetType()) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: + case compiler::DataType::FLOAT32: + if (isAccType) { + enc->result_.emplace_back(pandasm::Create_STOBJ(vd, id)); + } else { + enc->result_.emplace_back(pandasm::Create_STOBJ_V(vs, vd, id)); + } + break; + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: + if (isAccType) { + enc->result_.emplace_back(pandasm::Create_STOBJ_64(vd, id)); + } else { + enc->result_.emplace_back(pandasm::Create_STOBJ_V_64(vs, vd, id)); + } + break; + case compiler::DataType::REFERENCE: + if (isAccType) { + enc->result_.emplace_back(pandasm::Create_STOBJ_OBJ(vd, id)); + } else { + enc->result_.emplace_back(pandasm::Create_STOBJ_V_OBJ(vs, vd, id)); + } + break; + default: + std::cerr + << "Wrong DataType for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +void CodeGenStatic::VisitStoreStaticIntrinsic(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIntrinsic(); + + compiler::Register vs = inst->GetSrcReg(0U); + std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetImm(0)); + + switch (inst->GetType()) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: + case compiler::DataType::FLOAT32: + DoLda(vs, enc->result_); + enc->result_.emplace_back(pandasm::Create_STSTATIC(id)); + break; + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: + DoLda64(vs, enc->result_); + enc->result_.emplace_back(pandasm::Create_STSTATIC_64(id)); + break; + case compiler::DataType::REFERENCE: + DoLdaObj(vs, enc->result_); + enc->result_.emplace_back(pandasm::Create_STSTATIC_OBJ(id)); + break; + default: + std::cerr + << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +void CodeGenStatic::VisitLoadObjectIntrinsic(GraphVisitor *v, Inst *instBase) +{ + auto enc = static_cast(v); + auto inst = instBase->CastToIntrinsic(); + + compiler::Register vs = inst->GetSrcReg(0U); + compiler::Register vd = inst->GetDstReg(); + std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetImm(0)); + + bool isAccType = (inst->GetDstReg() == compiler::ACC_REG_ID); + + switch (inst->GetType()) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: + case compiler::DataType::FLOAT32: + if (isAccType) { + enc->result_.emplace_back(pandasm::Create_LDOBJ(vs, id)); + } else { + enc->result_.emplace_back(pandasm::Create_LDOBJ_V(vd, vs, id)); + } + break; + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: + if (isAccType) { + enc->result_.emplace_back(pandasm::Create_LDOBJ_64(vs, id)); + } else { + enc->result_.emplace_back(pandasm::Create_LDOBJ_V_64(vd, vs, id)); + } + break; + case compiler::DataType::REFERENCE: + if (isAccType) { + enc->result_.emplace_back(pandasm::Create_LDOBJ_OBJ(vs, id)); + } else { + enc->result_.emplace_back(pandasm::Create_LDOBJ_V_OBJ(vd, vs, id)); + } + break; + default: + std::cerr + << "Wrong DataType for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +void CodeGenStatic::VisitLoadStaticIntrinsic(GraphVisitor *v, Inst *instBase) +{ + std::cerr << "codegen VisitLoadStatic\n"; + auto enc = static_cast(v); + auto inst = instBase->CastToIntrinsic(); + + compiler::Register vd = inst->GetDstReg(); + std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetImm(0)); + + switch (inst->GetType()) { + case compiler::DataType::BOOL: + case compiler::DataType::UINT8: + case compiler::DataType::INT8: + case compiler::DataType::UINT16: + case compiler::DataType::INT16: + case compiler::DataType::UINT32: + case compiler::DataType::INT32: + case compiler::DataType::FLOAT32: + enc->result_.emplace_back(pandasm::Create_LDSTATIC(id)); + DoSta(vd, enc->result_); + break; + case compiler::DataType::INT64: + case compiler::DataType::UINT64: + case compiler::DataType::FLOAT64: + enc->result_.emplace_back(pandasm::Create_LDSTATIC_64(id)); + DoSta64(vd, enc->result_); + break; + case compiler::DataType::REFERENCE: + enc->result_.emplace_back(pandasm::Create_LDSTATIC_OBJ(id)); + DoStaObj(vd, enc->result_); + break; + default: + std::cerr << "CodeGen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed\n"; + enc->success_ = false; + } +} + +void CodeGenStatic::VisitCatchPhi(GraphVisitor *v, Inst *inst) +{ + if (inst->CastToCatchPhi()->IsAcc()) { + bool hasRealUsers = false; + for (auto &user : inst->GetUsers()) { + if (!user.GetInst()->IsSaveState()) { + hasRealUsers = true; + break; + } + } + if (hasRealUsers) { + auto enc = static_cast(v); + enc->result_.emplace_back(pandasm::Create_STA_OBJ(inst->GetDstReg())); + } + } +} + +#include "generated/codegen_intrinsics_static.cpp" +#include "generated/insn_selection_static.cpp" +} // namespace libabckit diff --git a/libabckit/src/codegen/codegen_static.h b/libabckit/src/codegen/codegen_static.h new file mode 100644 index 0000000000000000000000000000000000000000..39a39a31a673b5b5cbdf389daaa4522342caf7da --- /dev/null +++ b/libabckit/src/codegen/codegen_static.h @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2023-2024 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. + */ + +#ifndef LIBABCKIT_SRC_CODEGEN_CODEGEN_STATIC_H +#define LIBABCKIT_SRC_CODEGEN_CODEGEN_STATIC_H + +#include "static_core/assembler/assembly-function.h" +#include "static_core/assembler/assembly-ins.h" +#include "static_core/compiler/optimizer/pass.h" +#include "static_core/compiler/optimizer/ir/basicblock.h" +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir/graph_visitor.h" +#include "static_core/libpandabase/utils/logger.h" + +#include "ins_create_api.h" +#include "libabckit/src/ir_impl.h" + + +namespace libabckit { + +using namespace ark; + +using compiler::BasicBlock; +using compiler::Inst; +using compiler::Opcode; + +constexpr compiler::Register MIN_REGISTER_NUMBER = 0; +constexpr compiler::Register MAX_NUM_SHORT_CALL_ARGS = 2; +constexpr compiler::Register MAX_NUM_NON_RANGE_ARGS = 4; +constexpr compiler::Register MAX_NUM_INPUTS = MAX_NUM_NON_RANGE_ARGS; +constexpr ark::compiler::Register NUM_COMPACTLY_ENCODED_REGS = 16; +[[maybe_unused]] constexpr compiler::Register MAX_8_BIT_REG = 255 - 1U; // exclude INVALID_REG + +void DoLdaObj(compiler::Register reg, std::vector &result); +void DoLda(compiler::Register reg, std::vector &result); +void DoLda64(compiler::Register reg, std::vector &result); +void DoStaObj(compiler::Register reg, std::vector &result); +void DoSta(compiler::Register reg, std::vector &result); +void DoSta64(compiler::Register reg, std::vector &result); +void DoSta(compiler::DataType::Type type, compiler::Register reg, std::vector &result); +void DoLdaDyn(compiler::Register reg, std::vector &result); +void DoStaDyn(compiler::Register reg, std::vector &result); + +// NOLINTNEXTLINE(fuchsia-multiple-inheritance) +class CodeGenStatic : public compiler::Optimization, public compiler::GraphVisitor { +public: + explicit CodeGenStatic(compiler::Graph *graph, pandasm::Function *function, const abckit_IrInterface *iface) + : compiler::Optimization(graph), function_(function), irInterface_(iface) + { + } + ~CodeGenStatic() override = default; + NO_COPY_SEMANTIC(CodeGenStatic); + NO_MOVE_SEMANTIC(CodeGenStatic); + + bool RunImpl() override; + const char *GetPassName() const override + { + return "CodeGenStatic"; + } + std::vector GetEncodedInstructions() const + { + return res_; + } + + void Reserve(size_t resSize = 0) + { + if (resSize > 0) { + result_.reserve(resSize); + } + } + + bool GetStatus() const + { + return success_; + } + + const std::vector &GetResult() const + { + return result_; + } + + std::vector &&GetResult() + { + return std::move(result_); + } + + static std::string LabelName(uint32_t id) + { + return "label_" + std::to_string(id); + } + + void EmitLabel(const std::string &label) + { + pandasm::Ins l; + l.label = label; + l.setLabel = true; + result_.emplace_back(l); + } + + void EmitJump(const BasicBlock *bb); + + void EncodeSpillFillData(const compiler::SpillFillData &sf); + void EncodeSta(compiler::Register reg, compiler::DataType::Type type); + void AddLineNumber(const Inst *inst, size_t idx); + void AddColumnNumber(const Inst *inst, uint32_t idx); + void AddLineAndColumnNumber(const Inst *inst, size_t idx); + + const ArenaVector &GetBlocksToVisit() const override + { + return GetGraph()->GetBlocksRPO(); + } + static void VisitSpillFill(GraphVisitor *v, Inst *inst); + static void VisitConstant(GraphVisitor *v, Inst *inst); + static void VisitCallStatic(GraphVisitor *visitor, Inst *inst); + static void VisitCallVirtual(GraphVisitor *visitor, Inst *inst); + static void VisitInitObject(GraphVisitor *visitor, Inst *inst) { + UNREACHABLE(); + } + static void VisitCatchPhi(GraphVisitor *visitor, Inst *inst); + + static void VisitIntrinsic(GraphVisitor *visitor, Inst *inst); + + static void VisitIf(GraphVisitor *v, Inst *instBase); + static void VisitIfImm(GraphVisitor *v, Inst *instBase); + static void VisitCast(GraphVisitor *v, Inst *instBase); + static void IfImmZero(GraphVisitor *v, Inst *instBase); + static void IfImmNonZero(GraphVisitor *v, Inst *instBase); + static void IfImm64(GraphVisitor *v, Inst *instBase); + static void CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId); + static void CallHandler(GraphVisitor *visitor, Inst *inst); + static void VisitStoreObject(GraphVisitor *v, Inst *instBase) + { + UNREACHABLE(); + } + static void VisitStoreStatic(GraphVisitor *v, Inst *instBase) + { + UNREACHABLE(); + } + static void VisitLoadObject(GraphVisitor *v, Inst *instBase) + { + UNREACHABLE(); + } + static void VisitLoadStatic(GraphVisitor *v, Inst *instBase) + { + UNREACHABLE(); + } + static void VisitLoadString(GraphVisitor *v, Inst *instBase) + { + UNREACHABLE(); + } + static void VisitReturn(GraphVisitor *v, Inst *instBase); + +#include "generated/codegen_visitors_static.inc" +#include "generated/insn_selection_static.h" + + void VisitDefault(Inst *inst) override + { + std::cerr << "Opcode " << compiler::GetOpcodeString(inst->GetOpcode()) << " not yet implemented in CodeGen"; + success_ = false; + } + +#include "compiler/optimizer/ir/visitor.inc" + +private: + void AppendCatchBlock(uint32_t typeId, const compiler::BasicBlock *tryBegin, const compiler::BasicBlock *tryEnd, + const compiler::BasicBlock *catchBegin, const compiler::BasicBlock *catchEnd = nullptr); + void VisitTryBegin(const compiler::BasicBlock *bb); + +private: + pandasm::Function *function_; + const abckit_IrInterface *irInterface_; + + std::vector res_; + std::vector catchBlocks_; + + bool success_ {true}; + std::vector result_; +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_CODEGEN_CODEGEN_STATIC_H diff --git a/libabckit/src/codegen/codegen_static_isapi.rb b/libabckit/src/codegen/codegen_static_isapi.rb new file mode 100644 index 0000000000000000000000000000000000000000..b6ad585540de60e20a02e4cb419a6bbf9dae1799 --- /dev/null +++ b/libabckit/src/codegen/codegen_static_isapi.rb @@ -0,0 +1,567 @@ +# Copyright (c) 2021-2022 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. + +Instruction.class_eval do + def src_acc_kind + op = acc_and_operands.select { |op| op.acc? && op.src? }.first + raise "There is no src acc for #{mnemonic}" unless op + data_kind_helper(op) + end + + def dst_acc_kind + op = acc_and_operands.select { |op| op.acc? && op.dst? }.first + raise "There is no dst acc for #{mnemonic}" unless op + data_kind_helper(op) + end + + private + # return one of 32, 64, 'ref' + def data_kind_helper(op) + m = /[fiub](?\d+)/.match(op.type) + if m + size = m[:size].to_i + if size == 64 + return 64 + else + return 32 + end + end + return 'ref' if op.type == 'ref' + raise "Unexpected operand type #{op.type} in data_kind_helper" + end +end + +def instruction_hash + unless defined? @instruction_hash + @instruction_hash = Hash.new { |_, key| raise "No instruction with '#{key}' mnemonic" } + Panda.instructions.each { |insn| @instruction_hash[insn.mnemonic] = insn } + end + @instruction_hash +end + +# Classes for bytecode description +Visitor = Struct.new(:ir_op, :cpp, :switch) +Switch = Struct.new(:expr, :cases) do + def encode + res = "switch (#{expr}) {\n" + cases.each do |c| + res << c.encode + end + res << "default: +std::cerr << \"Codegen for \" << compiler::GetOpcodeString(inst->GetOpcode()) << \" failed\\n\"; +enc->success_ = false; +}" + res + end + + def check_width + res = "switch (#{expr}) {\n" + cases.each do |c| + res << c.check_width + end + res << "default: + std::cerr << \"CheckWidth for \" << compiler::GetOpcodeString(inst->GetOpcode()) << \" failed\\n\"; +re->success_ = false; +}" + res + end +end + +Case = Struct.new(:types, :node) do + def proxy(method) + res = types.map { |type| "case #{type}:" }.join("\n") + res << " {\n" + res << node.send(method) + res << "break;\n}\n" + res + end + + def encode + proxy(:encode) + end + + def check_width + proxy(:check_width) + end +end + +Leaf = Struct.new(:instruction, :args) do + def encode + res = "" + args_str = args.join(",\n") + if instruction.acc_read? + res << do_lda(instruction) + res << "\n" + end + res << "enc->result_.emplace_back(pandasm::Create_#{instruction.asm_token}(\n" + res << args_str + res << "\n));\n" + if instruction.acc_write? + res << do_sta(instruction) + res << "\n" + end + res + end + + def check_width + reg = instruction.operands.select(&:reg?).first + if reg + "re->Check#{reg.width}Width(inst);\n" + else + "return;\n" + end + end +end + +If = Struct.new(:condition, :true_expr, :false_expr) do + def proxy(method) + res = "if (#{condition}) {\n" + res << true_expr.send(method) + res << "} else {\n" + res << false_expr.send(method) + res << "}\n" + res + end + + def encode + proxy(:encode) + end + + def check_width + proxy(:check_width) + end +end + +Empty = Struct.new(:dummy) do + def encode; end + def check_width; end +end + + +def visit(ir_op, cpp = nil) + @table ||= [] + @table << Visitor.new(ir_op, cpp, yield) +end + +def visitors + @table +end + +def switch(expr, cases) + Switch.new(expr, cases) +end + +def plain(opcode, *args) + Leaf.new(instruction_hash[opcode], args.to_a) +end + +def empty + Empty.new +end + +def if_(condition, true_expr, false_expr) + If.new(condition, true_expr, false_expr) +end + +def prefixed_case(prefix, types, node) + types = types.map { |t| "#{prefix}#{t}" } + Case.new(types, node) +end + +def case_(types, opcode, *args) + prefixed_case("compiler::DataType::", types, plain(opcode, *args)) +end + +def cc_case(types, opcode, *args) + prefixed_case("compiler::CC_", types, plain(opcode, *args)) +end + +def case_switch(types, condition, inner_cases) + prefixed_case("compiler::DataType::", types, switch(condition, inner_cases)) +end + +def case_value(value, node) + Case.new([value], node) +end + +def case_true(opcode, *args) + case_value('1', plain(opcode, *args)) +end + +def case_true_node(node) + case_value('1', node) +end + +def case_false(opcode, *args) + case_value('0', plain(opcode, *args)) +end + +def case_false_node(node) + case_value('0', node) +end + +def generate_arith_op(op) + switch("static_cast(#{dst_r} != #{r(0)} && #{dst_r} != #{r(1)})", + [case_true(op, r(0), r(1)), + case_false_node(is_commutative?(op) ? + if_("#{dst_r} == #{r(0)}", + plain("#{op}v", r(0), r(1)), + plain("#{op}v", r(1), r(0))) : + plain(op, r(0), r(1)) + ) + ] + ) +end + +# Type/cc cases for instruction selection +def i32_types + @i32_types ||= %w[BOOL UINT8 INT8 UINT16 INT16 UINT32 INT32] +end + +def i64_types + @i64_types ||= %w[INT64 UINT64] +end + +def f32_types + @f32_types ||= %w[FLOAT32] +end + +def f64_types + @f64_types ||= %w[FLOAT64] +end + +def b64_types + @b64_types ||= i64_types + f64_types +end + +def b32_types + @b32_types ||= i32_types + f32_types +end + +def void_types + @void_types ||= %w[VOID] +end + +def cc_cases + @cc_cases ||= %w[EQ NE LT LE GT GE] +end + +# Switch condition printers +def type + 'inst->GetType()' +end + +def src_type + 'inst->GetInputType(0)' +end + +# we could use switch on 'bool' type for if-else purposes, but that hurts clang_tidy +def is_acc?(reg) + "#{reg} == compiler::ACC_REG_ID" +end + +def is_not_acc?(reg) + "#{reg} != compiler::ACC_REG_ID" +end + +def is_compact?(reg) + "#{reg} < NUM_COMPACTLY_ENCODED_REGS" +end + +def is_not_compact?(reg) + "#{reg} >= NUM_COMPACTLY_ENCODED_REGS" +end + +def is_fcmpg? + 'static_cast(inst->IsFcmpg())' +end + +def is_inci? + "static_cast(CanConvertToIncI(inst))" +end + +def is_commutative?(op) + ["add", "mul", "and", "or", "xor"].include?(op) +end + +def is_arith_iv? + "#{is_not_acc?(r(0))} && #{is_not_acc?(dst_r)} && (#{is_compact?(r(0))} || #{is_compact?(dst_r)})" +end + +def cast_to_int(val) + "static_cast(#{val})" +end + +# Operand printers +def dst_r + 'inst->GetDstReg()' +end + +def r(num) + "inst->GetSrcReg(#{num})" +end + +def imm + 'static_cast(inst->GetImm() & 0xffffffff)' +end + +def label + 'LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())' +end + +def string_id + 'enc->irInterface_->GetStringIdByOffset(inst->GetImm(0))' +end + +def literalarray_id + 'enc->irInterface_->GetLiteralArrayIdByOffset(inst->GetImm(0))' +end + +def type_id(idx) + "enc->irInterface_->GetTypeIdByOffset(inst->GetImm(#{idx}))" +end + +def field_id + 'enc->irInterface_->GetFieldIdByOffset(inst->GetTypeId())' +end + +# Lda/Sta printers +def do_lda(instruction) + lda = case instruction.src_acc_kind + when 32 + instruction_hash['lda'] + when 64 + instruction_hash['lda.64'] + when 'ref' + instruction_hash['lda.obj'] + end + reg_num = if instruction.mnemonic.include?('ldarr') || instruction.mnemonic.include?('stobj') || instruction.mnemonic.include?('ststatic') + 1 + elsif instruction.mnemonic.include?('starr') + 2 + else + 0 + end + "if (inst->GetSrcReg(#{reg_num}) != compiler::ACC_REG_ID) { + enc->result_.emplace_back(pandasm::Create_#{lda.asm_token}(inst->GetSrcReg(#{reg_num}))); + }" +end + +def do_sta(instruction) + sta = case instruction.dst_acc_kind + when 32 + instruction_hash['sta'] + when 64 + instruction_hash['sta.64'] + when 'ref' + instruction_hash['sta.obj'] + end + "if (inst->GetDstReg() != compiler::ACC_REG_ID) { + enc->result_.emplace_back(pandasm::Create_#{sta.asm_token}(inst->GetDstReg())); + }" +end + +# Misc printers +def visitor_sig(op_name, with_class = true) + "void #{'CodeGenStatic::' if with_class}Visit#{op_name}(GraphVisitor* v, Inst* instBase)" +end + +# Bytecode description itself + +# Wrap all `insn` declaration in a function to call from template +# (because Panda::instructions is initialized only in templates) +def call_me_from_template + %w[And Xor Or Shl Shr AShr].each do |op| + visit(op) do + op = op.downcase + switch(type, + [case_switch(i32_types, cast_to_int(is_not_compact?(r(0))), + [case_true_node(if_(is_acc?(dst_r), + plain("#{op}2", r(1)), + plain("#{op}2v", dst_r, r(1)))), + case_false_node(if_("#{is_compact?(dst_r)}", + generate_arith_op(op), + plain(op, r(0), r(1))))]), + case_switch(i64_types, cast_to_int(is_acc?(dst_r)), + [case_true("#{op}2.64", r(1)), + case_false("#{op}2v.64", dst_r, r(1))])] + ) + end + end + + %w[add sub mul div mod].each do |op| + visit(op.capitalize) do + switch(type, + [case_switch(i32_types, cast_to_int(is_not_compact?(r(0))), + [case_true_node(if_(is_acc?(dst_r), + plain("#{op}2", r(1)), + plain("#{op}2v", dst_r, r(1)))), + case_false_node(if_("#{is_compact?(dst_r)}", + generate_arith_op(op), + plain(op, r(0), r(1))))]), + case_switch(i64_types, cast_to_int(is_acc?(dst_r)), + [case_true("#{op}2.64", r(1)), + case_false("#{op}2v.64", dst_r, r(1))]), + case_switch(f32_types, cast_to_int(is_acc?(dst_r)), + [case_true("f#{op}2", r(1)), + case_false("f#{op}2v", dst_r, r(1))]), + case_switch(f64_types, cast_to_int(is_acc?(dst_r)), + [case_true("f#{op}2.64", r(1)), + case_false("f#{op}2v.64", dst_r, r(1))])] + ) + end + end + + visit('AddI') do + switch(type, + [case_switch(i32_types, is_inci?, + [case_true('inci', r(0), imm), + case_false_node(if_(is_arith_iv?, + plain("addiv", dst_r, r(0), imm), + plain("addi", imm)))])] + ) + end + + visit('SubI') do + switch(type, + [case_switch(i32_types, is_inci?, + [case_true('inci', r(0), "-(#{imm})"), + case_false_node(if_(is_arith_iv?, + plain("subiv", dst_r, r(0), imm), + plain("subi", imm)))])] + ) + end + + visit('Not') do + switch(type, + [case_(i32_types, 'not'), + case_(i64_types, 'not.64')] + ) + end + + visit('Neg') do + switch(type, + [case_(i32_types, 'neg'), + case_(i64_types, 'neg.64'), + case_(f32_types, 'fneg'), + case_(f64_types, 'fneg.64')] + ) + end + + visit('Cmp') do + switch('inst->GetOperandsType()', + [case_(%w[UINT8 UINT16 UINT32], 'ucmp', r(1)), + case_(%w[INT64], 'cmp.64', r(1)), + case_(%w[UINT64], 'ucmp.64', r(1)), + case_switch(['FLOAT32'], is_fcmpg?, + [case_true('fcmpg', r(1)), + case_false('fcmpl', r(1))]), + case_switch(['FLOAT64'], is_fcmpg?, + [case_true('fcmpg.64', r(1)), + case_false('fcmpl.64', r(1))])] + ) + end + + visit('ReturnVoid') do + plain('return.void') + end + + visit('ThrowIntrinsic') do + plain('throw', r(0)) + end + + visit('NullPtr') do + switch(cast_to_int(is_acc?(dst_r)), + [case_true('lda.null'), + case_false('mov.null', dst_r)] + ) + end + + visit('LoadConstArrayIntrinsic') do + plain('lda.const', dst_r, literalarray_id) + end + + visit('LoadStringIntrinsic') do + plain('lda.str', string_id) + end + + visit('NewArrayIntrinsic') do + plain('newarr', dst_r, r(0), type_id(0)) + end + + visit('LenArray') do + plain('lenarr', r(0)) + end + + visit('LoadArrayIntrinsic') do + switch(type, + [case_(['INT8'], 'ldarr.8', r(0)), + case_(['UINT8'], 'ldarru.16', r(0)), + case_(['INT16'], 'ldarr.16', r(0)), + case_(['UINT16'], 'ldarru.16', r(0)), + case_(['INT32', 'UINT32'], 'ldarr', r(0)), + case_(['INT64', 'UINT64'], 'ldarr.64', r(0)), + case_(['REFERENCE'], 'ldarr.obj', r(0)), + case_(['FLOAT32'], 'fldarr.32', r(0)), + case_(['FLOAT64'], 'fldarr.64', r(0))] + ) + end + + visit('StoreArrayIntrinsic') do + switch(type, + [case_(['INT8', 'UINT8'], 'starr.8', r(0), r(1)), + case_(['INT16', 'UINT16'], 'starr.16', r(0), r(1)), + case_(['INT32', 'UINT32'], 'starr', r(0), r(1)), + case_(['INT64', 'UINT64'], 'starr.64', r(0), r(1)), + case_(['REFERENCE'], 'starr.obj', r(0), r(1)), + case_(['FLOAT32'], 'fstarr.32', r(0), r(1)), + case_(['FLOAT64'], 'fstarr.64', r(0), r(1))] + ) + end + + visit('CheckCastIntrinsic') do + plain('checkcast', type_id(0)) + end + + visit('IsInstanceIntrinsic') do + plain('isinstance', type_id(0)) + end + + visit('NewObjectIntrinsic') do + plain('newobj', dst_r, type_id(0)) + end + + visit('IsUndefinedIntrinsic') do + plain('ets.isundefined') + end + + # Empty visitors for IR instructions we want to ignore + # (Add missing IRs on demand) + %w[NullCheck BoundsCheck ZeroCheck NegativeCheck SafePoint + InitClass SaveStateDeoptimize RefTypeCheck Phi + Try SaveState LoadClass LoadAndInitClass Parameter LoadRuntimeClass].each do |op| + visit(op) do + empty + end + end + + %w[MulI DivI ModI ShlI ShrI AShrI AndI OrI XorI].each do |op| + visit(op) do + switch(type, + [case_switch(i32_types, cast_to_int(is_arith_iv?), + [case_true("#{op.downcase}v", dst_r, r(0), imm), + case_false("#{op.downcase}", imm)])] + ) + end + end +end diff --git a/libabckit/src/codegen/common.h b/libabckit/src/codegen/common.h new file mode 100644 index 0000000000000000000000000000000000000000..003c1788785f9dab7ee8763519453b2b2832a501 --- /dev/null +++ b/libabckit/src/codegen/common.h @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_CODEGEN_COMMON_H +#define LIBABCKIT_SRC_CODEGEN_COMMON_H + +#include "static_core/compiler/optimizer/ir/constants.h" +#include "static_core/compiler/optimizer/ir/inst.h" + +namespace libabckit { +using namespace ark; +static constexpr compiler::Register MIN_REGISTER_NUMBER = 0; +static constexpr compiler::Register MAX_NUM_SHORT_CALL_ARGS = 2; +static constexpr compiler::Register MAX_NUM_NON_RANGE_ARGS = 4; +static constexpr compiler::Register MAX_NUM_INPUTS = MAX_NUM_NON_RANGE_ARGS; +static constexpr compiler::Register NUM_COMPACTLY_ENCODED_REGS = 16; +static constexpr uint32_t MAX_BYTECODE_SIZE = 100000U; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_CODEGEN_COMMON_H diff --git a/libabckit/src/codegen/ic_slot_allocator.cpp b/libabckit/src/codegen/ic_slot_allocator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..077cb67bc5d9291cbcc6fbc00c75de70c7da20b3 --- /dev/null +++ b/libabckit/src/codegen/ic_slot_allocator.cpp @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2023-2024 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 "ic_slot_allocator.h" + +#include "generated/ic_info.h" + +namespace libabckit { + +using namespace ark; + +bool ICSlotAllocator::RunImpl() +{ + if (!allocate8BitICSlots()) { + return false; + } + + if (!allocate8Or16BitICSlots()) { + return false; + } + + if (!allocate16BitICSlots()) { + return false; + } + + return true; +} + +template +void ICSlotAllocator::visitInstructions(const Callback& callback) +{ + for (auto bb : GetGraph()->GetBlocksRPO()) { + for (auto inst : bb->AllInsts()) { + callback(inst); + } + } +} + +bool ICSlotAllocator::allocate8BitICSlots() +{ + visitInstructions([this](compiler::Inst *inst){ + if (inst->GetOpcode() != compiler::Opcode::Intrinsic) { + return; + } + + auto intrinsicInst = inst->CastToIntrinsic(); + auto intrinsicId = intrinsicInst->GetIntrinsicId(); + auto ICFlags = getICFlags(intrinsicId); + if ((ICFlags & IC_FLAGS::EIGHT_BIT_IC) == 0) { + return; + } + + if ((ICFlags & IC_FLAGS::ONE_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT) { + intrinsicInst->SetImm(0, nextFree8BitSlot_); + nextFree8BitSlot_ += 1U; + (*ICSlotNumber_)++; + } else if ((ICFlags & IC_FLAGS::TWO_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT - 1U) { + intrinsicInst->SetImm(0, nextFree8BitSlot_); + nextFree8BitSlot_ += 2U; + (*ICSlotNumber_) += 2; + } else { + intrinsicInst->SetImm(0, INVALID_8_BIT_SLOT); + } + }); + + return true; +} + +bool ICSlotAllocator::allocate8Or16BitICSlots() +{ + visitInstructions([this](compiler::Inst *inst) { + if (inst->GetOpcode() != compiler::Opcode::Intrinsic) { + return; + } + + auto intrinsicInst = inst->CastToIntrinsic(); + auto intrinsicId = intrinsicInst->GetIntrinsicId(); + auto ICFlags = getICFlags(intrinsicId); + if ((ICFlags & IC_FLAGS::EIGHT_SIXTEEN_BIT_IC) == 0) { + return; + } + + if ((ICFlags & IC_FLAGS::ONE_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT) { + if (!hasInstWith8Or16BitSignature8BitICSlot(intrinsicId)) { + intrinsicInst->SetIntrinsicId(getIdWithInvertedICImm(intrinsicId)); + } + intrinsicInst->SetImm(0, nextFree8BitSlot_); + nextFree8BitSlot_ += 1U; + (*ICSlotNumber_)++; + } else if ((ICFlags & IC_FLAGS::TWO_SLOT) != 0 && nextFree8BitSlot_ < INVALID_8_BIT_SLOT - 1U) { + if (!hasInstWith8Or16BitSignature8BitICSlot(intrinsicId)) { + intrinsicInst->SetIntrinsicId(getIdWithInvertedICImm(intrinsicId)); + } + intrinsicInst->SetImm(0, nextFree8BitSlot_); + nextFree8BitSlot_ += 2U; + (*ICSlotNumber_) += 2; + } else if ((ICFlags & IC_FLAGS::ONE_SLOT) && nextFree16BitSlot_ < INVALID_16_BIT_SLOT) { + if (hasInstWith8Or16BitSignature8BitICSlot(intrinsicId)) { + intrinsicInst->SetIntrinsicId(getIdWithInvertedICImm(intrinsicId)); + } + intrinsicInst->SetImm(0, nextFree16BitSlot_); + nextFree16BitSlot_ += 1U; + (*ICSlotNumber_)++; + } else if ((ICFlags & IC_FLAGS::TWO_SLOT) && nextFree16BitSlot_ < INVALID_16_BIT_SLOT - 1U) { + if (hasInstWith8Or16BitSignature8BitICSlot(intrinsicId)) { + intrinsicInst->SetIntrinsicId(getIdWithInvertedICImm(intrinsicId)); + } + intrinsicInst->SetImm(0, nextFree16BitSlot_); + nextFree16BitSlot_ += 2U; + (*ICSlotNumber_) += 2; + } else { + if (!hasInstWith8Or16BitSignature8BitICSlot(intrinsicId)) { + intrinsicInst->SetIntrinsicId(getIdWithInvertedICImm(intrinsicId)); + } + intrinsicInst->SetImm(0, INVALID_8_BIT_SLOT); + } + }); + + return true; +} + +bool ICSlotAllocator::allocate16BitICSlots() { + visitInstructions([this](compiler::Inst *inst){ + if (inst->GetOpcode() != compiler::Opcode::Intrinsic) { + return; + } + + auto intrinsicInst = inst->CastToIntrinsic(); + auto intrinsicId = intrinsicInst->GetIntrinsicId(); + auto ICFlags = getICFlags(intrinsicId); + if ((ICFlags & IC_FLAGS::SIXTEEN_BIT_IC) == 0) { + return; + } + + if ((ICFlags & IC_FLAGS::ONE_SLOT) != 0 && nextFree16BitSlot_ < INVALID_16_BIT_SLOT) { + intrinsicInst->SetImm(0, nextFree16BitSlot_); + nextFree16BitSlot_ += 1U; + (*ICSlotNumber_)++; + } else if ((ICFlags & IC_FLAGS::TWO_SLOT) != 0 && nextFree16BitSlot_ < INVALID_16_BIT_SLOT - 1U) { + intrinsicInst->SetImm(0, nextFree16BitSlot_); + nextFree16BitSlot_ += 2U; + (*ICSlotNumber_) += 2; + } else { + intrinsicInst->SetImm(0, INVALID_16_BIT_SLOT); + } + }); + + return true; +} +} \ No newline at end of file diff --git a/libabckit/src/codegen/ic_slot_allocator.h b/libabckit/src/codegen/ic_slot_allocator.h new file mode 100644 index 0000000000000000000000000000000000000000..2e62ed6ea091c5c2b7aa1f81032c8c0456774396 --- /dev/null +++ b/libabckit/src/codegen/ic_slot_allocator.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023-2024 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. + */ + +#ifndef LIBABCKIT_SRC_CODEGEN_IC_SLOT_ALLOCATOR_H +#define LIBABCKIT_SRC_CODEGEN_IC_SLOT_ALLOCATOR_H + +#include "compiler/optimizer/ir/basicblock.h" +#include "compiler/optimizer/ir/graph.h" +#include "compiler/optimizer/ir/graph_visitor.h" +#include "compiler/optimizer/ir/constants.h" +#include "compiler/optimizer/ir/inst.h" +#include "compiler/optimizer/pass.h" + +namespace libabckit { + +using namespace ark; + +using compiler::BasicBlock; +using compiler::Inst; +using compiler::Opcode; + +class ICSlotAllocator : public compiler::Optimization { +public: + explicit ICSlotAllocator(compiler::Graph *graph, uint16_t *ICSlotNumber) + : compiler::Optimization(graph), ICSlotNumber_(ICSlotNumber) + { + } + + ~ICSlotAllocator() override = default; + bool RunImpl() override; + + const char *GetPassName() const override + { + return "ICSlotAllocator"; + } + +private: + template + void visitInstructions(const Callback& callback); + + bool allocate8BitICSlots(); + bool allocate8Or16BitICSlots(); + bool allocate16BitICSlots(); + + uint8_t nextFree8BitSlot_ = 0x0; + uint16_t nextFree16BitSlot_ = 0x100; + uint16_t *ICSlotNumber_ = nullptr; + + static constexpr uint8_t INVALID_8_BIT_SLOT = 0xFF; + static constexpr uint16_t INVALID_16_BIT_SLOT = 0xFFFF; +}; + +} + +#endif //LIBABCKIT_SRC_CODEGEN_IC_SLOT_ALLOCATOR_H diff --git a/libabckit/src/codegen/templates/codegen_call_intrinsics_static.inc.erb b/libabckit/src/codegen/templates/codegen_call_intrinsics_static.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..1d5cc557f39c635c61db3427c1ded59566aee922 --- /dev/null +++ b/libabckit/src/codegen/templates/codegen_call_intrinsics_static.inc.erb @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2024 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. + */ + +% Runtime.intrinsics.select{ |i| i.static && !i.signature.stackrange && !i.is_stub && !i.compiler_only && i.has_impl? && +% !i.clear_flags.include?('call') }.each do |intrinsic| + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_<%= intrinsic.enum_name %>: { +% types = intrinsic.signature.args.map { |i| i.gsub("\\[", "[]") } + [intrinsic.signature.ret] +% # `inspect` escapes possible backslashes in ret type descriptor +% plugin_opts = Common::plugins[intrinsic.space.upcase] +% sep = plugin_opts ? plugin_opts["class_name_separator"] : nil +% class_name = intrinsic.class_name +% signature = types.join(';') +% if sep && sep != '.' then +% class_name = class_name.gsub('.', sep) +% signature = signature.gsub('.', sep) +% end + CodeGenStatic::CallHandler(visitor, inst, <%= "#{class_name}.#{intrinsic.method_name}:#{signature};".inspect %>); + break; + } +% end \ No newline at end of file diff --git a/libabckit/src/codegen/templates/codegen_intrinsics_static.cpp.erb b/libabckit/src/codegen/templates/codegen_intrinsics_static.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..b4fe5f4edec8a1de62444b055f6f252dcabccfeb --- /dev/null +++ b/libabckit/src/codegen/templates/codegen_intrinsics_static.cpp.erb @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +// NOLINTNEXTLINE(readability-function-size) +void CodeGenStatic::VisitIntrinsic(GraphVisitor *visitor, Inst *instBase) +{ + ASSERT(instBase->IsIntrinsic()); + auto inst = instBase->CastToIntrinsic(); + auto enc = static_cast(visitor); + switch (inst->GetIntrinsicId()) { +% Common::each_plugin_suboption("bytecodeopt", "codegen_intrinsics_inc") do |codegen_intrinsics_inc, plugin_lang| + // Lang <%= plugin_lang %> + #include "<%= codegen_intrinsics_inc %>" +% end +#include "codegen_call_intrinsics_static.inc" +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: +% if intrinsic.class_name == 'Equals' + VisitEtsEquals(visitor, instBase); +% else + Visit<%= intrinsic.class_name %>Intrinsic(visitor, instBase); +% end + return; +% end + default: { + enc->success_ = false; + LOG(ERROR,COMPILER) << "Unsupported intrinsic"; + } + } +} diff --git a/libabckit/src/codegen/templates/codegen_visitors_static.inc.erb b/libabckit/src/codegen/templates/codegen_visitors_static.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..880a87979de4b338550013956aa375b14e4b3c34 --- /dev/null +++ b/libabckit/src/codegen/templates/codegen_visitors_static.inc.erb @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +<%= Common::include_plugin_files "bytecodeopt", "codegen_visitors_inc" %> + +<%plugins_overrides = Hash.new() + Common::each_plugin_suboption("bytecodeopt", "codegen_visitors_overrides") do |codegen_visitors_overrides, plugin_lang| + codegen_visitors_overrides.each do |visitor| + plugins_overrides[visitor].nil? ? plugins_overrides[visitor] = [].append(plugin_lang) + : plugins_overrides[visitor].append(plugin_lang) + end + end + ["LoadObject", "LoadStatic", "StoreObject", "StoreStatic"].each do |visitor|%> +static bool TryPlugin<%= visitor %>Visitor(GraphVisitor *v, [[maybe_unused]] Inst *inst) { + [[maybe_unused]] auto lang = static_cast(v)->GetGraph()->GetLanguage(); +% if plugins_overrides[visitor] +% plugins_overrides[visitor].each do |lang| + if (lang == <%= Common::plugins[lang]["lang_enum"] %>) { + return <%= lang.capitalize %>Visit<%= visitor %>(v, inst); + } +% end +% end + return false; +} +% end diff --git a/libabckit/src/codegen/templates/insn_selection_static.cpp.erb b/libabckit/src/codegen/templates/insn_selection_static.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..f6f34505144645d5b88f28c08cf28ea954e2d218 --- /dev/null +++ b/libabckit/src/codegen/templates/insn_selection_static.cpp.erb @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2021-2023 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. + */ + +// Autogenerated file -- DO NOT EDIT! +// NOLINTBEGIN(readability-magic-numbers) + +% call_me_from_template + +% visitors.each do |visitor| +<%= visitor_sig(visitor.ir_op) %> { + pandasm::Ins ins; + [[maybe_unused]] auto enc = static_cast(v); +% name = nil +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| +% if (visitor.ir_op == "#{intrinsic.class_name}Intrinsic") +% name = "Intrinsic" +% end +% end +% name = visitor.ir_op unless name + [[maybe_unused]] auto inst = instBase->CastTo<%= name %>(); +<%= visitor.cpp %> +<%= visitor.switch.encode %> +} +% end + +void CodeGenStatic::VisitInitObjectIntrinsic(GraphVisitor *visitor, Inst *inst) +{ + CallHandler(visitor, inst); +} diff --git a/libabckit/src/codegen/templates/insn_selection_static.h.erb b/libabckit/src/codegen/templates/insn_selection_static.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..137514638c4f0fdd575aa84018d5f24970bfaa6e --- /dev/null +++ b/libabckit/src/codegen/templates/insn_selection_static.h.erb @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2021-2023 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. + */ + +// Autogenerated file -- DO NOT EDIT + +% call_me_from_template + +% exist_visitors = Array.new +% visitors.each do |visitor| +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| +% if (visitor.ir_op == "#{intrinsic.class_name}Intrinsic") +% exist_visitors.push(intrinsic.class_name) +% end +% end +static <%= visitor_sig(visitor.ir_op, false) %>; +% end +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| +% if !(exist_visitors.include? intrinsic.class_name) +% exist_visitors.push(intrinsic.class_name) +static <%= visitor_sig("#{intrinsic.class_name}Intrinsic", false) %>; +% end +% end \ No newline at end of file diff --git a/libabckit/src/codegen/templates_dynamic/BUILD.gn b/libabckit/src/codegen/templates_dynamic/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..5dc2f97806bc1508876b867a267e1ed3dcf4e562 --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/BUILD.gn @@ -0,0 +1,60 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "insn_selection_dynamic.h.erb", + "insn_selection_dynamic.cpp.erb", + "check_width_dynamic.cpp.erb", + "check_width_dynamic.h.erb" + ] + sources = "." + destination = "$target_gen_dir/../generated" + requires = [ + "codegen_dynamic_isapi.rb", + "$ark_root/assembler/asm_isapi.rb", + ] +} + +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "ic_info.h.erb", + ] + sources = "." + destination = "$target_gen_dir/../generated" + requires = [ + "codegen_dynamic_isapi.rb", + "$ark_root/assembler/asm_isapi.rb", + ] +} + +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "generate_ecma.inl.erb" + ] + sources = "." + requires = [ "$ark_root/assembler/asm_isapi.rb" ] + destination = "$target_gen_dir/../generated" +} + +ark_gen_file("codegen_visitors_dyn_inc") { + extra_dependencies = [ "$ark_root:concat_plugins_yamls" ] + template_file = "codegen_visitors_dyn.inc.erb" + data_file = "$ark_root/templates/plugin_options.yaml" + requires = [ "$ark_root/templates/plugin_options.rb" ] + output_file = "$target_gen_dir/../generated/codegen_visitors_dyn.inc" +} diff --git a/libabckit/src/codegen/templates_dynamic/check_width_dynamic.cpp.erb b/libabckit/src/codegen/templates_dynamic/check_width_dynamic.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..42fa6e9740d8b082ae646e282584eee9e951aa47 --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/check_width_dynamic.cpp.erb @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +void RegEncoderDynamic::VisitIf([[maybe_unused]] GraphVisitor* v, Inst* inst_base) { + [[maybe_unused]] auto re = static_cast(v); + [[maybe_unused]] auto inst = inst_base->CastToIf(); + switch (inst->GetCc()) { + case compiler::CC_EQ: + case compiler::CC_NE: + case compiler::CC_LT: + case compiler::CC_LE: + case compiler::CC_GT: + case compiler::CC_GE: { + re->Check8Width(inst); + break; + } + default: + std::cerr << "CheckWidth for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed"; + re->success_ = false; + } +} +void RegEncoderDynamic::VisitIfImm([[maybe_unused]] GraphVisitor* v, Inst* inst_base) { + [[maybe_unused]] auto re = static_cast(v); + [[maybe_unused]] auto inst = inst_base->CastToIfImm(); + switch (inst->GetCc()) { + case compiler::CC_EQ: + case compiler::CC_NE: + case compiler::CC_LT: + case compiler::CC_LE: + case compiler::CC_GT: + case compiler::CC_GE: { + break; + } + default: + std::cerr << "CheckWidth for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed"; + re->success_ = false; + } +} +void RegEncoderDynamic::VisitCast([[maybe_unused]] GraphVisitor* v, Inst* instBase) { + [[maybe_unused]] auto re = static_cast(v); + [[maybe_unused]] auto inst = instBase->CastToCast(); +} +% call_me_from_template + +% visitors.each do |visitor| +void RegEncoderDynamic::Visit<%= visitor.ir_op %>([[maybe_unused]] GraphVisitor* v, Inst* inst_base) { + [[maybe_unused]] auto re = static_cast(v); + [[maybe_unused]] auto inst = inst_base->CastTo<%= visitor.ir_op %>(); +<%= visitor.switch.check_width %> +} +% end diff --git a/libabckit/src/codegen/templates_dynamic/check_width_dynamic.h.erb b/libabckit/src/codegen/templates_dynamic/check_width_dynamic.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..84a6654366cecf20de7befb0705a6b1426f98cca --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/check_width_dynamic.h.erb @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +static void VisitIf([[maybe_unused]] GraphVisitor* v, Inst* inst_base); +static void VisitIfImm([[maybe_unused]] GraphVisitor* v, Inst* inst_base); +static void VisitCast([[maybe_unused]] GraphVisitor* v, Inst* inst_base); +% call_me_from_template + +% visitors.each do |visitor| +static void Visit<%= visitor.ir_op %>([[maybe_unused]] GraphVisitor* v, Inst* inst_base); +% end diff --git a/libabckit/src/codegen/templates_dynamic/codegen_dynamic_isapi.rb b/libabckit/src/codegen/templates_dynamic/codegen_dynamic_isapi.rb new file mode 100644 index 0000000000000000000000000000000000000000..f8a4ccc5973336d9f2e359d165080f56f86ffaa7 --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/codegen_dynamic_isapi.rb @@ -0,0 +1,317 @@ +# Copyright (c) 2024 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. + +# ISAPI specialization for bytecode optimizer + +Instruction.class_eval do + def src_acc_kind + op = acc_and_operands.select { |op| op.acc? && op.src? }.first + raise "There is no src acc for #{mnemonic}" unless op + data_kind_helper(op) + end + + def dst_acc_kind + op = acc_and_operands.select { |op| op.acc? && op.dst? }.first + raise "There is no dst acc for #{mnemonic}" unless op + data_kind_helper(op) + end + + private + # return one of 32, 64, 'ref' + def data_kind_helper(op) + m = /[fiub](?\d+)/.match(op.type) + if m + size = m[:size].to_i + if size == 64 + return 64 + else + return 32 + end + end + return 'ref' if op.type == 'ref' + raise "Unexpected operand type #{op.type} in data_kind_helper" + end +end + +def instruction_hash + unless defined? @instruction_hash + @instruction_hash = Hash.new { |_, key| raise "No instruction with '#{key}' mnemonic" } + Panda.instructions.each { |insn| @instruction_hash[insn.mnemonic] = insn } + end + @instruction_hash +end + +# Classes for bytecode description +Visitor = Struct.new(:ir_op, :switch) +Switch = Struct.new(:expr, :cases) do + def encode + res = "switch (#{expr}) {\n" + cases.each do |c| + res << c.encode + end + res << "default: +std::cerr << \"Codegen for \" << compiler::GetOpcodeString(inst->GetOpcode()) << \" failed\"; +enc->success_ = false; +}" + res + end + + def check_width + res = "switch (#{expr}) {\n" + cases.each do |c| + res << c.check_width + end + res << "default: +std::cerr << \"CheckWidth for \" << compiler::GetOpcodeString(inst->GetOpcode()) << \" failed\"; +re->success_ = false; +}" + res + end +end + +Case = Struct.new(:types, :node) do + def proxy(method) + res = types.map { |type| "case #{type}:" }.join("\n") + res << " {\n" + res << node.send(method) + res << "break;\n}\n" + res + end + + def encode + proxy(:encode) + end + + def check_width + proxy(:check_width) + end +end + +Leaf = Struct.new(:instruction, :args) do + def encode + res = "" + args_str = args.join(",\n") + if instruction.acc_read? + res << do_lda(instruction) + res << "\n" + end + res << "enc->result_.emplace_back(pandasm::Create_#{instruction.asm_token}(\n" + res << args_str + res << "\n));\n" + if instruction.acc_write? + res << do_sta(instruction) + res << "\n" + end + res + end + + def check_width + reg = instruction.operands.select(&:reg?).first + if reg + "re->Check#{reg.width}Width(inst);\n" + else + "return;\n" + end + end +end + +Empty = Struct.new(:dummy) do + def encode; end + def check_width; end +end + +# Sugar for bytecode description +def visit(ir_op) + @table ||= [] + @table << Visitor.new(ir_op, yield) +end + +def visitors + @table +end + +def switch(expr, cases) + Switch.new(expr, cases) +end + +def plain(opcode, *args) + Leaf.new(instruction_hash[opcode], args.to_a) +end + +def empty + Empty.new +end + +def prefixed_case(prefix, types, node) + types = types.map { |t| "#{prefix}#{t}" } + Case.new(types, node) +end + +def case_(types, opcode, *args) + prefixed_case("compiler::DataType::", types, plain(opcode, *args)) +end + +def cc_case(types, opcode, *args) + prefixed_case("compiler::CC_", types, plain(opcode, *args)) +end + +def case_switch(types, condition, inner_cases) + prefixed_case("compiler::DataType::", types, switch(condition, inner_cases)) +end + +def case_true(opcode, *args) + Case.new(['1'], plain(opcode, *args)) +end + +def case_false(opcode, *args) + Case.new(['0'], plain(opcode, *args)) +end + +# Type/cc cases for instruction selection +def i32_types + @i32_types ||= %w[BOOL UINT8 INT8 UINT16 INT16 UINT32 INT32] +end + +def i64_types + @i64_types ||= %w[INT64 UINT64] +end + +def f32_types + @f32_types ||= %w[FLOAT32] +end + +def f64_types + @f64_types ||= %w[FLOAT64] +end + +def b64_types + @b64_types ||= i64_types + f64_types +end + +def b32_types + @b32_types ||= i32_types + f32_types +end + +def void_types + @void_types ||= %w[VOID] +end + +def cc_cases + @cc_cases ||= %w[EQ NE LT LE GT GE] +end + +# Switch condition printers +def type + 'inst->GetType()' +end + +def src_type + 'inst->GetInputType(0)' +end + +# we could use switch on 'bool' type for if-else purposes, but that hurts clang_tidy +def if_acc?(reg) + "static_cast(#{reg} == compiler::ACC_REG_ID)" +end + +def if_fcmpg? + 'static_cast(inst->IsFcmpg())' +end + +# Operand printers +def dst_r + 'inst->GetDstReg()' +end + +def r(num) + "inst->GetSrcReg(#{num})" +end + +def imm + 'static_cast(inst->GetImm() & 0xffffffff)' +end + +def label + 'LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())' +end + +def string_id + 'enc->ir_interface_->GetStringIdByOffset(inst->GetTypeId())' +end + +def literalarray_id + 'enc->ir_interface_->GetLiteralArrayIdByOffset(inst->GetTypeId()).value()' +end + +def type_id + 'enc->ir_interface_->GetTypeIdByOffset(inst->GetTypeId())' +end + +def field_id + 'enc->ir_interface_->GetFieldIdByOffset(inst->GetTypeId())' +end + +# Lda/Sta printers +def do_lda(instruction) + lda = case instruction.src_acc_kind + when 32 + instruction_hash['lda'] + when 64 + instruction_hash['lda.64'] + when 'ref' + instruction_hash['lda.obj'] + end + reg_num = if instruction.mnemonic.include?('ldarr') || instruction.mnemonic.include?('stobj') || instruction.mnemonic.include?('ststatic') + 1 + elsif instruction.mnemonic.include?('starr') + 2 + else + 0 + end + "if (inst->GetSrcReg(#{reg_num}) != compiler::ACC_REG_ID) { + enc->result_.emplace_back(pandasm::Create_#{lda.asm_token}(inst->GetSrcReg(#{reg_num}))); + }" +end + +def do_sta(instruction) + sta = case instruction.dst_acc_kind + when 32 + instruction_hash['sta'] + when 64 + instruction_hash['sta.64'] + when 'ref' + instruction_hash['sta.obj'] + end + "if (inst->GetDstReg() != compiler::ACC_REG_ID) { + enc->result_.emplace_back(pandasm::Create_#{sta.asm_token}(inst->GetDstReg())); + }" +end + +# Misc printers +def visitor_sig(op_name, with_class = true) + "void #{'CodeGenDynamic::' if with_class}Visit#{op_name}(GraphVisitor* v, Inst* inst_base)" +end + +# Bytecode description itself + +# Wrap all `insn` declaration in a function to call from template +# (because Panda::instructions is initialized only in templates) +def call_me_from_template + # Empty visitors for IR instructions we want to ignore + # (Add missing IRs on demand) + %w[Phi Try SaveState Parameter].each do |op| + visit(op) do + empty + end + end +end diff --git a/libabckit/src/codegen/templates_dynamic/codegen_visitors_dyn.inc.erb b/libabckit/src/codegen/templates_dynamic/codegen_visitors_dyn.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..9e2b11bcb5dfc6638ed2c0a74e3568e37711474d --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/codegen_visitors_dyn.inc.erb @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% Common::plugins.each do |plugin_lang, plugin_opts| +% next unless plugin_opts["libabckit"] +% next unless plugin_opts["libabckit"]["codegen_visitors_dyn_inc"] +#include "<%= plugin_opts["libasmkit"]["codegen_visitors_dyn_inc"] %>" +% end diff --git a/libabckit/src/codegen/templates_dynamic/generate_ecma.inl.erb b/libabckit/src/codegen/templates_dynamic/generate_ecma.inl.erb new file mode 100644 index 0000000000000000000000000000000000000000..715580c269556e94834aa634074c2ec0b66e7d14 --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/generate_ecma.inl.erb @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +// NOLINTNEXTLINE(readability-function-size) +void libabckit::CodeGenDynamic::VisitEcma(ark::compiler::GraphVisitor *visitor, Inst *inst_base) +{ + ASSERT(inst_base->IsIntrinsic()); + auto inst = inst_base->CastToIntrinsic(); + auto enc = static_cast(visitor); + + switch (inst->GetIntrinsicId()) { +% instructions = Panda::instructions.select{|b| b.namespace == "ecmascript"} +% if instructions.first && instructions.first.intrinsic_name +% instructions = instructions.group_by(&:intrinsic_name) +% else +% instructions = instructions.group_by(&:opcode) +% end +% instructions.each do |intrinsic_name, group| +% inst = group.first +% if !(inst.opcode.upcase.include? "DEPRECATED_") +% next if inst.properties.include?("jump") +% opcode = inst.opcode.upcase +% params_arr = inst.operands +% group.each do |i| +% intr_id = i.opcode.upcase + case compiler::RuntimeInterface::IntrinsicId::DYN_<%= intr_id %>: +% end + { +% if inst.acc.include?("in") + auto acc_src = inst->GetSrcReg(inst->GetInputsCount() - 1); + if (acc_src != compiler::ACC_REG_ID) { + DoLda(acc_src, enc->result_); + } +% end +% params_str = "" +% vreg_index = 0 +% imm_index = 0 +% id_index = 0 +% input_index = 0 +% params_arr.each do |param| +% if param.reg? + auto v<%= vreg_index %> = inst->GetSrcReg(<%= input_index %>); +% params_str = params_str + "v#{vreg_index}, " +% vreg_index = vreg_index + 1 +% input_index = input_index + 1 +% elsif param.id? +% if param.method_id? + ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty) + auto ir_id<%= id_index %> = static_cast(inst->GetImms()[<%= imm_index %>]); + auto bc_id<%= id_index %> = enc->ir_interface_->GetMethodIdByOffset(ir_id<%= id_index %>); +% params_str = params_str + "bc_id#{id_index}, " +% elsif param.string_id? + ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty) + auto ir_id<%= id_index %> = static_cast(inst->GetImms()[<%= imm_index %>]); + auto bc_id<%= id_index %> = enc->ir_interface_->GetStringIdByOffset(ir_id<%= id_index %>); +% params_str = params_str + "bc_id#{id_index}, " +% elsif param.literalarray_id? + ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty) + auto ir_id<%= id_index %> = static_cast(inst->GetImms()[<%= imm_index %>]); + auto bc_id<%= id_index %> = enc->ir_interface_->GetLiteralArrayIdByOffset(ir_id<%= id_index %>); +% params_str = params_str + "bc_id#{id_index}, " +% end +% id_index = id_index + 1 +% imm_index = imm_index + 1 +% elsif param.imm? + ASSERT(inst->HasImms() && inst->GetImms().size() > <%= imm_index %>); // NOLINTNEXTLINE(readability-container-size-empty) +% if inst.properties.include?("jump") +% params_str += "LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId()), " +% else + auto imm<%= imm_index %> = static_cast(inst->GetImms()[<%= imm_index %>]); +% params_str = params_str + "imm#{imm_index}, " +% imm_index = imm_index + 1 +% end +% end +% end +% if params_arr.length > 0 +% params_str = params_str.chop +% params_str = params_str.chop +% end + enc->result_.emplace_back(PandasmWrapper::Create_<%= inst.asm_token %>_Wrapper(<%= params_str %>)); +% if inst.acc.include?("out") + auto acc_dst = inst->GetDstReg(); + if (acc_dst != compiler::ACC_REG_ID) { + DoSta(inst->GetDstReg(), enc->result_); + } +% end + break; + } +% end +% end + default: + enc->success_ = false; + LOG(ERROR,COMPILER) << "Unsupported ecma opcode"; + } +} diff --git a/libabckit/src/codegen/templates_dynamic/ic_info.h.erb b/libabckit/src/codegen/templates_dynamic/ic_info.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..20cd594a69ead86d725cf7c339ab6f4852366c6f --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/ic_info.h.erb @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2023-2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +#ifndef LIBABCKIT_SRC_CODEGEN_IC_FLAGS_GETTER_H +#define LIBABCKIT_SRC_CODEGEN_IC_FLAGS_GETTER_H + +#include + +#include "compiler/optimizer/ir/runtime_interface.h" + +% def hasICSlot(inst) +% if ((inst.properties.include? "ic_slot") || (inst.properties.include? "jit_ic_slot")) +% return true +% end +% return false +% end +% +% def findInvertedInst(inst) +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inverted_inst| +% if (inst.mnemonic == inverted_inst.mnemonic && inst.opcode != inverted_inst.opcode) +% instFormat = inst.format.pretty.upcase.gsub("PREF_", "") +% invertedInstFormat = inverted_inst.format.pretty.upcase.gsub("PREF_", "") +% if ((instFormat.start_with?("IMM8") && invertedInstFormat.start_with?("IMM16")) || +% (instFormat.start_with?("IMM16") && invertedInstFormat.start_with?("IMM8"))) +% return inverted_inst +% end +% end +% end +% return nil +% end + +namespace libabckit { + enum IC_FLAGS : uint8_t { + ONE_SLOT = 1U << 0U, + TWO_SLOT = 1U << 1U, + EIGHT_BIT_IC = 1U << 2U, + SIXTEEN_BIT_IC = 1U << 3U, + EIGHT_SIXTEEN_BIT_IC = 1U << 4U + }; + + uint8_t getICFlags(compiler::RuntimeInterface::IntrinsicId intrinsicId) + { + switch (intrinsicId) + { +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| +% if (!hasICSlot(inst)) +% next +% end +% result_ic_flags_string = "" +% if (inst.properties.include? "one_slot") +% result_ic_flags_string += "IC_FLAGS::ONE_SLOT" +% elsif (inst.properties.include? "two_slot") +% result_ic_flags_string += "IC_FLAGS::TWO_SLOT" +% end +% +% invertedInst = findInvertedInst(inst) +% instFormat = inst.format.pretty.upcase.gsub("PREF_", "") +% if (invertedInst != nil) +% result_ic_flags_string += "|IC_FLAGS::EIGHT_SIXTEEN_BIT_IC" +% elsif (instFormat.start_with?("IMM8")) +% result_ic_flags_string += "|IC_FLAGS::EIGHT_BIT_IC" +% elsif (instFormat.start_with?("IMM16")) +% result_ic_flags_string += "|IC_FLAGS::SIXTEEN_BIT_IC" +% end + case compiler::RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: { + return <%= result_ic_flags_string %>; + } +% end + default: { + return 0; + } + } + } + + compiler::RuntimeInterface::IntrinsicId getIdWithInvertedICImm(compiler::RuntimeInterface::IntrinsicId intrinsicId) + { + assert((getICFlags(intrinsicId) & IC_FLAGS::EIGHT_SIXTEEN_BIT_IC) != 0); + switch (intrinsicId) + { +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| +% if (!hasICSlot(inst)) +% next +% end +% invertedInst = findInvertedInst(inst) +% if (invertedInst == nil) +% next +% end + case compiler::RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: { + return compiler::RuntimeInterface::IntrinsicId::DYN_<%= invertedInst.opcode.upcase %>; + } +% end + default: { + return compiler::RuntimeInterface::IntrinsicId::INVALID; + } + } + } + + bool hasInstWith8Or16BitSignature8BitICSlot(compiler::RuntimeInterface::IntrinsicId intrinsicId) + { + assert((getICFlags(intrinsicId) & IC_FLAGS::EIGHT_SIXTEEN_BIT_IC) != 0); + switch (intrinsicId) + { +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| +% if (!hasICSlot(inst)) +% next +% end +% invertedInst = findInvertedInst(inst) +% if (invertedInst == nil) +% next +% end +% +% if (inst.format.pretty.upcase.start_with?("IMM8")) + case compiler::RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: { + return true; + } +% end +% end + default: { + return false; + } + } + } +} + +#endif //LIBABCKIT_SRC_CODEGEN_IC_FLAGS_GETTER_H \ No newline at end of file diff --git a/libabckit/src/codegen/templates_dynamic/insn_selection_dynamic.cpp.erb b/libabckit/src/codegen/templates_dynamic/insn_selection_dynamic.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..92124276e71c65dcb4c1362b1c04979d335ca149 --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/insn_selection_dynamic.cpp.erb @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% call_me_from_template + +% visitors.each do |visitor| +<%= visitor_sig(visitor.ir_op) %> { + [[maybe_unused]] auto enc = static_cast(v); + [[maybe_unused]] auto inst = inst_base->CastTo<%= visitor.ir_op %>(); +<%= visitor.switch.encode %> +} +% end diff --git a/libabckit/src/codegen/templates_dynamic/insn_selection_dynamic.h.erb b/libabckit/src/codegen/templates_dynamic/insn_selection_dynamic.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..de5e6c55bc71af0394cb06f0a2113396ad65eef0 --- /dev/null +++ b/libabckit/src/codegen/templates_dynamic/insn_selection_dynamic.h.erb @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% call_me_from_template + +% visitors.each do |visitor| +static <%= visitor_sig(visitor.ir_op, false) %>; +% end diff --git a/libabckit/src/ir_impl.cpp b/libabckit/src/ir_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..339d4a12017e5d30e52966c4a00a699924d3178d --- /dev/null +++ b/libabckit/src/ir_impl.cpp @@ -0,0 +1,908 @@ +/** + * Copyright (c) 2024 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 // ??? +#include +#include "libabckit/include/abckit.h" +#include "libabckit/include/ir_core.h" + +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/adapter_static/ir_static.h" + +#include "libabckit/src/macros.h" +#include "libabckit/src/logger.h" + +#include + +namespace libabckit { + +// ======================================== +// Api for Graph manipulation +// ======================================== + +extern "C" abckit_Isa_Type GraphGetIsa(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + switch (ctxG->ctxI->mode) { + case Mode::DYNAMIC: + return abckit_Isa_Type::abckit_Isa_Type_DYNAMIC; + case Mode::STATIC: + return abckit_Isa_Type::abckit_Isa_Type_STATIC; + default: + LIBABCKIT_UNREACHABLE; + } +} + +extern "C" abckit_BasicBlock *GgetStartBasicBlock(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return GgetStartBasicBlockStatic(ctx); +} + +extern "C" abckit_BasicBlock *GgetEndBasicBlock([[maybe_unused]] abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return GgetEndBasicBlockStatic(ctx); +} + +extern "C" uint32_t GgetNumberOfBasicBlocks(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return GgetNumberOfBasicBlocksStatic(ctx); +} + +extern "C" void GvisitBlocksRPO([[maybe_unused]] abckit_Graph *ctx, [[maybe_unused]] void *data, + [[maybe_unused]] void (*cb)(abckit_BasicBlock *bb, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return GvisitBlocksRPOStatic(ctx, data, cb); +} + +extern "C" abckit_BasicBlock *GgetBasicBlock(abckit_Graph *ctx, uint32_t id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return GgetBasicBlockStatic(ctx, id); +} + +extern "C" abckit_Inst *GgetParameter(abckit_Graph *ctx, uint32_t index) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return GgetParameterStatic(ctx, index); +} + +extern "C" void GinsertTryCatch(abckit_BasicBlock *tryFirstBB, abckit_BasicBlock *tryLastBB, + abckit_BasicBlock *catchBeginBB, abckit_BasicBlock *catchEndBB) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(tryFirstBB); + LIBABCKIT_BAD_ARGUMENT_VOID(tryLastBB); + LIBABCKIT_BAD_ARGUMENT_VOID(catchBeginBB); + LIBABCKIT_BAD_ARGUMENT_VOID(catchEndBB); + + GinsertTryCatchStatic(tryFirstBB, tryLastBB, catchBeginBB, catchEndBB); +} + +extern "C" void Gdump(abckit_Graph *ctxG, int fd) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, LIBABCKIT_RETURN_VOID); + + return GdumpStatic(ctxG, fd); +} + +extern "C" void GrunPassRemoveUnreachableBlocks(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, LIBABCKIT_RETURN_VOID); + + GrunPassRemoveUnreachableBlocksStatic(ctx); +} + +// ======================================== +// Api for basic block manipulation +// ======================================== + +extern "C" abckit_BasicBlock *BBcreateEmpty(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBcreateEmptyStatic(ctx); +} + +extern "C" uint32_t BBgetId(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetIdStatic(basicBlock); +} + +extern "C" abckit_Graph *BBgetGraph(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetGraphStatic(basicBlock); +} + +extern "C" uint64_t BBgetPredBlockCount(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetPredBlockCountStatic(basicBlock); +} + +extern "C" abckit_BasicBlock *BBgetPredBlock(abckit_BasicBlock *basicBlock, int32_t index) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetPredBlockStatic(basicBlock, index); +} + +extern "C" void BBsetPredBlock(abckit_BasicBlock *basicBlock, abckit_BasicBlock *predBlock, int32_t index) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + BBsetPredBlockStatic(basicBlock, predBlock, index); +} + +extern "C" void BBsetPredBlocks(abckit_BasicBlock *basicBlock, size_t argCount...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + std::va_list args; + va_start(args, argCount); + BBsetPredBlocksStatic(basicBlock, argCount, args); +} + +extern "C" void BBvisitPredBlocks(abckit_BasicBlock *basicBlock, void *data, + void (*cb)(abckit_BasicBlock *basicBlock, abckit_BasicBlock *predBasicBlock, + void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBvisitPredBlocksStatic(basicBlock, data, cb); +} + +extern "C" uint64_t BBgetSuccBlockCount(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_IMPLEMENTED + LIBABCKIT_CLEAR_LAST_ERROR + + return BBgetSuccBlockCountStatic(basicBlock); +} + +extern "C" abckit_BasicBlock *BBgetSuccBlock(abckit_BasicBlock *basicBlock, int32_t index) +{ + LIBABCKIT_IMPLEMENTED + LIBABCKIT_CLEAR_LAST_ERROR + + return BBgetSuccBlockStatic(basicBlock, index); +} + +extern "C" void BBsetSuccBlock(abckit_BasicBlock *basicBlock, abckit_BasicBlock *succBlock, int32_t index) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + BBsetSuccBlockStatic(basicBlock, succBlock, index); +} + +extern "C" void BBsetSuccBlocks(abckit_BasicBlock *basicBlock, size_t argCount...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + std::va_list args; + va_start(args, argCount); + BBsetSuccBlocksStatic(basicBlock, argCount, args); +} + +extern "C" void BBvisitSuccBlocks(abckit_BasicBlock *basicBlock, void *data, + void (*cb)(abckit_BasicBlock *basicBlock, abckit_BasicBlock *succBasicBlock, + void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return BBvisitSuccBlocksStatic(basicBlock, data, cb); +} + +extern "C" abckit_BasicBlock *BBgetTrueBranch(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetTrueBranchStatic(basicBlock); +} + +extern "C" abckit_BasicBlock *BBgetFalseBranch(abckit_BasicBlock *curBasicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetFalseBranchStatic(curBasicBlock); +} + +extern "C" abckit_BasicBlock *BBsplitBlockAfterInstruction(abckit_Inst *inst, bool makeEdge) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBsplitBlockAfterInstructionStatic(inst, makeEdge); +} + +extern "C" void BBconnectBlocks(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool connectViaTrueEdge) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + BBconnectBlocksStatic(bb1, bb2, connectViaTrueEdge); +} + +extern "C" void BBdisconnectBlocks(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + BBdisconnectBlocksStatic(bb1, bb2); +} + +extern "C" void BBaddInstFront(abckit_BasicBlock *basicBlock, abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + BBaddInstFrontStatic(basicBlock, inst); +} + +extern "C" void BBaddInstBack(abckit_BasicBlock *basicBlock, abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + BBaddInstBackStatic(basicBlock, inst); +} + +extern "C" void BBclear(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return BBclearStatic(basicBlock); +} + +extern "C" abckit_Inst *BBgetFirstInst(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return BBgetFirstInstStatic(basicBlock); +} + +extern "C" abckit_Inst *BBgetLastInst(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return BBgetLastInstStatic(basicBlock); +} + +extern "C" uint32_t BBgetNumberOfInstructions(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetNumberOfInstructionsStatic(basicBlock); +} + +extern "C" abckit_BasicBlock *BBgetImmediateDominator(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBgetImmediateDominatorStatic(basicBlock); +} + +extern "C" bool BBcheckDominance(abckit_BasicBlock *basicBlock, abckit_BasicBlock *dominator) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBcheckDominanceStatic(basicBlock, dominator); +} + +extern "C" void BBvisitDominatedBlocks(abckit_BasicBlock *basicBlock, void *data, + void (*cb)(abckit_BasicBlock *basicBlock, abckit_BasicBlock *dominatedBasicBlock, + void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + BBvisitDominatedBlocksStatic(basicBlock, data, cb); +} + +extern "C" bool BBisStart(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisStartStatic(basicBlock); +} + +extern "C" bool BBisEnd(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisEndStatic(basicBlock); +} + +extern "C" bool BBisLoopHead(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisLoopHeadStatic(basicBlock); +} + +extern "C" bool BBisLoopPrehead(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisLoopPreheadStatic(basicBlock); +} + +extern "C" bool BBisTryBegin(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisTryBeginStatic(basicBlock); +} + +extern "C" bool BBisTry(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisTryStatic(basicBlock); +} + +extern "C" bool BBisTryEnd(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisTryEndStatic(basicBlock); +} + +extern "C" bool BBisCatchBegin(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisCatchBeginStatic(basicBlock); +} + +extern "C" bool BBisCatch(abckit_BasicBlock *basicBlock) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + return BBisCatchStatic(basicBlock); +} + +extern "C" void BBdump(abckit_BasicBlock *basicBlock, int fd) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + BBdumpStatic(basicBlock, fd); +} + +extern "C" abckit_Inst *BBcreatePhi(abckit_BasicBlock *bb, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(bb, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_CHECK_ALLOCATION(BBcreatePhiStatic(bb, argCount, args)); +} + +// ======================================== +// Api for instruction manipulation +// ======================================== + +extern "C" abckit_Inst *GcreateConstantI64(abckit_Graph *ctx, int64_t value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + + return GcreateConstantI64Static(ctx, value); +} + +extern "C" abckit_Inst *GcreateConstantI32(abckit_Graph *ctx, int32_t value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + + return GcreateConstantI32Static(ctx, value); +} + +extern "C" abckit_Inst *GcreateConstantU64(abckit_Graph *ctx, uint64_t value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + + return GcreateConstantU64Static(ctx, value); +} + +extern "C" abckit_Inst *GcreateConstantF64(abckit_Graph *ctx, double value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + + return GcreateConstantF64Static(ctx, value); +} + +extern "C" void Iremove(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + + return IremoveStatic(inst); +} + +extern "C" uint32_t IgetId(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetIdStatic(inst); +} + +extern "C" abckit_Inst *IgetNext(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetNextStatic(inst); +} + +extern "C" abckit_Inst *IgetPrev(abckit_Inst *instprev) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(instprev, nullptr); + + return IgetPrevStatic(instprev); +} + +extern "C" void IinsertAfter(abckit_Inst *inst, abckit_Inst *refInst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return IinsertAfterStatic(inst, refInst); +} + +extern "C" void IinsertBefore(abckit_Inst *inst, abckit_Inst *refInst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + return IinsertBeforeStatic(inst, refInst); +} + +extern "C" abckit_Type *IgetType(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + return IgetTypeStatic(inst); +} + +extern "C" abckit_BasicBlock *IgetBasicBlock(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + return IgetBasicBlockStatic(inst); +} + +extern "C" bool IcheckIsCall(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, false); + return IcheckIsCallStatic(inst); +} + +extern "C" bool IcheckDominance(abckit_Inst *inst, abckit_Inst *dominator) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, false); + LIBABCKIT_BAD_ARGUMENT(dominator, false); + + return IcheckDominanceStatic(inst, dominator); +} + +extern "C" uint32_t IgetUserCount(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetUserCountStatic(inst); +} + +extern "C" void IvisitUsers(abckit_Inst *inst, void *data, void (*cb)(abckit_Inst *inst, abckit_Inst *user, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + IvisitUsersStatic(inst, data, cb); +} + +extern "C" uint32_t IgetInputCount(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetInputCountStatic(inst); +} + +extern "C" abckit_Inst *IgetInput(abckit_Inst *inst, uint32_t index) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetInputStatic(inst, index); +} + +extern "C" void IvisitInputs(abckit_Inst *inst, void *data, + void (*cb)(abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + IvisitInputsStatic(inst, data, cb); +} + +extern "C" void IsetInput(abckit_Inst *inst, abckit_Inst *input, uint32_t index) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(input); + + LIBABCKIT_WRONG_CTX_VOID(inst->ctxG, input->ctxG); + IsetInputStatic(inst, input, index); +} + +extern "C" void IsetInputs(abckit_Inst *inst, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + + std::va_list args; + va_start(args, argCount); + IsetInputsStatic(inst, argCount, args); +} + +extern "C" void IappendInput(abckit_Inst *inst, abckit_Inst *input) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(input); + + LIBABCKIT_WRONG_CTX_VOID(inst->ctxG, input->ctxG); + IappendInputStatic(inst, input); +} + +extern "C" void Idump(abckit_Inst *inst, int fd) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + + IdumpStatic(inst, fd); +} + +extern "C" abckit_Method *IgetMethod(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetMethodStatic(inst); +} + +extern "C" void IsetMethod(abckit_Inst *inst, abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(method); + + LIBABCKIT_BAD_ARGUMENT_VOID(method->m); + LIBABCKIT_BAD_ARGUMENT_VOID(inst->ctxG); + LIBABCKIT_WRONG_CTX_VOID(inst->ctxG->ctxI, method->m->ctxI); + return IsetMethodStatic(inst, method); +} + +extern "C" uint64_t IgetImmediate(abckit_Inst *inst, size_t idx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetImmediateStatic(inst, idx); +} + +extern "C" void IsetImmediate(abckit_Inst *inst, size_t idx, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + + IsetImmediateStatic(inst, idx, imm); +} + +extern "C" uint64_t IgetImmediateCount(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetImmediateCountStatic(inst); +} + +extern "C" abckit_LiteralArray *IgetLiteralArray(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + return IgetLiteralArrayStatic(inst); +} + +extern "C" void IsetLiteralArray(abckit_Inst *inst, abckit_LiteralArray *la) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(la); + + return IsetLiteralArrayStatic(inst, la); +} + +extern "C" abckit_String *IgetString(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetStringStatic(inst); +} + +extern "C" void IsetString(abckit_Inst *inst, abckit_String *str) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(str); + + return IsetStringStatic(inst, str); +} + +extern "C" int64_t IgetConstantValueI64(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetConstantValueI64Static(inst); +} + +extern "C" uint64_t IgetConstantValueU64(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetConstantValueU64Static(inst); +} + +extern "C" double IgetConstantValueF64(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(inst, 0); + + return IgetConstantValueF64Static(inst); +} + +abckit_GraphApi g_GraphApiImpl = { + GraphGetIsa, + + // ======================================== + // Api for Graph manipulation + // ======================================== + + GgetStartBasicBlock, + GgetEndBasicBlock, + GgetNumberOfBasicBlocks, + GvisitBlocksRPO, + GgetBasicBlock, + GgetParameter, + GinsertTryCatch, + Gdump, + GcreateConstantI32, + GcreateConstantI64, + GcreateConstantU64, + GcreateConstantF64, + GrunPassRemoveUnreachableBlocks, + + // ======================================== + // Api for basic block manipulation + // ======================================== + + BBcreateEmpty, + BBgetId, + BBgetGraph, + BBgetPredBlockCount, + BBgetPredBlock, + BBsetPredBlock, + BBsetPredBlocks, + BBvisitPredBlocks, + BBgetSuccBlockCount, + BBgetSuccBlock, + BBsetSuccBlock, + BBsetSuccBlocks, + BBvisitSuccBlocks, + BBgetTrueBranch, + BBgetFalseBranch, + BBsplitBlockAfterInstruction, + BBconnectBlocks, + BBdisconnectBlocks, + BBaddInstFront, + BBaddInstBack, + BBclear, + BBgetFirstInst, + BBgetLastInst, + BBgetNumberOfInstructions, + BBgetImmediateDominator, + BBcheckDominance, + BBvisitDominatedBlocks, + BBisStart, + BBisEnd, + BBisLoopHead, + BBisLoopPrehead, + BBisTryBegin, + BBisTry, + BBisTryEnd, + BBisCatchBegin, + BBisCatch, + BBdump, + BBcreatePhi, + + // ======================================== + // Api for instruction manipulation + // ======================================== + + Iremove, + IgetId, + IgetNext, + IgetPrev, + IinsertAfter, + IinsertBefore, + IgetType, + IgetBasicBlock, + IcheckDominance, + IcheckIsCall, + IgetUserCount, + IvisitUsers, + IgetInputCount, + IgetInput, + IvisitInputs, + IsetInput, + IsetInputs, + IappendInput, + Idump, + IgetMethod, + IsetMethod, + IgetImmediate, + IsetImmediate, + IgetImmediateCount, + IgetLiteralArray, + IsetLiteralArray, + IgetString, + IsetString, + IgetConstantValueI64, + IgetConstantValueU64, + IgetConstantValueF64, +}; + +} // namespace libabckit + +extern "C" abckit_GraphApi const *abckit_GetGraphApiImpl(int version) +{ + if (version != LIBABCKIT_VERSION) { + return nullptr; + } + return &libabckit::g_GraphApiImpl; +} diff --git a/libabckit/src/ir_impl.h b/libabckit/src/ir_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..91f8bcc639d6fbcf059e1da3f394c6275a8a3156 --- /dev/null +++ b/libabckit/src/ir_impl.h @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_IR_IMPL_H +#define LIBABCKIT_SRC_IR_IMPL_H + +#include "libabckit/include/metadata.h" +#include "libabckit/include/ir_core.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace ark::compiler { +class BasicBlock; +class Inst; +class Graph; +} // namespace ark::compiler + +struct abckit_IrInterface { + abckit_IrInterface(std::unordered_map methodsArg, + std::unordered_map fieldsArg, + std::unordered_map classesArg, + std::unordered_map stringsArg, + std::unordered_map literalarraysArg) + : methods(methodsArg), + fields(fieldsArg), + classes(classesArg), + strings(stringsArg), + literalarrays(literalarraysArg) + { + } + + virtual ~abckit_IrInterface() = default; + + std::string GetMethodIdByOffset(uint32_t offset) const; + std::string GetStringIdByOffset(uint32_t offset) const; + std::string GetLiteralArrayIdByOffset(uint32_t offset) const; + std::string GetTypeIdByOffset(uint32_t offset) const; + std::string GetFieldIdByOffset(uint32_t offset) const; + + std::unordered_map methods; + std::unordered_map fields; + std::unordered_map classes; + std::unordered_map strings; + std::unordered_map literalarrays; +}; + +struct abckit_Inst { + abckit_Graph *ctxG; + ark::compiler::Inst *impl; +}; + +struct abckit_BasicBlock { + abckit_Graph *ctxG; + ark::compiler::BasicBlock *impl; +}; + +struct abckit_Graph { + abckit_File *ctxI; + abckit_Method *method; + abckit_IrInterface *irInterface; + std::unordered_map implToBB; + std::unordered_map implToInst; + std::unordered_map ptrToMethod; + std::unordered_map ptrToClass; + ark::compiler::Graph *impl; + void *internal; +}; + +#endif //LIBABCKIT_SRC_IR_IMPL_H diff --git a/libabckit/src/ir_interface_impl.cpp b/libabckit/src/ir_interface_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..01438f0e51a75ab07f9c1161a6f5536876cbcdc4 --- /dev/null +++ b/libabckit/src/ir_interface_impl.cpp @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/ir_impl.h" +#include + +std::string abckit_IrInterface::GetMethodIdByOffset(uint32_t offset) const +{ + auto it = methods.find(offset); + assert(it != methods.cend()); + + return std::string(it->second); +} + +std::string abckit_IrInterface::GetStringIdByOffset(uint32_t offset) const +{ + auto it = strings.find(offset); + assert(it != strings.cend()); + + return std::string(it->second); +} + +std::string abckit_IrInterface::GetLiteralArrayIdByOffset(uint32_t offset) const +{ + auto it = literalarrays.find(offset); + assert(it != literalarrays.cend()); + + return std::string(it->second); +} + +std::string abckit_IrInterface::GetTypeIdByOffset(uint32_t offset) const +{ + auto it = classes.find(offset); + assert(it != classes.cend()); + + return std::string(it->second); +} + +std::string abckit_IrInterface::GetFieldIdByOffset(uint32_t offset) const +{ + auto it = fields.find(offset); + assert(it != fields.cend()); + + return std::string(it->second); +} diff --git a/libabckit/src/irbuilder_dynamic/BUILD.gn b/libabckit/src/irbuilder_dynamic/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..753c3c471ec77d8565252c617d232f1b5bca62ac --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/BUILD.gn @@ -0,0 +1,61 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ohos_source_set("libabckit_ir_builder_dynamic_source_set") { + sources = [ + "ir_builder_dyn.cpp", + "inst_builder_dyn.cpp", + "$target_gen_dir/generated/inst_builder_dyn_gen.cpp" + ] + + cross_values_gen_dir = get_label_info("$ark_root/cross_values:cross_values_getters_generate(${default_toolchain})", + "target_gen_dir") + entrypoints_compiler_gen_dir = get_label_info("$ark_root/runtime:arkruntime_gen_entrypoints_entrypoints_compiler_inl", "target_gen_dir") + intrinsics_gen_dir = get_label_info("$ark_root/../libabckit/src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_enum_inl", "target_gen_dir") + intrinsics_compiler_gen_dir = get_label_info("$ark_root/compiler:libarkcompiler_intrinsics_gen_inl_get_intrinsics_names_inl(${host_toolchain})", "target_gen_dir") + include_dirs = [ + "$target_gen_dir", + "$entrypoints_compiler_gen_dir/generated", + "$intrinsics_gen_dir/../generated", + "$cross_values_gen_dir", + "$ark_root/runtime", + "$intrinsics_compiler_gen_dir", + "$ark_root", # this target should not include headers from dynamic runtime, so static_core must be listed first + "$ark_root/..", + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/:ark_config", + "$ark_root/compiler:arkcompiler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/runtime:profiling_gen_public_config" + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/compiler:libarktscompiler", + "templates:isa_gen_libabckit_inst_builder_dyn_gen_cpp", + "templates:isa_gen_libabckit_bytecode_inst_enum_gen_h", + "templates:isa_gen_libabckit_bytecode_inst-inl_gen_h", + "../templates/bct_intrinsics:ark_gen_libabckit_inst_builder_bct_intrinsics_inc" + ] +} \ No newline at end of file diff --git a/libabckit/src/irbuilder_dynamic/bytecode_inst-inl.h b/libabckit/src/irbuilder_dynamic/bytecode_inst-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..c18ba2d4894ac0a3d9d51a7226a744145de77bc9 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/bytecode_inst-inl.h @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_BYTECODE_INST_INL_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_BYTECODE_INST_INL_H + +#include "libabckit/src/irbuilder_dynamic/bytecode_inst.h" +#include "libabckit/src/macros.h" + +namespace libabckit { + +template +inline auto BytecodeInst::ReadHelper(size_t byteoffset, size_t bytecount, size_t offset, size_t width) const +{ + constexpr size_t BYTE_WIDTH = 8; + + size_t right_shift = offset % BYTE_WIDTH; + + S v = 0; + for (size_t i = 0; i < bytecount; i++) { + S mask = static_cast(ReadByte(byteoffset + i)) << (i * BYTE_WIDTH); + v |= mask; + } + + v >>= right_shift; + size_t left_shift = sizeof(R) * BYTE_WIDTH - width; + + // Do sign extension using arithmetic shift. It's implementation defined + // so we check such behavior using static assert + // NOLINTNEXTLINE(hicpp-signed-bitwise) + static_assert((-1 >> 1) == -1); + + // NOLINTNEXTLINE(hicpp-signed-bitwise) + return static_cast(v << left_shift) >> left_shift; +} + +template +inline auto BytecodeInst::Read() const +{ + constexpr size_t BYTE_WIDTH = 8; + constexpr size_t BYTE_OFFSET = offset / BYTE_WIDTH; + constexpr size_t BYTE_OFFSET_END = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH; + constexpr size_t BYTE_COUNT = BYTE_OFFSET_END - BYTE_OFFSET; + + using storage_type = ark::helpers::TypeHelperT; + using return_type = ark::helpers::TypeHelperT; + + return ReadHelper(BYTE_OFFSET, BYTE_COUNT, offset, width); +} + +template +inline auto BytecodeInst::Read64(size_t offset, size_t width) const +{ + constexpr size_t BIT64 = 64; + constexpr size_t BYTE_WIDTH = 8; + + ASSERT((offset % BYTE_WIDTH) + width <= BIT64); + + size_t byteoffset = offset / BYTE_WIDTH; + size_t byteoffset_end = (offset + width + BYTE_WIDTH - 1) / BYTE_WIDTH; + size_t bytecount = byteoffset_end - byteoffset; + + using storage_type = ark::helpers::TypeHelperT; + using return_type = ark::helpers::TypeHelperT; + + return ReadHelper(byteoffset, bytecount, offset, width); +} + +inline size_t BytecodeInst::GetSize() const +{ + return Size(GetFormat()); +} + +#include + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_BYTECODE_INST_INL_H diff --git a/libabckit/src/irbuilder_dynamic/bytecode_inst.h b/libabckit/src/irbuilder_dynamic/bytecode_inst.h new file mode 100644 index 0000000000000000000000000000000000000000..4c66e36f85379b6bfa3158881d631eff51628a14 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/bytecode_inst.h @@ -0,0 +1,294 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_BYTECODE_INST_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_BYTECODE_INST_H + +#include +#include +#include +#include +#include +#include "libabckit/src/macros.h" + +#include "static_core/libpandabase/utils/bit_helpers.h" +#include "static_core/libpandabase/os/mem.h" +#include "static_core/libpandabase/os/filesystem.h" +#include "static_core/libpandabase/utils/span.h" +#include "static_core/libpandabase/utils/utf.h" + +#include + +namespace libabckit { + +using Index = uint16_t; + +class EntityId { +public: + explicit constexpr EntityId(uint32_t offset) : offset_(offset) {} + + EntityId() = default; + + ~EntityId() = default; + + uint32_t GetOffset() const + { + return offset_; + } + + static constexpr size_t GetSize() + { + return sizeof(uint32_t); + } + + friend bool operator<(const EntityId &l, const EntityId &r) + { + return l.offset_ < r.offset_; + } + + friend bool operator==(const EntityId &l, const EntityId &r) + { + return l.offset_ == r.offset_; + } + + friend std::ostream &operator<<(std::ostream &stream, const EntityId &id) + { + return stream << id.offset_; + } + +private: + uint32_t offset_ {0}; +}; + +class BytecodeId { +public: + constexpr explicit BytecodeId(uint32_t id) : id_(id) {} + + constexpr BytecodeId() = default; + + ~BytecodeId() = default; + + DEFAULT_COPY_SEMANTIC(BytecodeId); + NO_MOVE_SEMANTIC(BytecodeId); + + Index AsIndex() const + { + ASSERT(id_ < std::numeric_limits::max()); + return id_; + } + + EntityId AsFileId() const + { + return EntityId(id_); + } + + uint32_t AsRawValue() const + { + return id_; + } + + bool IsValid() const + { + return id_ != INVALID; + } + + bool operator==(BytecodeId id) const noexcept + { + return id_ == id.id_; + } + + friend std::ostream &operator<<(std::ostream &stream, BytecodeId id) + { + return stream << id.id_; + } + +private: + static constexpr size_t INVALID = std::numeric_limits::max(); + + uint32_t id_ {INVALID}; +}; + +class BytecodeInstBase { +public: + BytecodeInstBase() = default; + explicit BytecodeInstBase(const uint8_t *pc) : pc_ {pc} {} + ~BytecodeInstBase() = default; + +protected: + const uint8_t *GetPointer(int32_t offset) const + { + return pc_ + offset; + } + + const uint8_t *GetAddress() const + { + return pc_; + } + + const uint8_t *GetAddress() volatile const + { + return pc_; + } + + template + T Read(size_t offset) const + { + using unaligned_type __attribute__((aligned(1))) = const T; + return *reinterpret_cast(GetPointer(offset)); + } + + void Write(uint32_t value, uint32_t offset, uint32_t width) + { + auto *dst = const_cast(GetPointer(offset)); + if (memcpy_s(dst, width, &value, width) != 0) { + std::cerr << "Cannot write value : " << value << "at the dst offset : " << offset << std::endl; + } + } + +private: + const uint8_t *pc_ {nullptr}; +}; + +// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions, hicpp-special-member-functions) +class BytecodeInst : public BytecodeInstBase { + using Base = BytecodeInstBase; + +public: +#include + + BytecodeInst() = default; + + ~BytecodeInst() = default; + + explicit BytecodeInst(const uint8_t *pc) : Base {pc} + { + } + + template + BytecodeId GetId() const; + + template + uint16_t GetVReg() const; + + template + auto GetImm() const; + + BytecodeId GetId(size_t idx = 0) const; + + void UpdateId(BytecodeId new_id, uint32_t idx = 0); + + uint16_t GetVReg(size_t idx = 0) const; + + // Read imm and return it as int64_t/uint64_t + auto GetImm64(size_t idx = 0) const; + + BytecodeInst::Opcode GetOpcode() const; + + uint8_t GetPrimaryOpcode() const + { + return ReadByte(0); + } + + bool IsPrimaryOpcodeValid() const; + + uint8_t GetSecondaryOpcode() const; + + bool IsPrefixed() const; + + static constexpr uint8_t GetMinPrefixOpcodeIndex(); + + auto JumpTo(int32_t offset) const + { + return BytecodeInst(Base::GetPointer(offset)); + } + + template + BytecodeInst GetNext() const + { + return JumpTo(Size(format)); + } + + BytecodeInst GetNext() const + { + return JumpTo(GetSize()); + } + + const uint8_t *GetAddress() const + { + return Base::GetAddress(); + } + + const uint8_t *GetAddress() volatile const + { + return Base::GetAddress(); + } + + uint8_t ReadByte(size_t offset) const + { + return Base::template Read(offset); + } + + template + auto ReadHelper(size_t byteoffset, size_t bytecount, size_t offset, size_t width) const; + + template + auto Read() const; + + template + auto Read64(size_t offset, size_t width) const; + + size_t GetSize() const; + + Format GetFormat() const; + + bool HasFlag(Flags flag) const; + + bool IsIdMatchFlag(size_t idx, Flags flag) const; // idx-th id matches flag or not + + bool IsThrow(Exceptions exception) const; + + bool CanThrow() const; + + bool IsTerminator() const + { + return HasFlag(Flags::RETURN) || HasFlag(Flags::JUMP) || IsThrow(Exceptions::X_THROW); + } + + bool IsSuspend() const + { + return HasFlag(Flags::SUSPEND); + } + + static constexpr bool HasId(Format format, size_t idx); + + static constexpr bool HasVReg(Format format, size_t idx); + + static constexpr bool HasImm(Format format, size_t idx); + + static constexpr Format GetFormat(Opcode opcode); + + static constexpr size_t Size(Format format); + + // static constexpr size_t Size(Opcode opcode) + // { + // return Size(GetFormat(opcode)); + // } +}; + +std::ostream &operator<<(std::ostream &os, const BytecodeInst &inst); + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_BYTECODE_INST_H diff --git a/libabckit/src/irbuilder_dynamic/inst_builder_dyn-inl.h b/libabckit/src/irbuilder_dynamic/inst_builder_dyn-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..c6290d7d30f4b02eeba74553d01dbe90ff71393d --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/inst_builder_dyn-inl.h @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_INL_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_INL_H + +#include "libabckit/src/irbuilder_dynamic/inst_builder_dyn.h" + +namespace libabckit { + +template +void InstBuilder::BuildLoadFromPool(const BytecodeInst *bc_inst) +{ + static_assert(opcode == compiler::Opcode::LoadString); + BuildBCTLoadStringIntrinsic(bc_inst); +} + +void InstBuilder::BuildBCTLoadStringIntrinsic(const BytecodeInst *bcInst) +{ + ark::compiler::IntrinsicInst *inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::ANY, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STRING); + uint32_t stringId0 = bcInst->GetId(0).AsIndex(); + stringId0 = GetRuntime()->ResolveMethodIndex(GetGraph()->GetMethod(), stringId0); + inst->AddImm(GetGraph()->GetAllocator(), stringId0); + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); + UpdateDefinitionAcc(inst); +} + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_INL_H diff --git a/libabckit/src/irbuilder_dynamic/inst_builder_dyn.cpp b/libabckit/src/irbuilder_dynamic/inst_builder_dyn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f2aba144bb75795a3643a7a46de242f91054c18d --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/inst_builder_dyn.cpp @@ -0,0 +1,347 @@ +/** + * Copyright (c) 2021-2022 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 "libabckit/src/irbuilder_dynamic/inst_builder_dyn.h" +#include "libabckit/src/irbuilder_dynamic/phi_resolver_dyn.h" + +namespace libabckit { + +void InstBuilder::Prepare() +{ + SetCurrentBlock(GetGraph()->GetStartBlock()); +#ifndef PANDA_TARGET_WINDOWS + GetGraph()->ResetParameterInfo(); +#endif + auto num_args = GetRuntime()->GetMethodTotalArgumentsCount(GetMethod()); + // Create Parameter instructions for all arguments + for (size_t i = 0; i < num_args; i++) { + auto param_inst = GetGraph()->AddNewParameter(i); + auto type = compiler::DataType::Type::ANY; + auto reg_num = GetRuntime()->GetMethodRegistersCount(GetMethod()) + i; + ASSERT(!GetGraph()->IsBytecodeOptimizer() || reg_num != ark::compiler::INVALID_REG); + + param_inst->SetType(type); + SetParamSpillFill(GetGraph(), param_inst, num_args, i, type); + + UpdateDefinition(reg_num, param_inst); + } +} + +void InstBuilder::UpdateDefsForCatch() +{ + compiler::Inst *catch_phi = current_bb_->GetFirstInst(); + ASSERT(catch_phi != nullptr); + for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++) { + ASSERT(catch_phi->IsCatchPhi()); + defs_[current_bb_->GetId()][vreg] = catch_phi; + catch_phi = catch_phi->GetNext(); + } +} + +void InstBuilder::UpdateDefsForLoopHead() +{ + // If current block is a loop header, then propagate all definitions from preheader's predecessors to + // current block. + ASSERT(current_bb_->GetLoop()->GetPreHeader()); + auto pred_defs = defs_[current_bb_->GetLoop()->GetPreHeader()->GetId()]; + std::cerr << "basic block is loop header\n"; + for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++) { + auto def_inst = pred_defs[vreg]; + if (def_inst != nullptr) { + auto phi = GetGraph()->CreateInstPhi(); + phi->SetMarker(GetNoTypeMarker()); + phi->SetLinearNumber(vreg); + current_bb_->AppendPhi(phi); + (*current_defs_)[vreg] = phi; + std::cerr << "create Phi(id=" << phi->GetId() << ") for r" << vreg + << "(def id=" << pred_defs[vreg]->GetId() << ")\n"; + } + } +} + +void InstBuilder::UpdateDefs() +{ + current_bb_->SetMarker(visited_block_marker_); + if (current_bb_->IsCatchBegin()) { + UpdateDefsForCatch(); + } else if (current_bb_->IsLoopHeader() && !current_bb_->GetLoop()->IsIrreducible()) { + UpdateDefsForLoopHead(); + } else if (current_bb_->GetPredsBlocks().size() == 1) { + // Only one predecessor - simply copy all its definitions + auto &pred_defs = defs_[current_bb_->GetPredsBlocks()[0]->GetId()]; + std::copy(pred_defs.begin(), pred_defs.end(), current_defs_->begin()); + } else if (current_bb_->GetPredsBlocks().size() > 1) { + // If there are multiple predecessors, then add phi for each register that has different definitions + for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++) { + compiler::Inst *value = nullptr; + bool different = false; + for (auto pred_bb : current_bb_->GetPredsBlocks()) { + // When irreducible loop header is visited before it's back-edge, phi should be created, + // since we do not know if definitions are different at this point + if (!pred_bb->IsMarked(visited_block_marker_)) { + ASSERT(current_bb_->GetLoop()->IsIrreducible()); + different = true; + break; + } + if (value == nullptr) { + value = defs_[pred_bb->GetId()][vreg]; + } else if (value != defs_[pred_bb->GetId()][vreg]) { + different = true; + break; + } + } + if (different) { + auto phi = GetGraph()->CreateInstPhi(); + phi->SetMarker(GetNoTypeMarker()); + phi->SetLinearNumber(vreg); + current_bb_->AppendPhi(phi); + (*current_defs_)[vreg] = phi; + std::cerr << "create Phi(id=" << phi->GetId() << ") for r" << vreg << std::endl; + } else { + (*current_defs_)[vreg] = value; + } + } + } +} + +void InstBuilder::AddCatchPhiInputs(const ArenaUnorderedSet &catch_handlers, const compiler::InstVector &defs, + compiler::Inst *throwable_inst) +{ + ASSERT(!catch_handlers.empty()); + for (auto catch_bb : catch_handlers) { + auto inst = catch_bb->GetFirstInst(); + while (!inst->IsCatchPhi()) { + inst = inst->GetNext(); + } + ASSERT(inst != nullptr); + GetGraph()->AppendThrowableInst(throwable_inst, catch_bb); + for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++, inst = inst->GetNext()) { + ASSERT(inst->GetOpcode() == ark::compiler::Opcode::CatchPhi); + auto catch_phi = inst->CastToCatchPhi(); + if (catch_phi->IsAcc()) { + ASSERT(vreg == VREGS_AND_ARGS_COUNT); + continue; + } + auto input_inst = defs[vreg]; + if (input_inst != nullptr && input_inst != catch_phi) { + catch_phi->AppendInput(input_inst); + catch_phi->AppendThrowableInst(throwable_inst); + } + } + } +} + +void InstBuilder::SetParamSpillFill(compiler::Graph *graph, compiler::ParameterInst *param_inst, size_t num_args, size_t i, + compiler::DataType::Type type) +{ + if (graph->IsBytecodeOptimizer()) { + auto reg_src = static_cast(compiler::VIRTUAL_FRAME_SIZE - num_args + i); + compiler::DataType::Type reg_type; + if (compiler::DataType::IsReference(type)) { + reg_type = compiler::DataType::REFERENCE; + } else if (compiler::DataType::Is64Bits(type, graph->GetArch())) { + reg_type = compiler::DataType::UINT64; + } else { + reg_type = compiler::DataType::UINT32; + } + + param_inst->SetLocationData({compiler::LocationType::REGISTER, compiler::LocationType::REGISTER, reg_src, reg_src, reg_type}); + } +} + +/** + * Set type of instruction, then recursively set type to its inputs. + */ +void InstBuilder::SetTypeRec(compiler::Inst *inst, compiler::DataType::Type type) +{ + inst->SetType(type); + inst->ResetMarker(GetNoTypeMarker()); + for (auto input : inst->GetInputs()) { + if (input.GetInst()->IsMarked(GetNoTypeMarker())) { + SetTypeRec(input.GetInst(), type); + } + } +} + +/** + * Remove vreg from SaveState for the case + * BB 1 + * .... + * succs: [bb 2, bb 3] + * + * BB 2: preds: [bb 1] + * 89.i64 Sub v85, v88 -> (v119, v90) + * 90.f64 Cast v89 -> (v96, v92) + * succs: [bb 3] + * + * BB 3: preds: [bb 1, bb 2] + * ..... + * 119. SaveState v105(vr0), v106(vr1), v94(vr4), v89(vr8), v0(vr10), v1(vr11) -> (v120) + * + * v89(vr8) used only in BB 2, so we need to remove its from "119. SaveState" + */ +/* static */ +void InstBuilder::RemoveNotDominateInputs(compiler::SaveStateInst *save_state) +{ + size_t idx = 0; + size_t inputs_count = save_state->GetInputsCount(); + while (idx < inputs_count) { + auto input_inst = save_state->GetInput(idx).GetInst(); + // We can don't call IsDominate, if save_state and input_inst in one basic block. + // It's reduce number of IsDominate calls. + if (!input_inst->InSameBlockOrDominate(save_state)) { + save_state->RemoveInput(idx); + inputs_count--; + } else { + ASSERT(input_inst->GetBasicBlock() != save_state->GetBasicBlock() || input_inst->IsDominate(save_state)); + idx++; + } + } +} + +/** + * Fix instructions that can't be fully completed in building process. + */ +void InstBuilder::FixInstructions() +{ + // Remove dead Phi and set types to phi which have not type. + // Phi may not have type if all it users are pseudo instructions, like SaveState + for (auto bb : GetGraph()->GetBlocksRPO()) { + for (auto inst : bb->PhiInstsSafe()) { + inst->ReserveInputs(bb->GetPredsBlocks().size()); + for (auto &pred_bb : bb->GetPredsBlocks()) { + if (inst->GetLinearNumber() == compiler::INVALID_LINEAR_NUM) { + continue; + } + auto pred = defs_[pred_bb->GetId()][inst->GetLinearNumber()]; + if (pred == nullptr) { + // If any input of phi instruction is not defined then we assume that phi is dead. DCE should + // remove it. + continue; + } + inst->AppendInput(pred); + } + } + } + + // Check all instructions that have no type and fix it. Type is got from instructions with known input types. + for (auto bb : GetGraph()->GetBlocksRPO()) { + for (auto inst : bb->AllInsts()) { + if (inst->IsSaveState()) { + RemoveNotDominateInputs(static_cast(inst)); + continue; + } + auto input_idx = 0; + for (auto input : inst->GetInputs()) { + if (input.GetInst()->IsMarked(GetNoTypeMarker())) { + auto input_type = inst->GetInputType(input_idx); + if (input_type != compiler::DataType::NO_TYPE) { + SetTypeRec(input.GetInst(), input_type); + } + } + input_idx++; + } + } + } + // Resolve dead and inconsistent phi instructions + PhiResolver phi_resolver(GetGraph()); + phi_resolver.Run(); + ResolveConstants(); + CleanupCatchPhis(); +} + +compiler::SaveStateInst *InstBuilder::CreateSaveState(compiler::Opcode opc, size_t pc) +{ + ASSERT(opc == ark::compiler::Opcode::SaveState); + compiler::SaveStateInst *inst = GetGraph()->CreateInstSaveState(); + inst->SetPc(pc); + inst->SetMethod(GetMethod()); + inst->ReserveInputs(0); + return inst; +} + +size_t InstBuilder::GetMethodArgumentsCount(uintptr_t id) const +{ + return GetRuntime()->GetMethodArgumentsCount(GetMethod(), id); +} + +size_t InstBuilder::GetPc(const uint8_t *inst_ptr) const +{ + return inst_ptr - instructions_buf_; +} + +void InstBuilder::ResolveConstants() +{ + compiler::ConstantInst *curr_const = GetGraph()->GetFirstConstInst(); + while (curr_const != nullptr) { + SplitConstant(curr_const); + curr_const = curr_const->GetNextConst(); + } +} + +void InstBuilder::SplitConstant(compiler::ConstantInst *const_inst) +{ + if (const_inst->GetType() != compiler::DataType::INT64 || !const_inst->HasUsers()) { + return; + } + auto users = const_inst->GetUsers(); + auto curr_it = users.begin(); + while (curr_it != users.end()) { + auto user = (*curr_it).GetInst(); + compiler::DataType::Type type = user->GetInputType(curr_it->GetIndex()); + ++curr_it; + if (type != compiler::DataType::FLOAT32 && type != compiler::DataType::FLOAT64) { + continue; + } + compiler::ConstantInst *new_const = nullptr; + if (type == compiler::DataType::FLOAT32) { + auto val = bit_cast(static_cast(const_inst->GetIntValue())); + new_const = GetGraph()->FindOrCreateConstant(val); + } else { + auto val = bit_cast(const_inst->GetIntValue()); + new_const = GetGraph()->FindOrCreateConstant(val); + } + user->ReplaceInput(const_inst, new_const); + } +} + +void InstBuilder::CleanupCatchPhis() +{ + for (auto block : GetGraph()->GetBlocksRPO()) { + for (auto inst : block->AllInstsSafe()) { + if (!inst->IsCatchPhi() || inst->GetInputs().Empty()) { + continue; + } + // Remove catch-phis without real users + bool has_ss_users_only = true; + for (const auto &user : inst->GetUsers()) { + if (!user.GetInst()->IsSaveState()) { + has_ss_users_only = false; + break; + } + } + if (has_ss_users_only) { + auto users = inst->GetUsers(); + while (!users.Empty()) { + auto &user = users.Front(); + user.GetInst()->RemoveInput(user.GetIndex()); + } + block->RemoveInst(inst); + } + } + } +} + +} // namespace libabckit diff --git a/libabckit/src/irbuilder_dynamic/inst_builder_dyn.h b/libabckit/src/irbuilder_dynamic/inst_builder_dyn.h new file mode 100644 index 0000000000000000000000000000000000000000..36ca65cce44f2aa41a34ae76f9a74fe4897edc84 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/inst_builder_dyn.h @@ -0,0 +1,309 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_H + +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir/basicblock.h" +#include "static_core/compiler/optimizer/analysis/loop_analyzer.h" + +#include "libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h" +#include "libabckit/src/irbuilder_dynamic/bytecode_inst.h" + +namespace libabckit { + +using namespace ark; + +constexpr int64_t INVALID_OFFSET = std::numeric_limits::max(); + +class InstBuilder { +public: + InstBuilder(compiler::Graph *graph, AbckitRuntimeAdapterDynamic::MethodPtr method) + : graph_(graph), + runtime_(graph->GetRuntime()), + defs_(graph->GetLocalAllocator()->Adapter()), + method_(method), + VREGS_AND_ARGS_COUNT(graph->GetRuntime()->GetMethodRegistersCount(method) + + graph->GetRuntime()->GetMethodTotalArgumentsCount(method)), + instructions_buf_(GetGraph()->GetRuntime()->GetMethodCode(GetGraph()->GetMethod())), + class_id_ {runtime_->GetClassIdForMethod(method_)} + { + no_type_marker_ = GetGraph()->NewMarker(); + visited_block_marker_ = GetGraph()->NewMarker(); + + defs_.resize(graph_->GetVectorBlocks().size(), compiler::InstVector(graph->GetLocalAllocator()->Adapter())); + for (auto &v : defs_) { + v.resize(VREGS_AND_ARGS_COUNT + 1); + } + + for (auto bb : graph->GetBlocksRPO()) { + if (bb->IsCatchBegin()) { + for (size_t vreg = 0; vreg < GetVRegsCount(); vreg++) { + auto catch_phi = GetGraph()->CreateInstCatchPhi(); + catch_phi->SetPc(bb->GetGuestPc()); + catch_phi->SetMarker(GetNoTypeMarker()); + bb->AppendInst(catch_phi); + if (vreg == VREGS_AND_ARGS_COUNT) { + catch_phi->SetIsAcc(); + } + } + } + } + } + + NO_COPY_SEMANTIC(InstBuilder); + NO_MOVE_SEMANTIC(InstBuilder); + ~InstBuilder() + { + GetGraph()->EraseMarker(no_type_marker_); + GetGraph()->EraseMarker(visited_block_marker_); + } + + /** + * Content of this function is auto generated from inst_builder.erb and is located in inst_builder_gen.cpp file + * @param instruction Pointer to bytecode instruction + */ + void BuildInstruction(const BytecodeInst *instruction); + + bool IsFailed() const + { + return failed_; + } + + /** + * Return jump offset for instruction `inst`, 0 if it is not jump instruction. + */ + static int64_t GetInstructionJumpOffset(const BytecodeInst *inst); + + void SetCurrentBlock(compiler::BasicBlock *bb) + { + current_bb_ = bb; + current_defs_ = &defs_[bb->GetId()]; + } + + void Prepare(); + + void FixInstructions(); + void ResolveConstants(); + void SplitConstant(compiler::ConstantInst *const_inst); + void CleanupCatchPhis(); + + static void RemoveNotDominateInputs(compiler::SaveStateInst *save_state); + + size_t GetPc(const uint8_t *inst_ptr) const; + + void UpdateDefs(); + + const auto &GetCurrentDefs() + { + ASSERT(current_defs_ != nullptr); + return *current_defs_; + } + + void AddCatchPhiInputs(const ArenaUnorderedSet &catch_handlers, const compiler::InstVector &defs, + compiler::Inst *throwable_inst); + + compiler::SaveStateInst *CreateSaveState(compiler::Opcode opc, size_t pc); + + static void SetParamSpillFill(compiler::Graph *graph, compiler::ParameterInst *param_inst, size_t num_args, size_t i, + compiler::DataType::Type type); + + // void TryFillInstIdTypePair(size_t id, int32_t pc) + // { + // ASSERT(GetGraph()->IsBytecodeOptimizer()); + // ASSERT(GetGraph()->IsDynamicMethod()); + // GetGraph()->GetRuntime()->FillInstIdTypePairByPc(id, pc); + // } +private: + void UpdateDefsForCatch(); + void UpdateDefsForLoopHead(); + + size_t GetVRegsCount() const + { + return VREGS_AND_ARGS_COUNT + 1; + } + + void AddInstruction(compiler::Inst *inst) + { + ASSERT(current_bb_); + current_bb_->AppendInst(inst); + LIBABCKIT_LOG(DEBUG) << *inst << std::endl; + } + + void UpdateDefinition(size_t vreg, compiler::Inst *inst) + { + ASSERT(vreg < current_defs_->size()); + // LIBABCKIT_LOG(DEBUG) << "update def for r" << vreg << " from " + // << ((*current_defs_)[vreg] != nullptr + // ? std::to_string((*current_defs_)[vreg]->GetId()) + // : "null") + // << " to " << inst->GetId() << std::endl; + (*current_defs_)[vreg] = inst; + } + + void UpdateDefinitionAcc(compiler::Inst *inst) + { + #if 0 + if (inst == nullptr) { + LIBABCKIT_LOG(DEBUG) << "reset accumulator definition\n"; + } else { + LIBABCKIT_LOG(DEBUG) << "update accumulator from " + << ((*current_defs_)[VREGS_AND_ARGS_COUNT] != nullptr + ? std::to_string((*current_defs_)[VREGS_AND_ARGS_COUNT]->GetId()) + : "null") + << " to " << inst->GetId() <<"\n"; + } + #endif + (*current_defs_)[VREGS_AND_ARGS_COUNT] = inst; + } + + compiler::Inst *GetDefinition(size_t vreg) + { + ASSERT(vreg < current_defs_->size()); + ASSERT((*current_defs_)[vreg] != nullptr); + + if (vreg >= current_defs_->size() || (*current_defs_)[vreg] == nullptr) { + failed_ = true; + LIBABCKIT_LOG(DEBUG) << "GetDefinition failed for verg " << vreg << std::endl; + return nullptr; + } + return (*current_defs_)[vreg]; + } + + compiler::Inst *GetDefinitionAcc() + { + auto *acc_inst = (*current_defs_)[VREGS_AND_ARGS_COUNT]; + ASSERT(acc_inst != nullptr); + + if (acc_inst == nullptr) { + failed_ = true; + LIBABCKIT_LOG(DEBUG) << "GetDefinitionAcc failed\n"; + } + return acc_inst; + } + + auto FindOrCreate32BitConstant(uint32_t value) + { + auto inst = GetGraph()->FindOrCreateConstant(value); + if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) { + LIBABCKIT_LOG(DEBUG) << "create new constant: value=" << value << ", inst=" << inst->GetId() << std::endl; + } + return inst; + } + + auto FindOrCreateConstant(uint64_t value) + { + auto inst = GetGraph()->FindOrCreateConstant(value); + if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) { + LIBABCKIT_LOG(DEBUG) << "create new constant: value=" << value << ", inst=" << inst->GetId() << std::endl; + } + return inst; + } + + auto FindOrCreateDoubleConstant(double value) + { + auto inst = GetGraph()->FindOrCreateConstant(value); + if (inst->GetId() == GetGraph()->GetCurrentInstructionId() - 1) { + LIBABCKIT_LOG(DEBUG) << "create new constant: value=" << value << ", inst=" << inst->GetId() << std::endl; + } + return inst; + } + + void BuildEcma([[maybe_unused]] const BytecodeInst *bc_inst); + template + void BuildEcmaAsIntrinsics([[maybe_unused]] const BytecodeInst *bc_inst); + void BuildBCTLoadStringIntrinsic(const BytecodeInst *bcInst); + + template + void BuildLoadFromPool(const BytecodeInst *bc_inst); + + compiler::Graph *GetGraph() + { + return graph_; + } + + const compiler::Graph *GetGraph() const + { + return graph_; + } + + const compiler::RuntimeInterface *GetRuntime() const + { + return runtime_; + } + + compiler::RuntimeInterface *GetRuntime() + { + return runtime_; + } + + auto GetMethod() const + { + return method_; + } + + auto GetClassId() const + { + return class_id_; + } + + compiler::Marker GetNoTypeMarker() const + { + return no_type_marker_; + } + + compiler::Marker GetVisitedBlockMarker() const + { + return visited_block_marker_; + } + + void SetTypeRec(compiler::Inst *inst, compiler::DataType::Type type); + + size_t GetMethodArgumentsCount(uintptr_t id) const; + +private: + static constexpr size_t INPUT_2 = 2; + static constexpr size_t INPUT_3 = 3; + static constexpr size_t TWO_INPUTS = 2; + + compiler::Graph *graph_ {nullptr}; + compiler::RuntimeInterface *runtime_ {nullptr}; + compiler::BasicBlock *current_bb_ {nullptr}; + + // Definitions vector of currently processed basic block + compiler::InstVector *current_defs_ {nullptr}; + // Contains definitions of the virtual registers in all basic blocks + ArenaVector defs_; + + AbckitRuntimeAdapterDynamic::MethodPtr method_ {nullptr}; + // Set to true if builder failed to build IR + bool failed_ {false}; + // Number of virtual registers and method arguments + const size_t VREGS_AND_ARGS_COUNT; + // Marker for instructions with undefined type in the building phase + compiler::Marker no_type_marker_; + compiler::Marker visited_block_marker_; + + // Pointer to start position of bytecode instructions buffer + const uint8_t *instructions_buf_ {nullptr}; + + size_t class_id_; +#include "intrinsics_ir_build.inl.h" +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_INST_BUILDER_H diff --git a/libabckit/src/irbuilder_dynamic/ir_builder_dyn.cpp b/libabckit/src/irbuilder_dynamic/ir_builder_dyn.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb98ad1a38bef6c7480ee70b836e67d80c57eebc --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/ir_builder_dyn.cpp @@ -0,0 +1,530 @@ +/** + * Copyright (c) 2021-2022 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 +#include "bytecode_inst.h" +#include "static_core/compiler/optimizer/analysis/dominators_tree.h" +#include "static_core/compiler/optimizer/analysis/loop_analyzer.h" +#include "libabckit/src/irbuilder_dynamic/ir_builder_dyn.h" + +namespace libabckit { + +bool IrBuilderDynamic::RunImpl() +{ + // std::cerr << "Start building ir for method: " + // << GetGraph()->GetRuntime()->GetClassNameFromMethod(GetMethod()) << "." + // << GetGraph()->GetRuntime()->GetMethodName(GetMethod()) + // << "(args=" << GetGraph()->GetRuntime()->GetMethodTotalArgumentsCount(GetMethod()) + // << ", regs=" << GetGraph()->GetRuntime()->GetMethodRegistersCount(GetMethod()) + // << ")\n"; + + auto instructions_buf = GetGraph()->GetRuntime()->GetMethodCode(GetMethod()); + BytecodeInstructions pbc_instructions(instructions_buf, GetGraph()->GetRuntime()->GetMethodCodeSize(GetMethod())); + size_t vregs_count = GetGraph()->GetRuntime()->GetMethodRegistersCount(GetMethod()) + + GetGraph()->GetRuntime()->GetMethodTotalArgumentsCount(GetMethod()) + 1; + if (!CheckMethodLimitations(pbc_instructions, vregs_count)) { + return false; + } + GetGraph()->SetVRegsCount(vregs_count); + BuildBasicBlocks(pbc_instructions); + GetGraph()->RunPass(); + GetGraph()->RunPass(); + + InstBuilder inst_builder(GetGraph(), GetMethod()); + inst_builder.Prepare(); + inst_defs_.resize(vregs_count); + + // std::cerr << "Start instructions building...\n"; + for (auto bb : GetGraph()->GetBlocksRPO()) { + + if (!BuildBasicBlock(bb, &inst_builder, instructions_buf)) { + return false; + } + } + + GetGraph()->RunPass(); + GetGraph()->InvalidateAnalysis(); + GetGraph()->RunPass(); + inst_builder.FixInstructions(); + // if (compiler::options.IsCompilerPrintStats() || compiler::options.WasSetCompilerDumpStatsCsv()) { + // uint64_t pbc_inst_num = 0; + // for ([[maybe_unused]] auto i : pbc_instructions) { + // pbc_inst_num++; + // } + // GetGraph()->GetPassManager()->GetStatistics()->AddPbcInstNum(pbc_inst_num); + // } + // std::cerr << "IR successfully built: " << GetGraph()->GetVectorBlocks().size() + // << " basic blocks, " << GetGraph()->GetCurrentInstructionId() << " instructions\n"; + return true; +} + +bool IrBuilderDynamic::CheckMethodLimitations(const BytecodeInstructions &instructions, size_t vregs_count) +{ + // TODO(a.popov) Optimize catch-phi's memory consumption and get rid of this limitation + // static constexpr auto TRY_BLOCKS_LIMIT = 128U; + + // size_t bytecode_size_limit = options.GetCompilerMaxBytecodeSize(); + + // The option CompilerInlineFullIntrinsics increases the size of the code several times. + // So the limit for this option is reduced + // if (options.IsCompilerInlineFullIntrinsics()) { + // ASSERT(GetGraph()->IsDynamicMethod()); + // bytecode_size_limit >>= 2U; + // } + + // if (instructions.GetSize() > bytecode_size_limit) { + // std::cerr << "Method is too big: size=" << instructions.GetSize() + // << ", limit=" << bytecode_size_limit << std::endl; + // return false; + // } + // if (vregs_count >= options.GetCompilerMaxVregsNum()) { + // std::cerr << "Method has too many virtual registers: " << vregs_count + // << ", limit=" << options.GetCompilerMaxVregsNum() << std::endl; + // return false; + // } + + // auto abc_file = static_cast(GetGraph()->GetRuntime()->GetBinaryFileForMethod(GetMethod())); + // panda_file::MethodDataAccessor mda(*abc_file, + // panda_file::File::EntityId(GetGraph()->GetRuntime()->GetMethodId(GetMethod()))); + // panda_file::CodeDataAccessor cda(*abc_file, mda.GetCodeId().value()); + // if (cda.GetTriesSize() > TRY_BLOCKS_LIMIT) { + // COMPILER_LOG(INFO, IR_BUILDER) << "Method has too many try blocks: " << cda.GetTriesSize() + // << ", limit=" << TRY_BLOCKS_LIMIT; + // return false; + // } + return true; +} + +bool IrBuilderDynamic::BuildBasicBlock(compiler::BasicBlock *bb, InstBuilder *inst_builder, const uint8_t *instructions_buf) +{ + + inst_builder->SetCurrentBlock(bb); + inst_builder->UpdateDefs(); + ASSERT(bb->GetGuestPc() != ark::compiler::INVALID_PC); + // If block is not in the `blocks_` vector, it's auxiliary block without instructions + if (bb == blocks_[bb->GetGuestPc()]) { + return BuildInstructionsForBB(bb, inst_builder, instructions_buf); + } + // std::cerr << "Auxiliary block, skipping\n"; + + return true; +} + +bool IrBuilderDynamic::BuildInstructionsForBB(compiler::BasicBlock *bb, InstBuilder *inst_builder, const uint8_t *instructions_buf) +{ + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + BytecodeInstructions instructions(instructions_buf + bb->GetGuestPc(), std::numeric_limits::max()); + for (auto inst : instructions) { + auto pc = inst_builder->GetPc(inst.GetAddress()); + // Break if current pc is pc of some basic block, that means that it is the end of the current block. + if (pc != bb->GetGuestPc() && GetBlockForPc(pc) != nullptr) { + break; + } + // Copy current defs for assigning them to catch-phi if current inst is throwable + ASSERT(inst_builder->GetCurrentDefs().size() == inst_defs_.size()); + std::copy(inst_builder->GetCurrentDefs().begin(), inst_builder->GetCurrentDefs().end(), inst_defs_.begin()); + auto current_last_inst = bb->GetLastInst(); + auto bb_count = GetGraph()->GetVectorBlocks().size(); + inst_builder->BuildInstruction(&inst); + + if (inst_builder->IsFailed()) { + std::cerr << "Unsupported instruction\n"; + return false; + } + + // One PBC instruction can be expanded to the group of IR's instructions, find first built instruction in + // this group, and then mark all instructions as throwable; All instructions should be marked, since some of + // them can be deleted during optimizations, unnecessary catch-phi moves will be resolved before Register + // Allocator + auto throwable_inst = (current_last_inst == nullptr) ? bb->GetFirstInst() : current_last_inst->GetNext(); + ProcessThrowableInstructions(inst_builder, throwable_inst); + + auto &vb = GetGraph()->GetVectorBlocks(); + for (size_t i = bb_count; i < vb.size(); i++) { + ProcessThrowableInstructions(inst_builder, vb[i]->GetFirstInst()); + } + + // Break if we meet terminator instruction. If instruction in the middle of basic block we don't create + // further dead instructions. + if (inst.IsTerminator() && !inst.IsSuspend()) { + break; + } + } + return true; + +} + +void IrBuilderDynamic::ProcessThrowableInstructions(InstBuilder *inst_builder, compiler::Inst *throwable_inst) +{ + for (; throwable_inst != nullptr; throwable_inst = throwable_inst->GetNext()) { + if (throwable_inst->IsSaveState()) { + continue; + } + // std::cerr << "Throwable inst, Id = " << throwable_inst->GetId() << std::endl; + catch_handlers_.clear(); + EnumerateTryBlocksCoveredPc(throwable_inst->GetPc(), [this](const TryCodeBlock &try_block) { + auto tbb = try_block.begin_bb; + tbb->EnumerateCatchHandlers([this](compiler::BasicBlock *catch_handler, [[maybe_unused]] size_t type_id) { + catch_handlers_.insert(catch_handler); + return true; + }); + }); + if (!catch_handlers_.empty()) { + inst_builder->AddCatchPhiInputs(catch_handlers_, inst_defs_, throwable_inst); + } + } +} + +static inline bool InstNotJump(BytecodeInst *inst) +{ + return inst->GetAddress() != nullptr && InstBuilder::GetInstructionJumpOffset(inst) == INVALID_OFFSET && + !inst->HasFlag(BytecodeInst::RETURN); +} + +void IrBuilderDynamic::BuildBasicBlocks(const BytecodeInstructions &instructions) +{ + blocks_.resize(instructions.GetSize() + 1); + bool fallthrough = false; + + CreateBlock(0); + // Create basic blocks + for (auto inst : instructions) { + auto pc = instructions.GetPc(inst); + + if (fallthrough) { + CreateBlock(pc); + fallthrough = false; + } + auto offset = InstBuilder::GetInstructionJumpOffset(&inst); + if (offset != INVALID_OFFSET) { + auto target_pc = pc + static_cast(offset); + CreateBlock(target_pc); + if (inst.HasFlag(BytecodeInst::CONDITIONAL)) { + fallthrough = true; + } + } + } + CreateTryCatchBoundariesBlocks(); + GetGraph()->CreateStartBlock(); + GetGraph()->CreateEndBlock(instructions.GetSize()); + ConnectBasicBlocks(instructions); + ResolveTryCatchBlocks(); + // std::cerr << "Created " << GetGraph()->GetVectorBlocks().size() << " basic blocks\n"; +} + +template +void IrBuilderDynamic::EnumerateTryBlocksCoveredPc(uint32_t pc, const Callback &callback) +{ + for (const auto &[begin_pc, try_block] : try_blocks_) { + if (begin_pc <= pc && pc < try_block.boundaries.end_pc) { + callback(try_block); + } + } +} + +/** + * Return `TryCodeBlock` and flag if was created a new one + */ +IrBuilderDynamic::TryCodeBlock *IrBuilderDynamic::InsertTryBlockInfo(const Boundaries &try_boundaries) +{ + auto try_id = static_cast(try_blocks_.size()); + auto range = try_blocks_.equal_range(try_boundaries.begin_pc); + for (auto iter = range.first; iter != range.second; ++iter) { + // use try-block with the same boundaries + if (try_boundaries.end_pc == iter->second.boundaries.end_pc) { + return &iter->second; + } + // insert in the increasing `end_pc` order + if (try_boundaries.end_pc > iter->second.boundaries.end_pc) { + auto it = try_blocks_.emplace_hint(iter, try_boundaries.begin_pc, TryCodeBlock {try_boundaries}); + it->second.Init(GetGraph(), try_id); + return &it->second; + } + } + auto it = try_blocks_.emplace(try_boundaries.begin_pc, TryCodeBlock {try_boundaries}); + it->second.Init(GetGraph(), try_id); + return &it->second; +} + +void IrBuilderDynamic::CreateTryCatchBoundariesBlocks() +{ + auto *pfw = static_cast(GetGraph()->GetRuntime()->GetBinaryFileForMethod(GetMethod())); + pfw->EnumerateTryBlocks(GetMethod(), [pfw, this](void *try_block){ + auto [start, end] = pfw->GetTryBlockBoundaries(try_block); + auto *try_info = InsertTryBlockInfo({start, end}); + pfw->EnumerateCatchBlocksForTryBlock(try_block, [pfw, this, try_info](void *catch_block){ + auto pc = pfw->GetCatchBlockHandlerPc(catch_block); + catches_pc_.insert(pc); + try_info->catches->emplace_back(CatchCodeBlock {pc, 0u}); + }); + }); + + for (const auto &[pc, try_block] : try_blocks_) { + CreateBlock(pc); + CreateBlock(try_block.boundaries.end_pc); + } + for (auto pc : catches_pc_) { + CreateBlock(pc); + } +} + +struct BlocksConnectorInfo { + bool fallthrough {}; + bool dead_instructions {}; + BytecodeInst prev_inst {nullptr}; +}; + +void IrBuilderDynamic::ConnectBasicBlocks(const BytecodeInstructions &instructions) +{ + BlocksConnectorInfo info; + compiler::BasicBlock *curr_bb = blocks_[0]; + GetGraph()->GetStartBlock()->AddSucc(curr_bb); + for (auto inst : instructions) { + auto pc = instructions.GetPc(inst); + auto target_block = blocks_[pc]; + TrackTryBoundaries(pc); + if (info.fallthrough) { + ASSERT(target_block != nullptr); + // May be the second edge between same blocks + curr_bb->AddSucc(target_block, true); + info.fallthrough = false; + curr_bb = target_block; + } else if (target_block != nullptr) { + if (catches_pc_.count(pc) == 0) { + if (InstNotJump(&info.prev_inst) && !info.dead_instructions) { + curr_bb->AddSucc(target_block); + } + } + curr_bb = target_block; + info.dead_instructions = false; + } else if (info.dead_instructions) { + // We are processing dead instructions now, skipping them until we meet the next block. + continue; + } + if (auto jmp_target_block = GetBlockToJump(&inst, pc); jmp_target_block != nullptr) { + curr_bb->AddSucc(jmp_target_block); + // In case of unconditional branch, we reset curr_bb, so if next instruction won't start new block, then + // we'll skip further dead instructions. + info.fallthrough = inst.HasFlag(BytecodeInst::CONDITIONAL); + if (!info.fallthrough) { + info.dead_instructions = true; + } + } + info.prev_inst = inst; + } + + // Erase end block if it wasn't connected, should be infinite loop in the graph + if (GetGraph()->GetEndBlock()->GetPredsBlocks().empty()) { + GetGraph()->EraseBlock(GetGraph()->GetEndBlock()); + GetGraph()->SetEndBlock(nullptr); + // std::cerr << "Builded graph without end block\n"; + } +} + +void IrBuilderDynamic::TrackTryBoundaries(size_t pc) +{ + opened_try_blocks_.remove_if([pc](TryCodeBlock *try_block) { return try_block->boundaries.end_pc == pc; }); + + if (try_blocks_.count(pc) > 0) { + auto range = try_blocks_.equal_range(pc); + for (auto it = range.first; it != range.second; ++it) { + auto &try_block = it->second; + if (try_block.boundaries.end_pc > pc) { + opened_try_blocks_.push_back(&try_block); + auto allocator = GetGraph()->GetLocalAllocator(); + try_block.basic_blocks = allocator->New>(allocator->Adapter()); + } else { + // Empty try-block + ASSERT(try_block.boundaries.end_pc == pc); + } + } + } + + if (opened_try_blocks_.empty()) { + return; + } + + if (auto bb = blocks_[pc]; bb != nullptr) { + for (auto try_block : opened_try_blocks_) { + try_block->basic_blocks->push_back(bb); + } + } + + for (auto &try_block : opened_try_blocks_) { + try_block->contains_throwable_inst = true; + } +} + +compiler::BasicBlock *IrBuilderDynamic::GetBlockToJump(BytecodeInst *inst, size_t pc) +{ + if ((inst->HasFlag(BytecodeInst::RETURN) && !inst->HasFlag(BytecodeInst::SUSPEND)) || + inst->IsThrow(BytecodeInst::Exceptions::X_THROW)) { + return GetGraph()->GetEndBlock(); + } + +#ifdef ENABLE_BYTECODE_OPT + if (inst->GetOpcode() == BytecodeInst::Opcode::RETURNUNDEFINED) { + return GetGraph()->GetEndBlock(); + } +#endif + + if (auto offset = InstBuilder::GetInstructionJumpOffset(inst); offset != INVALID_OFFSET) { + ASSERT(blocks_[pc + static_cast(offset)] != nullptr); + return blocks_[pc + static_cast(offset)]; + } + return nullptr; +} + +/** + * Mark blocks which were connected to the graph. + * Catch-handlers will not be marked, since they have not been connected yet. + */ +static void MarkNormalControlFlow(compiler::BasicBlock *block, compiler::Marker marker) +{ + block->SetMarker(marker); + for (auto succ : block->GetSuccsBlocks()) { + if (!succ->IsMarked(marker)) { + MarkNormalControlFlow(succ, marker); + } + } +} + +void IrBuilderDynamic::MarkTryCatchBlocks(compiler::Marker marker) +{ + // All blocks without `normal` mark are considered as catch-blocks + for (auto bb : GetGraph()->GetBlocksRPO()) { + if (bb->IsMarked(marker)) { + continue; + } + if (bb->IsTryBegin()) { + bb->SetCatch(bb->GetSuccessor(0)->IsCatch()); + } else if (bb->IsTryEnd()) { + bb->SetCatch(bb->GetPredecessor(0)->IsCatch()); + } else { + bb->SetCatch(true); + } + } + + // Nested try-blocks can be removed, but referring to them basic blocks can be placed in the external try-blocks. + // So `try` marks are added after removing unreachable blocks + for (auto it : try_blocks_) { + const auto &try_block = it.second; + if (try_block.begin_bb->GetGraph() != try_block.end_bb->GetGraph()) { + RestoreTryEnd(try_block); + } + try_block.begin_bb->SetTryId(try_block.id); + try_block.end_bb->SetTryId(try_block.id); + if (try_block.basic_blocks == nullptr) { + continue; + } + for (auto bb : *try_block.basic_blocks) { + bb->SetTryId(try_block.id); + bb->SetTry(true); + } + } +} + +/* + * Connect catch-blocks to the graph. + */ +void IrBuilderDynamic::ResolveTryCatchBlocks() +{ + auto marker_holder = compiler::MarkerHolder(GetGraph()); + auto marker = marker_holder.GetMarker(); + MarkNormalControlFlow(GetGraph()->GetStartBlock(), marker); + ConnectTryCatchBlocks(); + GetGraph()->RemoveUnreachableBlocks(); + MarkTryCatchBlocks(marker); +} + +void IrBuilderDynamic::ConnectTryCatchBlocks() +{ + ArenaMap catch_blocks(GetGraph()->GetLocalAllocator()->Adapter()); + // Firstly create catch_begin blocks, as they should precede try_begin blocks + for (auto pc : catches_pc_) { + auto catch_begin = GetGraph()->CreateEmptyBlock(); + catch_begin->SetGuestPc(pc); + catch_begin->SetCatch(true); + catch_begin->SetCatchBegin(true); + auto first_catch_bb = GetBlockForPc(pc); + catch_begin->AddSucc(first_catch_bb); + catch_blocks.emplace(pc, catch_begin); + } + + // Connect try_begin and catch_begin blocks + for (auto it : try_blocks_) { + const auto &try_block = it.second; + if (try_block.contains_throwable_inst) { + ConnectTryCodeBlock(try_block, catch_blocks); + } else if (try_block.basic_blocks != nullptr) { + try_block.basic_blocks->clear(); + } + } +} + +void IrBuilderDynamic::ConnectTryCodeBlock(const TryCodeBlock &try_block, const ArenaMap &catch_blocks) +{ + auto try_begin = try_block.begin_bb; + ASSERT(try_begin != nullptr); + auto try_end = try_block.end_bb; + ASSERT(try_end != nullptr); + // Create auxiliary `Try` instruction + auto try_inst = GetGraph()->CreateInstTry(); + try_inst->SetTryEndBlock(try_end); + try_begin->AppendInst(try_inst); + // Insert `try_begin` and `try_end` + auto first_try_bb = GetBlockForPc(try_block.boundaries.begin_pc); + auto last_try_bb = GetPrevBlockForPc(try_block.boundaries.end_pc); + first_try_bb->InsertBlockBefore(try_begin); + last_try_bb->InsertBlockBeforeSucc(try_end, last_try_bb->GetSuccessor(0)); + // Connect catch-handlers + for (auto catch_block : *try_block.catches) { + auto catch_begin = catch_blocks.at(catch_block.pc); + if (!try_begin->HasSucc(catch_begin)) { + try_begin->AddSucc(catch_begin, true); + try_end->AddSucc(catch_begin, true); + } + try_inst->AppendCatchTypeId(catch_block.type_id, try_begin->GetSuccBlockIndex(catch_begin)); + } +} + +/** + * `try_end` restoring is required in the following case: + * try { + * try { a++;} + * catch { a++; } + * } + * + * Nested try doesn't contain throwable instructions and related catch-handler will not be connected to the graph. + * As a result all `catch` basic blocks will be eliminated together with outer's `try_end`, since it was inserted just + * after `catch` + */ +void IrBuilderDynamic::RestoreTryEnd(const TryCodeBlock &try_block) +{ + ASSERT(try_block.end_bb->GetGraph() == nullptr); + ASSERT(try_block.end_bb->GetSuccsBlocks().empty()); + ASSERT(try_block.end_bb->GetPredsBlocks().empty()); + + GetGraph()->RestoreBlock(try_block.end_bb); + auto last_try_bb = GetPrevBlockForPc(try_block.boundaries.end_pc); + last_try_bb->InsertBlockBeforeSucc(try_block.end_bb, last_try_bb->GetSuccessor(0)); + for (auto succ : try_block.begin_bb->GetSuccsBlocks()) { + if (succ->IsCatchBegin()) { + try_block.end_bb->AddSucc(succ); + } + } +} + +} // namespace libabckit diff --git a/libabckit/src/irbuilder_dynamic/ir_builder_dyn.h b/libabckit/src/irbuilder_dynamic/ir_builder_dyn.h new file mode 100644 index 0000000000000000000000000000000000000000..4202c45e2501603cda049d4c4a207db01ad374e0 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/ir_builder_dyn.h @@ -0,0 +1,155 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_IR_BUILDER_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_IR_BUILDER_H + +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/ir/basicblock.h" +#include "static_core/compiler/optimizer/pass.h" +#include "libabckit/src/irbuilder_dynamic/pbc_iterator_dyn.h" +#include "libabckit/src/irbuilder_dynamic/inst_builder_dyn.h" + + +namespace libabckit { + +using namespace ark; + +class Method; + +/** + * Build IR from JS bytecode + */ +class IrBuilderDynamic : public compiler::Optimization { + struct Boundaries { + uint32_t begin_pc; + uint32_t end_pc; + }; + + struct CatchCodeBlock { + uint32_t pc {}; + uint32_t type_id {}; + }; + + struct TryCodeBlock { + Boundaries boundaries {}; // NOLINT(misc-non-private-member-variables-in-classes) + compiler::BasicBlock *begin_bb {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes) + compiler::BasicBlock *end_bb {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes) + ArenaVector *catches {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes) + ArenaVector *basic_blocks {nullptr}; // NOLINT(misc-non-private-member-variables-in-classes) + uint32_t id {compiler::INVALID_ID}; // NOLINT(misc-non-private-member-variables-in-classes) + bool contains_throwable_inst {false}; // NOLINT(misc-non-private-member-variables-in-classes) + + void Init(compiler::Graph *graph, uint32_t try_id) + { + id = try_id; + auto allocator = graph->GetLocalAllocator(); + catches = allocator->New>(allocator->Adapter()); + begin_bb = graph->CreateEmptyBlock(boundaries.begin_pc); + begin_bb->SetTryBegin(true); + end_bb = graph->CreateEmptyBlock(boundaries.end_pc); + end_bb->SetTryEnd(true); + // Order of try-blocks should be saved in the graph to restore it in the generated bytecode + graph->AppendTryBeginBlock(begin_bb); + } + }; + +public: + explicit IrBuilderDynamic(compiler::Graph *graph) : IrBuilderDynamic(graph, graph->GetMethod()) {} + + IrBuilderDynamic(compiler::Graph *graph, AbckitRuntimeAdapterDynamic::MethodPtr method) + : Optimization(graph), + blocks_(graph->GetLocalAllocator()->Adapter()), + catches_pc_(graph->GetLocalAllocator()->Adapter()), + try_blocks_(graph->GetLocalAllocator()->Adapter()), + opened_try_blocks_(graph->GetLocalAllocator()->Adapter()), + catch_handlers_(graph->GetLocalAllocator()->Adapter()), + inst_defs_(graph->GetLocalAllocator()->Adapter()), + method_(method) + { + } + + NO_COPY_SEMANTIC(IrBuilderDynamic); + NO_MOVE_SEMANTIC(IrBuilderDynamic); + ~IrBuilderDynamic() override = default; + + bool RunImpl() override; + + const char *GetPassName() const override + { + return "IrBuilderDynamic"; + } + + auto GetMethod() const + { + return method_; + } + +private: + void CreateBlock(size_t pc) + { + if (blocks_[pc] == nullptr) { + blocks_[pc] = GetGraph()->CreateEmptyBlock(); + blocks_[pc]->SetGuestPc(pc); + } + } + + compiler::BasicBlock *GetBlockForPc(size_t pc) + { + return blocks_[pc]; + } + + compiler::BasicBlock *GetPrevBlockForPc(size_t pc) + { + do { + ASSERT(pc > 0); + pc--; + } while (blocks_[pc] == nullptr || blocks_[pc]->GetGraph() == nullptr); + return blocks_[pc]; + } + + bool CheckMethodLimitations(const BytecodeInstructions &instructions, size_t vregs_count); + void BuildBasicBlocks(const BytecodeInstructions &instructions); + bool BuildBasicBlock(compiler::BasicBlock *bb, InstBuilder *inst_builder, const uint8_t *instructions_buf); + bool BuildInstructionsForBB(compiler::BasicBlock *bb, InstBuilder *inst_builder, const uint8_t *instructions_buf); + void SplitConstant(compiler::ConstantInst *const_inst); + void ConnectBasicBlocks(const BytecodeInstructions &instructions); + void CreateTryCatchBoundariesBlocks(); + void ResolveTryCatchBlocks(); + void ConnectTryCatchBlocks(); + IrBuilderDynamic::TryCodeBlock *InsertTryBlockInfo(const Boundaries &try_boundaries); + void TrackTryBoundaries(size_t pc); + compiler::BasicBlock *GetBlockToJump(BytecodeInst *inst, size_t pc); + compiler::BasicBlock *GetBlockForSaveStateDeoptimize(compiler::BasicBlock *block); + void MarkTryCatchBlocks(compiler::Marker marker); + template + void EnumerateTryBlocksCoveredPc(uint32_t pc, const Callback &callback); + void ConnectTryCodeBlock(const TryCodeBlock &try_block, const ArenaMap &catch_blocks); + void ProcessThrowableInstructions(InstBuilder *inst_builder, compiler::Inst *throwable_inst); + void RestoreTryEnd(const TryCodeBlock &try_block); + +private: + ArenaVector blocks_; + ArenaSet catches_pc_; + ArenaMultiMap try_blocks_; + ArenaList opened_try_blocks_; + ArenaUnorderedSet catch_handlers_; + compiler::InstVector inst_defs_; + AbckitRuntimeAdapterDynamic::MethodPtr method_ = nullptr; +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_IR_BUILDER_H diff --git a/libabckit/src/irbuilder_dynamic/pbc_iterator_dyn.h b/libabckit/src/irbuilder_dynamic/pbc_iterator_dyn.h new file mode 100644 index 0000000000000000000000000000000000000000..63de49b42e42ed99e6dbadfe27b0c103f77f9212 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/pbc_iterator_dyn.h @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_PBC_ITERATOR_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_PBC_ITERATOR_H + +#include "libabckit/src/irbuilder_dynamic/bytecode_inst.h" +#include "libabckit/src/irbuilder_dynamic/bytecode_inst-inl.h" + +namespace libabckit { + +using namespace ark; + +struct BytecodeIterator { + explicit BytecodeIterator(BytecodeInst inst) : inst_(inst) {} + explicit BytecodeIterator(const uint8_t *data) : inst_(data) {} + + BytecodeIterator &operator++() + { + inst_ = inst_.GetNext(); + return *this; + } + + BytecodeInst operator*() + { + return inst_; + } + bool operator!=(const BytecodeIterator &rhs) + { + return inst_.GetAddress() != rhs.inst_.GetAddress(); + } + +private: + BytecodeInst inst_; +}; + +struct BytecodeInstructions { + BytecodeInstructions(const uint8_t *data, size_t size) : data_(data), size_(size) {} + + // NOLINTNEXTLINE(readability-identifier-naming) + BytecodeIterator begin() const + { + return BytecodeIterator(data_); + } + // NOLINTNEXTLINE(readability-identifier-naming) + BytecodeIterator end() const + { + return BytecodeIterator(data_ + size_); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) + } + + size_t GetPc(const BytecodeInst INST) const + { + return INST.GetAddress() - data_; + } + size_t GetSize() const + { + return size_; + } + +private: + const uint8_t *data_; + size_t size_; +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_PBC_ITERATOR_H diff --git a/libabckit/src/irbuilder_dynamic/phi_resolver_dyn.h b/libabckit/src/irbuilder_dynamic/phi_resolver_dyn.h new file mode 100644 index 0000000000000000000000000000000000000000..bb11bd1fd8a86c40dc91c79e90742aecc41698e6 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/phi_resolver_dyn.h @@ -0,0 +1,221 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +#ifndef LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_PHI_RESOLVER_H +#define LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_PHI_RESOLVER_H + +#include "libabckit/src/irbuilder_dynamic/inst_builder_dyn.h" + +namespace libabckit { +/** + * Resolve phi instructions in the given graph. Resolving phi is: + * - remove phi if it has only SafePoint in users + * - if phi has no type, then set type determined from its inputs + */ +class PhiResolver { +public: + explicit PhiResolver(compiler::Graph *graph) + : graph_(graph), + real_inputs_(graph->GetLocalAllocator()->Adapter()), + phi_users_(graph->GetLocalAllocator()->Adapter()), + real_users_(graph->GetLocalAllocator()->Adapter()) + { + } + + NO_MOVE_SEMANTIC(PhiResolver); + NO_COPY_SEMANTIC(PhiResolver); + ~PhiResolver() = default; + + void Run() + { + for (auto bb : graph_->GetBlocksRPO()) { + for (auto inst : bb->AllInstsSafe()) { + if (!inst->IsPhi() && inst->GetOpcode() != compiler::Opcode::CatchPhi) { + continue; + } + if (inst->HasType() || (!inst->GetUsers().Empty() && CheckPhiInputs(inst))) { + continue; + } + CleanUp(); + inst->SetMarker(marker_); + FindUsersRec(inst); + if (has_save_state_inst_only_) { + // Remove virtual registers of SafePoint instructions which input phis to be removed. + for (auto user : real_users_) { + ASSERT(user->IsSaveState()); + auto save_state = static_cast(user); + size_t idx = 0; + size_t inputs_count = save_state->GetInputsCount(); + while (idx < inputs_count) { + auto input_inst = save_state->GetInput(idx).GetInst(); + if (input_inst->IsMarked(marker_)) { + save_state->RemoveInput(idx); + inputs_count--; + } else { + idx++; + } + } + } + // Phi has only SafePoint in users, we can remove this phi and all phi in collected list. + inst->RemoveUsers(); + inst->GetBasicBlock()->RemoveInst(inst); + for (auto phi : phi_users_) { + phi->RemoveUsers(); + phi->GetBasicBlock()->RemoveInst(phi); + } + } else { + SetTypeByInputs(inst); + ASSERT(inst->HasType() || (inst->IsCatchPhi() && !inst->CastToCatchPhi()->IsAcc())); + } + graph_->EraseMarker(marker_); + } + } + } + +private: + void CleanUp() + { + phi_users_.clear(); + real_users_.clear(); + has_save_state_inst_only_ = true; + marker_ = graph_->NewMarker(); + } + static void SetTypeByInputs(compiler::Inst *inst) + { + if (inst->IsCatchPhi() && inst->CastToCatchPhi()->IsAcc()) { + inst->SetType(compiler::DataType::REFERENCE); + return; + } + for (auto input : inst->GetInputs()) { + auto input_type = input.GetInst()->GetType(); + if (input_type != compiler::DataType::NO_TYPE) { + inst->SetType(input_type); + break; + } + } + } + void FindUsersRec(compiler::Inst *inst) + { + for (auto &user : inst->GetUsers()) { + if (user.GetInst()->SetMarker(marker_)) { + continue; + } + if (user.GetInst()->IsPhi() || user.GetInst()->GetOpcode() == compiler::Opcode::CatchPhi) { + phi_users_.push_back(user.GetInst()); + FindUsersRec(user.GetInst()); + } else { + if (!user.GetInst()->IsSaveState()) { + has_save_state_inst_only_ = false; + break; + } + real_users_.push_back(user.GetInst()); + } + } + } + + void FindInputsRec(compiler::Inst *inst) + { + ASSERT(inst->IsPhi() || inst->GetOpcode() == compiler::Opcode::CatchPhi); + // We can't set real type if there aren't inputs from Phi/CathPhi + // We add the Phi/CathPhi in the list and return false from CheckPhiInputs + if (inst->GetInputs().Empty()) { + real_inputs_.push_back(inst); + return; + } + for (auto &input : inst->GetInputs()) { + auto input_inst = input.GetInst(); + if (input_inst->SetMarker(marker_)) { + continue; + } + if (input_inst->IsPhi() || input_inst->GetOpcode() == compiler::Opcode::CatchPhi) { + if (input_inst->GetType() != compiler::DataType::NO_TYPE) { + real_inputs_.push_back(input_inst); + continue; + } + FindInputsRec(input_inst); + } else { + real_inputs_.push_back(input_inst); + } + } + } + // Returns false if block with input instruction doesn't dominate the predecessor of the PHI block + bool CheckPhiInputs(compiler::Inst *phi_inst) + { + ASSERT(phi_inst->GetOpcode() == compiler::Opcode::Phi || phi_inst->GetOpcode() == compiler::Opcode::CatchPhi); + if (phi_inst->GetOpcode() == compiler::Opcode::Phi) { + if (phi_inst->GetInputsCount() != phi_inst->GetBasicBlock()->GetPredsBlocks().size()) { + return false; + } + for (size_t index = 0; index < phi_inst->GetInputsCount(); ++index) { + auto pred = phi_inst->GetBasicBlock()->GetPredBlockByIndex(index); + auto input_bb = phi_inst->GetInput(index).GetInst()->GetBasicBlock(); + if (!input_bb->IsDominate(pred)) { + return false; + } + } + } + compiler::DataType::Type type = compiler::DataType::NO_TYPE; + real_inputs_.clear(); + marker_ = graph_->NewMarker(); + phi_inst->SetMarker(marker_); + FindInputsRec(phi_inst); + graph_->EraseMarker(marker_); + + bool has_constant_input = false; + for (auto input_inst : real_inputs_) { + auto input_type = input_inst->GetType(); + if (input_type == compiler::DataType::NO_TYPE) { + return false; + } + if (input_inst->IsConst() && input_type == compiler::DataType::INT64) { + if (type != compiler::DataType::NO_TYPE && compiler::DataType::GetCommonType(type) != compiler::DataType::INT64) { + return false; + } + has_constant_input = true; + continue; + } + if (type == compiler::DataType::NO_TYPE) { + if (has_constant_input && compiler::DataType::GetCommonType(input_type) != compiler::DataType::INT64) { + return false; + } + type = input_type; + } else if (type != input_type) { + return false; + } + } + + if (type == compiler::DataType::NO_TYPE) { + // Do not remove phi with constants-only inputs. + if (!has_constant_input) { + return false; + } + type = compiler::DataType::INT64; + } + phi_inst->SetType(type); + return true; + } + +private: + compiler::Graph *graph_ {nullptr}; + compiler::InstVector real_inputs_; + compiler::InstVector phi_users_; + compiler::InstVector real_users_; + compiler::Marker marker_ {compiler::UNDEF_MARKER}; + bool has_save_state_inst_only_ {true}; +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_IR_BUILDER_DYNAMIC_PHI_RESOLVER_H diff --git a/libabckit/src/irbuilder_dynamic/templates/BUILD.gn b/libabckit/src/irbuilder_dynamic/templates/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..55a4ac6e98acc69a04841fd8bdbd73f25c4b5c27 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/templates/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ark_isa_gen("isa_gen_libabckit") { + template_files = [ "inst_builder_dyn_gen.cpp.erb" ] + sources = "." + destination = "$target_gen_dir/../generated" +} + +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "bytecode_inst_enum_gen.h.erb", + "bytecode_inst-inl_gen.h.erb" + ] + sources = "." + destination = "$target_gen_dir/../generated" + requires = [ "$ark_root/libpandafile/pandafile_isapi.rb" ] +} \ No newline at end of file diff --git a/libabckit/src/irbuilder_dynamic/templates/bytecode_inst-inl_gen.h.erb b/libabckit/src/irbuilder_dynamic/templates/bytecode_inst-inl_gen.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..7795977f75e51d42951e2ddd9c974ff17e1a54e8 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/templates/bytecode_inst-inl_gen.h.erb @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +/* static */ +constexpr bool BytecodeInst::HasId(Format format, size_t idx) { + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:id?) +% next if n == 0 + case Format::<%= fmt.pretty.upcase %>: + return idx < <%= n %>; +% end + default: { + return false; + } + } + + UNREACHABLE_CONSTEXPR(); +} + +/* static */ +constexpr bool BytecodeInst::HasVReg(Format format, size_t idx) { + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:reg?) +% next if n == 0 + case Format::<%= fmt.pretty.upcase %>: + return idx < <%= n %>; // NOLINT(readability-magic-numbers) +% end + default: { + return false; + } + } + + UNREACHABLE_CONSTEXPR(); +} + +/* static */ +constexpr bool BytecodeInst::HasImm(Format format, size_t idx) { + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:imm?) +% next if n == 0 + case Format::<%= fmt.pretty.upcase %>: + return idx < <%= n %>; +% end + default: { + return false; + } + } + + UNREACHABLE_CONSTEXPR(); +} + +/* static */ +constexpr size_t BytecodeInst::Size(Format format) { // NOLINTNEXTLINE(readability-function-size) + switch (format) { +% Panda::formats.each do |fmt| + case Format::<%= fmt.pretty.upcase %>: { + constexpr size_t SIZE = <%= fmt.size %>; + return SIZE; + } +% end + } + + UNREACHABLE_CONSTEXPR(); +} + +template +inline BytecodeId BytecodeInst::GetId() const { + static_assert(HasId(format, idx), "Instruction doesn't have id operand with such index"); + +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:id?) +% next if n == 0 +% +% id_ops = i.operands.select(&:id?) +% offsets = id_ops.map(&:offset) +% widths = id_ops.map(&:width) +% + // Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 + // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) + if (format == Format::<%= fmt.pretty.upcase %>) { +% if offsets.length == 1 && widths.length == 1 + return BytecodeId(static_cast(Read<<%= offsets[0] %>, <%= widths[0] %>>())); +% else + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + return BytecodeId(static_cast(Read())); +% end + } + +% end + UNREACHABLE(); +} + +inline void BytecodeInst::UpdateId(BytecodeId new_id, uint32_t idx /* = 0 */) { + Format format = GetFormat(); + ASSERT_PRINT(HasId(format, idx), "Instruction doesn't have imm operand with such index"); + + if (!HasId(format, idx)) { + return; + } + +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:id?) +% next if n == 0 +% +% id_ops = i.operands.select(&:id?) +% offsets = id_ops.map(&:offset) +% widths = id_ops.map(&:width) +% + // Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 + // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) + if (format == Format::<%= fmt.pretty.upcase %>) { + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + this->Write(new_id.AsRawValue(), OFFSETS[idx] / 8, WIDTHS[idx] / 8); + return; + } + +% end + UNREACHABLE(); +} + +inline BytecodeId BytecodeInst::GetId(size_t idx /* = 0 */) const { + Format format = GetFormat(); + ASSERT_PRINT(HasId(format, idx), "Instruction doesn't have id operand with such index"); + + if (!HasId(format, idx)) { + return {}; + } + + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:id?) +% next if n == 0 +% +% id_ops = i.operands.select(&:id?) +% offsets = id_ops.map(&:offset) +% widths = id_ops.map(&:width) +% + case Format::<%= fmt.pretty.upcase %>: { + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + return BytecodeId(static_cast(Read64(OFFSETS[idx], WIDTHS[idx]))); + } +% end + default: { + break; + } + } + + UNREACHABLE(); +} + +template +__attribute__ ((visibility("hidden"))) +ALWAYS_INLINE inline uint16_t BytecodeInst::GetVReg() const { // NOLINTNEXTLINE(readability-function-size) + static_assert(HasVReg(format, idx), "Instruction doesn't have vreg operand with such index"); + +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:reg?) +% next if n == 0 +% +% reg_ops = i.operands.select(&:reg?) +% offsets = reg_ops.map(&:offset) +% widths = reg_ops.map(&:width) +% + // Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 + // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) + if constexpr (format == Format::<%= fmt.pretty.upcase %>) { + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + return static_cast(Read()); + } + +% end + UNREACHABLE(); +} + +__attribute__ ((visibility("hidden"))) +ALWAYS_INLINE inline uint16_t BytecodeInst::GetVReg(size_t idx /* = 0 */) const { // NOLINTNEXTLINE(readability-function-size) + Format format = GetFormat(); + ASSERT_PRINT(HasVReg(format, idx), "Instruction doesn't have vreg operand with such index"); + + if (!HasVReg(format, idx)) { + return 0; + } + + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:reg?) +% next if n == 0 +% +% reg_ops = i.operands.select(&:reg?) +% offsets = reg_ops.map(&:offset) +% widths = reg_ops.map(&:width) +% + case Format::<%= fmt.pretty.upcase %>: { + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + if (idx > <%= n - 1 %>) { + break; + } + return static_cast(Read64(OFFSETS[idx], WIDTHS[idx])); + } +% end + default: { + break; + } + } + + UNREACHABLE(); +} + +template +inline auto BytecodeInst::GetImm() const { // NOLINTNEXTLINE(readability-function-size) + static_assert(HasImm(format, idx), "Instruction doesn't have imm operand with such index"); + +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:imm?) +% next if n == 0 +% +% imm_ops = i.operands.select(&:imm?) +% offsets = imm_ops.map(&:offset) +% widths = imm_ops.map(&:width) +% + // Disable check due to clang-tidy bug https://bugs.llvm.org/show_bug.cgi?id=32203 + // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) + if constexpr (format == Format::<%= fmt.pretty.upcase %>) { + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + return Read(); + } + +% end + UNREACHABLE(); +} + +inline auto BytecodeInst::GetImm64(size_t idx /* = 0 */) const { + Format format = GetFormat(); + ASSERT_PRINT(HasImm(format, idx), "Instruction doesn't have imm operand with such index"); + + if (!HasImm(format, idx)) { + return static_cast(0); + } + + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% fmt = i.format +% n = i.operands.count(&:imm?) +% next if n == 0 +% +% imm_ops = i.operands.select(&:imm?) +% offsets = imm_ops.map(&:offset) +% widths = imm_ops.map(&:width) +% + case Format::<%= fmt.pretty.upcase %>: { + constexpr std::array> OFFSETS{<%= offsets.join(", ") %>}; + constexpr std::array> WIDTHS{<%= widths.join(", ") %>}; + return Read64(OFFSETS[idx], WIDTHS[idx]); + } +% end + default: { + break; + } + } + + UNREACHABLE(); +} + +inline BytecodeInst::Opcode BytecodeInst::GetOpcode() const { + uint8_t primary = GetPrimaryOpcode(); + if (primary >= <%= Panda::prefixes.map(&:opcode_idx).min %>) { // NOLINT(readability-magic-numbers) + uint8_t secondary = GetSecondaryOpcode(); + return static_cast((secondary << 8U) | primary); // NOLINT(hicpp-signed-bitwise) + } + return static_cast(primary); +} + +inline uint8_t BytecodeInst::GetSecondaryOpcode() const { + ASSERT(GetPrimaryOpcode() >= <%= Panda::prefixes.map(&:opcode_idx).min %>); // NOLINT(readability-magic-numbers) + return ReadByte(1); +} + +/* static */ +constexpr uint8_t BytecodeInst::GetMinPrefixOpcodeIndex() { + return <%= Panda::prefixes.map(&:opcode_idx).min %>; // NOLINT(readability-magic-numbers) +} + +inline bool BytecodeInst::IsPrefixed() const { + return GetPrimaryOpcode() >= <%= Panda::prefixes.map(&:opcode_idx).min %>; // NOLINT(readability-magic-numbers) +} + +inline BytecodeInst::Format BytecodeInst::GetFormat() const { // NOLINT(readability-function-size) + return GetFormat(GetOpcode()); +} + +/* static */ +constexpr BytecodeInst::Format BytecodeInst::GetFormat(Opcode opcode) { // NOLINT(readability-function-size) + switch(opcode) { +% Panda::instructions.each do |i| +% if !(i.opcode.upcase.include? "DEPRECATED_") + case BytecodeInst::Opcode::<%= i.opcode.upcase %>: + return BytecodeInst::Format::<%= i.format.pretty.upcase %>; +% end +% end + default: + break; + } + + UNREACHABLE(); +} + +// NOLINTNEXTLINE(readability-function-size) +inline bool BytecodeInst::HasFlag(Flags flag) const { + switch(GetOpcode()) { +% Panda::instructions.each do |i| +% if !(i.opcode.upcase.include? "DEPRECATED_") +% flag_array = i.real_properties.map {|prop| "Flags::" + prop.upcase} +% flag_array += ['0'] if flag_array.empty? +% flags = flag_array.join(' | ') + case BytecodeInst::Opcode::<%= i.opcode.upcase %>: + return ((<%= flags %>) & flag) == flag; // NOLINT(hicpp-signed-bitwise) +% end +% end + default: + return false; + } + + UNREACHABLE(); +} + +// NOLINTNEXTLINE(readability-function-size) +inline bool BytecodeInst::IsIdMatchFlag(size_t idx, Flags flag) const { + switch(GetOpcode()) { +% Panda::instructions.each do |i| +% if !(i.opcode.upcase.include? "DEPRECATED_") +% flag_array = i.real_properties.map {|prop| prop.upcase} +% flag_array = [] if flag_array.empty? +% ids = [] +% flag_array.each do |f| +% if f == "STRING_ID" || f == "METHOD_ID" || f == "LITERALARRAY_ID" +% ids << "Flags::" + f +% end +% end + case BytecodeInst::Opcode::<%= i.opcode.upcase %>: { +% if ids.empty? + return false; + } +% else + constexpr std::array> ids_array { <%= ids.join(', ') %> }; + return ids_array[idx] == flag; + } +% end +% end +% end + default: + return false; + } +} + +// NOLINTNEXTLINE(readability-function-size) +inline bool BytecodeInst::IsThrow(Exceptions exception) const { + switch(GetOpcode()) { +% Panda::instructions.each do |i| +% if !(i.opcode.upcase.include? "DEPRECATED_") +% exception_array = i.exceptions.map {|prop| "Exceptions::" + prop.upcase} +% exception_array += ['0'] if exception_array.empty? +% exceptions = exception_array.join(' | ') + case BytecodeInst::Opcode::<%= i.opcode.upcase %>: + return ((<%= exceptions %>) & exception) == exception; // NOLINT(hicpp-signed-bitwise) +% end +% end + default: + return false; + } + + UNREACHABLE(); +} + +// NOLINTNEXTLINE(readability-function-size) +inline bool BytecodeInst::CanThrow() const { + switch(GetOpcode()) { +% Panda::instructions.each do |i| +% if !(i.opcode.upcase.include? "DEPRECATED_") + case BytecodeInst::Opcode::<%= i.opcode.upcase %>: + return <%= i.exceptions != ["x_none"] %>; +% end +% end + default: + return false; + } + + UNREACHABLE(); +} + +inline bool BytecodeInst::IsPrimaryOpcodeValid() const +{ + auto opcode = GetPrimaryOpcode(); + // NOLINTNEXTLINE(readability-magic-numbers) + if (((opcode >= <%= Panda::dispatch_table.invalid_non_prefixed_interval.min %>) && + // NOLINTNEXTLINE(readability-magic-numbers) + (opcode <= <%= Panda::dispatch_table.invalid_non_prefixed_interval.max %>)) || + // NOLINTNEXTLINE(readability-magic-numbers) + ((opcode >= <%= Panda::dispatch_table.invalid_prefixes_interval.min %>) && + // NOLINTNEXTLINE(readability-magic-numbers) + (opcode <= <%= Panda::dispatch_table.invalid_prefixes_interval.max %>))) { + // NOLINTNEXTLINE(readability-simplify-boolean-expr) + return false; + } + return true; +} diff --git a/libabckit/src/irbuilder_dynamic/templates/bytecode_inst_enum_gen.h.erb b/libabckit/src/irbuilder_dynamic/templates/bytecode_inst_enum_gen.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..afcaf4ee9b778cae73f2b1f19d391aecdf5648fc --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/templates/bytecode_inst_enum_gen.h.erb @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +enum class Format : uint8_t { +% Panda::formats.each do |fmt| + <%= fmt.pretty.upcase %>, +% end +}; + +enum class Opcode { +% last_name = "" +% Panda::instructions.each do |i| +% if !(i.opcode.upcase.include? "DEPRECATED_") + <%= i.opcode.upcase %> = <%= i.opcode_idx %>, +% last_name = i.opcode.upcase +% end +% end + LAST = <%= last_name %> +}; + +enum Flags : uint32_t { +% Panda::properties.each_with_index do |f, i| + <%= f.tag.upcase %> = <%= format("0x%x", 1 << i) %>, +% end +}; + +enum Exceptions : uint32_t { +% Panda::exceptions.each_with_index do |f, i| + <%= f.tag.upcase %> = <%= format("0x%x", 1 << i) %>, +% end +}; diff --git a/libabckit/src/irbuilder_dynamic/templates/inst_builder_dyn_gen.cpp.erb b/libabckit/src/irbuilder_dynamic/templates/inst_builder_dyn_gen.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..92d924f14eae38de5da1ac0de0d1a2da3959baa5 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/templates/inst_builder_dyn_gen.cpp.erb @@ -0,0 +1,374 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +<% +require 'yaml' + +Instruction.class_eval do + def get_input_idx(index, kind) + res = 0 + index += 1 if has_dst? + acc_and_operands.each_with_index do |op, i| + break if i == index + res += 1 if op.send(kind) + end + res + end + + def inputs + @inputs ||= acc_and_operands.select { |x| !x.dst? } + end + + def has_dst? + !acc_and_operands.empty? && acc_and_operands.first.dst? + end + + def get_input_string(index) + op = inputs[index] + return "GetDefinitionAcc()" if op.acc? + return "FindOrCreateConstant(instruction->GetImm<#{get_format}, #{get_input_idx(index, :imm?)}>())" if op.imm? + return "GetDefinition(instruction->GetId<#{get_format}, #{get_input_idx(index, :id?)}>().GetOffset())" if op.id? + raise "Invalid operand" unless op.reg? + return "GetDefinition(instruction->GetVReg<#{get_format}, #{get_input_idx(index, :reg?)}>())" + end + + def get_format + return "BytecodeInst::Format::#{format.pretty.upcase}" + end + +end + +def get_type(type) + @type_map ||= { + 'u1' => 'DataType::BOOL', + 'i8' => 'DataType::INT8', + 'i16' => 'DataType::INT16', + 'i32' => 'DataType::INT32', + 'i64' => 'DataType::INT64', + 'u8' => 'DataType::UINT8', + 'u16' => 'DataType::UINT16', + 'u32' => 'DataType::UINT32', + 'u64' => 'DataType::UINT64', + 'b32' => 'DataType::UINT32', + 'b64' => 'DataType::UINT64', + 'f32' => 'DataType::FLOAT32', + 'f64' => 'DataType::FLOAT64', + 'ref' => 'DataType::REFERENCE', + 'any' => 'DataType::ANY', + 'i8[]' => 'DataType::INT8', + 'i16[]' => 'DataType::INT16', + 'i32[]' => 'DataType::INT32', + 'i64[]' => 'DataType::INT64', + 'u8[]' => 'DataType::UINT8', + 'u16[]' => 'DataType::UINT16', + 'u32[]' => 'DataType::UINT32', + 'u64[]' => 'DataType::UINT64', + 'b32[]' => 'DataType::UINT32', + 'b64[]' => 'DataType::UINT64', + 'f32[]' => 'DataType::FLOAT32', + 'f64[]' => 'DataType::FLOAT64', + 'ref[]' => 'DataType::REFERENCE', + 'none' => 'DataType::NO_TYPE'} + return 'DataType::ANY' if @type_map[type].nil? + # raise "Unknown type #{type}" if @type_map[type].nil? + return @type_map[type] +end + +def get_template_by_inst(inst) + if (inst.namespace == "ecmascript") + return "ecma" + else + return get_template(inst.stripped_mnemonic) + end +end + +def get_template(mn) + @tmpl_map ||= { + /ldarr/ => "ldarr", + /starr$/ => "starr", + /^return.*/ => "return", + /^[uf]?cmp/ => "cmp", + /^[ifu][813264]{1,2}to[ifu][813264]{1,2}$/ => "cast", + /^j(eq|ne|lt|gt|le|ge|stricteq|nstricteq)(z|null|undefined)?$/ => "if", + /^jmp.*/ => "jump", + /(fdiv|fmod|add|sub|mul|and|or|xor|ashr|shr|shl|neg|not)[2i]?$/ => "binop", + /^(div|mod)u?[2i]?$/ => "binop_z", + /^inci$/ => "inci", + /^movi?$/ => "mov", + /^fmovi?$/ => "fmovi", + /^sta$/ => "sta", + /^ldai?$/ => "lda", + /^fldai?$/ => "fldai", + /^lenarr$/ => "lenarr", + /^newarr$/ => "newarr", + /^call/ => "call", + /^newobj/ => "newobj", + /^initobj/ => "initobj", + /^ldobj/ => "ldobj", + /^stobj/ => "stobj", + /^ldstatic/ => "ldstatic", + /^ststatic/ => "ststatic", + /^isinstance/ => "isinstance", + /^checkcast/ => "checkcast", + /^throw/ => "throw", + /^monitor/ => "monitor", + /^nop/ => "nop", + /^builtin/ => "builtin", + /^ecma/ => "ecma", + /^$/ => "unimplemented" + } + res = @tmpl_map.select { |k, v| mn.match k } + raise "Template not found or multiple match: #{mn}" unless res.size == 1 + return res.first[1] +end + +def template(name, inst, indent, context = {}) + @inst_yaml ||= YAML.load_file(File.join(File.dirname(__FILE__), 'inst_templates.yaml')) + raise "Template '#{name}' not found in templates file" unless @inst_yaml['templates'].key? name + indent + ERB.new(@inst_yaml['templates'][name], nil, '%-').result(binding).gsub("\n", "\n#{indent}") +end + +def get_cc(inst) + return 'compiler::ConditionCode::CC_EQ' if inst.opcode.start_with? 'jeq' + return 'compiler::ConditionCode::CC_NE' if inst.opcode.start_with? 'jne' + return 'compiler::ConditionCode::CC_LT' if inst.opcode.start_with? 'jlt' + return 'compiler::ConditionCode::CC_GT' if inst.opcode.start_with? 'jgt' + return 'compiler::ConditionCode::CC_LE' if inst.opcode.start_with? 'jle' + return 'compiler::ConditionCode::CC_GE' if inst.opcode.start_with? 'jge' + return 'compiler::ConditionCode::CC_EQ' if inst.opcode.start_with? 'jstricteq' + return 'compiler::ConditionCode::CC_NE' if inst.opcode.start_with? 'jnstricteq' + raise 'get_cc: wrong opcode #{inst.opcode}' +end + +%> + +#include "libabckit/src/irbuilder_dynamic/inst_builder_dyn.h" +#include "libabckit/src/irbuilder_dynamic/ir_builder_dyn.h" +#include "static_core/compiler/optimizer/ir/inst.h" +#include "libabckit/src/irbuilder_dynamic/bytecode_inst.h" +#include "libabckit/src/irbuilder_dynamic/bytecode_inst-inl.h" +#include "libabckit/src/irbuilder_dynamic/inst_builder_dyn-inl.h" + +namespace libabckit { + +using namespace ark; + +// NOLINTNEXTLINE(readability-function-size) +void InstBuilder::BuildInstruction(const BytecodeInst* instruction) { + switch(instruction->GetOpcode()) { +% Panda::instructions.each_with_index do |inst, idx| +% if !(inst.opcode.upcase.include? "DEPRECATED_") +% tmpl = inst.mnemonic.include?('polymorphic') ? 'unimplemented' : get_template_by_inst(inst) + // NOLINTNEXTLINE(bugprone-branch-clone) + case BytecodeInst::Opcode::<%= inst.opcode.upcase %>: { +% if tmpl == 'unimplemented' + // Not implemented + failed_ = true; +% else +<%= template(tmpl, inst, ' ' * 8) %> +% end + break; + } +% end +% end + } +} + +// NOLINTNEXTLINE(readability-function-size) +int64_t InstBuilder::GetInstructionJumpOffset(const BytecodeInst* inst) { + switch(inst->GetOpcode()) { +% Panda::instructions.each_with_index do |inst, idx| +% if !(inst.opcode.upcase.include? "DEPRECATED_") + // NOLINTNEXTLINE(bugprone-branch-clone) + case BytecodeInst::Opcode::<%= inst.opcode.upcase %>: +% if inst.jump? + return inst->GetImm, 0>(); +% else + return INVALID_OFFSET; +% end +% end +% end + } + return INVALID_OFFSET; +} + +// TODO(vpukhov): Move this logic from core into plugins/ecmascript +// Currently we support two strategies for building IR from ecma.* instructions: +// 1) Each ecma.* instruction is translated to a corresponding intrinsic call. +// This is used for bytecode optimizer and slow paths during compiling +// to native code (in both JIT and AOT modes). +// 2) Semantics of each ecma.* instruction is taken from the corresponding +// IRtoC handler and is inlined into compiled function. +// This is used only for native compilation (again, both JIT and AOT). +// InstBuilder::BuildEcma selects proper strategy and calls relevant builder. + +// NOLINTNEXTLINE(readability-function-size) +void InstBuilder::BuildEcma([[maybe_unused]] const BytecodeInst* bc_inst) +{ +#ifdef ENABLE_BYTECODE_OPT + switch (bc_inst->GetOpcode()) { +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| +% if !(inst.opcode.upcase.include? "DEPRECATED_") + case BytecodeInst::Opcode::<%= inst.opcode.upcase %>: { +% if inst.compilable? && inst.inlinable? + // +compilable, +inlinable: ecma.* -> intrinsics for BCO, inline IRtoC otherwise: + if (GetGraph()->IsBytecodeOptimizer()) { + BuildEcmaAsIntrinsics(bc_inst); + } else { + BuildEcmaAsIntrinsics(bc_inst); + } +% elsif inst.compilable? + // +compilable, -inlinable: ecma.* -> intrinsics for all scenarios: + BuildEcmaAsIntrinsics(bc_inst); +% else +% abort "isa.yaml inconsistency: #{inst.opcode.upcase} is not compilable, but inlinable" if inst.inlinable? + // -compilable, -inlinable: ecma.* -> intrinsics for BCO, fail IR builder otherwise: + if (GetGraph()->IsBytecodeOptimizer()) { + BuildEcmaAsIntrinsics(bc_inst); + } else { + failed_ = true; + } +% end + break; + } +% end +% end + default: { + failed_ = true; + std::cerr << "Unknown ecma.* opcode: " << static_cast(bc_inst->GetOpcode()) << std::endl; + return; + } + } +#endif +} + +template +void InstBuilder::BuildEcmaAsIntrinsics(const BytecodeInst* bc_inst) // NOLINT(readability-function-size) +{ + switch (bc_inst->GetOpcode()) { +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| +% if !(inst.opcode.upcase.include? "DEPRECATED_") +% opc = inst.opcode.upcase +% name = opc +% acc_read = inst.acc.include?("in") +% acc_write = inst.acc.include?("out") +% ret_type = acc_write ? "compiler::DataType::ANY" : "compiler::DataType::VOID" +% iname = inst.intrinsic_name ? inst.intrinsic_name : opc +% intrinsic_id = "compiler::RuntimeInterface::IntrinsicId::DYN_" + iname +% intrinsic_external_js_id = "compiler::RuntimeInterface::IntrinsicId::DYN_" + opc + case BytecodeInst::Opcode::<%= opc %>: { + + auto intrinsic_id = <%= intrinsic_external_js_id %>; + + auto inst = GetGraph()->CreateInstIntrinsic(<%= ret_type %>, GetPc(bc_inst->GetAddress()), intrinsic_id); + +% params_arr = inst.operands +% format = "BytecodeInst::Format::" + inst.format.pretty.upcase +% range_should_exclude_last = (name.include? "NEWOBJRANGE") || (name.include? "SUPERCALLTHISRANGE") || (name.include? "SUPERCALLARROWRANGE") || (name.include? "CALLRANGE") +% is_range_call = (name.include? "CALLTHISRANGE") || (name.include? "CREATEOBJECTWITHEXCLUDEDKEYS") || range_should_exclude_last +% need_newtarget = (name.include? "SUPERCALLSPREAD") || (name.include? "SUPERCALL") +% num_vregs = params_arr.select{|b| b.reg?}.length +% num_imms = params_arr.select{|b| b.imm?}.length +% num_ids = params_arr.select{|b| b.id?}.length +% num_inputs = acc_read ? num_vregs + 1 : num_vregs + 0 +% if range_should_exclude_last +% num_inputs = num_inputs - 1 +% end +% if need_newtarget +% num_inputs = num_inputs + 1 +% end +% has_ic_slot = inst.properties.include?('ic_slot') || inst.properties.include?('jit_ic_slot') +% if is_range_call + size_t args_count = <%= num_inputs %>U + static_cast(bc_inst->GetImm<<%= format %>, <%= has_ic_slot ? 1 : 0 %>>()); +% else + size_t args_count {<%= num_inputs %>U}; +% end +% if need_newtarget + if (GetGraph()->IsBytecodeOptimizer()) { + --args_count; + } +% end + inst->ReserveInputs(args_count); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), args_count); + // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon) + if constexpr (with_speculative) { + inst->SetInlined(true); + } + +% imm_index = 0 +% vreg_index = 0 +% id16_index = 0 +% params_arr.each do |param| +% if param.imm? + auto imm<%= imm_index %> = static_cast(bc_inst->GetImm<<%= format %>, <%= imm_index %>>()); + inst->AddImm(GetGraph()->GetAllocator(), imm<%= imm_index %>); +% imm_index = imm_index + 1 +% elsif param.reg? + { + auto input = GetDefinition(bc_inst->GetVReg<<%= format %>, <%= vreg_index %>>()); + inst->AppendInput(input); + inst->AddInputType(compiler::DataType::ANY); + } +% vreg_index = vreg_index + 1 +% elsif param.id? +% if inst.properties.include?("method_id") + auto m_idx<%= id16_index %> = bc_inst->template GetId<<%= format %>, <%= id16_index %>>().AsRawValue(); + m_idx<%= id16_index %> = GetRuntime()->ResolveMethodIndex(GetGraph()->GetMethod(), m_idx<%= id16_index %>); + inst->AddImm(GetGraph()->GetAllocator(), m_idx<%= id16_index %>); +% elsif inst.properties.include?("string_id") + auto string_id<%= id16_index %> = bc_inst->template GetId<<%= format %>, <%= id16_index %>>().AsRawValue(); + string_id<%= id16_index %> = GetRuntime()->ResolveMethodIndex(GetGraph()->GetMethod(), string_id<%= id16_index %>); + inst->AddImm(GetGraph()->GetAllocator(), string_id<%= id16_index %>); +% elsif inst.properties.include?("literalarray_id") + auto literalarray_id<%= id16_index %> = bc_inst->template GetId<<%= format %>, <%= id16_index %>>().AsRawValue(); + literalarray_id<%= id16_index %> = GetRuntime()->ResolveMethodIndex(GetGraph()->GetMethod(), literalarray_id<%= id16_index %>); + inst->AddImm(GetGraph()->GetAllocator(), literalarray_id<%= id16_index %>); +% end +% id16_index = id16_index + 1 +% end +% end +% if is_range_call +% range_reg_idx = (name.include? "CREATEOBJECTWITHEXCLUDEDKEYS") ? 1 : 0 +% imm_arg_num = has_ic_slot ? 'imm1' : 'imm0' +% num_actual_vregs = range_should_exclude_last ? imm_arg_num : imm_arg_num + " + 1" + size_t start_reg = bc_inst->GetVReg<<%= format %>, <%= range_reg_idx %>>(); + for (uint32_t i = 1; i < <%= num_actual_vregs %>; ++i) { + auto input = GetDefinition(start_reg + i); + inst->AppendInput(input); + inst->AddInputType(compiler::DataType::ANY); + } +% end +% if acc_read + { + auto input = GetDefinitionAcc(); + inst->AppendInput(input); + inst->AddInputType(compiler::DataType::ANY); + } +% end + AddInstruction(inst); +% if acc_write + UpdateDefinitionAcc(inst); +% end + break; + } +% end +% end + default: + failed_ = true; + std::cerr << "unknown Ecma opcode!" << static_cast(bc_inst->GetOpcode()) << std::endl; + return; + } +} +} // namespace libabckit diff --git a/libabckit/src/irbuilder_dynamic/templates/inst_templates.yaml b/libabckit/src/irbuilder_dynamic/templates/inst_templates.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5338f0c9eb7464b127155b969f82abc68e912b37 --- /dev/null +++ b/libabckit/src/irbuilder_dynamic/templates/inst_templates.yaml @@ -0,0 +1,233 @@ +# Copyright (c) 2021-2022 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. + +templates: + binop: |- + % regex_arithm = /(fdiv|fmod|add|sub|mul|and|or|xor|ashr|shr|shl|neg|not)[2i]?/ + % opc = inst.stripped_mnemonic.match regex_arithm + % raise "Wrong binop instruction" unless opc + % opc = opc[1].capitalize.gsub('Ashr', 'AShr').gsub('Fdiv', 'Div').gsub('Fmod', 'Mod') + auto inst = graph_->CreateInst<%= opc %>(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); + <%=template('operands', inst, '')-%> + AddInstruction(inst); + binop_z: |- + % opc = inst.stripped_mnemonic =~ /div/ ? 'Div' : 'Mod' + auto inst_save_state = CreateSaveState(compiler::Opcode::SaveState, GetPc(instruction->GetAddress())); + auto inst_check = graph_->CreateInstZeroCheck(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); + % if inst.acc_and_operands.last.imm? + if (graph_->IsBytecodeOptimizer()) { + inst_check->SetInput(0, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); + } else { + inst_check->SetInput(0, <%= inst.get_input_string(1) %>); + } + % else + inst_check->SetInput(0, <%= inst.get_input_string(1) %>); + % end + inst_check->SetInput(1, inst_save_state); + auto inst = graph_->CreateInst<%= opc %>(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); + inst->SetInput(0, <%= inst.get_input_string(0) %>); + inst->SetInput(1, inst_check); + UpdateDefinitionAcc(inst); + AddInstruction(inst_save_state); + AddInstruction(inst_check); + AddInstruction(inst); + inci: |- + auto inst = graph_->CreateInstAdd(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); + inst->SetInput(0, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + if (graph_->IsBytecodeOptimizer()) { + inst->SetInput(1, FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + } else { + inst->SetInput(1, FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + } + AddInstruction(inst); + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); + cast: |- + auto inst = graph_->CreateInstCast(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); + auto input = GetDefinitionAcc(); + inst->SetInput(0, input); + inst->SetOperandsType(compiler::<%= get_type(inst.type(0)) %>); + if (!input->HasType()) { + input->SetType(compiler::<%= get_type(inst.type(0)) %>); + } + UpdateDefinitionAcc(inst); + AddInstruction(inst); + cmp: |- + % if inst.mnemonic.include? "obj" + auto inst = graph_->CreateInstCompare(compiler::DataType::BOOL, GetPc(instruction->GetAddress()), compiler::ConditionCode::CC_NE); + % else + auto inst = graph_->CreateInstCmp(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); + % end + inst->SetInput(0, GetDefinitionAcc()); + inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + inst->SetOperandsType(compiler::<%= get_type(inst.type(0)) %>); + % if inst.stripped_mnemonic.start_with? 'fcmp' + inst->Set<%= inst.opcode =~ /^fcmpg/ ? 'Fcmpg' : 'Fcmpl' %>(); + % end + AddInstruction(inst); + UpdateDefinitionAcc(inst); + if: |- + #ifdef ENABLE_LIBABCKIT + if (graph_->GetMode().IsBCT()) { + auto inst = graph_->CreateInstIf(compiler::DataType::BOOL, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); + inst->SetOperandsType(compiler::<%= get_type(inst.type(0)) %>); + % if inst.acc_and_operands.size > 2 + inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + % else + inst->SetInput(1, FindOrCreateConstant(0)); + % end + inst->SetInput(0, GetDefinitionAcc()); + AddInstruction(inst); + } else { + #endif + auto inst = graph_->CreateInstCompare(compiler::DataType::BOOL, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); + inst->SetOperandsType(compiler::<%= get_type(inst.type(0)) %>); + % if inst.acc_and_operands.size > 2 + inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + % else + inst->SetInput(1, FindOrCreateConstant(0)); + % end + inst->SetInput(0, GetDefinitionAcc()); + auto inst_jump = graph_->CreateInstIfImm(compiler::DataType::NO_TYPE, GetPc(instruction->GetAddress()), compiler::ConditionCode::CC_NE, 0); + inst_jump->SetOperandsType(compiler::DataType::BOOL); + inst_jump->SetInput(0, inst); + inst_jump->SetMethod(graph_->GetMethod()); + AddInstruction(inst); + AddInstruction(inst_jump); + #ifdef ENABLE_LIBABCKIT + } + #endif + jump: |- + mov: |- + % if inst.acc_and_operands[1].imm? + % if inst.mnemonic == "movi" + if (graph_->IsBytecodeOptimizer()) { + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + } else { + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + } + % else + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + % end + % else + % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 1>())); + % end + fmovi: |- + % if inst.mnemonic == "fmovi" + auto imm = bit_cast(instruction->GetImm<<%=inst.get_format%>, 0>()); + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateFloatConstant(imm)); + % else + auto imm = bit_cast(instruction->GetImm<<%=inst.get_format%>, 0>()); + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateDoubleConstant(imm)); + % end + sta: |- + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinitionAcc()); + lda: |- + % if inst.acc_and_operands[1].imm? + % if inst.mnemonic == "ldai" + if (graph_->IsBytecodeOptimizer()) { + UpdateDefinitionAcc(FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + } else { + UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + } + % else + UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); + % end + % elsif inst.acc_and_operands[1].id? + BuildLoadFromPool>(instruction); + % else + % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? + UpdateDefinitionAcc(GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + % end + fldai: |- + auto imm = bit_cast(instruction->GetImm<<%=inst.get_format%>, 0>()); + UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm)); + operands: |- + % inst.inputs.each_with_index do |op, idx| + % if op.imm? + if (graph_->IsBytecodeOptimizer()) { + inst->SetInput(<%= idx %>, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); + } else { + inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); + } + % else + inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); + % end + % end + % if inst.has_dst? + % if inst.acc_and_operands.first.acc? + UpdateDefinitionAcc(inst); + % else + UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); + % end + % end + return: |- + % opcode = inst.opcode.include?('void') ? 'ReturnVoid' : 'Return' + auto inst = graph_->CreateInst<%= opcode %>(GetCurrentMethodReturnType(), GetPc(instruction->GetAddress())); + <%=template('operands', inst, '')-%> + AddInstruction(inst); + ecma: |- + % name = inst.opcode.upcase.split('')[1] + % if !(inst.opcode.upcase.include? "DEPRECATED_") + % case name + % when "RETURNUNDEFINED" + auto cvat_input = FindOrCreateConstant(0); + cvat_input->SetType(compiler::DataType::Type::INT64); + auto cvat = graph->CreateInstCastValueToAnyType(0); + cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE); + cvat->SetInput(0, cvat_input); + auto inst = graph_->CreateInstReturn(compiler::DataType::ANY, GetPc(instruction->GetAddress())); + inst->SetInput(0, cvat); + AddInstruction(cvat); + AddInstruction(inst); + % when "RETURN" + auto inst = graph_->CreateInstReturn(compiler::DataType::ANY, GetPc(instruction->GetAddress())); + inst->SetInput(0, GetDefinitionAcc()); + AddInstruction(inst); + % when "JFALSE", "JTRUE" + % cmp_imm = name == "JFALSE" ? 0 : 1 + auto cvat_input = FindOrCreateConstant(<%= cmp_imm %>); + cvat_input->SetType(compiler::DataType::INT64); + auto cvat = graph_->CreateInstCastValueToAnyType(0); + cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE); + cvat->SetInput(0, cvat_input); + #ifdef ENABLE_LIBABCKIT + if (graph_->GetMode().IsBCT()) { + auto if_inst = graph_->CreateInstIf(compiler::DataType::BOOL, GetPc(instruction->GetAddress()), compiler::ConditionCode::CC_EQ); + if_inst->SetOperandsType(compiler::DataType::ANY); + if_inst->SetInput(0, GetDefinitionAcc()); + if_inst->SetInput(1, cvat); + AddInstruction(cvat); + AddInstruction(if_inst); + } else { + #endif + auto cmp_inst = graph_->CreateInstCompare(compiler::DataType::BOOL, GetPc(instruction->GetAddress()), compiler::ConditionCode::CC_EQ); + cmp_inst->SetOperandsType(compiler::DataType::ANY); + cmp_inst->SetInput(0, GetDefinitionAcc()); + cmp_inst->SetInput(1, cvat); + auto jmp_inst = graph_->CreateInstIfImm(compiler::DataType::NO_TYPE, GetPc(instruction->GetAddress()), compiler::ConditionCode::CC_NE, 0); + jmp_inst->SetOperandsType(compiler::DataType::BOOL); + jmp_inst->SetInput(0, cmp_inst); + AddInstruction(cvat); + AddInstruction(cmp_inst); + AddInstruction(jmp_inst); + #ifdef ENABLE_LIBABCKIT + } + #endif + % else + BuildEcma(instruction); + % end + % end + nop: |- + unimplemented: |- + // TODO(msherstennikov): implement diff --git a/libabckit/src/isa_dynamic_impl.cpp b/libabckit/src/isa_dynamic_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a28a3e5bcf7e109dcc0734946f5b13f046d1c0fd --- /dev/null +++ b/libabckit/src/isa_dynamic_impl.cpp @@ -0,0 +1,3003 @@ +/** + * Copyright (c) 2024 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 // ??? +#include +#include "libabckit/include/abckit.h" +#include "libabckit/include/ir_core.h" +#include "libabckit/include/isa/isa_dynamic.h" + +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/adapter_static/ir_static.h" + +#include "libabckit/src/macros.h" + +#include + +namespace libabckit { + +extern "C" abckit_IsaApiDynamicOpcode IgetDYNAMICOpcode(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, abckit_IsaApiDynamicOpcode_INVALID); + + return IgetOpcodeDynamicStatic(inst); +} + +extern "C" abckit_Inst *IcreateDYNAMICLoadString(abckit_Graph *ctx, abckit_String *str) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr) + LIBABCKIT_BAD_ARGUMENT(str, nullptr) + LIBABCKIT_WRONG_MODE(ctx, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateLoadStringStatic(ctx, str)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCmp(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::DYNAMIC, nullptr); + + return IcreateCmpStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdnan(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdnanStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdinfinity(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdinfinityStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdundefined(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdundefinedStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdnull(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdnullStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdsymbol(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdsymbolStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdglobal(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdglobalStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdtrue(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdtrueStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdfalse(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdfalseStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdhole(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdholeStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdnewtarget(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdnewtargetStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdthis(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdthisStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICPoplexenv(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynPoplexenvStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetunmappedargs(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynGetunmappedargsStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICAsyncfunctionenter(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynAsyncfunctionenterStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdfunction(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdfunctionStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICDebugger(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynDebuggerStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetpropiterator(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGetpropiteratorStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetiterator(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGetiteratorStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICCloseiterator(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCloseiteratorStatic(ctxG, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetasynciterator(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGetasynciteratorStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdprivateproperty(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLdprivatepropertyStatic(ctxG, acc, imm0, imm1); +} + +extern "C" abckit_Inst *IcreateDYNAMICStprivateproperty(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStprivatepropertyStatic(ctxG, acc, imm0, imm1, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICTestin(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynTestinStatic(ctxG, acc, imm0, imm1); +} + +extern "C" abckit_Inst *IcreateDYNAMICDefinefieldbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDefinefieldbynameStatic(ctxG, acc, string, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateemptyobject(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynCreateemptyobjectStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateemptyarray(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynCreateemptyarrayStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreategeneratorobj(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCreategeneratorobjStatic(ctxG, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateiterresultobj(abckit_Graph *ctxG, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCreateiterresultobjStatic(ctxG, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateobjectwithexcludedkeys(abckit_Graph *ctxG, uint64_t imm0, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCreateobjectwithexcludedkeysStatic(ctxG, imm0, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideCreateobjectwithexcludedkeys(abckit_Graph *ctxG, uint64_t imm0, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideCreateobjectwithexcludedkeysStatic(ctxG, imm0, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreatearraywithbuffer(abckit_Graph *ctxG, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCreatearraywithbufferStatic(ctxG, literalArray); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateobjectwithbuffer(abckit_Graph *ctxG, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCreateobjectwithbufferStatic(ctxG, literalArray); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateregexpwithliteral(abckit_Graph *ctxG, abckit_String *string, + uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynCreateregexpwithliteralStatic(ctxG, string, imm0); + +} + +extern "C" abckit_Inst *IcreateDYNAMICNewobjapply(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynNewobjapplyStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICNewobjrange(abckit_Graph *ctxG, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr) + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr) + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynNewobjrangeStatic(ctxG, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideNewobjrange(abckit_Graph *ctxG, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynWideNewobjrangeStatic(ctxG, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICNewlexenv(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynNewlexenvStatic(ctxG, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideNewlexenv(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideNewlexenvStatic(ctxG, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICNewlexenvwithname(abckit_Graph *ctxG, uint64_t imm0, + abckit_LiteralArray *literalArray) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynNewlexenvwithnameStatic(ctxG, imm0, literalArray); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideNewlexenvwithname(abckit_Graph *ctxG, uint64_t imm0, + abckit_LiteralArray *literalArray) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideNewlexenvwithnameStatic(ctxG, imm0, literalArray); +} + +extern "C" abckit_Inst *IcreateDYNAMICCreateasyncgeneratorobj(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCreateasyncgeneratorobjStatic(ctxG, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICAsyncgeneratorresolve(abckit_Graph *ctxG, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_BAD_ARGUMENT(input2, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input2->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAsyncgeneratorresolveStatic(ctxG, input0, input1, input2); +} + +extern "C" abckit_Inst *IcreateDYNAMICAdd2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAdd2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICSub2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynSub2Static(ctxG, acc, input0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICMul2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynMul2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICDiv2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDiv2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICMod2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynMod2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICEq(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynEqStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICNoteq(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynNoteqStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLess(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLessStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLesseq(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLesseqStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICGreater(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGreaterStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICGreatereq(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGreatereqStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICShl2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynShl2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICShr2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynShr2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICAshr2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAshr2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICAnd2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAnd2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICOr2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynOr2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICXor2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynXor2Static(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICExp(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynExpStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICTypeof(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynTypeofStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICTonumber(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynTonumberStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICTonumeric(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynTonumberStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICNeg(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynNegStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICNot(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynNotStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICInc(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynIncStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICDec(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDecStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICIstrue(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynIstrueStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICIsfalse(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynIsfalseStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICIsin(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynIsinStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICInstanceof(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynInstanceofStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStrictnoteq(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStrictnoteqStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStricteq(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStricteqStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeNotifyconcurrentresult(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeNotifyconcurrentresultStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeDefinefieldbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeDefinefieldbyvalueStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeDefinefieldbyindex(abckit_Graph *ctxG, abckit_Inst *acc, + uint64_t imm0, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeDefinefieldbyindexStatic(ctxG, acc, imm0, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeTopropertykey(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeTopropertykeyStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeCreateprivateproperty(abckit_Graph *ctxG, uint64_t imm0, + abckit_LiteralArray *literalArray) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeCreateprivatepropertyStatic(ctxG, imm0, literalArray); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeDefineprivateproperty(abckit_Graph *ctxG, abckit_Inst *acc, + uint64_t imm0, uint64_t imm1, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeDefineprivatepropertyStatic(ctxG, acc, imm0, imm1, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeCallinit(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallruntimeCallinitStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeDefinesendableclass(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + + LIBABCKIT_BAD_ARGUMENT(method->m, nullptr); + LIBABCKIT_WRONG_CTX(ctxG->ctxI, method->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeDefinesendableclassStatic(ctxG, method, literalArray, imm0, input0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeLdsendableclass(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeLdsendableclassStatic(ctxG, imm0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeLdsendableexternalmodulevar(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeLdsendableexternalmodulevarStatic(ctxG, imm0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeWideldsendableexternalmodulevar(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeWideldsendableexternalmodulevarStatic(ctxG, imm0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeNewsendableenv(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeNewsendableenvStatic(ctxG, imm0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeWidenewsendableenv(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeWidenewsendableenvStatic(ctxG, imm0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeStsendablevar(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeStsendablevarStatic(ctxG, acc, imm0, imm1)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeWidestsendablevar(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeWidestsendablevarStatic(ctxG, acc, imm0, imm1)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeLdsendablevar(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeLdsendablevarStatic(ctxG, imm0, imm1)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeWideldsendablevar(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeWideldsendablevarStatic(ctxG, imm0, imm1)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeIstrue(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeIstrueStatic(ctxG, acc)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallruntimeIsfalse(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallruntimeIsfalseStatic(ctxG, acc)); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrow(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynThrowStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowNotexists(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynThrowNotexistsStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowPatternnoncoercible(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynThrowPatternnoncoercibleStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowDeletesuperproperty(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynThrowDeletesuperpropertyStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowConstassignment(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynThrowConstassignmentStatic(ctxG, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowIfnotobject(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynThrowIfnotobjectStatic(ctxG, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowUndefinedifhole(abckit_Graph *ctxG, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynThrowUndefinedifholeStatic(ctxG, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowIfsupernotcorrectcall(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynThrowIfsupernotcorrectcallStatic(ctxG, acc, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICThrowUndefinedifholewithname(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynThrowUndefinedifholewithnameStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallarg0(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallarg0Static(ctxG, acc)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallarg1(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallarg1Static(ctxG, acc, input0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallargs2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallargs2Static(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallargs3(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_BAD_ARGUMENT(input2, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input2->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallargs3Static(ctxG, acc, input0, input1, input2); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallrange(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallrangeStatic(ctxG, acc, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideCallrange(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynWideCallrangeStatic(ctxG, acc, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICSupercallspread(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynSupercallspreadStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICApply(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynApplyStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallthis0(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallthis0Static(ctxG, acc, input0)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallthis1(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallthis1Static(ctxG, acc, input0, input1)); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallthis2(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_BAD_ARGUMENT(input2, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input2->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallthis2Static(ctxG, acc, input0, input1, input2); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallthis3(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1, abckit_Inst *input2, abckit_Inst *input3) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_BAD_ARGUMENT(input2, nullptr); + LIBABCKIT_BAD_ARGUMENT(input3, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input2->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input3->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCallthis3Static(ctxG, acc, input0, input1, input2, input3); +} + +extern "C" abckit_Inst *IcreateDYNAMICCallthisrange(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + std::va_list args; + va_start(args, argCount); + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynCallthisrangeStatic(ctxG, acc, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideCallthisrange(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynWideCallthisrangeStatic(ctxG, acc, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICSupercallthisrange(abckit_Graph *ctxG, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynSupercallthisrangeStatic(ctxG, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideSupercallthisrange(abckit_Graph *ctxG, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynWideSupercallthisrangeStatic(ctxG, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICSupercallarrowrange(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + std::va_list args; + va_start(args, argCount); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynSupercallarrowrangeStatic(ctxG, acc, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideSupercallarrowrange(abckit_Graph *ctxG, abckit_Inst *acc, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + std::va_list args; + va_start(args, argCount); + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynWideSupercallarrowrangeStatic(ctxG, acc, argCount, args)); +} + +extern "C" abckit_Inst *IcreateDYNAMICDefinegettersetterbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_BAD_ARGUMENT(input2, nullptr); + LIBABCKIT_BAD_ARGUMENT(input3, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input2->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input3->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDefinegettersetterbyvalueStatic(ctxG, acc, input0, input1, input2, input3); +} + +extern "C" abckit_Inst *IcreateDYNAMICDefinefunc(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + LIBABCKIT_BAD_ARGUMENT(method->m, nullptr); + LIBABCKIT_WRONG_CTX(ctxG->ctxI, method->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDefinefuncStatic(ctxG, method, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICDefinemethod(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, + uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(method->m, nullptr); + LIBABCKIT_WRONG_CTX(ctxG->ctxI, method->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDefinemethodStatic(ctxG, acc, method, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICDefineclasswithbuffer(abckit_Graph *ctxG, abckit_Method *method, + abckit_LiteralArray *literalArray, uint64_t imm0, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(method->m, nullptr); + LIBABCKIT_WRONG_CTX(ctxG->ctxI, method->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDefineclasswithbufferStatic(ctxG, method, literalArray, imm0, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICResumegenerator(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynResumegeneratorStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetresumemode(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGetresumemodeStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICGettemplateobject(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGettemplateobjectStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetnextpropname(abckit_Graph *ctxG, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGetnextpropnameStatic(ctxG, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICDelobjprop(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDelobjpropStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICSuspendgenerator(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynSuspendgeneratorStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICAsyncfunctionawaituncaught(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAsyncfunctionawaituncaughtStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCopydataproperties(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynCopydatapropertiesStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStarrayspread(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStarrayspreadStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICSetobjectwithproto(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynSetobjectwithprotoStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdobjbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLdobjbyvalueStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStobjbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStobjbyvalueStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICStownbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStownbyvalueStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdsuperbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLdsuperbyvalueStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStsuperbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStsuperbyvalueStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdobjbyindex(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLdobjbyindexStatic(ctxG, acc, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideLdobjbyindex(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideLdobjbyindexStatic(ctxG, acc, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStobjbyindex(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStobjbyindexStatic(ctxG, acc, input0, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideStobjbyindex(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideStobjbyindexStatic(ctxG, acc, input0, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStownbyindex(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStownbyindexStatic(ctxG, acc, input0, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideStownbyindex(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0, + uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideStownbyindexStatic(ctxG, acc, input0, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICAsyncfunctionresolve(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAsyncfunctionresolveStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICAsyncfunctionreject(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAsyncfunctionrejectStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICCopyrestargs(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynCopyrestargsStatic(ctxG, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideCopyrestargs(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideCopyrestargsStatic(ctxG, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdlexvar(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdlexvarStatic(ctxG, imm0, imm1); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideLdlexvar(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideLdlexvarStatic(ctxG, imm0, imm1); +} + +extern "C" abckit_Inst *IcreateDYNAMICStlexvar(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStlexvarStatic(ctxG, acc, imm0, imm1); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideStlexvar(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0, + uint64_t imm1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideStlexvarStatic(ctxG, acc, imm0, imm1); +} + +extern "C" abckit_Inst *IcreateDYNAMICGetmodulenamespace(abckit_Graph *ctxG, abckit_Module *md) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(md, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG->ctxI, md->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynGetmodulenamespaceStatic(ctxG, md); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideGetmodulenamespace(abckit_Graph *ctxG, abckit_Module *md) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(md, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG->ctxI, md->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideGetmodulenamespaceStatic(ctxG, md); +} + +extern "C" abckit_Inst *IcreateDYNAMICStmodulevar(abckit_Graph *ctxG, abckit_Inst *acc, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(ed, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStmodulevarStatic(ctxG, acc, ed); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideStmodulevar(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_ExportDescriptor *ed) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(ed, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideStmodulevarStatic(ctxG, acc, ed); +} + +extern "C" abckit_Inst *IcreateDYNAMICTryldglobalbyname(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateDynTryldglobalbynameStatic(ctxG, string)); +} + +extern "C" abckit_Inst *IcreateDYNAMICTrystglobalbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynTrystglobalbynameStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdglobalvar(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdglobalvarStatic(ctxG, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICStglobalvar(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStglobalvarStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdobjbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + LIBABCKIT_CHECK_ALLOCATION(IcreateDynLdobjbynameStatic(ctxG, acc, string)); +} + +extern "C" abckit_Inst *IcreateDYNAMICStobjbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStobjbynameStatic(ctxG, acc, string, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICStownbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStownbynameStatic(ctxG, acc, string, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdsuperbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLdsuperbynameStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICStsuperbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string, + abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStsuperbynameStatic(ctxG, acc, string, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdlocalmodulevar(abckit_Graph *ctxG, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(ed, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdlocalmodulevarStatic(ctxG, ed); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideLdlocalmodulevar(abckit_Graph *ctxG, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(ed, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideLdlocalmodulevarStatic(ctxG, ed); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdexternalmodulevar(abckit_Graph *ctxG, abckit_ImportDescriptor *id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(id, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdexternalmodulevarStatic(ctxG, id); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideLdexternalmodulevar(abckit_Graph *ctxG, abckit_ImportDescriptor *id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(id, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideLdexternalmodulevarStatic(ctxG, id); +} + +extern "C" abckit_Inst *IcreateDYNAMICStconsttoglobalrecord(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStconsttoglobalrecordStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICSttoglobalrecord(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynSttoglobalrecordStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICStownbyvaluewithnameset(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStownbyvaluewithnamesetStatic(ctxG, acc, input0, input1); +} + +extern "C" abckit_Inst *IcreateDYNAMICStownbynamewithnameset(abckit_Graph *ctxG, abckit_Inst *acc, + abckit_String *string, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStownbynamewithnamesetStatic(ctxG, acc, string, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdbigint(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdbigintStatic(ctxG, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdthisbyname(abckit_Graph *ctxG, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynLdthisbynameStatic(ctxG, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICStthisbyname(abckit_Graph *ctxG, abckit_Inst *acc, abckit_String *string) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(string, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStthisbynameStatic(ctxG, acc, string); +} + +extern "C" abckit_Inst *IcreateDYNAMICLdthisbyvalue(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynLdthisbyvalueStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICStthisbyvalue(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynStthisbyvalueStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideLdpatchvar(abckit_Graph *ctxG, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynWideLdpatchvarStatic(ctxG, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICWideStpatchvar(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynWideStpatchvarStatic(ctxG, acc, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICDynamicimport(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynDynamicimportStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICAsyncgeneratorreject(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctxG, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynAsyncgeneratorrejectStatic(ctxG, acc, input0); +} + +extern "C" abckit_Inst *IcreateDYNAMICSetgeneratorstate(abckit_Graph *ctxG, abckit_Inst *acc, uint64_t imm0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynSetgeneratorstateStatic(ctxG, acc, imm0); +} + +extern "C" abckit_Inst *IcreateDYNAMICReturn(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynReturnStatic(ctxG, acc); +} + +extern "C" abckit_Inst *IcreateDYNAMICReturnundefined(abckit_Graph *ctxG) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + return IcreateDynReturnundefinedStatic(ctxG); +} + +extern "C" abckit_Inst *IcreateDYNAMICIf(abckit_Graph *ctxG, abckit_Inst *input, abckit_IsaApiDynamicConditionCode cc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(input, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, input->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + return IcreateDynIfStatic(ctxG, input, cc); +} + +extern "C" abckit_Inst *IcreateDYNAMICTry(abckit_Graph *ctx) +{ + LIBABCKIT_UNIMPLEMENTED +} + +extern "C" abckit_Inst *IcreateDYNAMICCatchPhi(abckit_Graph *ctxG, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::DYNAMIC, nullptr); + + va_list args; + va_start(args, argCount); + + return IcreateCatchPhiStatic(ctxG, argCount, args); +} + +extern "C" abckit_IsaApiDynamicConditionCode IgetDYNAMICConditionCode(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, abckit_IsaApiDynamicConditionCode_CC_NONE); + + if (IgetDYNAMICOpcode(inst) != abckit_IsaApiDynamicOpcode_if) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "Trying to get condition code not from 'If' instruction\n"; + return abckit_IsaApiDynamicConditionCode_CC_NONE; + } + + return IgetConditionCodeDynamicStatic(inst); +} + +extern "C" void IsetDYNAMICConditionCode(abckit_Inst *inst, abckit_IsaApiDynamicConditionCode cc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + if (cc == abckit_IsaApiDynamicConditionCode_CC_NONE) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + if (IgetDYNAMICOpcode(inst) != abckit_IsaApiDynamicOpcode_if) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "Trying to get condition code not from 'If' instruction\n"; + return; + } + + bool ccDynamicResitiction = !((cc == abckit_IsaApiDynamicConditionCode_CC_NE) || (cc == abckit_IsaApiDynamicConditionCode_CC_EQ)); + if ((inst->ctxG->ctxI->mode == Mode::DYNAMIC) && ccDynamicResitiction) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "Wrong condition code set for dynamic if\n"; + return; + } + + IsetConditionCodeDynamicStatic(inst, cc); +} + +extern "C" abckit_ImportDescriptor *IgetImportDescriptor(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetImportDescriptorStatic(inst); +} + +extern "C" void IsetImportDescriptor(abckit_Inst *inst, abckit_ImportDescriptor *id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(id); + + IsetImportDescriptorStatic(inst, id); +} + +extern "C" abckit_ExportDescriptor *IgetExportDescriptor(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetExportDescriptorStatic(inst); +} + +extern "C" void IsetExportDescriptor(abckit_Inst *inst, abckit_ExportDescriptor *ed) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(ed); + + IsetExportDescriptorStatic(inst, ed); +} + +extern "C" abckit_Module *IgetModule(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetModuleStatic(inst); +} + +extern "C" void IsetModule(abckit_Inst *inst, abckit_Module *md) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(md); + + LIBABCKIT_BAD_ARGUMENT_VOID(inst->ctxG); + LIBABCKIT_WRONG_CTX_VOID(inst->ctxG->ctxI, md->ctxI); + IsetModuleStatic(inst, md); +} + +abckit_IsaApiDynamic g_IsaApiDynamicImpl = { + IgetModule, + IsetModule, + IgetDYNAMICConditionCode, + IsetDYNAMICConditionCode, + IgetDYNAMICOpcode, + IgetImportDescriptor, + IsetImportDescriptor, + IgetExportDescriptor, + IsetExportDescriptor, + + IcreateDYNAMICLoadString, + IcreateDYNAMICCmp, + IcreateDYNAMICLdnan, + IcreateDYNAMICLdinfinity, + IcreateDYNAMICLdundefined, + IcreateDYNAMICLdnull, + IcreateDYNAMICLdsymbol, + IcreateDYNAMICLdglobal, + IcreateDYNAMICLdtrue, + IcreateDYNAMICLdfalse, + IcreateDYNAMICLdhole, + IcreateDYNAMICLdnewtarget, + IcreateDYNAMICLdthis, + IcreateDYNAMICPoplexenv, + IcreateDYNAMICGetunmappedargs, + IcreateDYNAMICAsyncfunctionenter, + IcreateDYNAMICLdfunction, + IcreateDYNAMICDebugger, + IcreateDYNAMICGetpropiterator, + IcreateDYNAMICGetiterator, + IcreateDYNAMICCloseiterator, + IcreateDYNAMICGetasynciterator, + IcreateDYNAMICLdprivateproperty, + IcreateDYNAMICStprivateproperty, + IcreateDYNAMICTestin, + IcreateDYNAMICDefinefieldbyname, + IcreateDYNAMICCreateemptyobject, + IcreateDYNAMICCreateemptyarray, + IcreateDYNAMICCreategeneratorobj, + IcreateDYNAMICCreateiterresultobj, + IcreateDYNAMICCreateobjectwithexcludedkeys, + IcreateDYNAMICWideCreateobjectwithexcludedkeys, + IcreateDYNAMICCreatearraywithbuffer, + IcreateDYNAMICCreateobjectwithbuffer, + IcreateDYNAMICCreateregexpwithliteral, + IcreateDYNAMICNewobjapply, + IcreateDYNAMICNewobjrange, + IcreateDYNAMICWideNewobjrange, + IcreateDYNAMICNewlexenv, + IcreateDYNAMICWideNewlexenv, + IcreateDYNAMICNewlexenvwithname, + IcreateDYNAMICWideNewlexenvwithname, + IcreateDYNAMICCreateasyncgeneratorobj, + IcreateDYNAMICAsyncgeneratorresolve, + IcreateDYNAMICAdd2, + IcreateDYNAMICSub2, + IcreateDYNAMICMul2, + IcreateDYNAMICDiv2, + IcreateDYNAMICMod2, + IcreateDYNAMICEq, + IcreateDYNAMICNoteq, + IcreateDYNAMICLess, + IcreateDYNAMICLesseq, + IcreateDYNAMICGreater, + IcreateDYNAMICGreatereq, + IcreateDYNAMICShl2, + IcreateDYNAMICShr2, + IcreateDYNAMICAshr2, + IcreateDYNAMICAnd2, + IcreateDYNAMICOr2, + IcreateDYNAMICXor2, + IcreateDYNAMICExp, + IcreateDYNAMICTypeof, + IcreateDYNAMICTonumber, + IcreateDYNAMICTonumeric, + IcreateDYNAMICNeg, + IcreateDYNAMICNot, + IcreateDYNAMICInc, + IcreateDYNAMICDec, + IcreateDYNAMICIstrue, + IcreateDYNAMICIsfalse, + IcreateDYNAMICIsin, + IcreateDYNAMICInstanceof, + IcreateDYNAMICStrictnoteq, + IcreateDYNAMICStricteq, + IcreateDYNAMICCallruntimeNotifyconcurrentresult, + IcreateDYNAMICCallruntimeDefinefieldbyvalue, + IcreateDYNAMICCallruntimeDefinefieldbyindex, + IcreateDYNAMICCallruntimeTopropertykey, + IcreateDYNAMICCallruntimeCreateprivateproperty, + IcreateDYNAMICCallruntimeDefineprivateproperty, + IcreateDYNAMICCallruntimeCallinit, + IcreateDYNAMICCallruntimeDefinesendableclass, + IcreateDYNAMICCallruntimeLdsendableclass, + IcreateDYNAMICCallruntimeLdsendableexternalmodulevar, + IcreateDYNAMICCallruntimeWideldsendableexternalmodulevar, + IcreateDYNAMICCallruntimeNewsendableenv, + IcreateDYNAMICCallruntimeWidenewsendableenv, + IcreateDYNAMICCallruntimeStsendablevar, + IcreateDYNAMICCallruntimeWidestsendablevar, + IcreateDYNAMICCallruntimeLdsendablevar, + IcreateDYNAMICCallruntimeWideldsendablevar, + IcreateDYNAMICCallruntimeIstrue, + IcreateDYNAMICCallruntimeIsfalse, + IcreateDYNAMICThrow, + IcreateDYNAMICThrowNotexists, + IcreateDYNAMICThrowPatternnoncoercible, + IcreateDYNAMICThrowDeletesuperproperty, + IcreateDYNAMICThrowConstassignment, + IcreateDYNAMICThrowIfnotobject, + IcreateDYNAMICThrowUndefinedifhole, + IcreateDYNAMICThrowIfsupernotcorrectcall, + IcreateDYNAMICThrowUndefinedifholewithname, + IcreateDYNAMICCallarg0, + IcreateDYNAMICCallarg1, + IcreateDYNAMICCallargs2, + IcreateDYNAMICCallargs3, + IcreateDYNAMICCallrange, + IcreateDYNAMICWideCallrange, + IcreateDYNAMICSupercallspread, + IcreateDYNAMICApply, + IcreateDYNAMICCallthis0, + IcreateDYNAMICCallthis1, + IcreateDYNAMICCallthis2, + IcreateDYNAMICCallthis3, + IcreateDYNAMICCallthisrange, + IcreateDYNAMICWideCallthisrange, + IcreateDYNAMICSupercallthisrange, + IcreateDYNAMICWideSupercallthisrange, + IcreateDYNAMICSupercallarrowrange, + IcreateDYNAMICWideSupercallarrowrange, + IcreateDYNAMICDefinegettersetterbyvalue, + IcreateDYNAMICDefinefunc, + IcreateDYNAMICDefinemethod, + IcreateDYNAMICDefineclasswithbuffer, + IcreateDYNAMICResumegenerator, + IcreateDYNAMICGetresumemode, + IcreateDYNAMICGettemplateobject, + IcreateDYNAMICGetnextpropname, + IcreateDYNAMICDelobjprop, + IcreateDYNAMICSuspendgenerator, + IcreateDYNAMICAsyncfunctionawaituncaught, + IcreateDYNAMICCopydataproperties, + IcreateDYNAMICStarrayspread, + IcreateDYNAMICSetobjectwithproto, + IcreateDYNAMICLdobjbyvalue, + IcreateDYNAMICStobjbyvalue, + IcreateDYNAMICStownbyvalue, + IcreateDYNAMICLdsuperbyvalue, + IcreateDYNAMICStsuperbyvalue, + IcreateDYNAMICLdobjbyindex, + IcreateDYNAMICWideLdobjbyindex, + IcreateDYNAMICStobjbyindex, + IcreateDYNAMICWideStobjbyindex, + IcreateDYNAMICStownbyindex, + IcreateDYNAMICWideStownbyindex, + IcreateDYNAMICAsyncfunctionresolve, + IcreateDYNAMICAsyncfunctionreject, + IcreateDYNAMICCopyrestargs, + IcreateDYNAMICWideCopyrestargs, + IcreateDYNAMICLdlexvar, + IcreateDYNAMICWideLdlexvar, + IcreateDYNAMICStlexvar, + IcreateDYNAMICWideStlexvar, + IcreateDYNAMICGetmodulenamespace, + IcreateDYNAMICWideGetmodulenamespace, + IcreateDYNAMICStmodulevar, + IcreateDYNAMICWideStmodulevar, + IcreateDYNAMICTryldglobalbyname, + IcreateDYNAMICTrystglobalbyname, + IcreateDYNAMICLdglobalvar, + IcreateDYNAMICStglobalvar, + IcreateDYNAMICLdobjbyname, + IcreateDYNAMICStobjbyname, + IcreateDYNAMICStownbyname, + IcreateDYNAMICLdsuperbyname, + IcreateDYNAMICStsuperbyname, + IcreateDYNAMICLdlocalmodulevar, + IcreateDYNAMICWideLdlocalmodulevar, + IcreateDYNAMICLdexternalmodulevar, + IcreateDYNAMICWideLdexternalmodulevar, + IcreateDYNAMICStconsttoglobalrecord, + IcreateDYNAMICSttoglobalrecord, + IcreateDYNAMICStownbyvaluewithnameset, + IcreateDYNAMICStownbynamewithnameset, + IcreateDYNAMICLdbigint, + IcreateDYNAMICLdthisbyname, + IcreateDYNAMICStthisbyname, + IcreateDYNAMICLdthisbyvalue, + IcreateDYNAMICStthisbyvalue, + IcreateDYNAMICWideLdpatchvar, + IcreateDYNAMICWideStpatchvar, + IcreateDYNAMICDynamicimport, + IcreateDYNAMICAsyncgeneratorreject, + IcreateDYNAMICSetgeneratorstate, + IcreateDYNAMICReturn, + IcreateDYNAMICReturnundefined, + IcreateDYNAMICIf, + IcreateDYNAMICTry, + IcreateDYNAMICCatchPhi, +}; + +} // namespace libabckit + +extern "C" abckit_IsaApiDynamic const *abckit_GetIsaApiDynamicImpl(int version) +{ + if (version != LIBABCKIT_VERSION) { + return nullptr; + } + return &libabckit::g_IsaApiDynamicImpl; +} diff --git a/libabckit/src/isa_static_impl.cpp b/libabckit/src/isa_static_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9632b3686aebc80c33b97d82b2ee78457acea613 --- /dev/null +++ b/libabckit/src/isa_static_impl.cpp @@ -0,0 +1,883 @@ +/** + * Copyright (c) 2024 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 // ??? +#include +#include "libabckit/include/abckit.h" +#include "libabckit/include/ir_core.h" +#include "libabckit/include/isa/isa_static.h" + +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/adapter_static/ir_static.h" + +#include "libabckit/src/macros.h" + +#include + +namespace libabckit { + +extern "C" abckit_Inst *IcreateCmp(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + return IcreateCmpStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateLoadString(abckit_Graph *ctx, abckit_String *str) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr) + LIBABCKIT_BAD_ARGUMENT(str, nullptr) + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + LIBABCKIT_CHECK_ALLOCATION(IcreateLoadStringStatic(ctx, str)); +} + +extern "C" abckit_Inst *IcreateReturn(abckit_Graph *ctx, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr) + LIBABCKIT_BAD_ARGUMENT(input0, nullptr) + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateReturnStatic(ctx, input0); +} + +extern "C" abckit_Inst *IcreateIf(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode cc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr) + LIBABCKIT_BAD_ARGUMENT(input0, nullptr) + LIBABCKIT_BAD_ARGUMENT(input1, nullptr) + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + if (cc == abckit_IsaApiStaticConditionCode_CC_NONE) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return nullptr; + } + + return IcreateIfStaticStatic(ctx, input0, input1, cc); +} + +extern "C" abckit_Inst *IcreateTry(abckit_Graph *ctx) +{ + LIBABCKIT_UNIMPLEMENTED +} + +extern "C" abckit_Inst *IcreateCatchPhi(abckit_Graph *ctxG, size_t argCount, ...) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + + LIBABCKIT_WRONG_MODE(ctxG, Mode::STATIC, nullptr); + + va_list args; + va_start(args, argCount); + + return IcreateCatchPhiStatic(ctxG, argCount, args); +} + +extern "C" abckit_Inst *IcreateNeg(abckit_Graph *ctx, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateNegStatic(ctx, input0); +} + +extern "C" abckit_Inst *IcreateNot(abckit_Graph *ctx, abckit_Inst *input0) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateNotStatic(ctx, input0); +} + +extern "C" abckit_Inst *IcreateAdd(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateAddStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateSub(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateSubStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateMul(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateMulStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateDiv(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateDivStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateMod(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateModStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateShl(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateShlStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateShr(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateShrStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateAShr(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateAShrStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateAnd(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateAndStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateOr(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateOrStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateXor(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateXorStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateCast(abckit_Graph *ctx, abckit_Inst *input0, abckit_TypeId targetType) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateCastStatic(ctx, input0, targetType); +} + +extern "C" abckit_Inst *GcreateNullPtr(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + + return GcreateNullPtrStatic(ctx); +} + +extern "C" abckit_Inst *IcreateNewArray(abckit_Graph *ctx, abckit_Class *inputClass, abckit_Inst *inputSize) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputClass, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputSize, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, inputSize->ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputClass->m, nullptr); + LIBABCKIT_WRONG_CTX(ctx->ctxI, inputClass->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateNewArrayStatic(ctx, inputClass, inputSize); +} + +extern "C" abckit_Inst *IcreateNewObject(abckit_Graph *ctx, abckit_Class *inputClass) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputClass, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputClass->m, nullptr); + LIBABCKIT_WRONG_CTX(ctx->ctxI, inputClass->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateNewObjectStatic(ctx, inputClass); +} + +extern "C" abckit_Inst *IcreateInitObject(abckit_Graph *ctx, abckit_Method *inputMethod, size_t argCount, + ... /* method params */) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputMethod, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputMethod->m, nullptr); + LIBABCKIT_WRONG_CTX(ctx->ctxI, inputMethod->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + va_list args; + va_start(args, argCount); + + return IcreateInitObjectStatic(ctx, inputMethod, argCount, args); +} + +extern "C" abckit_Inst *IcreateLoadArray(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_TypeId return_type_id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(arrayRef, nullptr); + LIBABCKIT_BAD_ARGUMENT(idx, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, arrayRef->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, idx->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateLoadArrayStatic(ctx, arrayRef, idx, return_type_id); +} + +extern "C" abckit_Inst *IcreateStoreArray(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(arrayRef, nullptr); + LIBABCKIT_BAD_ARGUMENT(idx, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, arrayRef->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, idx->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, value->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateStoreArrayStatic(ctx, arrayRef, idx, value, value_type_id); +} + +extern "C" abckit_Inst *IcreateStoreArrayWide(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(arrayRef, nullptr); + LIBABCKIT_BAD_ARGUMENT(idx, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, arrayRef->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, idx->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, value->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateStoreArrayWideStatic(ctx, arrayRef, idx, value, value_type_id); +} + +extern "C" abckit_Inst *IcreateLenArray(abckit_Graph *ctx, abckit_Inst *arr) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(arr, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, arr->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateLenArrayStatic(ctx, arr); +} + +extern "C" abckit_Inst *IcreateLoadConstArray(abckit_Graph *ctx, abckit_LiteralArray *literalArray) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(literalArray, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + return IcreateLoadConstArrayStatic(ctx, literalArray); +} + +extern "C" abckit_Inst *IcreateCheckCast(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputObj, nullptr); + LIBABCKIT_BAD_ARGUMENT(targetType, nullptr); + LIBABCKIT_WRONG_CTX(ctx, inputObj->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateCheckCastStatic(ctx, inputObj, targetType); +} + +extern "C" abckit_Inst *IcreateIsInstance(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputObj, nullptr); + LIBABCKIT_BAD_ARGUMENT(targetType, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, inputObj->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateIsInstanceStatic(ctx, inputObj, targetType); +} + +extern "C" abckit_Inst *IcreateLoadUndefined(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + return IcreateLoadUndefinedStatic(ctx); +} + +extern "C" abckit_Inst *IcreateReturnVoid(abckit_Graph *ctx) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + + return IcreateReturnVoidStatic(ctx); +} + +extern "C" abckit_Inst *IcreateEquals(abckit_Graph *ctx, abckit_Inst *input0, abckit_Inst *input1) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + LIBABCKIT_BAD_ARGUMENT(input1, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_CTX(ctx, input1->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateEqualsStatic(ctx, input0, input1); +} + +extern "C" abckit_Inst *IcreateCallStatic(abckit_Graph *ctx, abckit_Method *inputMethod, size_t argCount, + ... /* method params */) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputMethod, nullptr); + + va_list args; + va_start(args, argCount); + LIBABCKIT_BAD_ARGUMENT(inputMethod->m, nullptr); + LIBABCKIT_WRONG_CTX(ctx->ctxI, inputMethod->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateCallStaticStatic(ctx, inputMethod, argCount, args); +} + +extern "C" abckit_Inst *IcreateCallVirtual(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Method *inputMethod, + size_t argCount, ... /* method params */) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputMethod, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputObj, nullptr); + + va_list args; + va_start(args, argCount); + + LIBABCKIT_WRONG_CTX(ctx, inputObj->ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputMethod->m, nullptr); + LIBABCKIT_WRONG_CTX(ctx->ctxI, inputMethod->m->ctxI, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateCallVirtualStatic(ctx, inputObj, inputMethod, argCount, args); +} + +extern "C" abckit_Inst *IcreateAddI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateAddIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateSubI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateSubIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateMulI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateMulIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateDivI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateDivIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateModI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateModIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateShlI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateShlIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateShrI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateShrIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateAShrI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateAShrIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateAndI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateAndIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateOrI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateOrIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateXorI(abckit_Graph *ctx, abckit_Inst *input0, uint64_t imm) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(input0, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, input0->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateXorIStatic(ctx, input0, imm); +} + +extern "C" abckit_Inst *IcreateThrow(abckit_Graph *ctxG, abckit_Inst *acc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxG, nullptr); + LIBABCKIT_BAD_ARGUMENT(acc, nullptr); + + LIBABCKIT_WRONG_CTX(ctxG, acc->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctxG, Mode::STATIC, nullptr); + return IcreateThrowStatic(ctxG, acc); +} + +extern "C" abckit_IsaApiStaticOpcode IgetOpcode(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, abckit_IsaApiStaticOpcode_INVALID); + + return IgetOpcodeStaticStatic(inst); +} + +extern "C" abckit_Class *IgetClass(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, nullptr); + + return IgetClassStatic(inst); +} + +extern "C" void IsetClass(abckit_Inst *inst, abckit_Class *klass) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + LIBABCKIT_BAD_ARGUMENT_VOID(klass); + + IsetClassStatic(inst, klass); +} + +extern "C" abckit_IsaApiStaticConditionCode IgetConditionCode(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, abckit_IsaApiStaticConditionCode_CC_NONE); + + if (IgetOpcode(inst) != abckit_IsaApiStaticOpcode_If) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "Trying to get condition code not from 'If' instruction\n"; + return abckit_IsaApiStaticConditionCode_CC_NONE; + } + + return IgetConditionCodeStaticStatic(inst); +} + +extern "C" void IsetConditionCode(abckit_Inst *inst, abckit_IsaApiStaticConditionCode cc) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + if (cc == abckit_IsaApiStaticConditionCode_CC_NONE) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + return; + } + + if (IgetOpcode(inst) != abckit_IsaApiStaticOpcode_If) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "Trying to get condition code not from 'If' instruction\n"; + return; + } + + bool ccDynamicResitiction = !((cc == abckit_IsaApiStaticConditionCode_CC_NE) || (cc == abckit_IsaApiStaticConditionCode_CC_EQ)); + if ((inst->ctxG->ctxI->mode == Mode::DYNAMIC) && ccDynamicResitiction) { + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); + LIBABCKIT_LOG(DEBUG) << "Wrong condition code set for dynamic if\n"; + return; + } + + IsetConditionCodeStaticStatic(inst, cc); +} + +extern "C" void IsetTargetType(abckit_Inst *inst, abckit_TypeId t) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(inst); + + IsetTargetTypeStatic(inst, t); +} + +extern "C" abckit_TypeId IgetTargetType(abckit_Inst *inst) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(inst, abckit_TypeId::abckit_TypeId_INVALID); + + return IgetTargetTypeStatic(inst); +} + +extern "C" abckit_Inst *IcreateIsUndefined(abckit_Graph *ctx, abckit_Inst *inputObj) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(inputObj, nullptr); + + LIBABCKIT_WRONG_CTX(ctx, inputObj->ctxG, nullptr); + LIBABCKIT_WRONG_MODE(ctx, Mode::STATIC, nullptr); + return IcreateIsUndefinedStatic(ctx, inputObj); +} + +abckit_IsaApiStatic g_IsaApiStaticImpl = { + + IgetClass, + IsetClass, + IgetConditionCode, + IsetConditionCode, + IgetOpcode, + IsetTargetType, + IgetTargetType, + + IcreateCmp, + IcreateLoadString, + IcreateReturn, + IcreateIf, + IcreateTry, + IcreateCatchPhi, + IcreateNeg, + IcreateNot, + IcreateAdd, + IcreateSub, + IcreateMul, + IcreateDiv, + IcreateMod, + IcreateShl, + IcreateShr, + IcreateAShr, + IcreateAnd, + IcreateOr, + IcreateXor, + IcreateCast, + GcreateNullPtr, + IcreateNewArray, + IcreateNewObject, + IcreateInitObject, + IcreateLoadArray, + IcreateStoreArray, + IcreateStoreArrayWide, + IcreateLenArray, + IcreateLoadConstArray, + IcreateCheckCast, + IcreateIsInstance, + IcreateLoadUndefined, + IcreateReturnVoid, + IcreateEquals, + IcreateCallStatic, + IcreateCallVirtual, + IcreateAddI, + IcreateSubI, + IcreateMulI, + IcreateDivI, + IcreateModI, + IcreateShlI, + IcreateShrI, + IcreateAShrI, + IcreateAndI, + IcreateOrI, + IcreateXorI, + IcreateThrow, + IcreateIsUndefined, +}; + +} // namespace libabckit + +extern "C" abckit_IsaApiStatic const *abckit_GetIsaApiStaticImpl(int version) +{ + if (version != LIBABCKIT_VERSION) { + return nullptr; + } + return &libabckit::g_IsaApiStaticImpl; +} diff --git a/libabckit/src/logger.h b/libabckit/src/logger.h new file mode 100644 index 0000000000000000000000000000000000000000..8944cebfc9fa7c831bbb0e5fe4c7d1791d38bb56 --- /dev/null +++ b/libabckit/src/logger.h @@ -0,0 +1,237 @@ +/** + * Copyright (c) 2024 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. + */ + +// #pragma once + +#ifndef LIBABCKIT_LOGGER +#define LIBABCKIT_LOGGER + +#include +#include +#include +#include +#include +#include + +#define LIBABCKIT_PREFIX "[ LIBABCKIT ]" +#define LIBABCKIT_FUNC_NAME __func__ + + +std::vector const TRUE_VALUES = {"ON", "on", "1", "true", "TRUE", "enable", "ENABLE"}; + +namespace libabckit { + + class null_buffer : public std::streambuf { + public: + int overflow(int c) { return c; } + }; + extern thread_local null_buffer n_b; + extern thread_local std::ostream null_stream; + + struct abckit_component { + protected: + std::string name; + std::string prefix; + bool is_enabled = true; + public: + abckit_component(const std::string &component_name_, bool enabled_ = true) : + name(component_name_), is_enabled(enabled_) { + prefix = "[" + component_name_ + "]\t"; + } + abckit_component(const std::string &component_name_) : + name(component_name_) { + prefix = "[" + component_name_ + "]\t"; + is_enabled = true; + } + void disable() { is_enabled = false; } + void enable() { is_enabled = true; } + bool check_status() { return is_enabled; } + std::string get_prefix() { return prefix; } + }; + + class logger { + public: + + enum LOG_LEVEL { DEBUG = 1, + WARNING, + ERROR, + FATAL, + UNIMPLEMENTED, + IMPLEMENTED, + UNKNOWN, + INCORRECT_LOG_LVL}; + + inline static std::map levels_set = { + {"DEBUG", LOG_LEVEL::DEBUG}, + {"WARNING", LOG_LEVEL::WARNING}, + {"ERROR", LOG_LEVEL::ERROR}, + {"FATAL", LOG_LEVEL::FATAL}, + {"UNIMPLEMENTED", LOG_LEVEL::UNIMPLEMENTED}, + {"IMPLEMENTED", LOG_LEVEL::IMPLEMENTED}, + {"UNKNOWN", LOG_LEVEL::UNKNOWN}, + {"INCORRECT_LOG_LVL", LOG_LEVEL::INCORRECT_LOG_LVL}, + }; + enum MODE { DEBUG_MODE = 1, RELEASE_MODE, SILENCE_MODE}; + + MODE logger_mode = MODE::RELEASE_MODE; // default + inline static std::map components = {}; + inline static bool is_initialized = false; + + static logger *logger_; + + static void Initialize(MODE mode) { + if (is_initialized) return; + if (const char* env = std::getenv("LIBABCKIT_DEBUG_MODE")) + if ((std::find(TRUE_VALUES.begin(), TRUE_VALUES.end(), + (std::string)env)) != TRUE_VALUES.end()) + mode = MODE::DEBUG_MODE; + logger_ = new logger(mode); + is_initialized = true; + } + + logger() {} + logger(MODE mode) : logger_mode(mode) {} + + inline static std::string msg_prefix = ""; + + static bool check_logging_mode() { + return !(logger_->logger_mode == MODE::SILENCE_MODE); + } + + static bool check_log_level(std::string level) { + return (logger_->levels_set.find(level) != logger_->levels_set.end()); + } + + static bool check_if_permissible(LOG_LEVEL level) { + if (logger_->logger_mode == MODE::DEBUG_MODE) + return true; // permissible + if (logger_->logger_mode == MODE::RELEASE_MODE) + return (level == LOG_LEVEL::FATAL || level == LOG_LEVEL::ERROR); + return false; // suppressed + } + + static bool check_if_permissible(const LOG_LEVEL level, const std::string &component_name) { + if (!logger_->check_if_enable(component_name)) return false; + return logger_->check_if_permissible(level); + } + + static bool check_if_in_components(const std::string &side_name) { + return ( logger_->components.find(side_name) != logger_->components.end() ); + } + + void set_comp_opt(std::string &side_name, bool enable) { + if (!check_if_in_components(side_name)) { + logger_->components[side_name] = new abckit_component(side_name, enable); + return; + } + if (enable) logger_->components[side_name]->enable(); + else logger_->components[side_name]->enable(); + } + void disable_component(std::string &side_name) { set_comp_opt(side_name, false); } + void enable_component(std::string &side_name) { set_comp_opt(side_name, true); } + + static bool check_if_enable(const std::string &side_name) { + if (!check_if_in_components(side_name)) return true; + return logger_->components[side_name]->check_status(); + } + + static std::string message_comp_prefix(const std::string &component_name) { + return "[ LIBABCKIT " + (std::string)component_name + " ] "; + } + + static bool check_permission(const std::string &level_name) { + if (!check_log_level(level_name)) { + std::cout << '\n' << LIBABCKIT_PREFIX << " INCORRECT LOG LEVEL: " << level_name << '\n'; + return false; + } + LOG_LEVEL msg_level = logger_->levels_set[level_name]; + if (!check_logging_mode() || !check_if_permissible(msg_level)) return false; + if (msg_level == LOG_LEVEL::INCORRECT_LOG_LVL) return false; + return true; + } + + static std::ostream *get_logger_stream(const std::string &level_name) { + if (!check_permission(level_name)) + return &null_stream; + return &std::cerr; + } + + static std::ostream *message(const std::string &level_name) { + if (level_name == "FATAL") { std::cout << "FATAL: " << LIBABCKIT_FUNC_NAME << '\n'; std::abort();} + logger_->msg_prefix = LIBABCKIT_PREFIX; + return get_logger_stream(level_name); + } + + static std::ostream *message(const std::string &level_name, const std::string &component_name) { + if (!check_if_permissible(logger_->levels_set[level_name], component_name)) + return &null_stream; + logger_->msg_prefix = message_comp_prefix(component_name); + return get_logger_stream(level_name); + } + + ~logger() { + for (auto &p: components) { + free(p.second); + } + components.clear(); + } + }; +} + +extern thread_local libabckit::logger::MODE abckit_global_mode; + +#define LIBABCKIT_LOG_STREAM(level) \ + libabckit::logger::message(#level) + +#define LIBABCKIT_LOG(level) _LIBABCKIT_LOG(level) + +#define _LIBABCKIT_LOG(level) \ + libabckit::logger::Initialize(abckit_global_mode); \ + *LIBABCKIT_LOG_STREAM(level) << libabckit::logger::msg_prefix << "[" << LIBABCKIT_FUNC_NAME << "] " + + +#define LIBABCKIT_LOG_DUMP(dump, level) \ +do { if (libabckit::logger::check_permission(#level)) { \ + dump; } \ +} while (0) + +#define LIBABCKIT_LOG_FUNC LIBABCKIT_LOG(DEBUG) << '\n'; + +#define LIBABCKIT_IMPLEMENTED LIBABCKIT_LOG(DEBUG) << "implemented\n"; + +#define LIBABCKIT_UNIMPLEMENTED \ + LIBABCKIT_LOG(DEBUG) << "is not implemented yet!\n"; \ + abort(); + +#define LIBABCKIT_UNREACHABLE \ + LIBABCKIT_LOG(DEBUG) << "unreachable!\n"; \ + abort(); + +#define LIBABCKIT_PREFIX_TEST "[ LIBABCKIT TEST ]" + +#define LIBABCKIT_LOG_TEST(level) libabckit::logger::Initialize(abckit_global_mode); *LIBABCKIT_LOG_STREAM(level) << LIBABCKIT_PREFIX_TEST << "[" << LIBABCKIT_FUNC_NAME << "] " << " " + +#define EMBED_TEST_START(name) auto name = [&]() { +#define EMBED_TEST_END(name) \ + } \ + ; \ + name(); + +#define LIBABCKIT_UNREACHABLE_TEST(level) \ + LIBABCKIT_LOG_TEST(level) << "UNREACHABLE!\n"; \ + abort(); + +#endif + diff --git a/libabckit/src/macros.h b/libabckit/src/macros.h new file mode 100644 index 0000000000000000000000000000000000000000..35c06cc5af65c114900c85cf19365dbd9b0310f7 --- /dev/null +++ b/libabckit/src/macros.h @@ -0,0 +1,53 @@ +#ifndef LIBABCKIT_MACROS_H +#define LIBABCKIT_MACROS_H + +#include +#include "libabckit/src/statuses_impl.h" + +#include "libabckit/include/statuses.h" +#include "libabckit/src/statuses_impl.h" +#include "libabckit/src/logger.h" + +/* + * NOTE: __FUNCTION__ and __PRETTY_FUNCTION__ are non-standard extensions. Use __func__ for portability. + */ + +#define LIBABCKIT_CLEAR_LAST_ERROR statuses::SetLastError(abckit_Status_NO_ERROR); + +#define LIBABCKIT_RETURN_VOID +#define LIBABCKIT_BAD_ARGUMENT(argument, returnvalue) \ + if (argument == nullptr) { \ + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); \ + return returnvalue; \ + } +#define LIBABCKIT_BAD_ARGUMENT_VOID(argument) \ + if (argument == nullptr) { \ + statuses::SetLastError(abckit_Status_BAD_ARGUMENT); \ + return; \ + } + +#define LIBABCKIT_WRONG_CTX(lhs, rhs, returnvalue) \ + if (lhs != rhs) { \ + statuses::SetLastError(abckit_Status_WRONG_CTX); \ + return returnvalue; \ + } +#define LIBABCKIT_WRONG_CTX_VOID(lhs, rhs) \ + if (lhs != rhs) { \ + statuses::SetLastError(abckit_Status_WRONG_CTX); \ + return; \ + } + +#define LIBABCKIT_CHECK_ALLOCATION(func) \ + auto *ptr = func; \ + if (ptr == nullptr) { \ + statuses::SetLastError(abckit_Status_MEMORY_ALLOCATION); \ + } \ + return ptr; + +#define LIBABCKIT_WRONG_MODE(ctxG, expectedMode, returnValue) \ + if (ctxG->ctxI->mode != expectedMode) { \ + libabckit::statuses::SetLastError(abckit_Status_WRONG_MODE); \ + return returnValue; \ + } + +#endif diff --git a/libabckit/src/mem_manager/BUILD.gn b/libabckit/src/mem_manager/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..21f84eaab73499073b22798931469a715678b862 --- /dev/null +++ b/libabckit/src/mem_manager/BUILD.gn @@ -0,0 +1,40 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ohos_source_set("libabckit_mem_manager_source_set") { + sources = [ + "mem_manager.cpp", + ] + + include_dirs = [ + "$ark_root/static_core", + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/static_core:ark_config", + "$ark_root/static_core/libpandabase:arkbase_public_config", + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/static_core/libpandabase:libarktsbase", + ] +} diff --git a/libabckit/src/mem_manager/mem_manager.cpp b/libabckit/src/mem_manager/mem_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7796a2e8fe7eca50cecd378716da22e83178ff4d --- /dev/null +++ b/libabckit/src/mem_manager/mem_manager.cpp @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2024 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 "mem_manager.h" + +#include "mem/arena_allocator.h" +#include "mem/pool_manager.h" + +namespace libabckit { + +size_t MemManager::compilerMemSize = {}; +bool MemManager::isInitialized = false; + +MemManager::MemManager() +{ + MemManager::InitializeMemory(); +} + +void MemManager::InitializeMemory() +{ + ark::mem::MemConfig::Initialize(0, 0, MemManager::compilerMemSize, 0, 0, 0); + ark::PoolManager::Initialize(ark::PoolType::MMAP); + MemManager::isInitialized = true; +} + +MemManager::~MemManager() +{ + Finalize(); +} + +void MemManager::Finalize() +{ + if(MemManager::isInitialized) { + ark::PoolManager::Finalize(); + ark::mem::MemConfig::Finalize(); + MemManager::isInitialized = false; + } +} + +} // namespace libabckit diff --git a/libabckit/src/mem_manager/mem_manager.h b/libabckit/src/mem_manager/mem_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..2999695d8edede04de00e29aa338535a04e81db0 --- /dev/null +++ b/libabckit/src/mem_manager/mem_manager.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2024 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 +#include + +namespace libabckit { + +class MemManager { +public: + + [[maybe_unused]] static MemManager *Initialize(size_t compilerMemSize = 0) { + MemManager::compilerMemSize = compilerMemSize; + static auto memManager = libabckit::MemManager(); + if(!isInitialized) { + memManager.InitializeMemory(); + } + return &memManager; + }; + + static void Finalize(); + ~MemManager(); + +private: + MemManager(); + void InitializeMemory(); + static size_t compilerMemSize; + static bool isInitialized; +}; + +constexpr uint64_t SHIFT_KB = 10ULL; +constexpr uint64_t SHIFT_MB = 20ULL; +constexpr uint64_t SHIFT_GB = 30ULL; + +constexpr uint64_t operator"" _KB(long double count) +{ + return static_cast(count * (1ULL << SHIFT_KB)); +} + +constexpr uint64_t operator"" _KB(unsigned long long count) +{ + return count * (1ULL << SHIFT_KB); +} + +constexpr uint64_t operator"" _MB(long double count) +{ + return static_cast(count * (1ULL << SHIFT_MB)); +} + +constexpr uint64_t operator"" _MB(unsigned long long count) +{ + return count * (1ULL << SHIFT_MB); +} + +constexpr uint64_t operator"" _GB(long double count) +{ + return static_cast(count * (1ULL << SHIFT_GB)); +} + +constexpr uint64_t operator"" _GB(unsigned long long count) +{ + return count * (1ULL << SHIFT_GB); +} + +} // namespace libabckit diff --git a/libabckit/src/metadata_inspect_impl.cpp b/libabckit/src/metadata_inspect_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d9626d479c081ddac00e6e137c70dd5a337a8bd --- /dev/null +++ b/libabckit/src/metadata_inspect_impl.cpp @@ -0,0 +1,1443 @@ +/** + * Copyright (c) 2024 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 +#include +#include "libabckit/include/abckit.h" +#include "libabckit/include/metadata.h" + +#include "libabckit/src/adapter_dynamic/metadata_modify_dynamic.h" +#include "libabckit/src/macros.h" + +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/adapter_dynamic/metadata_inspect_dynamic.h" +#include "libabckit/src/adapter_static/metadata_inspect_static.h" + + +namespace libabckit { + +// ======================================== +// File +// ======================================== + +extern "C" abckit_File_Version FileGetVersion(abckit_File *ctx) +{ + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + + switch (ctx->mode) { + case Mode::DYNAMIC: + break; + case Mode::STATIC: { + abckit_File_Version version = FileGetVersionStatic(ctx); + return version; + break; + } + default: + LIBABCKIT_UNREACHABLE + } + return nullptr; + +} + + +extern "C" void FileEnumerateModules(abckit_File *ctxI, void *data, + bool (*cb)(abckit_Module *module, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(ctxI, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &[moduleName, module] : ctxI->localModules) { + cb(module.get(), data); + } + for (auto &[moduleName, module] : ctxI->externalModules) { + cb(module.get(), data); + } +} + +extern "C" void FileEnumerateExternalModules(abckit_File *ctxI, void *data, + bool (*cb)(abckit_Module *module, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(ctxI, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + for (auto &[moduleName, module] : ctxI->externalModules) { + cb(module.get(), data); + } +} + +// ======================================== +// Module +// ======================================== + +extern "C" abckit_File *ModuleGetInspectContext(abckit_Module *m) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + return m->ctxI; +} + +extern "C" abckit_String *ModuleGetName(abckit_Module *m) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + return m->moduleName; +} + +extern "C" bool ModuleIsExternal(abckit_Module *m) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, false); + return m->isExternal; +} + +extern "C" void ModuleEnumerateImports(abckit_Module *m, void *data, bool (*cb)(abckit_ImportDescriptor *i, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(m); + LIBABCKIT_BAD_ARGUMENT_VOID(cb); + + for (auto &id : m->id) { + if (!cb(id.get(), data)) { + return; + } + } +} + +extern "C" void ModuleEnumerateExports(abckit_Module *m, void *data, bool (*cb)(abckit_ExportDescriptor *e, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + for (auto &ed : m->ed) { + if (!cb(ed.get(), data)) { + return; + } + } +} + +extern "C" void ModuleEnumerateClasses(abckit_Module *m, void *data, bool cb(abckit_Class *klass, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + ModuleEnumerateClassesDynamic(m, data, cb); + break; + case Mode::STATIC: + ModuleEnumerateClassesStatic(m, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ModuleEnumerateTopLevelFunctions(abckit_Module *m, void *data, + bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleEnumerateTopLevelMethodsDynamic(m, data, cb); + break; + case Mode::STATIC: + return ModuleEnumerateTopLevelMethodsStatic(m, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ModuleEnumerateAnonymousFunctions(abckit_Module *m, void *data, + bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleEnumerateAnonymousFunctionsDynamic(m, data, cb); + break; + case Mode::STATIC: + return ModuleEnumerateAnonymousFunctionsStatic(m, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ModuleEnumerateAnnotationInterfaces(abckit_Module *m, void *data, + bool (*cb)(abckit_AnnotationInterface *ai, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleEnumerateAnnotationInterfacesDynamic(m, data, cb); + break; + case Mode::STATIC: + return ModuleEnumerateAnnotationInterfacesStatic(m, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// ImportDescriptor +// ======================================== + +extern "C" abckit_File *ImportDescriptorGetInspectContext(abckit_ImportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + return i->importingModule->ctxI; +} + +extern "C" abckit_Module *ImportDescriptorGetImportedModule(abckit_ImportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + return i->importedModule; +} + +extern "C" abckit_Module *ImportDescriptorGetImportingModule(abckit_ImportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + return i->importingModule; +} + +extern "C" abckit_String *ImportDescriptorGetName(abckit_ImportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + switch (i->importingModule->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = ImportDescriptorGetNameDynamic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = ImportDescriptorGetNameStatic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_String *ImportDescriptorGetAlias(abckit_ImportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + switch (i->importingModule->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = ImportDescriptorGetAliasDynamic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = ImportDescriptorGetAliasStatic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// ExportDescriptor +// ======================================== + +extern "C" abckit_File *ExportDescriptorGetInspectContext(abckit_ExportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + return i->exportingModule->ctxI; +} + +extern "C" abckit_Module *ExportDescriptorGetExportingModule(abckit_ExportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + return i->exportingModule; +} + +extern "C" abckit_Module *ExportDescriptorGetExportedModule(abckit_ExportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + return i->exportedModule; +} + +extern "C" abckit_String *ExportDescriptorGetName(abckit_ExportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + switch (i->exportingModule->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = ExportDescriptorGetNameDynamic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = ExportDescriptorGetNameStatic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_String *ExportDescriptorGetAlias(abckit_ExportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(i, nullptr); + switch (i->exportingModule->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = ExportDescriptorGetAliasDynamic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = ExportDescriptorGetAliasStatic(i); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Class +// ======================================== + +extern "C" abckit_File *ClassGetInspectContext(abckit_Class *klass) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(klass, nullptr); + return klass->m->ctxI; +} + +extern "C" abckit_Module *ClassGetModule(abckit_Class *klass) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(klass, nullptr); + + return klass->m; +} + +extern "C" abckit_String *ClassGetName(abckit_Class *klass) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(klass, nullptr) + + auto *ctx = ClassGetInspectContext(klass); + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto *res = ClassGetNameDynamic(klass); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = ClassGetNameStatic(klass); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ClassEnumerateMethods(abckit_Class *klass, void *data, bool (*cb)(abckit_Method *method, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(klass, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + auto *ctx = ClassGetInspectContext(klass); + switch (ctx->mode) { + case Mode::DYNAMIC: + return ClassEnumerateMethodsDynamic(klass, data, cb); + break; + case Mode::STATIC: + return ClassEnumerateMethodsStatic(klass, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ClassEnumerateAnnotations(abckit_Class *klass, void *data, + bool (*cb)(abckit_Annotation *anno, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(klass, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + auto *ctx = ClassGetInspectContext(klass); + switch (ctx->mode) { + case Mode::DYNAMIC: + return ClassEnumerateAnnotationsDynamic(klass, data, cb); + break; + case Mode::STATIC: + return ClassEnumerateAnnotationsStatic(klass, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// AnnotationInterface +// ======================================== + +extern "C" abckit_File *AnnotationInterfaceGetInspectContext(abckit_AnnotationInterface *anno) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(anno, nullptr); + LIBABCKIT_BAD_ARGUMENT(anno->m, nullptr); + return anno->m->ctxI; +} + +extern "C" abckit_Module *AnnotationInterfaceGetModule(abckit_AnnotationInterface *anno) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(anno, nullptr); + return anno->m; +} + +extern "C" abckit_String *AnnotationInterfaceGetName(abckit_AnnotationInterface *ai) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ai, nullptr); + + auto *ctx = AnnotationInterfaceGetInspectContext(ai); + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto res = AnnotationInterfaceGetNameDynamic(ai); + LIBABCKIT_CHECK_ALLOCATION(res); + break; + } + case Mode::STATIC: { + auto res = AnnotationInterfaceGetNameStatic(ai); + LIBABCKIT_CHECK_ALLOCATION(res); + break; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void AnnotationInterfaceEnumerateFields(abckit_AnnotationInterface *ai, void *data, + bool (*cb)(abckit_AnnotationInterfaceField *fld, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ai, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + for (auto &ed : ai->fields) { + if (!cb(ed.get(), data)) { + return; + } + } +} + +// ======================================== +// AnnotationInterfaceField +// ======================================== + +extern "C" abckit_File *AnnotationInterfaceFieldGetInspectContext(abckit_AnnotationInterfaceField *fld) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(fld, nullptr); + LIBABCKIT_BAD_ARGUMENT(fld->ai, nullptr); + LIBABCKIT_BAD_ARGUMENT(fld->ai->m, nullptr); + + return fld->ai->m->ctxI; +} + +extern "C" abckit_AnnotationInterface *AnnotationInterfaceFieldGetInterface(abckit_AnnotationInterfaceField *fld) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(fld, nullptr); + + return fld->ai; +} + +extern "C" abckit_String *AnnotationInterfaceFieldGetName(abckit_AnnotationInterfaceField *fld) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(fld, nullptr); + + return fld->name; +} + +extern "C" abckit_Type *AnnotationInterfaceFieldGetType(abckit_AnnotationInterfaceField *fld) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(fld, nullptr); + + return fld->type; +} + +extern "C" abckit_Value *AnnotationInterfaceFieldGetDefaultValue(abckit_AnnotationInterfaceField *fld) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(fld, nullptr); + + return fld->value; +} + +// ======================================== +// Method +// ======================================== + +extern "C" abckit_File *MethodGetInspectContext(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + return method->m->ctxI; +} + +extern "C" abckit_Module *MethodGetModule(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + + return method->m; +} + +extern "C" abckit_String *MethodGetName(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto *res = MethodGetNameDynamic(method); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = MethodGetNameStatic(method); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Class *MethodGetParentClass(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodGetParentClassDynamic(method); + } + case Mode::STATIC: { + return MethodGetParentClassStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void MethodEnumerateAnnotations(abckit_Method *method, void *data, + bool (*cb)(abckit_Annotation *anno, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(method, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + auto *ctx = MethodGetInspectContext(method); + switch (ctx->mode) { + case Mode::DYNAMIC: + return MethodEnumerateAnnotationsDynamic(method, data, cb); + break; + case Mode::STATIC: + return MethodEnumerateAnnotationsStatic(method, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Code *MethodGetCode(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto *res = MethodGetCodeDynamic(method); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = MethodGetCodeStatic(method); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool MethodIsStatic(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, false); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodIsStaticDynamic(method); + } + case Mode::STATIC: { + return MethodIsStaticStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool MethodIsNative(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, false); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodIsNativeDynamic(method); + } + case Mode::STATIC: { + return MethodIsNativeStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool MethodIsAbstract(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, false); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodIsAbstractDynamic(method); + } + case Mode::STATIC: { + return MethodIsAbstractStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool MethodIsExternal(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, false); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodIsExternalDynamic(method); + } + case Mode::STATIC: { + return MethodIsExternalStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool MethodIsCtor(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, false); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodIsCtorDynamic(method); + } + case Mode::STATIC: { + return MethodIsCtorStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool MethodIsAnonymous(abckit_Method *method) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(method, false); + + auto *ctx = method->m->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + return MethodIsAnonymousDynamic(method); + } + case Mode::STATIC: { + return MethodIsAnonymousStatic(method); + } + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Annotation +// ======================================== + +extern "C" abckit_File *AnnotationGetInspectContext(abckit_Annotation *anno) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(anno, nullptr); + + abckit_Module *module = nullptr; + if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } else if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + return module->ctxI; +} + +extern "C" abckit_AnnotationInterface *AnnotationGetInterface(abckit_Annotation *anno) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(anno, nullptr); + + auto *ctx = AnnotationGetInspectContext(anno); + switch (ctx->mode) { + case Mode::DYNAMIC: + return AnnotationGetInterfaceDynamic(anno); + break; + case Mode::STATIC: + return AnnotationGetInterfaceStatic(anno); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void AnnotationEnumerateElements(abckit_Annotation *anno, void *data, + bool (*cb)(abckit_AnnotationElement *ae, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(anno, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(cb, LIBABCKIT_RETURN_VOID); + + auto *ctx = AnnotationGetInspectContext(anno); + switch (ctx->mode) { + case Mode::DYNAMIC: + return AnnotationEnumerateElementsDynamic(anno, data, cb); + break; + case Mode::STATIC: + return AnnotationEnumerateElementsStatic(anno, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// AnnotationElement +// ======================================== + +extern "C" abckit_File *AnnotationElementGetInspectContext(abckit_AnnotationElement *ae) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ae, nullptr); + LIBABCKIT_BAD_ARGUMENT(ae->ann, nullptr); + + abckit_Module *module = nullptr; + if (std::holds_alternative(ae->ann->owner)) { + module = std::get(ae->ann->owner)->m; + } else if (std::holds_alternative(ae->ann->owner)) { + module = std::get(ae->ann->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + return module->ctxI; +} + +extern "C" abckit_Annotation *AnnotationElementGetAnnotation(abckit_AnnotationElement *ae) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ae, nullptr); + + return ae->ann; +} + +extern "C" abckit_String *AnnotationElementGetName(abckit_AnnotationElement *ae) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ae, nullptr); + LIBABCKIT_BAD_ARGUMENT(ae->ann, nullptr); + + auto *ctx = AnnotationGetInspectContext(ae->ann); + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto res = AnnotationElementGetNameDynamic(ae); + LIBABCKIT_CHECK_ALLOCATION(res); + break; + } + case Mode::STATIC: { + auto res = AnnotationElementGetNameStatic(ae); + LIBABCKIT_CHECK_ALLOCATION(res); + break; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Value *AnnotationElementGetValue(abckit_AnnotationElement *ae) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ae, nullptr); + + return ae->value.get(); +} + +// ======================================== +// Type +// ======================================== + +extern "C" abckit_TypeId TypeGetTypeId(abckit_Type *type) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(type, abckit_TypeId::abckit_TypeId_INVALID); + + return type->id; +} + +extern "C" abckit_Class *TypeGetReferenceClass(abckit_Type *type) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + LIBABCKIT_BAD_ARGUMENT(type, nullptr); + if (type->id != abckit_TypeId::abckit_TypeId_REFERENCE) { + return nullptr; + } + + return type->klass; +} + +// ======================================== +// Value +// ======================================== + +extern "C" abckit_Type *ValueGetType(abckit_File *ctx, abckit_Value *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return ValueGetTypeDynamic(ctx, value); + break; + case Mode::STATIC: + return ValueGetTypeStatic(ctx, value); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool ValueGetU1(abckit_File *ctx, abckit_Value *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, false); + LIBABCKIT_BAD_ARGUMENT(value, false); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return ValueGetU1Dynamic(ctx, value); + break; + case Mode::STATIC: + return ValueGetU1Static(ctx, value); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" double ValueGetDouble(abckit_File *ctx, abckit_Value *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, false); + LIBABCKIT_BAD_ARGUMENT(value, false); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return ValueGetDoubleDynamic(ctx, value); + break; + case Mode::STATIC: + return ValueGetDoubleStatic(ctx, value); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_String *ValueGetString(abckit_File *ctx, abckit_Value *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return ValueGetStringDynamic(ctx, value); + break; + case Mode::STATIC: + return ValueGetStringStatic(ctx, value); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_LiteralArray *ArrayValueGetLiteralArray(abckit_File *ctx, abckit_Value *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return ArrayValueGetLiteralArrayDynamic(ctx, value); + break; + case Mode::STATIC: + return ArrayValueGetLiteralArrayStatic(ctx, value); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// String +// ======================================== + +extern "C" void abckit_StringToString(abckit_File *ctxI, abckit_String *value, char *out, size_t *len) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctxI); + LIBABCKIT_BAD_ARGUMENT_VOID(value); + + if (out == nullptr) { + LIBABCKIT_BAD_ARGUMENT_VOID(len); + } + + switch (ctxI->mode) { + case Mode::DYNAMIC: + StringToStringDynamic(ctxI, value, out, len); + return; + case Mode::STATIC: + StringToStringStatic(ctxI, value, out, len); + return; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// LiteralArray +// ======================================== + +extern "C" void LiteralArrayEnumerateElements(abckit_File *ctx, abckit_LiteralArray *litArr, void *data, + bool (*cb)(abckit_File *ctx, abckit_Literal *v, void *data)) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctx); + LIBABCKIT_BAD_ARGUMENT_VOID(litArr); + LIBABCKIT_BAD_ARGUMENT_VOID(cb); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralArrayEnumerateElementsDynamic(ctx, litArr, data, cb); + break; + case Mode::STATIC: + return LiteralArrayEnumerateElementsStatic(ctx, litArr, data, cb); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Literal +// ======================================== + +extern "C" abckit_LiteralTag LiteralGetTag(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, abckit_LiteralTag_INVALID); + LIBABCKIT_BAD_ARGUMENT(lit, abckit_LiteralTag_INVALID); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetTagDynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetTagStatic(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" bool LiteralGetBool(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, false); + LIBABCKIT_BAD_ARGUMENT(lit, false); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetBoolDynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetBoolStatic(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" uint8_t LiteralGetU8(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, 0); + LIBABCKIT_BAD_ARGUMENT(lit, 0); + + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetU8Dynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetU8Static(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" uint16_t LiteralGetU16(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, 0); + LIBABCKIT_BAD_ARGUMENT(lit, 0); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetU16Dynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetU16Static(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" uint32_t LiteralGetU32(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, 0); + LIBABCKIT_BAD_ARGUMENT(lit, 0); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetU32Dynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetU32Static(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" uint64_t LiteralGetU64(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, 0); + LIBABCKIT_BAD_ARGUMENT(lit, 0); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetU64Dynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetU64Static(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" float LiteralGetFloat(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, 0); + LIBABCKIT_BAD_ARGUMENT(lit, 0); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetFloatDynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetFloatStatic(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" double LiteralGetDouble(abckit_File *ctx, abckit_Literal *lit) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, 0); + LIBABCKIT_BAD_ARGUMENT(lit, 0); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetDoubleDynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetDoubleStatic(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_String *LiteralGetString(abckit_File *ctx, abckit_Literal *lit) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(lit, nullptr); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return LiteralGetStringDynamic(ctx, lit); + break; + case Mode::STATIC: + return LiteralGetStringStatic(ctx, lit); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +abckit_InspectApi g_InspectApiImpl = { + // ======================================== + // File + // ======================================== + + FileGetVersion, + FileEnumerateModules, + FileEnumerateExternalModules, + + // ======================================== + // Module + // ======================================== + + ModuleGetInspectContext, + ModuleGetName, + ModuleIsExternal, + ModuleEnumerateImports, + ModuleEnumerateExports, + ModuleEnumerateClasses, + ModuleEnumerateTopLevelFunctions, + ModuleEnumerateAnonymousFunctions, + ModuleEnumerateAnnotationInterfaces, + + // ======================================== + // ImportDescriptor + // ======================================== + + ImportDescriptorGetInspectContext, + ImportDescriptorGetImportingModule, + ImportDescriptorGetImportedModule, + ImportDescriptorGetName, + ImportDescriptorGetAlias, + + // ======================================== + // ExportDescriptor + // ======================================== + + ExportDescriptorGetInspectContext, + ExportDescriptorGetExportingModule, + ExportDescriptorGetExportedModule, + ExportDescriptorGetName, + ExportDescriptorGetAlias, + + // ======================================== + // Class + // ======================================== + + ClassGetInspectContext, + ClassGetModule, + ClassGetName, + ClassEnumerateMethods, + ClassEnumerateAnnotations, + + // ======================================== + // AnnotationInterface + // ======================================== + + AnnotationInterfaceGetInspectContext, + AnnotationInterfaceGetModule, + AnnotationInterfaceGetName, + AnnotationInterfaceEnumerateFields, + + // ======================================== + // AnnotationInterfaceField + // ======================================== + + AnnotationInterfaceFieldGetInspectContext, + AnnotationInterfaceFieldGetInterface, + AnnotationInterfaceFieldGetName, + AnnotationInterfaceFieldGetType, + AnnotationInterfaceFieldGetDefaultValue, + + // ======================================== + // Method + // ======================================== + + MethodGetInspectContext, + MethodGetModule, + MethodGetName, + MethodGetParentClass, + MethodEnumerateAnnotations, + MethodGetCode, + MethodIsStatic, + MethodIsNative, + MethodIsAbstract, + MethodIsExternal, + MethodIsCtor, + MethodIsAnonymous, + + // ======================================== + // Annotation + // ======================================== + + AnnotationGetInspectContext, + AnnotationGetInterface, + AnnotationEnumerateElements, + AnnotationElementGetInspectContext, + AnnotationElementGetAnnotation, + AnnotationElementGetName, + AnnotationElementGetValue, + + // ======================================== + // Type + // ======================================== + + TypeGetTypeId, + TypeGetReferenceClass, + + // ======================================== + // Value + // ======================================== + + ValueGetType, + ValueGetU1, + ValueGetDouble, + ValueGetString, + ArrayValueGetLiteralArray, + + // ======================================== + // String + // ======================================== + + abckit_StringToString, + + // ======================================== + // LiteralArray + // ======================================== + + LiteralArrayEnumerateElements, + + // ======================================== + // Literal + // ======================================== + + LiteralGetTag, + LiteralGetBool, + LiteralGetU8, + LiteralGetU16, + LiteralGetU32, + LiteralGetU64, + LiteralGetFloat, + LiteralGetDouble, + LiteralGetString, +}; + +} // namespace libabckit + +extern "C" abckit_InspectApi const *abckit_GetInspectApiImpl(int version) +{ + if (version != LIBABCKIT_VERSION) { + return nullptr; + } + return &libabckit::g_InspectApiImpl; +} diff --git a/libabckit/src/metadata_inspect_impl.h b/libabckit/src/metadata_inspect_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..c156b877ab27450b9fc38cc0c0f1529670558b81 --- /dev/null +++ b/libabckit/src/metadata_inspect_impl.h @@ -0,0 +1,471 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_STD_METADATA_INSPECT_IMPL_H +#define LIBABCKIT_STD_METADATA_INSPECT_IMPL_H + +#include "libabckit/include/metadata.h" + +#include +#include +#include +#include +#include +#include + +namespace libabckit { + +enum class Mode { + DYNAMIC, + STATIC, +}; + +typedef struct pandasm_Program pandasm_Program; +typedef struct pandasm_Record pandasm_Record; +typedef struct pandasm_Field pandasm_Field; +typedef struct pandasm_Function pandasm_Function; +typedef struct pandasm_Annotation pandasm_Annotation; +typedef struct pandasm_AnnotationElement pandasm_AnnotationElement; +typedef struct pandasm_Value pandasm_Value; +typedef struct pandasm_Literal pandasm_Literal; +typedef struct pandasm_LiteralArray pandasm_LiteralArray; + +} // namespace libabckit + +/* ==================== + * Internal implementations for all of the abckit_* structures + */ + +/* + * FIXME: after v1 releases, move this enum to the user headers, add static types + * FIXME: come up with a better name + */ +enum abckit_ImportExportDescriptorKind { + UNTYPED, // Applies to: JavaScript +}; + +enum abckit_DynamicExportKind { + abckit_DynamicExportKind_LOCAL_EXPORT, + abckit_DynamicExportKind_INDIRECT_EXPORT, + abckit_DynamicExportKind_STAR_EXPORT, +}; + +struct abckit_Value { + /* + * Underlying implementation + */ + libabckit::pandasm_Value *impl; +}; + +struct abckit_AnnotationInterface { + /* + * To refer to the properties of the origin module. + */ + abckit_Module *m; + + /* + * Points to the pandasm_Record that stores annotation definition. + */ + libabckit::pandasm_Record *impl; + + /* + * Contains annotation interface fields + */ + std::vector> fields; +}; + +struct abckit_AnnotationInterfaceField { + /* + * To refer to the properties of the origin annotation interface. + */ + abckit_AnnotationInterface *ai; + + /* + * Field name + */ + abckit_String *name; + + /* + * Field type + */ + abckit_Type *type; + + /* + * Field value + */ + abckit_Value *value; +}; + +struct abckit_AnnotationElement { + /* + * To refer to the properties of the origin annotation. + */ + abckit_Annotation *ann; + + /* + * Name of annotation element + */ + std::string name; + + /* + * Value stored in annotation + */ + std::unique_ptr value; +}; + +struct abckit_Annotation { + /* + * To refer to the properties of the owner. + */ + std::variant owner; + + /* + * Name of the annotation + */ + std::string name; + + /* + * Annotation elements + */ + std::vector> elements; +}; + +union abckit_ClassPayload { + /* + * In JS class is defined by it's constructor. + */ + libabckit::pandasm_Function *fn; + /* + * In STS class is defined by corresponding pandasm_Record. + */ + libabckit::pandasm_Record *cl; +}; + +struct abckit_Class { + /* + * To refer to the properties of the origin module. + */ + abckit_Module *m; + + /* + * To store back links to the wrapped methods. + */ + std::vector> methods; + + /* + * Language-dependent implementation to store class data. + */ + abckit_ClassPayload impl; + + /* + * To store links to the wrapped annotations. + */ + std::vector> annotations; +}; + +struct abckit_Method { + /* + * To refer to the properties of the origin module. + */ + abckit_Module *m; + + /* + * To be able to refer to the class where method is defined. + * For global functions the rules are as follows: + * - Dynamic: pandasm_Function with js file name. + * - Static: pandasm_Record with name `L/.../ETSGLOBAL`. + */ + abckit_Class *klass; + + /* + * All info is stored inside pandasm_Function. + */ + libabckit::pandasm_Function *impl; + + /* + * To store links to the wrapped annotations. + */ + std::vector> annotations; +}; + +struct abckit_ModulePayloadDyn { + /* + * In JS module is defined by corresponding pandasm_Record and abckit_LiteralArray. + */ + const libabckit::pandasm_Record *record; + abckit_LiteralArray *moduleLiteralArray; + abckit_LiteralArray *scopeNamesLiteralArray; + bool absPaths; + size_t ModuleRequestsOffset; + size_t RegularImportsOffset; + size_t NamespaceImportsOffset; + size_t LocalExportsOffset; + size_t IndirectExportsOffset; + size_t StarExportsOffset; +}; + +union abckit_ModulePayload { + /* + * Implementation for JS. + */ + + abckit_ModulePayloadDyn dyn; + /* + * Some data structure for STS which should store module's name and other data. + */ +}; + +struct abckit_Module { + /* + * To refer to the properties of the original `.abc` file, such as is it dynamic, etc. + */ + abckit_File *ctxI; + + /* + * Stores module's dependencies. + * NOTE: For JS index here must match the index in `module_requests`. + */ + std::vector md; + + /* + * Stores module's imports. + * NOTE: For JS will need to perform linear search to find needed import, + * because namespace imports and regular imports are stored together here. + */ + std::vector> id; + + /* + * Stores module's exports. + * NOTE: For JS will need to perform linear search to find needed import, + * because local exports, indirect exports and star exports are stored together here. + */ + std::vector> ed; + + /* + * Tables to store and find wrapped entities by their name. + */ + std::unordered_map> ct; + std::unordered_map> at; + + /* + * Only stores top level functions. + */ + std::vector> methods; + + /* + * Current module's name. + */ + abckit_String *moduleName; + + /* + * Indicator whether current module is local or external. + */ + bool isExternal; + + /* + * Language-dependent implementation to store module data. + */ + abckit_ModulePayload impl; +}; + +struct abckit_String { + std::string impl; +}; + +struct abckit_Code { + libabckit::pandasm_Function *newCode; + abckit_Method *method; +}; + +struct abckit_Literal { + libabckit::pandasm_Literal* val; +}; + +struct abckit_Type { + abckit_TypeId id; + size_t rank; + abckit_Class *klass; +}; + +struct abckit_File { //abckit_Core_File + libabckit::Mode mode; + + /* + * Table to store wrapped internal modules. + */ + std::unordered_map> localModules; + + /* + * Table to store wrapped external modules. + */ + std::unordered_map> externalModules; + + /* + * To store the original program and update it. + */ + libabckit::pandasm_Program *program; + + std::vector> litvals; + std::vector> values; + std::vector> types; + + /* + * To store all program strings + */ + std::unordered_map> strings; + + /* + * To to store the .abc file version + */ + abckit_File_Version version; + + void *internal; +}; + +struct abckit_DynamicImportDescriptorPayload { + /* + * Indicator whether import is namespace or regular. + */ + bool isRegularImport; + /* + * Offset in the corresponding `XXX_imports` in mainline. + */ + uint32_t moduleRecordIndexOff; +}; + +union abckit_StaticImportDescriptorPayload { + /* + * Implementation for abckit_ImportExportDescriptorKind::ANNOTATION. + */ + abckit_AnnotationInterface *ai; + /* + * Implementation for abckit_ImportExportDescriptorKind::CLASS. + */ + abckit_Class *cl; + /* + * Implementation for abckit_ImportExportDescriptorKind::FUNCTION. + */ + abckit_Method *fn; + /* + * Implementation for abckit_ImportExportDescriptorKind::FIELD. + */ + abckit_Field *fld; +}; + +union abckit_ImportDescriptorPayload { + /* + * Implementation for abckit_ImportExportDescriptorKind::UNTYPED. + */ + abckit_DynamicImportDescriptorPayload dyn; + /* + * Implementation for static kinds. + */ + abckit_StaticImportDescriptorPayload stat; +}; + +struct abckit_ImportDescriptor { + /* + * Back link to the importing module. + */ + abckit_Module *importingModule; + /* + * Link to the module from which entity is imported. + */ + abckit_Module *importedModule; + /* + * Kind of the imported entity. + * Use abckit_ImportExportDescriptorKind::UNTYPED for imports from dynamic modules. + * Other kinds are used for imports from static modules. + */ + abckit_ImportExportDescriptorKind kind; + /* + * Data needed to work with the import. + */ + abckit_ImportDescriptorPayload payload; +}; + +struct abckit_DynamicExportDescriptorPayload { + /* + * The kind of export. Used to determine where to look by the index. + */ + abckit_DynamicExportKind kind; + /* + * For special StarExport case 'export * as from "..."'. + * It converts to NamespaceImport + LocalExport: + * import * as =ens{$i} from "..."; + * export =ens{$i} as ; + */ + bool hasServiceImport; + /* + * For special StarExport case 'export * as from "..."'. + */ + size_t serviceNamespaceImportIdx; + /* + * Offset in the corresponding `XXX_exports` (depends on the `kind`) in mainline. + */ + uint32_t moduleRecordIndexOff; +}; + +union abckit_ExportDescriptorPayload { + /* + * Implementation for abckit_ImportExportDescriptorKind::UNTYPED. + */ + abckit_DynamicExportDescriptorPayload dyn; + /* + * Payload for abckit_ImportExportDescriptorKind::ANNOTATION. + * Should point to the LOCAL entity. + */ + abckit_AnnotationInterface *ai; + /* + * Payload for abckit_ImportExportDescriptorKind::CLASS. + * Should point to the LOCAL entity. + */ + abckit_Class *cl; + /* + * Payload for abckit_ImportExportDescriptorKind::FUNCTION. + * Should point to the LOCAL entity. + */ + abckit_Method *fn; + /* + * Payload for abckit_ImportExportDescriptorKind::FIELD. + * Should point to the LOCAL entity. + */ + abckit_Field *fld; +}; + +struct abckit_ExportDescriptor { + /* + * Back link to the exporting module. + */ + abckit_Module *exportingModule; + /* + * Link to the exported module. + */ + abckit_Module *exportedModule; + /* + * Kind of the exported entity. + * Use abckit_ImportExportDescriptorKind::UNTYPED for exports from dynamic modules. + * Other kinds are used for exports from static modules. + * NOTE: Use same enum as import API here. May need to rename this enum + * when implementing v2 API to something neutral, like abckit_DescriptorKind. + */ + abckit_ImportExportDescriptorKind kind; + /* + * Data needed to work with the import. + */ + abckit_ExportDescriptorPayload payload; +}; + +#endif // LIBABCKIT_STD_METADATA_INSPECT_IMPL_H diff --git a/libabckit/src/metadata_modify_impl.cpp b/libabckit/src/metadata_modify_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f25400cffbc13bb3fc4b30d25f1ce84dcbf5c491 --- /dev/null +++ b/libabckit/src/metadata_modify_impl.cpp @@ -0,0 +1,849 @@ +/** + * Copyright (c) 2024 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 +#include +#include +#include "libabckit/include/abckit.h" +#include "libabckit/include/metadata.h" + +#include "libabckit/src/macros.h" + +#include "libabckit/src/metadata_inspect_impl.h" +#include "libabckit/src/metadata_modify_impl.h" +#include "libabckit/src/adapter_dynamic/metadata_modify_dynamic.h" +#include "libabckit/src/adapter_static/metadata_modify_static.h" + +namespace libabckit { + +// ======================================== +// File +// ======================================== + +extern "C" abckit_Module *FileAddExternalModule(abckit_File *ctx, + const struct abckit_ExternalModuleCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (ctx->mode) { + case Mode::DYNAMIC: + return FileAddExternalModuleDynamic(ctx, params); + break; + case Mode::STATIC: + return FileAddExternalModuleStatic(ctx, params); + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Module +// ======================================== + +extern "C" abckit_ImportDescriptor *ModuleAddImportFromDynamicModule( + abckit_Module *m, const abckit_ImportFromDynamicModuleCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleAddImportFromDynamicModuleDynamic(m, params); + break; + case Mode::STATIC: + return ModuleAddImportFromDynamicModuleStatic(m, params); + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ModuleRemoveImport(abckit_Module *m, abckit_ImportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(i, LIBABCKIT_RETURN_VOID); + + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleRemoveImportDynamic(m, i); + break; + case Mode::STATIC: + return ModuleRemoveImportStatic(m, i); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_ExportDescriptor *DynamicModuleAddExport(abckit_Module *m, + const abckit_DynamicModuleExportCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return DynamicModuleAddExportDynamic(m, params); + break; + case Mode::STATIC: + return DynamicModuleAddExportStatic(m, params); + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ModuleRemoveExport(abckit_Module *m, abckit_ExportDescriptor *i) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(i, LIBABCKIT_RETURN_VOID); + + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleRemoveExportDynamic(m, i); + break; + case Mode::STATIC: + return ModuleRemoveExportStatic(m, i); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_AnnotationInterface *ModuleAddAnnotationInterface( + abckit_ModifyContext *ctx, abckit_Module *m, const abckit_AnnotationInterfaceCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (m->ctxI->mode) { + case Mode::DYNAMIC: + return ModuleAddAnnotationInterfaceDynamic(ctx, m, params); + break; + case Mode::STATIC: + return ModuleAddAnnotationInterfaceStatic(ctx, m, params); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Class +// ======================================== + +extern "C" abckit_Annotation *ClassAddAnnotation(abckit_ModifyContext *ctx, abckit_Class *klass, + const abckit_AnnotationCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(klass, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (klass->m->ctxI->mode) { + case Mode::DYNAMIC: + return ClassAddAnnotationDynamic(ctx, klass, params); + break; + case Mode::STATIC: + return ClassAddAnnotationStatic(ctx, klass, params); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void ClassRemoveAnnotation(abckit_ModifyContext *ctx, abckit_Class *klass, abckit_Annotation *anno) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctx); + LIBABCKIT_BAD_ARGUMENT_VOID(klass); + LIBABCKIT_BAD_ARGUMENT_VOID(anno); + + switch (klass->m->ctxI->mode) { + case Mode::DYNAMIC: + ClassRemoveAnnotationDynamic(ctx, klass, anno); + break; + case Mode::STATIC: + ClassRemoveAnnotationStatic(ctx, klass, anno); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// AnnotationInterface +// ======================================== + +extern "C" abckit_AnnotationInterfaceField *AnnotationInterfaceAddField( + abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(ai, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (ai->m->ctxI->mode) { + case Mode::DYNAMIC: + return AnnotationInterfaceAddFieldDynamic(ctx, ai, params); + break; + case Mode::STATIC: + return AnnotationInterfaceAddFieldStatic(ctx, ai, params); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void AnnotationInterfaceRemoveField(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + abckit_AnnotationInterfaceField *field) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctx); + LIBABCKIT_BAD_ARGUMENT_VOID(ai); + LIBABCKIT_BAD_ARGUMENT_VOID(field); + + switch (ai->m->ctxI->mode) { + case Mode::DYNAMIC: + AnnotationInterfaceRemoveFieldDynamic(ctx, ai, field); + break; + case Mode::STATIC: + AnnotationInterfaceRemoveFieldStatic(ctx, ai, field); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Method +// ======================================== + +extern "C" void MethodSetCode(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code) +{ + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(ctxM, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(method, LIBABCKIT_RETURN_VOID); + LIBABCKIT_BAD_ARGUMENT(code, LIBABCKIT_RETURN_VOID); + + LIBABCKIT_BAD_ARGUMENT(method->m, LIBABCKIT_RETURN_VOID); + LIBABCKIT_WRONG_CTX_VOID(ctxM->ctxI, method->m->ctxI); + + switch (ctxM->ctxI->mode) { + case Mode::DYNAMIC: + return MethodSetCodeDynamic(ctxM, method, code); + break; + case Mode::STATIC: + return MethodSetCodeStatic(ctxM, method, code); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Annotation *MethodAddAnnotation(abckit_ModifyContext *ctx, abckit_Method *method, + const abckit_AnnotationCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(method, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + switch (method->m->ctxI->mode) { + case Mode::DYNAMIC: + return MethodAddAnnotationDynamic(ctx, method, params); + break; + case Mode::STATIC: + return MethodAddAnnotationStatic(ctx, method, params); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void MethodRemoveAnnotation(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctx); + LIBABCKIT_BAD_ARGUMENT_VOID(method); + LIBABCKIT_BAD_ARGUMENT_VOID(anno); + + switch (method->m->ctxI->mode) { + case Mode::DYNAMIC: + MethodRemoveAnnotationDynamic(ctx, method, anno); + break; + case Mode::STATIC: + MethodRemoveAnnotationStatic(ctx, method, anno); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Annotation +// ======================================== + +extern "C" abckit_AnnotationElement *AnnotationAddAnnotationElement(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(anno, nullptr); + LIBABCKIT_BAD_ARGUMENT(params, nullptr); + + abckit_Module *module = nullptr; + if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } else if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT(module, nullptr); + + switch (module->ctxI->mode) { + case Mode::DYNAMIC: + return AnnotationAddAnnotationElementDynamic(ctx, anno, params); + break; + case Mode::STATIC: + return AnnotationAddAnnotationElementStatic(ctx, anno, params); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" void AnnotationRemoveAnnotationElement(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElement *elem) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT_VOID(ctx); + LIBABCKIT_BAD_ARGUMENT_VOID(anno); + LIBABCKIT_BAD_ARGUMENT_VOID(elem); + + abckit_Module *module = nullptr; + if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } else if (std::holds_alternative(anno->owner)) { + module = std::get(anno->owner)->m; + } + + LIBABCKIT_BAD_ARGUMENT_VOID(module); + + switch (module->ctxI->mode) { + case Mode::DYNAMIC: + AnnotationRemoveAnnotationElementDynamic(ctx, anno, elem); + break; + case Mode::STATIC: + AnnotationRemoveAnnotationElementStatic(ctx, anno, elem); + break; + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// Type +// ======================================== + +extern "C" abckit_Type *CreateType(abckit_ModifyContext *ctx, abckit_TypeId id) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + auto type = std::make_unique(); + type->rank = 0; + type->id = id; + type->klass = nullptr; + ctx->ctxI->types.emplace_back(std::move(type)); + auto res = ctx->ctxI->types.back().get(); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; +} + +extern "C" abckit_Type *CreateReferenceType(abckit_ModifyContext *ctx, abckit_Class *klass) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(klass, nullptr); + auto type = std::make_unique(); + type->id = abckit_TypeId::abckit_TypeId_REFERENCE; + type->rank = 0; + type->klass = klass; + ctx->ctxI->types.emplace_back(std::move(type)); + auto res = ctx->ctxI->types.back().get(); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; +} + +// ======================================== +// Value +// ======================================== + +extern "C" abckit_Value *CreateValueU1(abckit_ModifyContext *ctx, bool value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateValueU1Dynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateValueU1Dynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } + return CreateValueU1Dynamic(ctx, value); +} + +extern "C" abckit_Value *CreateValueDouble(abckit_ModifyContext *ctx, double value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateValueDoubleDynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateValueDoubleDynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } + return CreateValueDoubleDynamic(ctx, value); +} + +extern "C" abckit_Value *CreateValueString(abckit_ModifyContext *ctxM, const char *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxM, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + switch (ctxM->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateValueStringDynamic(ctxM, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateValueStringDynamic(ctxM, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } + return CreateValueStringDynamic(ctxM, value); +} + +extern "C" abckit_Value *CreateLiteralArrayValue(abckit_ModifyContext *ctx, abckit_Value **value, size_t size) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralArrayValueDynamic(ctx, value, size); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralArrayValueStatic(ctx, value, size); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// String +// ======================================== + +extern "C" abckit_String *CreateString(abckit_ModifyContext *ctxM, const char *value) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxM, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + + auto *ctx = ctxM->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto *res = CreateStringDynamic(ctxM, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateStringStatic(ctxM, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +// ======================================== +// LiteralArray +// ======================================== + +extern "C" abckit_LiteralArray *CreateLiteralArray(abckit_ModifyContext *ctxM, abckit_Literal **value, size_t size) +{ + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctxM, nullptr); + LIBABCKIT_BAD_ARGUMENT(value, nullptr); + auto *ctx = ctxM->ctxI; + switch (ctx->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralArrayDynamic(ctxM, value, size); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralArrayStatic(ctxM, value, size); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralBool(abckit_ModifyContext *ctx, bool value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralBoolDynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralBoolStatic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralU8(abckit_ModifyContext *ctx, uint8_t value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralU8Dynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralU8Static(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralU16(abckit_ModifyContext *ctx, uint16_t value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralU16Dynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralU16Static(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralU32(abckit_ModifyContext *ctx, uint32_t value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralU32Dynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralU32Static(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralU64(abckit_ModifyContext *ctx, uint64_t value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralU64Dynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralU64Static(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralFloat(abckit_ModifyContext *ctx, float value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralFloatDynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralFloatStatic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralDouble(abckit_ModifyContext *ctx, double value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralDoubleDynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralDoubleStatic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +extern "C" abckit_Literal *CreateLiteralString(abckit_ModifyContext *ctx, const char* value) { + LIBABCKIT_CLEAR_LAST_ERROR + LIBABCKIT_IMPLEMENTED + + LIBABCKIT_BAD_ARGUMENT(ctx, nullptr); + switch (ctx->ctxI->mode) { + case Mode::DYNAMIC: { + auto *res = CreateLiteralStringDynamic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + case Mode::STATIC: { + auto *res = CreateLiteralStringStatic(ctx, value); + LIBABCKIT_CHECK_ALLOCATION(res); + return res; + } + default: + LIBABCKIT_UNREACHABLE + } +} + +abckit_ModifyApi g_ModifyApiImpl = { + + // ======================================== + // File + // ======================================== + + FileAddExternalModule, + + // ======================================== + // Module + // ======================================== + + ModuleAddImportFromDynamicModule, + ModuleRemoveImport, + DynamicModuleAddExport, + ModuleRemoveExport, + ModuleAddAnnotationInterface, + + // ======================================== + // Class + // ======================================== + + ClassAddAnnotation, + ClassRemoveAnnotation, + + // ======================================== + // AnnotationInterface + // ======================================== + + AnnotationInterfaceAddField, + AnnotationInterfaceRemoveField, + + // ======================================== + // Method + // ======================================== + + MethodSetCode, + MethodAddAnnotation, + MethodRemoveAnnotation, + + // ======================================== + // Annotation + // ======================================== + + AnnotationAddAnnotationElement, + AnnotationRemoveAnnotationElement, + + // ======================================== + // Type + // ======================================== + + CreateType, + CreateReferenceType, + + // ======================================== + // Value + // ======================================== + + CreateValueU1, + CreateValueDouble, + CreateValueString, + CreateLiteralArrayValue, + + // ======================================== + // String + // ======================================== + + CreateString, + + // ======================================== + // LiteralArray + // ======================================== + + CreateLiteralArray, + + // ======================================== + // LiteralArray + // ======================================== + + CreateLiteralBool, + CreateLiteralU8, + CreateLiteralU16, + CreateLiteralU32, + CreateLiteralU64, + CreateLiteralFloat, + CreateLiteralDouble, + CreateLiteralString, +}; + +} // namespace libabckit + +extern "C" abckit_ModifyApi const *abckit_GetModifyApiImpl(int version) +{ + if (version != LIBABCKIT_VERSION) { + return nullptr; + } + return &libabckit::g_ModifyApiImpl; +} diff --git a/libabckit/src/metadata_modify_impl.h b/libabckit/src/metadata_modify_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..789e4542ddaca1c90df73cd706be1f17daa42f2d --- /dev/null +++ b/libabckit/src/metadata_modify_impl.h @@ -0,0 +1,25 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_STD_METADATA_MODIFY_IMPL_H +#define LIBABCKIT_STD_METADATA_MODIFY_IMPL_H + +#include "libabckit/src/metadata_inspect_impl.h" + +struct abckit_ModifyContext { + abckit_File *ctxI; +}; + +#endif //LIBABCKIT_STD_METADATA_MODIFY_IMPL_H diff --git a/libabckit/src/statuses_impl.cpp b/libabckit/src/statuses_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..78a061fd192eb1f00fa423f1ab5546de723f4362 --- /dev/null +++ b/libabckit/src/statuses_impl.cpp @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/statuses_impl.h" + +namespace libabckit::statuses { + +thread_local abckit_Status LastError; + +abckit_Status GetLastError() +{ + return LastError; +} + +void SetLastError(abckit_Status err) +{ + LastError = err; +} + +} // libabckit::statuses diff --git a/libabckit/src/statuses_impl.h b/libabckit/src/statuses_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..97a76fbab3316b1d5769020e328b644b79b62c3f --- /dev/null +++ b/libabckit/src/statuses_impl.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_STATUSES_IMPL_H +#define LIBABCKIT_SRC_STATUSES_IMPL_H + +#include "libabckit/include/statuses.h" + +namespace libabckit::statuses { + +abckit_Status GetLastError(); +void SetLastError(abckit_Status); + +} // libabckit::statuses + +#endif //LIBABCKIT_SRC_STATUSES_IMPL_H diff --git a/libabckit/src/templates/bct_intrinsics/BUILD.gn b/libabckit/src/templates/bct_intrinsics/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9b500274dcdf8f2c92959792d943bfd817d87768 --- /dev/null +++ b/libabckit/src/templates/bct_intrinsics/BUILD.gn @@ -0,0 +1,74 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +intrinsics_compiler_gen_dir = get_label_info("$ark_root/compiler:libarkcompiler_intrinsics_gen_inl_get_intrinsics_names_inl(${host_toolchain})", "target_gen_dir") +isa_gen_dir = get_label_info("$ark_root/isa:isa_combine", "target_gen_dir") +ark_gen("ark_gen_libabckit") { + data = [ "../../bct_compiler_intrinsics.yaml", + "$isa_gen_dir/isa.yaml" ] + template_files = [ + "inst_builder_bct_intrinsics.inc.erb" + ] + sources = "." + api = [ + "$ark_root/compiler/optimizer/templates/intrinsics/compiler_intrinsics.rb", + "$ark_root/isa/isapi.rb" + ] + extra_dependencies = [ "$ark_root/isa:isa_combine", + "$ark_root/runtime:arkruntime_gen_intrinsics_yaml", + "../dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_opcodes_inc" ] + requires = [ "$ark_root/libpandabase/utils.rb" ] + destination = "$intrinsics_compiler_gen_dir/generated" +} + +ark_gen("ark_gen_libabckit") { + data = [ "../../bct_compiler_intrinsics.yaml", + "$isa_gen_dir/isa.yaml" ] + template_files = [ + "bct_intrinsics_opcodes.inc.erb" + ] + sources = "." + api = [ + "$ark_root/compiler/optimizer/templates/intrinsics/compiler_intrinsics.rb", + "$ark_root/isa/isapi.rb" + ] + extra_dependencies = [ "$ark_root/isa:isa_combine", + "$ark_root/runtime:arkruntime_gen_intrinsics_yaml", + "../dyn_intrinsics/:isa_gen_libabckit_dyn_intrinsics_opcodes_inc" ] + requires = [ "$ark_root/libpandabase/utils.rb" ] + destination = "$intrinsics_compiler_gen_dir/generated" +} + +bco_gen_dir = get_label_info("$ark_root/bytecode_optimizer:libarktsbytecodeopt(${host_toolchain})", "target_gen_dir") +ark_gen("ark_gen_libabckit") { + data = [ "../../bct_compiler_intrinsics.yaml", + "$isa_gen_dir/isa.yaml" ] + template_files = [ + "bct_intrinsics_vreg_width.h.erb", + "bct_intrinsics.inl.erb" + ] + sources = "." + api = [ + "$ark_root/compiler/optimizer/templates/intrinsics/compiler_intrinsics.rb", + "$ark_root/isa/isapi.rb" + ] + extra_dependencies = [ "$ark_root/isa:isa_combine", + "$ark_root/runtime:arkruntime_gen_intrinsics_yaml", + "../dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_cases_inc" ] + requires = [ "$ark_root/libpandabase/utils.rb" ] + destination = "$bco_gen_dir/generated" +} \ No newline at end of file diff --git a/libabckit/src/templates/bct_intrinsics/bct_intrinsics.inl.erb b/libabckit/src/templates/bct_intrinsics/bct_intrinsics.inl.erb new file mode 100644 index 0000000000000000000000000000000000000000..f2dc4d03d446317d4d1e5b72c73c1eb67d941351 --- /dev/null +++ b/libabckit/src/templates/bct_intrinsics/bct_intrinsics.inl.erb @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +bool IsETSIntrinsic(compiler::RuntimeInterface::IntrinsicId intrinsicId) +{ + switch(intrinsicId) { +% ['LD_OBJ', 'ST_OBJ'].each do |name| + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_<%= name %>_BY_NAME_OBJ: + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_<%= name %>_BY_NAME_F64: + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_<%= name %>_BY_NAME_F32: + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_<%= name %>_BY_NAME_I64: + case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_<%= name %>_BY_NAME_I32: +% end + return true; + default: + return false; + } +} + +bool IsBCTIntrinsic(compiler::RuntimeInterface::IntrinsicId intrinsicId) +{ + switch(intrinsicId) { +#include "dyn_intrinsics_cases.inc" +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: +% end + return true; + default: + return IsETSIntrinsic(intrinsicId); + } +} + +% ['InitObject', 'LoadObject', 'StoreObject', 'LoadStatic', 'StoreStatic', 'LoadArray', 'StoreArray', 'NewArray'].each do |name| +bool IsBCT<%= name %>(compiler::RuntimeInterface::IntrinsicId intrinsicId) +{ + switch(intrinsicId) { +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: +% if (intrinsic.class_name == name) + return true; +% else + return false; +% end +% end + default: + return false; + } +} +% end + +bool IsBCTIntrinsicRange(compiler::RuntimeInterface::IntrinsicId id) +{ + if (id == compiler::RuntimeInterface::IntrinsicId::DYN_CALLRANGE_IMM8_IMM8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_WIDE_CALLRANGE_PREF_IMM16_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_CALLTHISRANGE_IMM8_IMM8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_WIDE_CALLTHISRANGE_PREF_IMM16_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_NEWOBJRANGE_IMM8_IMM8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_NEWOBJRANGE_IMM16_IMM8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_WIDE_NEWOBJRANGE_PREF_IMM16_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_SUPERCALLTHISRANGE_IMM8_IMM8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_SUPERCALLARROWRANGE_IMM8_IMM8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_WIDE_SUPERCALLTHISRANGE_PREF_IMM16_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_WIDE_SUPERCALLARROWRANGE_PREF_IMM16_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_CREATEOBJECTWITHEXCLUDEDKEYS_IMM8_V8_V8 || + id == compiler::RuntimeInterface::IntrinsicId::DYN_WIDE_CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8) + { + return true; + } + switch(id) { +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: +% if (intrinsic.method_name.include? "range") + return true; +% else + return false; +% end +% end + default: + return false; + } +} diff --git a/libabckit/src/templates/bct_intrinsics/bct_intrinsics_opcodes.inc.erb b/libabckit/src/templates/bct_intrinsics/bct_intrinsics_opcodes.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..75b375642696ab8876e7b051b10e7c6b7dd956a2 --- /dev/null +++ b/libabckit/src/templates/bct_intrinsics/bct_intrinsics_opcodes.inc.erb @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +#include "src/adapter_dynamic/runtime_adapter_dynamic.h" +#include "dyn_intrinsics_opcodes.inc" + +namespace libabckit { + +// NOLINTNEXTLINE(readability-function-size) +static inline abckit_IsaApiStaticOpcode GetStaticIntrinsicOpcode(compiler::IntrinsicInst *inst) { + switch(inst->GetIntrinsicId()) { +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: + return abckit_IsaApiStaticOpcode_<%= intrinsic.class_name %>; +% end + default: { + LIBABCKIT_UNREACHABLE + //return GetDYNIntrinsicOpcode(inst); + } + } +} + +static inline abckit_IsaApiDynamicOpcode GetDynamicIntrinsicOpcode(compiler::IntrinsicInst *inst) { + return GetDYNIntrinsicOpcode(inst); +} + +} // libabckit \ No newline at end of file diff --git a/libabckit/src/templates/bct_intrinsics/bct_intrinsics_vreg_width.h.erb b/libabckit/src/templates/bct_intrinsics/bct_intrinsics_vreg_width.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..773dd1b224099e80a99c7975c451f4dd8f741251 --- /dev/null +++ b/libabckit/src/templates/bct_intrinsics/bct_intrinsics_vreg_width.h.erb @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +#include "bytecode_optimizer/reg_encoder.h" + +void CheckWidthBCTIntrinsic(ark::bytecodeopt::RegEncoder *re, ark::compiler::Inst *inst) +{ + ASSERT(inst->IsIntrinsic()); + switch(inst->CastToIntrinsic()->GetIntrinsicId()) { +#include "dyn_intrinsics_cases.inc" +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case ark::compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: +% if (intrinsic.method_name.include? "range") + re->Check4Width(inst); + return; +% end +% inst = nil +% Panda::instructions.each do |asm_ins| +% if (asm_ins.mnemonic == intrinsic.method_name) +% inst = asm_ins +% end +% end +% reg = inst.operands.select(&:reg?).first +% if reg + re->Check<%= reg.width %>Width(inst); + return; +% else + return; +% end +% end + default: + return; + } +} + +bool IsDstRegNeedRenumbering(ark::compiler::Inst *inst) { + if (!inst->IsIntrinsic()) { + return false; + } + if (inst->CastToIntrinsic()->GetIntrinsicId() == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT || + inst->CastToIntrinsic()->GetIntrinsicId() == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT_WIDE || + inst->CastToIntrinsic()->GetIntrinsicId() == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT_OBJECT || + inst->CastToIntrinsic()->GetIntrinsicId() == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_NEW_ARRAY) { + return true; + } + return false; +} diff --git a/libabckit/src/templates/bct_intrinsics/inst_builder_bct_intrinsics.inc.erb b/libabckit/src/templates/bct_intrinsics/inst_builder_bct_intrinsics.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..a0c1c60bc9dcbae356be34d4003b19245accd6eb --- /dev/null +++ b/libabckit/src/templates/bct_intrinsics/inst_builder_bct_intrinsics.inc.erb @@ -0,0 +1,471 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +<% +require 'yaml' + +def get_type(type) + @type_map ||= { + 'u1' => 'DataType::BOOL', + 'i8' => 'DataType::INT8', + 'i16' => 'DataType::INT16', + 'i32' => 'DataType::INT32', + 'i64' => 'DataType::INT64', + 'u8' => 'DataType::UINT8', + 'u16' => 'DataType::UINT16', + 'u32' => 'DataType::UINT32', + 'u64' => 'DataType::UINT64', + 'b32' => 'DataType::UINT32', + 'b64' => 'DataType::UINT64', + 'f32' => 'DataType::FLOAT32', + 'f64' => 'DataType::FLOAT64', + 'ref' => 'DataType::REFERENCE', + 'any' => 'DataType::ANY', + 'i8[]' => 'DataType::INT8', + 'i16[]' => 'DataType::INT16', + 'i32[]' => 'DataType::INT32', + 'i64[]' => 'DataType::INT64', + 'u8[]' => 'DataType::UINT8', + 'u16[]' => 'DataType::UINT16', + 'u32[]' => 'DataType::UINT32', + 'u64[]' => 'DataType::UINT64', + 'b32[]' => 'DataType::UINT32', + 'b64[]' => 'DataType::UINT64', + 'f32[]' => 'DataType::FLOAT32', + 'f64[]' => 'DataType::FLOAT64', + 'ref[]' => 'DataType::REFERENCE', + 'none' => 'DataType::VOID'} + raise "Unknown type #{type}" if @type_map[type].nil? + @type_map[type] +end + +def get_cc(inst) + return 'ConditionCode::CC_EQ' if inst.opcode.start_with? 'jeq' + return 'ConditionCode::CC_NE' if inst.opcode.start_with? 'jne' + return 'ConditionCode::CC_LT' if inst.opcode.start_with? 'jlt' + return 'ConditionCode::CC_GT' if inst.opcode.start_with? 'jgt' + return 'ConditionCode::CC_LE' if inst.opcode.start_with? 'jle' + return 'ConditionCode::CC_GE' if inst.opcode.start_with? 'jge' + raise 'get_cc: wrong opcode #{inst.opcode}' +end + +%> + +#include "bct_intrinsics.inl" + +void InstBuilder::BuildDefaultBCTIntrinsic(const BytecodeInstruction *bcInst, RuntimeInterface::IntrinsicId intrinsicId) +{ + auto pc = GetPc(bcInst->GetAddress()); + ASSERT(!IsBCTInitObject(intrinsicId) && !IsBCTLoadObject(intrinsicId) && !IsBCTStoreObject(intrinsicId) && + !IsBCTLoadStatic(intrinsicId) && !IsBCTStoreStatic(intrinsicId) && !IsBCTLoadArray(intrinsicId) && !IsBCTStoreArray(intrinsicId)); + switch (intrinsicId) { +% inst = nil +% Compiler::intrinsics.select {|intrinsic| intrinsic.space == "bct" }.each do |intrinsic| + case ark::compiler::RuntimeInterface::IntrinsicId::<%= intrinsic.entrypoint_name %>: { +% Panda::instructions.each do |asm_ins| +% if (asm_ins.mnemonic == intrinsic.method_name) +% inst = asm_ins +% end +% end +% if (inst) +% format = "BytecodeInst::Format::" + inst.format.pretty.upcase +% acc_read = inst.acc.include?("in") +% acc_write = inst.acc.include?("out") +% ret_type = acc_write ? get_type(intrinsic.signature.ret) : "DataType::VOID" +% params_arr = inst.operands +% num_vregs = params_arr.select{|b| b.reg? && b.src?}.length +% num_imms = params_arr.select{|b| b.imm?}.length +% num_ids = params_arr.select{|b| b.id?}.length +% num_inputs = acc_read ? num_vregs + 1 : num_vregs + auto retType = ark::compiler::<%= get_type(intrinsic.signature.ret) %>; + ark::compiler::IntrinsicInst *inst = GetGraph()->CreateInstIntrinsic(retType, pc, intrinsicId); +% if (num_inputs != 0) + size_t inputsCount = <%= num_inputs %>; + inst->ReserveInputs(inputsCount); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), inputsCount); +% end +% imm_index = 0 +% vreg_index = 0 +% id16_index = 0 +% out_idx = nil +% params_arr.each do |param| +% if param.imm? + auto imm<%= imm_index %> = static_cast(bcInst->GetImm<<%= format %>, <%= imm_index %>>()); + inst->AddImm(GetGraph()->GetAllocator(), imm<%= imm_index %>); +% imm_index = imm_index + 1 +% elsif param.reg? +% if param.src? + { + auto input = GetDefinition(bcInst->GetVReg(<%= vreg_index %>)); + inst->AppendInput(input); + inst->AddInputType(ark::compiler::<%= get_type(param.type) %>); + } +% else +% out_idx = vreg_index +% end +% vreg_index = vreg_index + 1 +% elsif param.id? +% if inst.properties.include?("string_id") + uint32_t stringId<%= id16_index %> = bcInst->GetId(<%= id16_index %>).AsFileId().GetOffset(); + inst->AddImm(GetGraph()->GetAllocator(), stringId<%= id16_index %>); +% elsif inst.properties.include?("literalarray_id") + uint32_t literalarrayId<%= id16_index %> = bcInst->GetId(<%= id16_index %>).AsIndex(); + inst->AddImm(GetGraph()->GetAllocator(), literalarrayId<%= id16_index %>); +% elsif inst.properties.include?("type_id") + uint32_t typeId<%= id16_index %> = bcInst->GetId(<%= id16_index %>).AsIndex(); + typeId<%= id16_index %> = GetRuntime()->ResolveTypeIndex(GetGraph()->GetMethod(), typeId<%= id16_index %>); + inst->AddImm(GetGraph()->GetAllocator(), typeId<%= id16_index %>); +% elsif inst.properties.include?("method_id") + uint32_t mId<%= id16_index %> = bcInst->GetId(<%= id16_index %>).AsIndex(); + mId<%= id16_index %> = GetRuntime()->ResolveMethodIndex(GetGraph()->GetMethod(), mId<%= id16_index %>); + inst->AddImm(GetGraph()->GetAllocator(), mId<%= id16_index %>); +% end +% id16_index = id16_index + 1 +% end +% end +% if acc_read + { + auto input = GetDefinitionAcc(); + inst->AppendInput(input); +% op = inst.acc_and_operands.select { |op| op.acc? && op.src? }.first + inst->AddInputType(ark::compiler::<%= get_type(op.type) %>); + } +% end + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); +% if acc_write + UpdateDefinitionAcc(inst); +% end +% if out_idx + UpdateDefinition(bcInst->GetVReg(<%= out_idx %>), inst); +% end +% end + return; + } +% end + default: + return; + } +} + +constexpr compiler::Register MAX_NUM_SHORT_CALL_ARGS = 2; +constexpr compiler::Register MAX_NUM_NON_RANGE_ARGS = 4; + +void InstBuilder::BuildBCTInitObjectIntrinsic(const BytecodeInstruction *bcInst, bool isRange) +{ + auto methodId = GetRuntime()->ResolveMethodIndex(GetMethod(), bcInst->GetId(0).AsIndex()); + size_t argsCount = GetMethodArgumentsCount(methodId); + ark::compiler::IntrinsicInst *inst {nullptr}; + if (argsCount > MAX_NUM_NON_RANGE_ARGS) { + inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_INIT_OBJECT_RANGE); + } else if (argsCount > MAX_NUM_SHORT_CALL_ARGS) { + inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_INIT_OBJECT); + } else { + inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_INIT_OBJECT_SHORT); + } + inst->AddImm(GetGraph()->GetAllocator(), methodId); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), argsCount); + if (isRange) { + auto startReg = bcInst->GetVReg(0); + for (size_t i = 0; i < argsCount; startReg++, i++) { + inst->AppendInput(GetDefinition(startReg)); + inst->AddInputType(GetRuntime()->GetMethodArgumentType(GetMethod(), methodId, i)); + } + } else { + for (size_t i = 0; i < argsCount; i++) { + inst->AppendInput(GetDefinition(bcInst->GetVReg(i))); + inst->AddInputType(GetRuntime()->GetMethodArgumentType(GetMethod(), methodId, i)); + } + } + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); + UpdateDefinitionAcc(inst); +} + +template +void InstBuilder::BuildBCTLoadObjectIntrinsic(const BytecodeInstruction *bcInst, ark::compiler::DataType::Type rawRetType) +{ + auto fieldId = GetRuntime()->ResolveFieldIndex(GetMethod(), bcInst->GetId(0).AsIndex()); + auto retType = rawRetType; + if (rawRetType != ark::compiler::DataType::REFERENCE) { + retType = GetRuntime()->GetFieldTypeById(GetMethod(), fieldId); + } + ark::compiler::IntrinsicInst *inst {nullptr}; + switch (rawRetType) { + case ark::compiler::DataType::UINT32: { + inst = GetGraph()->CreateInstIntrinsic(retType, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT); + break; + } + case ark::compiler::DataType::UINT64: { + inst = GetGraph()->CreateInstIntrinsic(retType, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT_WIDE); + break; + } + case ark::compiler::DataType::REFERENCE: { + inst = GetGraph()->CreateInstIntrinsic(retType, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT_OBJECT); + break; + } + default: + UNREACHABLE(); + } + inst->AddImm(GetGraph()->GetAllocator(), fieldId); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), 1); + inst->AppendInput(GetDefinition(bcInst->GetVReg(IS_ACC_WRITE ? 0 : 1))); + inst->AddInputType(ark::compiler::DataType::REFERENCE); + + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); + if constexpr (IS_ACC_WRITE) { + UpdateDefinitionAcc(inst); + } else { + UpdateDefinition(bcInst->GetVReg(0), inst); + } +} + +template +void InstBuilder::BuildBCTStoreObjectIntrinsic(const BytecodeInstruction *bcInst, ark::compiler::DataType::Type rawType) +{ + auto fieldId = GetRuntime()->ResolveFieldIndex(GetMethod(), bcInst->GetId(0).AsIndex()); + auto type = rawType; + if (rawType != ark::compiler::DataType::REFERENCE) { + type = GetRuntime()->GetFieldTypeById(GetMethod(), fieldId); + } + ark::compiler::IntrinsicInst *inst {nullptr}; + switch (rawType) { + case ark::compiler::DataType::UINT32: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_OBJECT); + break; + } + case ark::compiler::DataType::UINT64: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_OBJECT_WIDE); + break; + } + case ark::compiler::DataType::REFERENCE: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_OBJECT_OBJECT); + break; + } + default: + UNREACHABLE(); + } + + inst->AddImm(GetGraph()->GetAllocator(), fieldId); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), 2); + ark::compiler::Inst *storeVal = nullptr; + if constexpr (IS_ACC_READ) { + storeVal = GetDefinitionAcc(); + } else { + storeVal = GetDefinition(bcInst->GetVReg(0)); + } + inst->AppendInput(GetDefinition(bcInst->GetVReg(IS_ACC_READ ? 0 : 1))); + inst->AddInputType(ark::compiler::DataType::REFERENCE); + inst->AppendInput(storeVal); + inst->AddInputType(type); + + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); +} + +void InstBuilder::BuildBCTLoadStaticIntrinsic(const BytecodeInstruction *bcInst, ark::compiler::DataType::Type rawType) +{ + auto fieldId = GetRuntime()->ResolveFieldIndex(GetMethod(), bcInst->GetId(0).AsIndex()); + auto type = rawType; + if (rawType != ark::compiler::DataType::REFERENCE) { + type = GetRuntime()->GetFieldTypeById(GetMethod(), fieldId); + } + ark::compiler::IntrinsicInst *inst {nullptr}; + switch (rawType) { + case ark::compiler::DataType::UINT32: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STATIC); + break; + } + case ark::compiler::DataType::UINT64: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STATIC_WIDE); + break; + } + case ark::compiler::DataType::REFERENCE: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STATIC_OBJECT); + break; + } + default: + UNREACHABLE(); + } + inst->AddImm(GetGraph()->GetAllocator(), fieldId); + + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); + UpdateDefinitionAcc(inst); +} + +void InstBuilder::BuildBCTStoreStaticIntrinsic(const BytecodeInstruction *bcInst, ark::compiler::DataType::Type rawType) +{ + auto fieldId = GetRuntime()->ResolveFieldIndex(GetMethod(), bcInst->GetId(0).AsIndex()); + auto type = rawType; + if (rawType != ark::compiler::DataType::REFERENCE) { + type = GetRuntime()->GetFieldTypeById(GetMethod(), fieldId); + } + ark::compiler::IntrinsicInst *inst {nullptr}; + switch (rawType) { + case ark::compiler::DataType::UINT32: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_STATIC); + break; + } + case ark::compiler::DataType::UINT64: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_STATIC_WIDE); + break; + } + case ark::compiler::DataType::REFERENCE: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_STATIC_OBJECT); + break; + } + default: + UNREACHABLE(); + } + inst->AddImm(GetGraph()->GetAllocator(), fieldId); + inst->AllocateInputTypes(GetGraph()->GetAllocator(), 1); + inst->AppendInput(GetDefinitionAcc()); + inst->AddInputType(type); + + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); +} + +void InstBuilder::BuildBCTLoadArrayIntrinsic(const BytecodeInstruction *bcInst, ark::compiler::DataType::Type type) +{ + ark::compiler::IntrinsicInst *inst {nullptr}; + switch (type) { + case ark::compiler::DataType::UINT8: + case ark::compiler::DataType::INT8: + case ark::compiler::DataType::UINT16: + case ark::compiler::DataType::INT16: + case ark::compiler::DataType::UINT32: + case ark::compiler::DataType::INT32: + case ark::compiler::DataType::FLOAT32: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_ARRAY); + break; + } + case ark::compiler::DataType::UINT64: + case ark::compiler::DataType::INT64: + case ark::compiler::DataType::FLOAT64: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_ARRAY_WIDE); + break; + } + case ark::compiler::DataType::REFERENCE: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_ARRAY_OBJECT); + break; + } + default: + UNREACHABLE(); + } + inst->AllocateInputTypes(GetGraph()->GetAllocator(), 2); + inst->AppendInput(GetDefinition(bcInst->GetVReg(0))); + inst->AddInputType(ark::compiler::DataType::REFERENCE); + inst->AppendInput(GetDefinitionAcc()); + inst->AddInputType(ark::compiler::DataType::INT32); + + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); + UpdateDefinitionAcc(inst); +} + +void InstBuilder::BuildBCTStoreArrayIntrinsic(const BytecodeInstruction *bcInst, ark::compiler::DataType::Type type) +{ + ark::compiler::IntrinsicInst *inst {nullptr}; + switch (type) { + case ark::compiler::DataType::UINT8: + case ark::compiler::DataType::INT8: + case ark::compiler::DataType::UINT16: + case ark::compiler::DataType::INT16: + case ark::compiler::DataType::UINT32: + case ark::compiler::DataType::INT32: + case ark::compiler::DataType::FLOAT32: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_ARRAY); + break; + } + case ark::compiler::DataType::UINT64: + case ark::compiler::DataType::INT64: + case ark::compiler::DataType::FLOAT64: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_ARRAY_WIDE); + break; + } + case ark::compiler::DataType::REFERENCE: { + inst = GetGraph()->CreateInstIntrinsic(type, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_STORE_ARRAY_OBJECT); + break; + } + default: + UNREACHABLE(); + } + inst->AllocateInputTypes(GetGraph()->GetAllocator(), 3); + inst->AppendInput(GetDefinition(bcInst->GetVReg(0))); + inst->AddInputType(ark::compiler::DataType::REFERENCE); + inst->AppendInput(GetDefinition(bcInst->GetVReg(1))); + inst->AddInputType(ark::compiler::DataType::INT32); + inst->AppendInput(GetDefinitionAcc()); + inst->AddInputType(type); + + auto method = GetGraph()->GetMethod(); + inst->SetMethod(method); + AddInstruction(inst); +} + +// void InstBuilder::BuildBCTLaunchIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead) +// { +// auto methodId = GetRuntime()->ResolveMethodIndex(GetMethod(), bcInst->GetId(0).AsIndex()); +// size_t argsCount = GetMethodArgumentsCount(methodId); +// ark::compiler::IntrinsicInst *inst {nullptr}; +// auto isStatic = GetRuntime()->IsMethodStatic(GetMethod(), methodId); +// if (isStatic) { +// if (argsCount > MAX_NUM_NON_RANGE_ARGS) { +// inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LAUNCH_RANGE); +// } else if (argsCount > MAX_NUM_SHORT_CALL_ARGS) { +// inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LAUNCH); +// } else { +// inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LAUNCH_SHORT); +// } +// } else { +// if (argsCount > MAX_NUM_NON_RANGE_ARGS) { +// inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LAUNCH_VIRT_RANGE); +// } else if (argsCount > MAX_NUM_SHORT_CALL_ARGS) { +// inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LAUNCH_VIRT); +// } else { +// inst = GetGraph()->CreateInstIntrinsic(ark::compiler::DataType::REFERENCE, GetPc(bcInst->GetAddress()), ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LAUNCH_VIRT_SHORT); +// } +// } +// inst->AddImm(GetGraph()->GetAllocator(), methodId); +// inst->AllocateInputTypes(GetGraph()->GetAllocator(), argsCount); +// if (isRange) { +// auto startReg = bcInst->GetVReg(0); +// for (size_t i = 0; i < argsCount; startReg++, i++) { +// inst->AppendInput(GetDefinition(startReg)); +// inst->AddInputType(GetRuntime()->GetMethodArgumentType(GetMethod(), methodId, i)); +// } +// } else { +// for (size_t i = 0; i < argsCount; i++) { +// inst->AppendInput(GetArgDefinition(bcInst, i, accRead)); +// inst->AddInputType(GetRuntime()->GetMethodArgumentType(GetMethod(), methodId, i)); +// } +// } +// auto method = GetGraph()->GetMethod(); +// inst->SetMethod(method); +// AddInstruction(inst); +// UpdateDefinitionAcc(inst); +// } diff --git a/libabckit/src/templates/dyn_intrinsics/BUILD.gn b/libabckit/src/templates/dyn_intrinsics/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..146de57daa1b1cca2b1e12378d6d3bc084df144a --- /dev/null +++ b/libabckit/src/templates/dyn_intrinsics/BUILD.gn @@ -0,0 +1,39 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +intrinsics_compiler_gen_dir = get_label_info("$ark_root/static_core/compiler:libarkcompiler_intrinsics_gen_inl_get_intrinsics_names_inl(${host_toolchain})", "target_gen_dir") +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "get_dyn_intrinsics_names.inc.erb", + "dyn_intrinsics_flags.inc.erb", + "dyn_intrinsics_enum.inc.erb", + "dyn_intrinsics_opcodes.inc.erb" + ] + sources = "." + requires = [ "$ark_root/assembler/asm_isapi.rb" ] + destination = "$intrinsics_compiler_gen_dir/generated" +} + +bco_gen_dir = get_label_info("$ark_root/static_core/bytecode_optimizer:libarktsbytecodeopt(${host_toolchain})", "target_gen_dir") +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "dyn_intrinsics_cases.inc.erb" + ] + sources = "." + requires = [ "$ark_root/assembler/asm_isapi.rb" ] + destination = "$bco_gen_dir/generated" +} diff --git a/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_cases.inc.erb b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_cases.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..691b84fa4a505c8313ab39f6cad690b2589a1efc --- /dev/null +++ b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_cases.inc.erb @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| + case ark::compiler::RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: +% end diff --git a/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_enum.inc.erb b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_enum.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..ef3d710f2e9becdde83dd9d05033cdfa7d9b883e --- /dev/null +++ b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_enum.inc.erb @@ -0,0 +1,20 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| + DYN_<%= inst.opcode.upcase %>, +% end diff --git a/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_flags.inc.erb b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_flags.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..5f75b4a9e19356c2e619d17f0bd3677ff6793b1b --- /dev/null +++ b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_flags.inc.erb @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2021-2024 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. + */ + +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| + case RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: + { + constexpr auto CLEAR_FLAGS = compiler::inst_flags::BARRIER|compiler::inst_flags::REQUIRE_STATE|compiler::inst_flags::CALL|compiler::inst_flags::HEAP_INV|compiler::inst_flags::CAN_THROW|compiler::inst_flags::ACC_READ|compiler::inst_flags::ACC_WRITE; + constexpr auto SET_FLAGS = 0U; + static_assert((SET_FLAGS & CLEAR_FLAGS) == 0, "DYN_<%= inst.opcode.upcase %> CLEAR_FLAGS cannot intersect SET_FLAGS"); + inst->ClearFlag(static_cast(CLEAR_FLAGS)); +% if inst.throwing? + inst->SetFlag(compiler::inst_flags::CAN_THROW); +% end +% if inst.exceptions.include?('x_throw') || inst.properties.include?('return') + inst->SetFlag(compiler::inst_flags::CF); + inst->SetFlag(compiler::inst_flags::TERMINATOR); +% end +% if inst.acc.include?("in") + inst->SetFlag(compiler::inst_flags::ACC_READ); +% end +% addition_acc_write_opcodes = ["DEFINEPROPERTYBYNAME_IMM8_ID16_V8", +% "CALLRUNTIME_DEFINEFIELDBYVALUE_PREF_IMM8_V8_V8", +% "CALLRUNTIME_DEFINEPRIVATEPROPERTY_PREF_IMM8_IMM16_IMM16_V8", +% "STPRIVATEPROPERTY_IMM8_IMM16_IMM16_V8", +% "THROW_UNDEFINEDIFHOLEWITHNAME_PREF_ID16"] +% if inst.acc.include?("out") || (addition_acc_write_opcodes.include? inst.opcode.upcase) + inst->SetFlag(compiler::inst_flags::ACC_WRITE); +% end + break; + } +% end diff --git a/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_opcodes.inc.erb b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_opcodes.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..89144432e408932ddbee69375a32b62d1638c6a2 --- /dev/null +++ b/libabckit/src/templates/dyn_intrinsics/dyn_intrinsics_opcodes.inc.erb @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +#include "libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h" + +namespace libabckit { + +// NOLINTNEXTLINE(readability-function-size) +static inline abckit_IsaApiDynamicOpcode GetDYNIntrinsicOpcode(compiler::IntrinsicInst *inst) { + switch(inst->GetIntrinsicId()) { +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| + case compiler::RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: { +% if (inst.mnemonic.include? "deprecated") + return abckit_IsaApiDynamicOpcode_INVALID; +% else + return abckit_IsaApiDynamicOpcode_<%= inst.mnemonic.gsub('.', '_')%>; +% end + } +% end + default: { + return abckit_IsaApiDynamicOpcode_INVALID; + } + } +} + +} // libabckit \ No newline at end of file diff --git a/libabckit/src/templates/dyn_intrinsics/get_dyn_intrinsics_names.inc.erb b/libabckit/src/templates/dyn_intrinsics/get_dyn_intrinsics_names.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..2317e5064fc8fd0b1202d3e2956645152bcf8ece --- /dev/null +++ b/libabckit/src/templates/dyn_intrinsics/get_dyn_intrinsics_names.inc.erb @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2021-2022 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% Panda::instructions.select{|b| b.namespace == "ecmascript"}.each do |inst| + case RuntimeInterface::IntrinsicId::DYN_<%= inst.opcode.upcase %>: { + return "<%= inst.mnemonic%>"; + } +% end + diff --git a/libabckit/src/wrappers/BUILD.gn b/libabckit/src/wrappers/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..5a984ebd2c9155ac7d0296b1a0f7e09bce4f7948 --- /dev/null +++ b/libabckit/src/wrappers/BUILD.gn @@ -0,0 +1,73 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ark_isa_gen("isa_gen_libabckit") { + template_files = [ + "opc_to_string.h.erb", + "ins_create_wrapper_api.inc.erb", + ] + sources = "templates" + destination = "$target_gen_dir/generated" + requires = [ + "$ark_root/assembler/asm_isapi.rb", + "$ark_root/libpandafile/pandafile_isapi.rb", + ] +} + +ohos_source_set("libabckit_pandasm_wrapper_source_set") { + sources = [ "pandasm_wrapper.cpp" ] + + include_dirs = [ + "$ark_root", + "$target_gen_dir", + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/:ark_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/libpandabase:arkbase_public_config", + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + ":isa_gen_libabckit_ins_create_wrapper_api_inc", + ":isa_gen_libabckit_opc_to_string_h", + "$ark_root/assembler:libarkassembler", + ] +} + +ohos_source_set("libabckit_abcfile_wrapper_source_set") { + sources = [ "abcfile_wrapper.cpp" ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root:ark_config", + "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/libpandabase:arkbase_public_config", + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ "$ark_root/libpandafile:libarkfile" ] +} diff --git a/libabckit/src/wrappers/abcfile_wrapper.cpp b/libabckit/src/wrappers/abcfile_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5edf8ce467fe254f3a4fdcb2e268c5c7a9327a5 --- /dev/null +++ b/libabckit/src/wrappers/abcfile_wrapper.cpp @@ -0,0 +1,169 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/wrappers/abcfile_wrapper.h" + +#include "libpandafile/bytecode_instruction.h" +#include "libpandafile/class_data_accessor.h" +#include "libpandafile/code_data_accessor.h" +#include "libpandafile/code_data_accessor-inl.h" +#include "libpandafile/field_data_accessor.h" +#include "libpandafile/file.h" +#include "libpandafile/file_items.h" +#include "libpandafile/method_data_accessor.h" +#include "libpandafile/method_data_accessor-inl.h" +#include "libpandafile/proto_data_accessor.h" +#include "libpandafile/proto_data_accessor-inl.h" +#include "libpandafile/type_helper.h" + +namespace libabckit { + +using namespace panda; + +FileWrapper::~FileWrapper() +{ + delete reinterpret_cast(abc_file_); +} + +static panda_file::File::EntityId MethodCast(void* method) +{ + return panda_file::File::EntityId(reinterpret_cast(method)); +} + +uint32_t FileWrapper::ResolveOffsetByIndex(void* parent_method, uint16_t index) const +{ + auto *pf = reinterpret_cast(abc_file_); + return pf->ResolveOffsetByIndex(MethodCast(parent_method), index).GetOffset(); +} + +size_t FileWrapper::GetMethodTotalArgumentsCount(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + + ASSERT(!mda.IsExternal()); + panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value()); + + return cda.GetNumArgs(); +} + +size_t FileWrapper::GetMethodArgumentsCount([[maybe_unused]] void* caller, uint32_t id) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, panda_file::File::EntityId(id)); + panda_file::ProtoDataAccessor pda(*pf, mda.GetProtoId()); + + return pda.GetNumArgs(); +} + +size_t FileWrapper::GetMethodRegistersCount(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + ASSERT(!mda.IsExternal()); + panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value()); + return cda.GetNumVregs(); +} + +const uint8_t *FileWrapper::GetMethodCode(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + ASSERT(!mda.IsExternal()); + panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value()); + return cda.GetInstructions(); +} + +size_t FileWrapper::GetMethodCodeSize(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + + ASSERT(!mda.IsExternal()); + panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value()); + + return cda.GetCodeSize(); +} + +uint8_t FileWrapper::GetMethodSourceLanguage(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + + ASSERT(!mda.IsExternal()); + + auto source_lang = mda.GetSourceLang(); + ASSERT(source_lang.has_value()); + + return static_cast(source_lang.value()); +} + +size_t FileWrapper::GetClassIdForMethod(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + return static_cast(mda.GetClassId().GetOffset()); +} + +std::string FileWrapper::GetClassNameFromMethod(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + auto string_data = pf->GetStringData(mda.GetClassId()); + return std::string(reinterpret_cast(string_data.data)); +} + +std::string FileWrapper::GetMethodName(void* method) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + auto string_data = pf->GetStringData(mda.GetNameId()); + return std::string(reinterpret_cast(string_data.data)); +} + +void FileWrapper::EnumerateTryBlocks(void* method, const std::function &cb) const +{ + auto *pf = reinterpret_cast(abc_file_); + panda_file::MethodDataAccessor mda(*pf, MethodCast(method)); + panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value()); + + cda.EnumerateTryBlocks([&cb](panda_file::CodeDataAccessor::TryBlock &try_block) { + cb(reinterpret_cast(&try_block)); + return true; + }); +} + +std::pair FileWrapper::GetTryBlockBoundaries(void *try_block) const +{ + auto *try_block_p = reinterpret_cast(try_block); + return { try_block_p->GetStartPc(), try_block_p->GetStartPc() + try_block_p->GetLength() }; +} + +void FileWrapper::EnumerateCatchBlocksForTryBlock(void *try_block, const std::function &cb) const +{ + auto *try_block_p = reinterpret_cast(try_block); + try_block_p->EnumerateCatchBlocks([&cb](panda_file::CodeDataAccessor::CatchBlock &catch_block) { + cb(reinterpret_cast(&catch_block)); + return true; + }); +} + +uint32_t FileWrapper::GetCatchBlockHandlerPc(void *catch_block) const +{ + auto *try_block_p = reinterpret_cast(catch_block); + return try_block_p->GetHandlerPc(); +} + +} diff --git a/libabckit/src/wrappers/abcfile_wrapper.h b/libabckit/src/wrappers/abcfile_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..ce1c814b3d4428140a7cb9a5d2612095d2e53784 --- /dev/null +++ b/libabckit/src/wrappers/abcfile_wrapper.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_WRAPPERS_ABCFILE_WRAPPER_H +#define LIBABCKIT_SRC_WRAPPERS_ABCFILE_WRAPPER_H + +#include +#include +#include +#include +#include + +namespace libabckit { + +class FileWrapper { +public: + FileWrapper(void *abc_file) : abc_file_(abc_file) {} + FileWrapper(const void *abc_file) : abc_file_(abc_file) {} + ~FileWrapper(); + + size_t GetMethodTotalArgumentsCount(void *method) const; + size_t GetMethodArgumentsCount([[maybe_unused]] void *caller, uint32_t id) const; + size_t GetMethodRegistersCount(void *method) const; + const uint8_t *GetMethodCode(void *method) const; + size_t GetMethodCodeSize(void *method) const; + uint8_t GetMethodSourceLanguage(void *method) const; + size_t GetClassIdForMethod(void *method) const; + std::string GetClassNameFromMethod(void *method) const; + std::string GetMethodName(void *method) const; + uint32_t ResolveOffsetByIndex(void *method, uint16_t index) const; + void EnumerateTryBlocks(void* method, const std::function &cb) const; + void EnumerateCatchBlocksForTryBlock(void *try_block, const std::function &cb) const; + std::pair GetTryBlockBoundaries(void *try_block) const; + uint32_t GetCatchBlockHandlerPc(void *catch_block) const; + +private: + const void *abc_file_; +}; + +} + +#endif //LIBABCKIT_SRC_WRAPPERS_ABCFILE_WRAPPER_H diff --git a/libabckit/src/wrappers/graph_wrapper/BUILD.gn b/libabckit/src/wrappers/graph_wrapper/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f1fcd5bcb649b77cb34f3265a174f181019dffe8 --- /dev/null +++ b/libabckit/src/wrappers/graph_wrapper/BUILD.gn @@ -0,0 +1,62 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") + +ohos_source_set("libabckit_graph_wrapper_source_set") { + sources = [ + "graph_wrapper.cpp" + ] + + cross_values_gen_dir = get_label_info("$ark_root/cross_values:cross_values_getters_generate(${default_toolchain})", + "target_gen_dir") + entrypoints_compiler_gen_dir = get_label_info("$ark_root/runtime:arkruntime_gen_entrypoints_entrypoints_compiler_inl", "target_gen_dir") + bytecode_inst_enum_gen_dir = get_label_info("$ark_root/../libabckit/src/irbuilder_dynamic/templates:isa_gen_libabckit_bytecode_inst_enum_gen_h", "target_gen_dir") + intrinsics_gen_dir = get_label_info("$ark_root/../libabckit/src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_enum_inl", "target_gen_dir") + reg_encoder_visitors_dir = get_label_info("$ark_root/bytecode_optimizer:reg_encoder_visitors_inc", "target_gen_dir") + codegen_visitors_dyn_dir = get_label_info("$ark_root/../libabckit/src/codegen/templates_dynamic:codegen_visitors_dyn_inc", "target_gen_dir") + ins_create_wrapper_dyn_dir = get_label_info("$ark_root/../libabckit/src/wrappers:isa_gen_libabckit_ins_create_wrapper_api_inc", "target_gen_dir") + include_dirs = [ + "$ark_root/runtime/libpandabase", + "$ark_root/runtime", + "$entrypoints_compiler_gen_dir/generated", + "$bytecode_inst_enum_gen_dir/..", + "$intrinsics_gen_dir/../generated", + "$reg_encoder_visitors_dir", + "$codegen_visitors_dyn_dir/..", + "$cross_values_gen_dir", + "$ins_create_wrapper_dyn_dir", + "$ark_root", # this target should not include headers from dynamic runtime, so static_core must be listed first + "$ark_root/.." + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" + + configs = [ + "$ark_root/:ark_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/compiler:arkcompiler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", + "$ark_root/runtime:profiling_gen_public_config" + ] + + configs += [ "$abckit_root:libabckit_coverage" ] + + deps = [ + "$ark_root/compiler:libarktscompiler" + ] +} diff --git a/libabckit/src/wrappers/graph_wrapper/graph_wrapper.cpp b/libabckit/src/wrappers/graph_wrapper/graph_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..84efccf176e9c60bd43b036e472f5f59d93accbd --- /dev/null +++ b/libabckit/src/wrappers/graph_wrapper/graph_wrapper.cpp @@ -0,0 +1,236 @@ +/** + * Copyright (c) 2024 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 "libabckit/src/wrappers/graph_wrapper/graph_wrapper.h" +#include "libabckit/src/wrappers/abcfile_wrapper.h" +#include "libabckit/src/macros.h" +#include "libabckit/src/irbuilder_dynamic/ir_builder_dyn.h" +#include "libabckit/src/adapter_dynamic/runtime_adapter_dynamic.h" +#include "libabckit/src/adapter_static/helpers_static.h" +#include "libabckit/src/codegen/codegen_dynamic.h" +#include "libabckit/src/codegen/ic_slot_allocator.h" + +#include "static_core/compiler/optimizer/analysis/dominators_tree.h" +#include "static_core/assembler/assembly-function.h" +#include "static_core/assembler/assembly-record.h" +#include "static_core/assembler/mangling.h" +#include "static_core/bytecode_optimizer/check_resolver.h" +#include "static_core/bytecode_optimizer/reg_acc_alloc.h" +#include "static_core/bytecode_optimizer/reg_encoder.h" +#include "static_core/compiler/optimizer/ir/graph.h" +#include "static_core/compiler/optimizer/optimizations/move_constants.h" +#include "static_core/compiler/optimizer/optimizations/regalloc/reg_alloc.h" +#include "static_core/compiler/optimizer/optimizations/regalloc/reg_alloc_resolver.h" +#include "static_core/compiler/optimizer/optimizations/regalloc/reg_alloc_graph_coloring.h" +#include "static_core/compiler/optimizer/optimizations/cleanup.h" +#include "static_core/compiler/optimizer/optimizations/try_catch_resolving.h" +#include "static_core/libpandabase/utils/arch.h" + +#include +#include + +namespace libabckit { + +using namespace ark; + +struct CtxGInternalDynamic { + ArenaAllocator *allocator; + ArenaAllocator *localAllocator; + const abckit_IrInterface *irInterface; + AbckitRuntimeAdapterDynamic *runtimeAdapter; +}; + +std::tuple GraphWrapper::BuildGraphDynamic(FileWrapper *pf, + abckit_IrInterface *irInterface, + abckit_File *ctxI, + uint32_t methodOffset) +{ + ark::compiler::g_options.SetCompilerUseSafepoint(false); + + ArenaAllocator *allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER); + ArenaAllocator *localAllocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true); + AbckitRuntimeAdapterDynamic *adapter = new AbckitRuntimeAdapterDynamic(*pf); + + + auto methodPtr = reinterpret_cast(methodOffset); // FIXME + auto graph = + allocator->New(allocator, localAllocator, Arch::NONE, methodPtr, adapter, /*osrMode*/ false, + /*parent*/ nullptr, /*isDynamic*/ false, /*bytecodeOpt*/ true); + if (graph == nullptr) { + LIBABCKIT_LOG(DEBUG) << "codeToGraphDynamic: graph == nullptr\n"; + return {nullptr, abckit_Status::abckit_Status_TODO}; + } + graph->SetDynamicMethod(); + graph->SetBCT(); + bool irBuilderRes = graph->RunPass(); + if (!irBuilderRes) { + LIBABCKIT_LOG(DEBUG) << "codeToGraphDynamic: !irBuilderRes\n"; + return {nullptr, abckit_Status::abckit_Status_TODO}; + } + graph->RunPass(); + graph->RunPass(); + + LIBABCKIT_LOG_DUMP(graph->Dump(&std::cerr), DEBUG); + CheckInvalidOpcodes(graph, true); + + auto ctxG = new abckit_Graph; + ctxG->irInterface = irInterface; + ctxG->impl = graph; + ctxG->ctxI = ctxI; + CreateGraphWrappers(ctxG); + + auto *ctxGInternal = new CtxGInternalDynamic {allocator, localAllocator, irInterface, adapter}; + ctxG->internal = ctxGInternal; + + return {ctxG, abckit_Status::abckit_Status_NO_ERROR}; +} + +std::tuple GraphWrapper::BuildCodeDynamic(abckit_Graph *ctxG, std::string funcName) +{ + auto graph = ctxG->impl; + graph->RemoveUnreachableBlocks(); + + CheckInvalidOpcodes(graph, true); + + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + LIBABCKIT_LOG_DUMP(graph->Dump(&std::cerr), DEBUG); + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + + ctxG->impl->InvalidateAnalysis(); + ctxG->impl->InvalidateAnalysis(); + + if (!graph->RunPass()) { + LIBABCKIT_LOG(DEBUG) << funcName << ": ICDominatorsTree failed!\n"; + return {nullptr, abckit_Status_TODO}; + } + + uint16_t ICSlotNumber = 0; + if (!graph->RunPass(&ICSlotNumber)) { + LIBABCKIT_LOG(DEBUG) << funcName << ": ICSlotAllocator failed!\n"; + return {nullptr, abckit_Status_TODO}; + } + + graph->RunPass(); + graph->RunPass(); + compiler::RegAllocResolver(graph).ResolveCatchPhis(); + + if (!graph->RunPass(compiler::VIRTUAL_FRAME_SIZE)) { + LIBABCKIT_LOG(DEBUG) << funcName << ": RegAllocGraphColoring failed!\n"; + return {nullptr, abckit_Status_TODO}; + } + + if (!graph->RunPass()) { + LIBABCKIT_LOG(DEBUG) << funcName << ": RegEncoder failed!\n"; + return {nullptr, abckit_Status_TODO}; + } + + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + LIBABCKIT_LOG_DUMP(graph->Dump(&std::cerr), DEBUG); + LIBABCKIT_LOG(DEBUG) << "============================================\n"; + + FunctionWrapper *wrFunc = PandasmWrapper::CreateWrappedFunction(); + if (!graph->RunPass(wrFunc, ctxG->irInterface)) { + LIBABCKIT_LOG(DEBUG) << funcName << ": Code generation failed!\n"; + return {nullptr, abckit_Status_TODO}; + } + + wrFunc->valueOfFirstParam = static_cast(graph->GetStackSlotsCount()) - 1L; // Work-around promotion rules + wrFunc->regsNum = static_cast(wrFunc->valueOfFirstParam + 1U); + wrFunc->slotsNum = static_cast(ICSlotNumber); + + return {new abckit_Code( + {reinterpret_cast(PandasmWrapper::GetPandasmFunction(wrFunc)), ctxG->method}), + abckit_Status_NO_ERROR}; +} + +void GraphWrapper::CreateGraphWrappers(abckit_Graph *ctxG) +{ + auto *graph = ctxG->impl; + + for (auto *bbImpl : graph->GetBlocksRPO()) { + auto *bb = graph->GetLocalAllocator()->New(); + bb->ctxG = ctxG; + bb->impl = bbImpl; + ctxG->implToBB.insert({bbImpl, bb}); + for (auto *instImpl : bbImpl->AllInsts()) { + auto *inst = graph->GetLocalAllocator()->New(); + inst->ctxG = ctxG; + inst->impl = instImpl; + ctxG->implToInst.insert({instImpl, inst}); + } + } + + // Find all function names and abckit methods + std::unordered_map namesToMethods; + auto *ctxI = ctxG->ctxI; + for (auto& [ _, module] : ctxI->localModules) { + for (auto& method : module->methods) { + auto *func = reinterpret_cast(method->impl); + namesToMethods[func->name] = method.get(); + } + for (auto& [_, klass] : module->ct) { + for (auto& method : klass->methods) { + auto *func = reinterpret_cast(method->impl); + namesToMethods[func->name] = method.get(); + } + } + } + + // Fill map offset to abckit_method for this graph context + for (auto& [offset, str] : ctxG->irInterface->methods) { + auto it = namesToMethods.find(pandasm::DeMangleName(str)); + if (it != namesToMethods.end()) { + ctxG->ptrToMethod[offset] = it->second; + } + } + + // Valid only for static, because in dynamic mode + // classes are contained as functions + if (ctxI->mode == libabckit::Mode::STATIC) { + // Find all class names and abckit classes + std::unordered_map namesToClasses; + for (auto& [ _, module] : ctxI->localModules) { + for (auto& [_, klass] : module->ct) { + auto *func = reinterpret_cast(klass->impl.cl); + namesToClasses[func->name] = klass.get(); + } + } + // Fill map offset to abckit_Class for this graph context + for (auto& [offset, str] : ctxG->irInterface->classes) { + auto it = namesToClasses.find(pandasm::DeMangleName(str)); + if (it != namesToClasses.end()) { + ctxG->ptrToClass[offset] = it->second; + } + } + } +} + +void GraphWrapper::DestroyGraphDynamic(abckit_Graph *ctxG) +{ + LIBABCKIT_LOG_FUNC + auto *ctxGInternal = (CtxGInternalDynamic *)ctxG->internal; + // dirty hack to obtain FileWrapper pointer + // TODO(mshimenkov): refactor it + auto *fileWrapper = reinterpret_cast(ctxGInternal->runtimeAdapter->GetBinaryFileForMethod(nullptr)); + delete fileWrapper; + delete ctxGInternal->runtimeAdapter; + delete ctxGInternal->irInterface; + delete ctxGInternal->localAllocator; + delete ctxGInternal->allocator; + delete ctxGInternal; + delete ctxG; +} + +} // libabckit diff --git a/libabckit/src/wrappers/graph_wrapper/graph_wrapper.h b/libabckit/src/wrappers/graph_wrapper/graph_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..1faae47da2e5642b7e14946503fe47920c760e1c --- /dev/null +++ b/libabckit/src/wrappers/graph_wrapper/graph_wrapper.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_WRAPPERS_GRAPH_WRAPPER_H +#define LIBABCKIT_SRC_WRAPPERS_GRAPH_WRAPPER_H + +#include "libabckit/include/metadata.h" +#include "libabckit/include/statuses.h" +#include "libabckit/src/ir_impl.h" + +#include +#include +#include + +#include "libabckit/src/wrappers/abcfile_wrapper.h" + +namespace libabckit { + +class GraphWrapper { +public: + GraphWrapper() {} + static void CreateGraphWrappers(abckit_Graph *ctxG); + static std::tuple BuildGraphDynamic(FileWrapper *pf, + abckit_IrInterface *irInterface, + abckit_File *ctxI, + uint32_t methodOffset); + static std::tuple BuildCodeDynamic(abckit_Graph *ctxG, std::string funcName); + static void DestroyGraphDynamic(abckit_Graph *ctxG); +}; + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_WRAPPERS_GRAPH_WRAPPER_H diff --git a/libabckit/src/wrappers/pandasm_wrapper.cpp b/libabckit/src/wrappers/pandasm_wrapper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..216f19e11c16245ee3978f59cbb6e64097098c43 --- /dev/null +++ b/libabckit/src/wrappers/pandasm_wrapper.cpp @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2021-2022 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 "libabckit/src/wrappers/pandasm_wrapper.h" +#include "libabckit/src/ir_impl.h" + +#include "assembler/assembly-function.h" +#include "assembler/assembly-emitter.h" +#include "assembler/assembly-literals.h" +#include "assembler/mangling.h" + +#include + +namespace libabckit { +using namespace panda; + +std::string InsWrapper::OPCODE_INVALID = "INVALID"; + +void FunctionWrapper::Fill() +{ + pandasm::Function *func = reinterpret_cast(impl); + name = func->name; + regsNum = func->regs_num; + valueOfFirstParam = func->value_of_first_param; + for (auto insn: func->ins) { + auto insDebug = InsWrapper::DebugIns(insn.ins_debug.line_number, insn.ins_debug.whole_line, insn.ins_debug.bound_left, insn.ins_debug.bound_right); + auto insWrap = InsWrapper(OpcToString(insn.opcode), insn.regs, insn.ids, insn.imms, insn.label, insn.set_label, insDebug); + ins.push_back(insWrap); + } + for (auto cb: func->catch_blocks) { + auto catchBlockWrap = FunctionWrapper::CatchBlockWrapper(cb.whole_line, cb.exception_record, cb.try_begin_label, cb.try_end_label, cb.catch_begin_label, cb.catch_end_label); + catchBlocks.push_back(catchBlockWrap); + } +} + +void FunctionWrapper::Update() +{ + pandasm::Function *func = reinterpret_cast(impl); + func->ins.clear(); + func->catch_blocks.clear(); + func->name = name; + func->regs_num = regsNum; + func->value_of_first_param = valueOfFirstParam; + func->slots_num = slotsNum; + for (auto insWrap: ins) { + auto insDebug = pandasm::debuginfo::Ins(insWrap.insDebug.lineNumber, insWrap.insDebug.wholeLine, insWrap.insDebug.boundLeft, insWrap.insDebug.boundRight); + auto insn = pandasm::Ins(); + insn.opcode = OpcFromName(insWrap.opcode); + insn.regs = std::move(insWrap.regs); + insn.ids = std::move(insWrap.ids); + insn.imms = std::move(insWrap.imms); + insn.label = std::move(insWrap.label); + insn.set_label = insWrap.setLabel; + insn.ins_debug = insDebug; + func->ins.push_back(insn); + } + for (auto cbWrap: catchBlocks) { + auto catchBlock = pandasm::Function::CatchBlock(); + catchBlock.whole_line = std::move(cbWrap.wholeLine); + catchBlock.exception_record = std::move(cbWrap.exceptionRecord); + catchBlock.try_begin_label = std::move(cbWrap.tryBeginLabel); + catchBlock.try_end_label = std::move(cbWrap.tryEndLabel); + catchBlock.catch_begin_label = std::move(cbWrap.catchBeginLabel); + catchBlock.catch_end_label = std::move(cbWrap.catchEndLabel); + func->catch_blocks.push_back(catchBlock); + } +} + +FunctionWrapper *PandasmWrapper::CreateWrappedFunction() +{ + auto *newFunc = new panda::pandasm::Function("newCode", panda::panda_file::SourceLang::ECMASCRIPT); + return GetWrappedFunction(newFunc); +} + +std::map PandasmWrapper::GetUnwrappedLiteralArrayTable(void *program) +{ + auto *prog = reinterpret_cast(program); + std::map res; + for(auto &[id, s] : prog->literalarray_table) { + res[id] = reinterpret_cast(&s); + } + return res; +} + +// std::string DeMangleName(const std::string &name) +// { +// return pandasm::DeMangleName(name); +// } + +} // namespace libabckit diff --git a/libabckit/src/wrappers/pandasm_wrapper.h b/libabckit/src/wrappers/pandasm_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..c3472aeee2c6383ef61dca63dd1df5832c5cf0f8 --- /dev/null +++ b/libabckit/src/wrappers/pandasm_wrapper.h @@ -0,0 +1,188 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_SRC_WRAPPERS_PANDASM_WRAPPER_H +#define LIBABCKIT_SRC_WRAPPERS_PANDASM_WRAPPER_H + +#include +#include +#include +#include +#include +#include + +namespace libabckit { + +struct LiteralArrayWrapper; +struct InsWrapper; + +struct LiteralArrayWrapper { + + enum class LiteralTagWrapper : uint8_t { + TAGVALUE = 0x00, + BOOL = 0x01, + INTEGER = 0x02, + FLOAT = 0x03, + DOUBLE = 0x04, + STRING = 0x05, + METHOD = 0x06, + GENERATORMETHOD = 0x07, + ACCESSOR = 0x08, + METHODAFFILIATE = 0x09, + ARRAY_U1 = 0x0a, + ARRAY_U8 = 0x0b, + ARRAY_I8 = 0x0c, + ARRAY_U16 = 0x0d, + ARRAY_I16 = 0x0e, + ARRAY_U32 = 0x0f, + ARRAY_I32 = 0x10, + ARRAY_U64 = 0x11, + ARRAY_I64 = 0x12, + ARRAY_F32 = 0x13, + ARRAY_F64 = 0x14, + ARRAY_STRING = 0x15, + ASYNCGENERATORMETHOD = 0x16, + LITERALBUFFERINDEX = 0x17, + LITERALARRAY = 0x18, + BUILTINTYPEINDEX = 0x19, + GETTER = 0x1a, + SETTER = 0x1b, + NULLVALUE = 0xff + }; + + struct LiteralWrapper { + LiteralTagWrapper tag; + std::variant value; + }; + + std::vector literals; + + explicit LiteralArrayWrapper(std::vector lits) : literals(std::move(lits)) + { + } + explicit LiteralArrayWrapper() = default; +}; + +struct FunctionWrapper { + struct CatchBlockWrapper { + std::string wholeLine; + std::string exceptionRecord; + std::string tryBeginLabel; + std::string tryEndLabel; + std::string catchBeginLabel; + std::string catchEndLabel; + + CatchBlockWrapper() = default; + CatchBlockWrapper(std::string ln, std::string excr, std::string tbl, std::string tel, std::string cbl, std::string cel) + : wholeLine(ln), exceptionRecord(excr), tryBeginLabel(tbl), tryEndLabel(tel), catchBeginLabel(cbl), catchEndLabel(cel) + { + } + }; + explicit FunctionWrapper(void *func) : impl(func) + { + } + + void Fill(); + void Update(); + + void *impl = nullptr; + std::string name = ""; + int64_t valueOfFirstParam = -1; + size_t regsNum = 0; + size_t slotsNum = 0; + std::vector ins = {}; + std::vector catchBlocks = {}; +}; + +struct InsWrapper { + + static std::string OPCODE_INVALID; + + struct DebugIns { + size_t lineNumber = 0; + uint32_t columnNumber = 0; + std::string wholeLine = ""; // TODO(mbolshov): redundant given file and line_number + size_t boundLeft = 0; + size_t boundRight = 0; + + void SetLineNumber(size_t ln) + { + lineNumber = ln; + } + + void SetColumnNumber(size_t cn) + { + columnNumber = cn; + } + + DebugIns() = default; + DebugIns(size_t ln, std::string &fc, size_t bl, size_t br) + : lineNumber(ln), wholeLine(fc), boundLeft(bl), boundRight(br) + { + } + }; + using IType = std::variant; + + constexpr static uint16_t ACCUMULATOR = -1; + constexpr static size_t MAX_CALL_SHORT_ARGS = 2; + constexpr static size_t MAX_CALL_ARGS = 4; + constexpr static uint16_t MAX_NON_RANGE_CALL_REG = 15; + constexpr static uint16_t MAX_RANGE_CALL_START_REG = 255; + + std::string opcode = OPCODE_INVALID; + std::vector regs; + std::vector ids; + std::vector imms; + std::string label; + bool setLabel = false; + DebugIns insDebug; + + InsWrapper() = default; + InsWrapper(std::string opcodeArg, std::vector regsArg, std::vector idsArg, std::vector immsArg, std::string labelArg, bool setLabelArg, DebugIns insDebugArg) + : opcode(opcodeArg), regs(regsArg), ids(idsArg), imms(immsArg), label(labelArg), setLabel(setLabelArg), insDebug(insDebugArg) + { + } +#include +}; + +class PandasmWrapper { +public: + using ArgTypes = std::variant; + + static FunctionWrapper *CreateWrappedFunction(); + + static FunctionWrapper *GetWrappedFunction(void *function) + { + auto wrFunc = new FunctionWrapper(function); + wrFunc->Fill(); + return wrFunc; + } + + static std::map GetUnwrappedLiteralArrayTable(void *prog); + static void *GetPandasmFunction(FunctionWrapper *wrFunc) + { + wrFunc->Update(); + auto function = wrFunc->impl; + delete wrFunc; + return function; + } +#include +}; + +// std::string DeMangleName(const std::string &name); + +} // namespace libabckit + +#endif //LIBABCKIT_SRC_WRAPPERS_PANDASM_WRAPPER_H diff --git a/libabckit/src/wrappers/templates/ins_create_wrapper_api.inc.erb b/libabckit/src/wrappers/templates/ins_create_wrapper_api.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..35196cb5eaf380dcb5716d89409ee57c8d357abd --- /dev/null +++ b/libabckit/src/wrappers/templates/ins_create_wrapper_api.inc.erb @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-2023 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. + */ + +// Autogenerated file -- DO NOT EDIT! + +% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group| +% insn = group.first +% signature = assembler_signature(group, insn.jump?) +% signature_str = signature.map { |o| "#{o.type} #{o.name}" }.join(', ') +% if !(insn.opcode.upcase.include? "DEPRECATED_") +static InsWrapper Create_<%= insn.asm_token %>_Wrapper(<%= signature_str %>) +{ + InsWrapper <%=insn.emitter_name%>_; + <%=group.first.emitter_name%>_.opcode = "<%= insn.asm_token.downcase %>"; +% format = format_ops(insn.format) +% format.each { |o| o.width = storage_width(o.width) } +% count_reg = 0 +% format.each_with_index do |o, i| +% if o.name.start_with?('v') +% count_reg += 1 +% end +% end +% if count_reg > 0 then + <%=group.first.emitter_name%>_.regs.reserve(<%= count_reg %>); +% end +% format.each_with_index do |o, i| +% if o.name.start_with?('imm') +% if insn.jump? + <%=group.first.emitter_name%>_.ids.push_back(label); +% else + <%=group.first.emitter_name%>_.imms.emplace_back(<%= o.name %>); +% end +% elsif o.name.start_with?('id') + <%=group.first.emitter_name%>_.ids.push_back(<%= o.name %>); +% else + <%=group.first.emitter_name%>_.regs.push_back(<%= o.name %>); +% end +% end + return <%=insn.emitter_name%>_; +} +% end +% end diff --git a/libabckit/src/wrappers/templates/opc_to_string.h.erb b/libabckit/src/wrappers/templates/opc_to_string.h.erb new file mode 100644 index 0000000000000000000000000000000000000000..3790a3ca6f9001bc11187b0abdc90c075e1497c5 --- /dev/null +++ b/libabckit/src/wrappers/templates/opc_to_string.h.erb @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2024 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 +#include "assembler/assembly-ins.h" + +namespace libabckit { + +std::string OpcToString(panda::pandasm::Opcode opcode) { + switch(opcode) { +% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group| +% insn = group.first +% if !(insn.opcode.upcase.include? "DEPRECATED_") + case panda::pandasm::Opcode::<%= insn.asm_token%>: { + return "<%= insn.mnemonic%>"; + } +% end +% end +% Panda::pseudo_instructions.each do |insn| + case panda::pandasm::Opcode::<%= insn.opcode.upcase %>: { + return "<%= insn.opcode %>"; + } +% end + default: { + return "INVALID"; + } + } + UNREACHABLE(); +} + +panda::pandasm::Opcode OpcFromName(std::string name) { +% Panda::instructions.group_by(&:mnemonic).each do |mnemonic, group| +% insn = group.first +% if !(insn.opcode.upcase.include? "DEPRECATED_") + if (name == "<%= insn.mnemonic.gsub('.', '_') %>") { + return panda::pandasm::Opcode::<%= insn.asm_token%>; + } +% end +% end +% Panda::pseudo_instructions.each do |insn| + if (name == "<%= insn.opcode.gsub('.', '_') %>") { + return panda::pandasm::Opcode::<%= insn.opcode %>; + } +% end + if (name == "INVALID") { + return panda::pandasm::Opcode::INVALID; + } + UNREACHABLE(); +} + +} // namespace libabckit diff --git a/libabckit/tests/BUILD.gn b/libabckit/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9be297ebfebb2b307e01480e374a5f06c1bf5803 --- /dev/null +++ b/libabckit/tests/BUILD.gn @@ -0,0 +1,537 @@ +# Copyright (c) 2024 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. + +# import("//arkcompiler/runtime_core/ark_config.gni") +import("//arkcompiler/runtime_core/libabckit/libabckit_config.gni") +import("//arkcompiler/runtime_core/libabckit/tests/test_helper.gni") +import("//arkcompiler/runtime_core/libabckit/tests/test_args.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//arkcompiler/ets_frontend/ets2panda/ets2abc_config.gni") +import("//arkcompiler/ets_runtime/js_runtime_config.gni") + + +template("create_merge_file") { + assert(defined(invoker.input_file), "input_file is required!") + assert(defined(invoker.output_file), "output_file is required!") + + extra_dependencies = [] + if (defined(invoker.extra_dependencies)) { + extra_dependencies += invoker.extra_dependencies + } + + action("$target_name") { + script = "./../scripts/create_merge_file.sh" + + args = [ rebase_path(invoker.input_file), + rebase_path(invoker.output_file) ] + + deps = extra_dependencies + + outputs = [ invoker.output_file ] + } +} + +test_js_path = + "//arkcompiler/runtime_core/libabckit/tests/" + +test_js_files = [ + "metadata/inspect_api/classes/classes_dynamic", + "metadata/inspect_api/classes/classes_empty_dynamic", + "metadata/inspect_api/literals/literals_dynamic", + "metadata/inspect_api/values/values_dynamic", + "metadata/inspect_api/modules/modules_dynamic", + "metadata/inspect_api/modules/modules_dynamic_external", + "metadata/modify_api/strings/strings_dynamic", + "metadata/modify_api/modules/modules_dynamic_modify", + "metadata/modify_api/literals/literals_dynamic", + "metadata/modify_api/values/values_dynamic", + "metadata/modify_api/types/types_dynamic", + + "ir/inst_manipulation/inst_manipulation_dynamic", + + "ir/basic_blocks/basic_blocks_dynamic", + + "ir/icreate/arithmetic/bininst_dynamic", + "ir/icreate/arithmetic/bininst_logical_dynamic", + "ir/icreate/arithmetic/bininst_shifts_dynamic", + "ir/icreate/arithmetic/unaryinst_dynamic", + "ir/icreate/loadstore/emptyobj", + "ir/icreate/loadstore/ld_dynamic", + "ir/icreate/loadstore/stownbyindex", + "ir/icreate/loadstore/stobjbyindex", + "ir/icreate/loadstore/ldobjbyvalue", + "ir/icreate/loadstore/ldobjbyname", + "ir/icreate/loadstore/ldobjbyindex", + "ir/icreate/loadstore/ldglobalvar", + "ir/icreate/loadstore/stglobalvar", + "ir/icreate/create_if/create_if_dynamic", + "ir/icreate/modules/inst_modules_dynamic", + + "ir/icreate/dyn_call/call_dynamic", + "ir/icreate/dyn_call_this/call_this_dynamic", + "ir/icreate/throw/throw_dynamic", + "ir/icreate/instanceof/instanceof_dynamic", + "ir/icreate/isin/isin_dynamic", + "ir/icreate/return/return_dynamic", + "ir/icreate/sendable/definesendableclass_dynamic", + "ir/icreate/generators/creategeneratorobj_dynamic", + "ir/icreate/iterators/createiterresultobj_dynamic", + "ir/icreate/iterators/getiterator_dynamic", + "ir/icreate/iterators/getpropiterator_dynamic", + "ir/create_constant/create_constant_dynamic", + + "ir/icreate/arrays/create_array_dynamic", + "ir/inst_inputs/inst_inputs_dynamic", + + "ir/string/string_dynamic", + "ir/method/method_dynamic", + "ir/loops/loop_dynamic", + + "ir/types_api/get_type_dynamic", + "ir/insert_try_catch/insert_try_catch_dynamic", + "ir/insert_try_catch/insert_try_catch_dynamic_wrapper", + + "scenarios/add_log/add_log_dynamic", + + "scenarios/api_scanner/dynamic/api_scanner", + "scenarios/branch_eliminator/dynamic/branch_eliminator", + + "internal/ICSlotAllocator/ICSlotAllocator", + "internal/implementation_api/abc_dynamic", + "internal/mem_manager/abc_dynamic_1", + "internal/mem_manager/abc_dynamic_2", + "wrong_mode_tests/mode_test_dynamic", +] + +test_ts_files = [ + "ir/icreate/catchphi/catchphi_dynamic", + + "ir/phi/phi_dynamic", + + "metadata/inspect_api/enumerators/enumerators0_dynamic", + "metadata/inspect_api/methods/methods_dynamic", + + "metadata/inspect_api/annotations/annotations_dynamic", + "metadata/modify_api/annotations/annotations_dynamic", +] + +test_ets_files = [ + "metadata/inspect_api/classes/classes_static", + "metadata/inspect_api/classes/classes_empty_static", + "metadata/inspect_api/methods/methods_static", + "metadata/inspect_api/enumerators/enumerators_static", + "metadata/inspect_api/files/file_static", + "metadata/inspect_api/literals/literals_static", + "metadata/inspect_api/values/values_static", + "metadata/modify_api/strings/strings_static", + "metadata/modify_api/types/types_static", + "metadata/modify_api/literals/literals_static", + "metadata/modify_api/values/values_static", + + "ir/inst_manipulation/inst_manipulation_static", + + "ir/basic_blocks/basic_blocks_static", + "ir/class/classes_api", + + "ir/graph_basic_block/graph_basic_block", + + "ir/icreate/arithmetic/bininst_imm_static", + "ir/icreate/arithmetic/bininst_logical_static", + "ir/icreate/arithmetic/bininst_logical_imm_static", + "ir/icreate/arithmetic/bininst_shifts_imm_static", + "ir/icreate/arithmetic/bininst_shifts_static", + "ir/icreate/arithmetic/bininst_static", + "ir/icreate/arithmetic/unaryinst_static", + "ir/icreate/arrays/load_array", + "ir/icreate/arrays/load_const_array", + "ir/icreate/arrays/new_array", + "ir/icreate/arrays/store_array", + "ir/icreate/arrays/store_array_wide", + "ir/icreate/arrays/len_array", + "ir/icreate/cast/cast_static", + "ir/icreate/cast/checkcast_static", + "ir/icreate/call/virtual/call_virtual_static", + "ir/icreate/catchphi/catchphi_static", + "ir/icreate/cmp/create_cmp_static", + "ir/icreate/load_undefined/load_undefined_static", + "ir/icreate/equals/equals_static", + "ir/icreate/is_instance/is_instance_static", + "ir/icreate/is_undefined/is_undefined_static", + "ir/icreate/create_if/create_if_static", + "ir/icreate/objects/objects", + "ir/icreate/throw/throw_static", + "ir/create_constant/create_constant_static", + + + "ir/icreate/return/return_static", + "ir/icreate/create_nullptr/create_nullptr_static", + + "ir/string/string_static", + "ir/method/method_static", + + "ir/inst_inputs/inst_inputs_static", + "ir/types_api/get_type_static", + + "ir/get_constant_value/get_constant_value_static", + "ir/phi/phi_static", + "ir/loops/loop_static", + + "ir/insert_try_catch/insert_try_catch_static", + + "internal/implementation_api/abc_static", + "internal/mem_manager/abc_static_1", + "internal/mem_manager/abc_static_2", + "wrong_mode_tests/mode_test_static", + + "scenarios/add_log/add_log_static", + "scenarios/parameter_check/parameter_check_static", + "scenarios/static_branch_elimination/static_branch_elimination", +] + +module_output_path = "arkcompiler/runtime_core/libabckit" + +foreach(file, test_js_files) { + test_js = "${test_js_path}${file}.js" + test_merge_file = "$target_out_dir/${file}_merge.txt" + test_abc = "$target_out_dir/${file}.abc" + + print("test_js $test_js") + print("test_merge_file $test_merge_file") + print("test_abc $test_abc") + + create_merge_file("${file}_merge") { + input_file = "$test_js" + output_file = "$test_merge_file" + } + es2abc_gen_abc("gen_${file}_abc") { + # Only targets in this file can depend on this. + extra_visibility = [ ":*" ] + extra_dependencies = [ ":${file}_merge" ] + src_js = "@" + rebase_path(test_merge_file) + dst_file = rebase_path(test_abc) + extra_args = [ "--module", "--merge-abc" ] + + in_puts = [ test_js ] + out_puts = [ test_abc ] + } +} + +foreach(file, test_ts_files) { + test_ts = "${test_js_path}${file}.ts" + test_merge_file = "$target_out_dir/${file}_merge.txt" + test_abc = "$target_out_dir/${file}.abc" + + print("test_ts $test_ts") + print("test_merge_file $test_merge_file") + print("test_abc $test_abc") + + create_merge_file("${file}_merge") { + input_file = "$test_ts" + output_file = "$test_merge_file" + } + es2abc_gen_abc("gen_${file}_abc") { + # Only targets in this file can depend on this. + extra_visibility = [ ":*" ] + extra_dependencies = [ ":${file}_merge" ] + src_js = "@" + rebase_path(test_merge_file) + dst_file = rebase_path(test_abc) + extra_args = [ "--module", "--merge-abc" ] + + extension = "ts" + in_puts = [ test_ts ] + out_puts = [ test_abc ] + } +} + +foreach(file, test_ets_files) { + ets2abc_gen_abc("gen_${file}_abc") { + test_ets = "${test_js_path}${file}.ets" + test_abc = "$target_out_dir/${file}.abc" + + # Only targets in this file can depend on this. + extra_visibility = [ ":*" ] + src_ets = rebase_path(test_ets) + dst_file = rebase_path(test_abc) + + in_puts = [ test_ets ] + out_puts = [ test_abc ] + } +} + +host_unittest_action("AbcKitTest") { + module_out_path = module_output_path + + sources = [ + "helpers/helpers.cpp", + "helpers/helpers_nullptr.cpp", + "helpers/helpers_wrong_ctx.cpp", + "helpers/visit_helper/visit_helper.cpp", + "helpers/helpers_mode.cpp", + + "metadata/inspect_api/strings/strings_test.cpp", + "metadata/inspect_api/literals/literals_test.cpp", + "metadata/inspect_api/values/values_test.cpp", + "metadata/inspect_api/annotations/annotations_test.cpp", + "metadata/inspect_api/classes/classes_test.cpp", + "metadata/inspect_api/enumerators/modules_test.cpp", + "metadata/inspect_api/methods/methods_test.cpp", + "metadata/inspect_api/modules/modules_dynamic_test.cpp", + "metadata/inspect_api/files/files_test.cpp", + "metadata/modify_api/annotations/annotations_test.cpp", + "metadata/modify_api/strings/strings_test.cpp", + "metadata/modify_api/modules/modules_dynamic_modify_test.cpp", + "metadata/modify_api/literals/literals_test.cpp", + "metadata/modify_api/values/values_test.cpp", + "metadata/modify_api/types/types_test.cpp", + + "ir/basic_blocks/basic_blocks_static.cpp", + "ir/class/classes_api.cpp", + "ir/inst_inputs/inst_inputs_test.cpp", + "ir/types_api/get_type_static.cpp", + "ir/types_api/get_type_dynamic.cpp", + "ir/inst_manipulation/inst_manipulation.cpp", + "ir/icreate/generators/creategeneratorobj_dynamic.cpp", + "ir/icreate/iterators/createiterresultobj_dynamic.cpp", + "ir/icreate/iterators/getiterator_dynamic.cpp", + "ir/icreate/iterators/getpropiterator_dynamic.cpp", + + "scenarios/add_log/add_log_dynamic_test.cpp", + "scenarios/add_log/add_log_static_test.cpp", + "scenarios/parameter_check/parameter_check_static.cpp", + "scenarios/static_branch_elimination/static_branch_elimination.cpp", + + "scenarios/api_scanner/dynamic/api_scanner.cpp", + "scenarios/api_scanner/dynamic/api_scanner_test.cpp", + "scenarios/branch_eliminator/dynamic/branch_eliminator.cpp", + "scenarios/branch_eliminator/dynamic/branch_eliminator_test.cpp", + "scenarios/router_map_generator/router_map_generator.cpp", + #TODO(qiuyu): add "scenarios/router_map_generator/router_map_generator_test.cpp" when annotation feature is ready + + "ir/create_constant/create_constant_static.cpp", + "ir/create_constant/create_constant_dynamic.cpp", + + "ir/icreate/arithmetic/bininst_dynamic.cpp", + "ir/icreate/arithmetic/bininst_static.cpp", + "ir/icreate/arithmetic/bininst_imm_static.cpp", + "ir/icreate/arithmetic/bininst_shifts_dynamic.cpp", + "ir/icreate/arithmetic/bininst_shifts_static.cpp", + "ir/icreate/arithmetic/bininst_shifts_imm_static.cpp", + "ir/icreate/arithmetic/unaryinst_dynamic.cpp", + "ir/icreate/arithmetic/unaryinst_static.cpp", + "ir/icreate/arithmetic/bininst_logical_dynamic.cpp", + "ir/icreate/arithmetic/bininst_logical_static.cpp", + "ir/icreate/arithmetic/bininst_logical_imm_static.cpp", + "ir/icreate/cast/cast_static.cpp", + "ir/icreate/catchphi/catchphi_static.cpp", + "ir/icreate/catchphi/catchphi_dynamic.cpp", + "ir/icreate/cmp/create_cmp_static.cpp", + "ir/icreate/call/virtual/call_virtual_static.cpp", + "ir/icreate/load_undefined/load_undefined_static.cpp", + "ir/icreate/equals/equals_static.cpp", + "ir/icreate/is_instance/is_instance.cpp", + "ir/icreate/is_undefined/is_undefined.cpp", + "ir/icreate/instanceof/instanceof_dynamic.cpp", + "ir/icreate/isin/isin_dynamic.cpp", + "ir/icreate/dyn_call/call_dynamic.cpp", + "ir/icreate/dyn_call_this/call_this_dynamic.cpp", + "ir/icreate/throw/throw_dynamic.cpp", + "ir/icreate/throw/throw_static.cpp", + "ir/icreate/loadstore/ld_dynamic.cpp", + "ir/icreate/loadstore/loadstore.cpp", + "ir/icreate/objects/objects.cpp", + + "ir/string/string_static.cpp", + "ir/string/string_dynamic.cpp", + "ir/method/method_static.cpp", + "ir/method/method_dynamic.cpp", + "ir/insert_try_catch/insert_try_catch_dynamic.cpp", + "ir/insert_try_catch/insert_try_catch_static.cpp", + + "ir/get_constant_value/get_constant_value_static.cpp", + "ir/icreate/arrays/create_array_dynamic.cpp", + "ir/icreate/arrays/arrays_static.cpp", + "ir/icreate/create_nullptr/create_nullptr_static.cpp", + "ir/icreate/return/return_static.cpp", + "ir/icreate/return/return_dynamic.cpp", + "ir/icreate/sendable/definesendableclass_dynamic.cpp", + "ir/icreate/create_if/create_if_static.cpp", + "ir/icreate/create_if/create_if_dynamic.cpp", + "ir/icreate/modules/inst_modules_dynamic.cpp", + + "ir/graph_basic_block/graph_basic_block_static.cpp", + + "ir/icreate/arithmetic/helpers_arithmetic.cpp", + + "ir/phi/phi.cpp", + "ir/loops/loops.cpp", + + "internal/ICSlotAllocator/ICSlotAllocator.cpp", + "internal/implementation_api/abc_stuff.cpp", + "internal/implementation_api/graph_stuff.cpp", + "internal/mem_manager/several_abc.cpp", + + "null_args_tests/null_args_tests_ApiImpl_0.cpp", + "null_args_tests/null_args_tests_GraphApiImpl_0.cpp", + "null_args_tests/null_args_tests_InspectApiImpl_0.cpp", + "null_args_tests/null_args_tests_IsaApiDynamicImpl_0.cpp", + "null_args_tests/null_args_tests_IsaApiDynamicImpl_1.cpp", + "null_args_tests/null_args_tests_IsaApiStaticImpl_0.cpp", + "null_args_tests/null_args_tests_ModifyApiImpl_0.cpp", + + "wrong_ctx_tests/wrong_ctx_tests_ApiImpl_0.cpp", + "wrong_ctx_tests/wrong_ctx_tests_GraphApiImpl_0.cpp", + "wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_0.cpp", + "wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_1.cpp", + "wrong_ctx_tests/wrong_ctx_tests_IsaApiStaticImpl_0.cpp", + "wrong_ctx_tests/wrong_ctx_tests_ModifyApiImpl_0.cpp", + + "wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_0.cpp", + "wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_1.cpp", + "wrong_mode_tests/wrong_mode_tests_IsaApiStaticImpl_0.cpp", + ] + + if (abckit_sanitizers) { + cflags = [ + "-fno-omit-frame-pointer", + "-fsanitize=address", + "-fsanitize-address-use-after-scope", + "-fsanitize=undefined" + ] + + ldflags = [ + "-lasan", + "-lubsan" + ] + } + + include_dirs = [ + "$ark_root/libabckit", + "$ark_root/libabckit/include", + "$ark_root/libabckit/src", + "$ark_root/libabckit/tests", + ] + + configs = [ "$ark_root/libabckit:libabckit_public_config" ] + + deps = [ + "$ark_root/libabckit:libabckit", + ":abckit_js_vm_helpers", + ":abckit_ets_vm_helpers", + ] + + foreach(file, test_js_files) { + deps += [ ":gen_${file}_abc" ] + } + + foreach(file, test_ts_files) { + deps += [ ":gen_${file}_abc" ] + } + + foreach(file, test_ets_files) { + deps += [ ":gen_${file}_abc" ] + } + + if (is_ohos && is_standard_system) { + test_abc_dir = "/data/test" + } else { + test_abc_dir = rebase_path(target_out_dir) + } + + test_js_dir = rebase_path(test_js_path) + + defines = [ + "ABCKIT_ABC_DIR=\"${test_abc_dir}/\"", + "ABCKIT_TEST_DIR=\"${test_js_dir}\"", + ] +} + +group("abckit_stress_test_package") { + deps = [ + "$ark_root/libabckit/abckit/stress_plugin:abckit_stress_plugin(${host_toolchain})", + "$ark_root/libabckit/abckit:abckit(${host_toolchain})", + "$ark_root/static_core/verification/verifier:verifier_bin(${host_toolchain})", + "$js_root/ecmascript/js_vm:ark_js_vm(${host_toolchain})", + ] +} + +action("abckit_stress_test") { + deps = [ + ":abckit_stress_test_package" + ] + + outputs = [ + "$target_gen_dir/abckit_stress_test.txt", + ] + + script = "stress/stress.py" +} + +group("unittest") { + testonly = true + if (enable_libabckit) { + deps = [ + ":AbcKitTest", + ":abckit_stress_test", + ] + } +} + +group("host_unittest") { + testonly = true + if (enable_libabckit) { + deps = [ + ":AbcKitTestAction", + ":abckit_stress_test", + ] + } +} + +ohos_source_set("abckit_js_vm_helpers") { + sources = [ + "helpers/helpers_js_runtime.cpp" + ] + + external_deps = [ + "ets_runtime:libark_jsruntime", + ] + + output_extension = "so" + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +ohos_source_set("abckit_ets_vm_helpers") { + sources = [ + "helpers/helpers_ets_runtime.cpp" + ] + + include_dirs = [ + "$ark_root", + "$ark_root/libabckit/src", + ] + + etsstdlib = rebase_path(get_label_info("$ark_root/static_core/plugins/ets:etsstdlib", "target_gen_dir")) + "/etsstdlib.abc" + defines = [ + "ABCKIT_ETS_STD_LIB=\"${etsstdlib}\"", + ] + + deps = [ + "$ark_root/static_core/runtime:libarkruntime", + "$ark_root/static_core/plugins/ets:etsstdlib", + ] + + output_extension = "so" + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} diff --git a/libabckit/tests/canary.c b/libabckit/tests/canary.c new file mode 100644 index 0000000000000000000000000000000000000000..6b1ecf718446dcec3672b40c29d5da5a858aabdc --- /dev/null +++ b/libabckit/tests/canary.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 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 "include/abckit.h" +#include "include/statuses.h" +#include "include/ir_core.h" +#include "include/metadata.h" + +/* + * This a canary file to check that the public API conforms to: + * -std=c99 -pedantic -Wall -Wextra -Werror + */ + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + return 0; +} diff --git a/libabckit/tests/helpers/helpers.cpp b/libabckit/tests/helpers/helpers.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aed988e562d60a98dd1b4c9b4c02ae92e859e905 --- /dev/null +++ b/libabckit/tests/helpers/helpers.cpp @@ -0,0 +1,583 @@ +/** + * Copyright (c) 2024 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 "helpers/helpers.h" + +#include "abckit.h" +#include "isa/isa_dynamic.h" +#include "metadata.h" +#include "src/metadata_inspect_impl.h" +#include "libabckit/src/logger.h" +#include "ir_core.h" + +#include +#include +#include +#include + +#include + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto gStat = abckit_GetIsaApiStaticImpl(1); +static auto gDyn = abckit_GetIsaApiDynamicImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +namespace libabckit::test::helpers { + +bool Match(const std::string &actual, const std::string &expected) +{ + std::smatch m; + auto res = std::regex_match(actual, m, std::regex(expected)); + if (!res) { + LIBABCKIT_LOG_TEST(DEBUG) << "Doesn't match:\n"; + LIBABCKIT_LOG_TEST(DEBUG) << "Actual:\n" << actual << '\n'; + LIBABCKIT_LOG_TEST(DEBUG) << "Expected:\n" << expected << '\n'; + } + return res; +} + +struct UserTransformerData { + abckit_Method *method; + const std::function &userTransformer; +}; + +static void TransformMethodImpl(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + auto userTransformerData = (UserTransformerData *)data; + + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + userTransformerData->userTransformer(ctxM, method, ctxG); + + abckit_Code *newCode = impl->graphToCode(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implM->MethodSetCode(ctxM, method, newCode); + + return; +} + +void TransformMethod(abckit_File *ctxI, const std::string &methodName, + const std::function &userTransformer) +{ + auto *method = findMethodByName(ctxI, methodName); + ASSERT_NE(method, nullptr); + + UserTransformerData utd({method, userTransformer}); + + impl->TransformMethod(method, (void *)&utd, TransformMethodImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void TransformMethod(const std::string &inputPath, const std::string &outputPath, const std::string &methodSignature, + const std::function &userTransformer, + const std::function &validateResult) +{ + LIBABCKIT_LOG_TEST(DEBUG) << "TransformMethod: " << inputPath << '\n'; + + // Open file + abckit_File *ctxI = impl->OpenAbc(inputPath.c_str()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Transform method + auto *method = findMethodByName(ctxI, methodSignature); + ASSERT_NE(method, nullptr); + UserTransformerData utd({method, userTransformer}); + impl->TransformMethod(method, (void *)&utd, TransformMethodImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Validate method + auto code = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + validateResult(ctxG); + impl->DestroyGraphContext(ctxG); + + // Write output + impl->WriteAbc(ctxI, outputPath.c_str()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void TransformMethod(const std::string &inputPath, const std::string &outputPath, const std::string &methodSignature, + const std::function &userTransformer) +{ + LIBABCKIT_LOG_TEST(DEBUG) << "TransformMethod: " << inputPath << '\n'; + + // Open file + abckit_File *ctxI = impl->OpenAbc(inputPath.c_str()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Transform method + auto *method = findMethodByName(ctxI, methodSignature); + ASSERT_NE(method, nullptr); + UserTransformerData utd({method, userTransformer}); + impl->TransformMethod(method, (void *)&utd, TransformMethodImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Write output + impl->WriteAbc(ctxI, outputPath.c_str()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +struct UserInspectorData { + abckit_Method *method; + const std::function &userInspector; +}; + +static void InspectMethodImpl(abckit_ModifyContext *ctxM, abckit_Method *method, void *data) +{ + auto userInspectorData = (UserInspectorData *)data; + + abckit_File *ctxI = implI->MethodGetInspectContext(method); + auto oldCode = implI->MethodGetCode(method); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, oldCode); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + userInspectorData->userInspector(ctxM, method, ctxG); + + impl->DestroyGraphContext(ctxG); + + return; +} + +void InspectMethod(abckit_File *ctxI, const std::string &methodName, + const std::function &userInspector) +{ + auto *method = findMethodByName(ctxI, methodName); + ASSERT_NE(method, nullptr); + + UserInspectorData utd({method, userInspector}); + + impl->TransformMethod(method, (void *)&utd, InspectMethodImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + +} + +void InspectMethod(const std::string &inputPath, const std::string &methodSignature, + const std::function &userInspector) +{ + LIBABCKIT_LOG_TEST(DEBUG) << "InspectMethod: " << inputPath << '\n'; + + // Open file + abckit_File *ctxI = impl->OpenAbc(inputPath.c_str()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Inspect method + auto *method = findMethodByName(ctxI, methodSignature); + ASSERT_NE(method, nullptr); + UserInspectorData uid({method, userInspector}); + impl->TransformMethod(method, (void *)&uid, InspectMethodImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->DestroyInspectContext(ctxI); +} + +std::vector BBgetPredBlocks(abckit_BasicBlock *bb) +{ + std::vector predBBs; + implG->BBvisitPredBlocks( + bb, (void *)&predBBs, + []([[maybe_unused]] abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, void *d) { + auto *preds = (std::vector *)d; + preds->emplace_back(succBasicBlock); + }); + return predBBs; +} + +std::vector BBgetSuccBlocks(abckit_BasicBlock *bb) +{ + std::vector succBBs; + implG->BBvisitSuccBlocks( + bb, (void *)&succBBs, + []([[maybe_unused]] abckit_BasicBlock *curBasicBlock, abckit_BasicBlock *succBasicBlock, void *d) { + auto *succs = (std::vector *)d; + succs->emplace_back(succBasicBlock); + }); + return succBBs; +} + +std::vector BBgetAllInsts(abckit_BasicBlock *bb) +{ + std::vector insts; + for (auto *inst = implG->BBgetFirstInst(bb); inst != nullptr; inst = implG->IgetNext(inst)) { + insts.emplace_back(inst); + } + + return insts; +} + +abckit_Inst *FindFirstInst(abckit_Graph *ctxG, abckit_IsaApiStaticOpcode opcode, const std::function &findIf) +{ + std::vector bbs; + implG->GvisitBlocksRPO(ctxG, &bbs, [](abckit_BasicBlock *bb, void *data) { + ((std::vector *)data)->emplace_back(bb); + }); + for (auto *bb : bbs) { + auto *curInst = implG->BBgetFirstInst(bb); + while (curInst != nullptr) { + if (gStat->IgetOpcode(curInst) == opcode && findIf(curInst)) { + return curInst; + } + curInst = implG->IgetNext(curInst); + } + } + return nullptr; +} + +abckit_Inst *FindFirstInst(abckit_Graph *ctxG, abckit_IsaApiDynamicOpcode opcode, const std::function &findIf) +{ + std::vector bbs; + implG->GvisitBlocksRPO(ctxG, &bbs, [](abckit_BasicBlock *bb, void *data) { + ((std::vector *)data)->emplace_back(bb); + }); + for (auto *bb : bbs) { + auto *curInst = implG->BBgetFirstInst(bb); + while (curInst != nullptr) { + if (gDyn->IgetOpcode(curInst) == opcode && findIf(curInst)) { + return curInst; + } + curInst = implG->IgetNext(curInst); + } + } + return nullptr; +} + +void ReplaceInst(abckit_Inst *what, abckit_Inst *with) +{ + auto *next = implG->IgetNext(what); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + struct ReplaceContext + { + abckit_Inst *oldInput = nullptr; + abckit_Inst *newInput = nullptr; + }; + + if (next != nullptr) { + ReplaceContext ctx = {what, with}; + + implG->IvisitInputs(next, &ctx, [](abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data){ + ReplaceContext *ctx = reinterpret_cast(data); + + if (input == ctx->oldInput) { + implG->IsetInput(inst, ctx->newInput, inputIdx); + } + }); + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(with, what); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->Iremove(what); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void EnumerateAllMethods(abckit_File *ctxI, const std::function& cb) +{ + implI->FileEnumerateModules(ctxI, (void*)&cb, [](abckit_Module *m, void *cb) { + implI->ModuleEnumerateClasses(m, cb, [](abckit_Class *klass, void *cb) { + implI->ClassEnumerateMethods(klass, cb, [](abckit_Method *method, void *cb) { + (*reinterpret_cast*>(cb))(method); + return true; + }); + return true; + }); + + implI->ModuleEnumerateTopLevelFunctions(m, cb, [](abckit_Method *method, void *cb) { + (*reinterpret_cast*>(cb))(method); + return true; + }); + + return true; + }); +} + +void assertModuleVisitor([[maybe_unused]] abckit_Module *module, [[maybe_unused]] void *data) +{ + assert(module != nullptr); + assert(module->ctxI != nullptr); + assert(data != nullptr); +} + +void assertImportVisitor([[maybe_unused]] abckit_ImportDescriptor *id, [[maybe_unused]] void *data) +{ + assert(id != nullptr); + assert(id->importingModule != nullptr); + assert(id->importedModule != nullptr); + assert(data != nullptr); +} + +void assertExportVisitor([[maybe_unused]] abckit_ExportDescriptor *ed, [[maybe_unused]] void *data) +{ + assert(ed != nullptr); + assert(ed->exportingModule != nullptr); + assert(ed->exportedModule != nullptr); + assert(data != nullptr); +} + +void assertClassVisitor([[maybe_unused]] abckit_Class *klass, [[maybe_unused]] void *data) +{ + assert(klass != nullptr); + [[maybe_unused]] abckit_File *ctx = implI->ClassGetInspectContext(klass); + assert(ctx != nullptr); + assert(data != nullptr); +} + +void assertMethodVisitor([[maybe_unused]] abckit_Method *method, [[maybe_unused]] void *data) +{ + assert(method != nullptr); + [[maybe_unused]] abckit_File *ctx = implI->MethodGetInspectContext(method); + assert(ctx != nullptr); + assert(data != nullptr); +} + +void assertOpenAbc(const char *fname, abckit_File **ctx) +{ + ASSERT_NE(impl, nullptr); + ASSERT_NE(implI, nullptr); + *ctx = impl->OpenAbc(fname); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(*ctx, nullptr); +} + +bool classByNameFinder(abckit_Class *klass, void *data) +{ + assertClassVisitor(klass, data); + + abckit_File *ctx = implI->ClassGetInspectContext(klass); + auto ctxFinder = reinterpret_cast(data); + auto name = abckit_StringToString(ctx, implI->ClassGetName(klass)); + if (name == ctxFinder->name) { + ctxFinder->klass = klass; + return false; + } + + return true; +} + + +bool moduleByNameFinder(abckit_Module *module, void *data) +{ + assertModuleVisitor(module, data); + + auto ctxFinder = reinterpret_cast(data); + auto name = abckit_StringToString(module->ctxI, implI->ModuleGetName(module)); + if (name == ctxFinder->name) { + ctxFinder->module = module; + return false; + } + + return true; +} + +bool importByAliasFinder(abckit_ImportDescriptor *id, void *data) +{ + assertImportVisitor(id, data); + + auto ctxFinder = reinterpret_cast(data); + auto name = abckit_StringToString(id->importingModule->ctxI, implI->ImportDescriptorGetAlias(id)); + if (name == ctxFinder->name) { + ctxFinder->id = id; + return false; + } + + return true; +} + +bool exportByAliasFinder(abckit_ExportDescriptor *ed, void *data) +{ + assertExportVisitor(ed, data); + + auto ctxFinder = reinterpret_cast(data); + auto name = abckit_StringToString(ed->exportingModule->ctxI, implI->ExportDescriptorGetAlias(ed)); + if (name == ctxFinder->name) { + ctxFinder->ed = ed; + return false; + } + + return true; +} + +std::string GetCropFuncName(std::string fullSig) +{ + auto fullName = fullSig.substr(0, fullSig.find(':')); + auto pos = fullName.rfind('.'); + return fullName.substr(pos + 1); +} + +struct MethodAndName final { + std::vector FoundMethods; + const std::string &MethodName; + bool fullSign = true; +}; + +static std::pair SplitFunctionName(const std::string &fullName) { + size_t colonPos = fullName.find(':'); + std::string croppedName = fullName.substr(0, colonPos); + size_t dotPos = croppedName.find('.'); + if (dotPos == std::string::npos) { + return {"", fullName}; + } + return {fullName.substr(0, dotPos), fullName.substr(dotPos + 1)}; +} + +void findMethodByNameImpl(abckit_File *ctxI, void *data) +{ + implI->FileEnumerateModules(ctxI, data, [](abckit_Module *m, void *data) { + auto moduleName = helpers::abckit_StringToString(implI->ModuleGetInspectContext(m), implI->ModuleGetName(m)); + auto MN = static_cast(data); + auto [funcModule, funcName] = SplitFunctionName(MN->MethodName); + if (!funcModule.empty()) { + if (funcModule != moduleName) { + return true; + } + } + implI->ModuleEnumerateClasses(m, data, [](abckit_Class *klass, void *data) { + implI->ClassEnumerateMethods(klass, data, [](abckit_Method *method, void *data) { + auto MN = static_cast(data); + auto *MethodCtxI = implI->MethodGetInspectContext(method); + auto currmname = implI->MethodGetName(method); + auto currMethodNameStr = helpers::abckit_StringToString(MethodCtxI, currmname); + auto currMethodName = MN->fullSign ? currMethodNameStr : GetCropFuncName(currMethodNameStr); + auto [methodModule, methodName] = SplitFunctionName(MN->MethodName); + if (currMethodName == methodName) { + LIBABCKIT_LOG_TEST(DEBUG) << "Method found by name: " << methodName << '\n'; + MN->FoundMethods.emplace_back(method); + } + return true; + }); + return true; + }); + + implI->ModuleEnumerateTopLevelFunctions(m, data, [](abckit_Method *method, void *data) { + auto MN = static_cast(data); + auto *MethodCtxI = implI->MethodGetInspectContext(method); + auto currmname = implI->MethodGetName(method); + auto currMethodNameStr = helpers::abckit_StringToString(MethodCtxI, currmname); + auto currMethodName = MN->fullSign ? currMethodNameStr : GetCropFuncName(currMethodNameStr); + auto [methodModule, methodName] = SplitFunctionName(MN->MethodName); + if (currMethodName == methodName) { + LIBABCKIT_LOG_TEST(DEBUG) << "Method found by name: " << methodName << '\n'; + MN->FoundMethods.emplace_back(method); + } + return true; + }); + + return true; + }); +} + +/* + Returns pointer to abckit_Method if found, + nullptr otherwise +*/ +abckit_Method *findMethodByName(abckit_File *ctxI, const std::string &name) +{ + MethodAndName MN {{}, name}; + LIBABCKIT_LOG_TEST(DEBUG) << "Method searching: " << name << '\n'; + findMethodByNameImpl(ctxI, &MN); + if (!MN.FoundMethods.empty()) { + EXPECT_EQ(MN.FoundMethods.size(), 1); + return MN.FoundMethods[0]; + } + + MN.fullSign = false; + findMethodByNameImpl(ctxI, &MN); + EXPECT_EQ(MN.FoundMethods.size(), 1); + return MN.FoundMethods[0]; +} + +bool methodByNameFinder(abckit_Method *method, void *data) +{ + assertMethodVisitor(method, data); + + abckit_File *ctx = implI->MethodGetInspectContext(method); + auto ctxFinder = reinterpret_cast(data); + auto fullName = abckit_StringToString(ctx, implI->MethodGetName(method)); + auto name = ctxFinder->fullSign ? fullName : GetCropFuncName(fullName); + if (name == ctxFinder->name) { + ctxFinder->method = method; + return false; + } + + return true; +} + +bool nameToModuleCollector(abckit_Module *module, void *data) +{ + assertModuleVisitor(module, data); + + abckit_File *ctx = implI->ModuleGetInspectContext(module); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(ctx != nullptr); + auto modules = reinterpret_cast *>(data); + auto moduleName = implI->ModuleGetName(module); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, moduleName); + LIBABCKIT_LOG_TEST(DEBUG) << "module name: " << name << std::endl; + assert(modules->find(name) == modules->end()); + modules->emplace(name, module); + + return true; +} + +bool moduleImportsCollector(abckit_ImportDescriptor *id, void *data) +{ + helpers::assertImportVisitor(id, data); + + auto imports = reinterpret_cast *>(data); + imports->insert(id); + + return true; +} + +bool moduleExportsCollector(abckit_ExportDescriptor *ed, void *data) +{ + helpers::assertExportVisitor(ed, data); + + auto exports = reinterpret_cast *>(data); + exports->insert(ed); + + return true; +} + +std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + assert(ctxI != nullptr); + assert(str != nullptr); + + std::size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + assert(len > 0); + + auto name = new char[len] {}; + implI->abckit_StringToString(ctxI, str, name, &len); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + std::string res {name}; + delete[] name; + + return res; +} + +} // namespace libabckit::test::helpers diff --git a/libabckit/tests/helpers/helpers.h b/libabckit/tests/helpers/helpers.h new file mode 100644 index 0000000000000000000000000000000000000000..3c79058dc6400f3641cccb8bb4f02e5db7a06778 --- /dev/null +++ b/libabckit/tests/helpers/helpers.h @@ -0,0 +1,221 @@ +/** + * Copyright (c) 2024 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. + */ +#ifndef LIBABCKIT_TESTS_HELPERS +#define LIBABCKIT_TESTS_HELPERS + +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "libabckit/src/logger.h" + +#include +#include +#include +#include + +#include + +namespace libabckit::test::helpers { + +std::vector BBgetPredBlocks(abckit_BasicBlock *bb); +std::vector BBgetSuccBlocks(abckit_BasicBlock *bb); +std::vector BBgetAllInsts(abckit_BasicBlock *bb); + +template +struct InstSchema { + InstSchema(size_t id, T o, const std::vector &i) + : id(id), opcode(o), inputs(std::move(i)) {} + size_t id; + T opcode; + std::vector inputs; +}; +template struct InstSchema; +template struct InstSchema; + +template +struct BBSchema { + BBSchema(const std::vector &p, const std::vector &s, const std::vector> &i) + : preds(std::move(p)), succs(std::move(s)), instSchemas(std::move(i)) {} + std::vector preds; + std::vector succs; + std::vector> instSchemas; +}; +template struct BBSchema; +template struct BBSchema; + +template +void VerifyGraph(abckit_Graph *ctxG, const std::vector> &bbSchemas) +{ + static auto implG = abckit_GetGraphApiImpl(1); + static auto gStat = abckit_GetIsaApiStaticImpl(1); + static auto gDyn = abckit_GetIsaApiDynamicImpl(1); + + LIBABCKIT_LOG(DEBUG) << " Graph:\n"; + LIBABCKIT_LOG_DUMP(implG->Gdump(ctxG, 2), DEBUG); + std::vector bbs; + + // Collect basic blocks + implG->GvisitBlocksRPO(ctxG, &bbs, [](abckit_BasicBlock *bb, void *data) { + ((std::vector *)data)->emplace_back(bb); + }); + + // Construct maps bb->idx + std::unordered_map bbToIdx; + ASSERT_EQ(bbs.size(), bbSchemas.size()); + for (size_t bbIdx = 0; bbIdx < bbs.size(); bbIdx++) { + auto *bb = bbs[bbIdx]; + bbToIdx.insert({bb, bbIdx}); + } + + std::unordered_map schemaIdToId; // Map from inst schema id to actual inst id + for (size_t bbIdx = 0; bbIdx < bbs.size(); bbIdx++) { + auto *bb = bbs[bbIdx]; + auto &bbSchema = bbSchemas[bbIdx]; + + // Verify bb predecessors + auto preds = BBgetPredBlocks(bb); + ASSERT_EQ(preds.size(), bbSchema.preds.size()); + for (size_t predIdx = 0; predIdx < preds.size(); predIdx++) { + ASSERT_EQ(bbToIdx.at(preds[predIdx]), bbSchema.preds[predIdx]); + } + + // Verify bb successors + auto succs = BBgetSuccBlocks(bb); + ASSERT_EQ(succs.size(), bbSchema.succs.size()); + for (size_t succIdx = 0; succIdx < succs.size(); succIdx++) { + ASSERT_EQ(bbToIdx.at(succs[succIdx]), bbSchema.succs[succIdx]); + } + + // Collect instructions + std::vector insts = BBgetAllInsts(bb); + + // Verify instructions + auto &instSchemas = bbSchema.instSchemas; + std::unordered_map idToInst; + ASSERT_EQ(insts.size(), instSchemas.size()); + for (size_t instIdx = 0; instIdx < insts.size(); instIdx++) { + auto &instSchema = instSchemas[instIdx]; + auto *inst = insts[instIdx]; + + if constexpr (std::is_same()) { + ASSERT_EQ(gDyn->IgetOpcode(inst), instSchema.opcode); + } else if constexpr (std::is_same()) { + ASSERT_EQ(gStat->IgetOpcode(inst), instSchema.opcode); + } else { + LIBABCKIT_UNREACHABLE + } + + auto instId = implG->IgetId(inst); + auto instSchemaId = instSchema.id; + schemaIdToId.insert({instSchemaId, instId}); + idToInst.insert({instId, inst}); + + // Verify inputs + auto inputCount = implG->IgetInputCount(inst); + ASSERT_EQ(inputCount, instSchema.inputs.size()); + for (size_t inputNumber = 0; inputNumber < inputCount; inputNumber++) { + auto input = implG->IgetInput(inst, inputNumber); + auto inputId = implG->IgetId(input); + auto inputIdx = instSchema.inputs[inputNumber]; + ASSERT_NE(schemaIdToId.find(inputIdx), schemaIdToId.end()); + ASSERT_EQ(schemaIdToId.at(inputIdx), inputId); + } + } + } +} + +bool Match(const std::string &actual, const std::string &expected); +void TransformMethod(abckit_File *ctxI, + const std::string &methodSignature, + const std::function &userTransformer); +void TransformMethod(const std::string &inputPath, + const std::string &outputPath, + const std::string &methodSignature, + const std::function &userTransformer); +void TransformMethod(const std::string &inputPath, + const std::string &outputPath, + const std::string &methodSignature, + const std::function &userTransformer, + const std::function& validateResult); + +void InspectMethod(abckit_File *ctxI, + const std::string &methodSignature, + const std::function &userTransformer); +void InspectMethod(const std::string &inputPath, + const std::string &methodSignature, + const std::function &userTransformer); + +abckit_Inst *FindFirstInst(abckit_Graph *ctxG, abckit_IsaApiStaticOpcode opcode, + const std::function &findIf = [](abckit_Inst *){ return true; }); +abckit_Inst *FindFirstInst(abckit_Graph *ctxG, abckit_IsaApiDynamicOpcode opcode, + const std::function &findIf = [](abckit_Inst *){ return true; }); +void ReplaceInst(abckit_Inst *what, abckit_Inst *with); +void EnumerateAllMethods(abckit_File *ctxI, const std::function& cb); + +struct ModuleByNameContext +{ + abckit_Module *module; + const char *name; +}; + +struct ImportByAliasContext +{ + abckit_ImportDescriptor *id; + const char *name; +}; + +struct ExportByAliasContext +{ + abckit_ExportDescriptor *ed; + const char *name; +}; + +struct ClassByNameContext +{ + abckit_Class *klass; + const char *name; +}; + +struct MethodByNameContext +{ + abckit_Method *method; + const char *name; + bool fullSign = false; +}; + +abckit_Method *findMethodByName(abckit_File *ctxI, const std::string &name); +bool moduleByNameFinder(abckit_Module *module, void *data); +bool importByAliasFinder(abckit_ImportDescriptor *id, void *data); +bool exportByAliasFinder(abckit_ExportDescriptor *ed, void *data); +bool classByNameFinder(abckit_Class *klass, void *data); +bool methodByNameFinder(abckit_Method *method, void *data); +bool nameToModuleCollector(abckit_Module *module, void *data); +bool moduleImportsCollector(abckit_ImportDescriptor *id, void *data); +bool moduleExportsCollector(abckit_ExportDescriptor *ed, void *data); + +void assertModuleVisitor(abckit_Module *module, void *data); +void assertImportVisitor(abckit_ImportDescriptor *id, void *data); +void assertExportVisitor(abckit_ExportDescriptor *id, void *data); +void assertClassVisitor(abckit_Class *klass, void *data); +void assertMethodVisitor(abckit_Method *method, void *data); +void assertOpenAbc(const char *fname, abckit_File **ctx); +std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str); +std::string GetCropFuncName(std::string fullSig); + +} // libabckit::test::helpers + +#endif /*LIBABCKIT_TESTS_HELPERS */ diff --git a/libabckit/tests/helpers/helpers_ets_runtime.cpp b/libabckit/tests/helpers/helpers_ets_runtime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b2e85871b46dc7e79a1dc4ce6d37eaa6ab25686c --- /dev/null +++ b/libabckit/tests/helpers/helpers_ets_runtime.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024 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 "helpers_runtime.h" +#include "libabckit/src/logger.h" +#include "static_core/plugins/ets/runtime/napi/ets_napi.h" +#include "mem_manager/mem_manager.h" + +#include +#include +#include +#include + +namespace libabckit::test::helpers { + +std::string ExecuteStaticAbc(const std::string &abcPath, const std::string &klassName, const std::string &methodName) +{ + LIBABCKIT_LOG(DEBUG) << "ExecuteStaticAbc: " << abcPath << ' ' << klassName << ' ' << methodName << '\n'; + + EtsEnv *env {nullptr}; + EtsVM *vm {nullptr}; + + std::vector options_vector; + + options_vector = {{EtsOptionType::ETS_BOOT_FILE, ABCKIT_ETS_STD_LIB}, + {EtsOptionType::ETS_BOOT_FILE, abcPath.c_str()}, + {EtsOptionType::ETS_ARK_FILE, abcPath.c_str()}, + {EtsOptionType::ETS_INTERPRETER_TYPE, "cpp"}, + {EtsOptionType::ETS_GC_TRIGGER_TYPE, "heap-trigger"}, + {EtsOptionType::ETS_NO_JIT, nullptr}}; + + EtsVMInitArgs vm_args; + vm_args.version = ETS_NAPI_VERSION_1_0; + vm_args.options = options_vector.data(); + vm_args.nOptions = static_cast(options_vector.size()); + + MemManager::Finalize(); + ETS_CreateVM(&vm, &env, &vm_args); + + auto klass = env->FindClass(klassName.c_str()); + if (klass == nullptr) { + LIBABCKIT_LOG(FATAL) << "No class " << klassName << " in " << abcPath << '\n'; + } + auto method = env->GetStaticp_method(klass, methodName.c_str(), nullptr); + if (klass == nullptr) { + LIBABCKIT_LOG(FATAL) << "No method " << methodName << " in " << klassName << '\n'; + } + + std::stringstream ss; + { + CoutRedirect coutRedirect(ss.rdbuf()); + env->CallStaticVoidMethod(klass, method); + } + + vm->DestroyEtsVM(); + + LIBABCKIT_LOG(DEBUG) << "Output:\n" << ss.str() << '\n'; + + return ss.str(); +} + +} // namespace libabckit::test::helpers diff --git a/libabckit/tests/helpers/helpers_js_runtime.cpp b/libabckit/tests/helpers/helpers_js_runtime.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5f6ae824134f3a71ec67aecadcfa5f5baced34b --- /dev/null +++ b/libabckit/tests/helpers/helpers_js_runtime.cpp @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2024 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 "helpers_runtime.h" +#include "libabckit/src/logger.h" +#include "ecmascript/napi/include/jsnapi.h" + +#include +#include + +using namespace panda; + +namespace libabckit::test::helpers { + +std::string ExecuteDynamicAbc(const std::string &abcPath, const std::string &entry) +{ + LIBABCKIT_LOG(DEBUG) << "ExecuteDynamicAbc: " << abcPath << ' ' << entry << '\n'; + + RuntimeOption option; + option.SetLogLevel(RuntimeOption::LOG_LEVEL::ERROR); + ecmascript::EcmaVM *vm = JSNApi::CreateJSVM(option); + + std::stringstream ss; + { + CoutRedirect coutRedirect(ss.rdbuf()); + JSNApi::Execute(vm, abcPath, entry, true); + } + JSNApi::DestroyJSVM(vm); + LIBABCKIT_LOG(DEBUG) << "Output:\n" << ss.str() << '\n'; + return ss.str(); +} + +} // namespace libabckit::test::helpers diff --git a/libabckit/tests/helpers/helpers_mode.cpp b/libabckit/tests/helpers/helpers_mode.cpp new file mode 100644 index 0000000000000000000000000000000000000000..859079a639e02476ef0cd3e6dcd01386ed9fdaa4 --- /dev/null +++ b/libabckit/tests/helpers/helpers_mode.cpp @@ -0,0 +1,642 @@ +/** + * Copyright (c) 2024 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 "adapter_dynamic/abckit_dynamic.h" +#include "adapter_static/abckit_static.h" +#include "adapter_dynamic/metadata_inspect_dynamic.h" +#include "adapter_static/metadata_inspect_static.h" +#include "metadata_modify_impl.h" +#include "helpers/helpers.h" +#include "helpers/helpers_mode.h" + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "ir_impl.h" + +#include +#include + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +namespace libabckit::test::helpers_mode { + +static abckit_Module *DUMMY_MODULE = new abckit_Module(); +static abckit_String *DUMMY_STRING = (abckit_String*)(0x1); + +static abckit_Class *DUMMY_CLASS = new abckit_Class(); +static abckit_Method *DUMMY_METHOD = new abckit_Method(); +static abckit_LiteralArray *DUMMY_LITARR = (abckit_LiteralArray*)(0x1); +static abckit_Inst *DUMMY_INST1 = new abckit_Inst(); +static abckit_Inst *DUMMY_INST2 = new abckit_Inst(); +static abckit_Inst *DUMMY_INST3 = new abckit_Inst(); +static abckit_Inst *DUMMY_INST4 = new abckit_Inst(); +static abckit_Inst *DUMMY_INST5 = new abckit_Inst(); +static abckit_ImportDescriptor *DUMMY_IMPORT = (abckit_ImportDescriptor*)(0x1); +static abckit_ExportDescriptor *DUMMY_EXPORT = (abckit_ExportDescriptor*)(0x1); +static abckit_Type *DUMMY_TYPE = (abckit_Type*)(0x1); + +abckit_Graph *OpenWrongModeFile(bool is_dynamic) { + if (is_dynamic) { + auto* file = impl->OpenAbc(ABCKIT_ABC_DIR "wrong_mode_tests/mode_test_static.abc"); + auto* foo = helpers::findMethodByName(file, "foo"); + auto* code = MethodGetCodeStatic(foo); + auto* graph = codeToGraphStatic(file, code); + return graph; + } + auto* file = impl->OpenAbc(ABCKIT_ABC_DIR "wrong_mode_tests/mode_test_dynamic.abc"); + auto* foo = helpers::findMethodByName(file, "foo"); + auto* code = MethodGetCodeDynamic(foo); + auto* graph = codeToGraphDynamic(file, code); + return graph; +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + auto *inst = ApiToCheck(graph); + + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(void (*ApiToCheck)(abckit_Graph *ctxG), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + ApiToCheck(graph); + + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(void (*ApiToCheck)(abckit_Graph *ctxG, int fd), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + ApiToCheck(graph, 0); + + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint32_t index), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + auto *inst = ApiToCheck(graph, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, int64_t value), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + int64_t val = 0; + abckit_Inst *inst = ApiToCheck(graph, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t value), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + uint64_t val = 0; + abckit_Inst *inst = ApiToCheck(graph, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + auto *inst = ApiToCheck(graph, 0, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *str), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, 0, DUMMY_INST1); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_LiteralArray *str), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + abckit_Inst *inst = ApiToCheck(graph, 0, DUMMY_LITARR); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t value, abckit_Inst *inst1, abckit_Inst *inst2), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + auto *inst = ApiToCheck(graph, 0, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, double value), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + double val = 0; + abckit_Inst *inst = ApiToCheck(graph, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + abckit_Inst *inst = ApiToCheck(graph, DUMMY_STRING); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str, uint64_t imm), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + abckit_Inst *inst = ApiToCheck(graph, DUMMY_STRING, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ExportDescriptor *e), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + abckit_Inst *inst = ApiToCheck(graph, DUMMY_EXPORT); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ImportDescriptor *i), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + abckit_Inst *inst = ApiToCheck(graph, DUMMY_IMPORT); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_TypeId typeId), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, abckit_TypeId_INVALID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_ExportDescriptor *e), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_EXPORT); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_IsaApiDynamicConditionCode cc), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, uint64_t imm1), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, 0, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, abckit_Inst *inst1), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, 0, DUMMY_INST2); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, uint64_t imm1, + abckit_Inst *input1), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, 0, 0, DUMMY_INST2); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, abckit_Method *method, size_t argCount, ...), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_MODULE->ctxI = graph->ctxI; + DUMMY_METHOD->m = DUMMY_MODULE; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input, size_t argCount, ...), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, size_t argCount, ...), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + auto *inst = ApiToCheck(graph, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_MODULE->ctxI = graph->ctxI; + DUMMY_METHOD->m = DUMMY_MODULE; + auto *inst = ApiToCheck(graph, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, size_t argCount, ...), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_MODULE->ctxI = graph->ctxI; + DUMMY_METHOD->m = DUMMY_MODULE; + auto *inst = ApiToCheck(graph, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Module *m), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + auto *inst = ApiToCheck(graph, DUMMY_MODULE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_CLASS->m = DUMMY_MODULE; + DUMMY_MODULE->ctxI = graph->ctxI; + auto *inst = ApiToCheck(graph, DUMMY_CLASS); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass1, abckit_Class *klass2), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_CLASS->m = DUMMY_MODULE; + DUMMY_MODULE->ctxI = graph->ctxI; + auto *inst = ApiToCheck(graph, DUMMY_CLASS, DUMMY_CLASS); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass, abckit_Inst *inst), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_CLASS->m = DUMMY_MODULE; + DUMMY_MODULE->ctxI = graph->ctxI; + auto *inst = ApiToCheck(graph, DUMMY_CLASS, DUMMY_INST1); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_LiteralArray *litarr), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + auto *inst = ApiToCheck(graph, DUMMY_LITARR); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *m, abckit_LiteralArray *litarr, uint64_t val, abckit_Inst *inst), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_MODULE->ctxI = graph->ctxI; + DUMMY_METHOD->m = DUMMY_MODULE; + auto *inst = ApiToCheck(graph, DUMMY_METHOD, DUMMY_LITARR, 0, DUMMY_INST1); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId targetType), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, abckit_TypeId::abckit_TypeId_I8); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + abckit_Inst *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_STRING); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + DUMMY_INST3->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, DUMMY_INST3); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + DUMMY_INST3->ctxG = graph; + DUMMY_INST4->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, DUMMY_INST3, DUMMY_INST4); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, abckit_Inst *input4), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + DUMMY_INST3->ctxG = graph; + DUMMY_INST4->ctxG = graph; + DUMMY_INST5->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, DUMMY_INST3, DUMMY_INST4, DUMMY_INST5); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1, abckit_Inst *input2), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_STRING, DUMMY_INST2); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0), bool is_dynamic) +{ + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0), bool is_dynamic) { + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_MODULE->ctxI = graph->ctxI; + DUMMY_METHOD->m = DUMMY_MODULE; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id), bool is_dynamic) { + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + DUMMY_INST2->ctxG = graph; + DUMMY_INST3->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_INST2, DUMMY_INST3, abckit_TypeId_INVALID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType), bool is_dynamic) { + auto* graph = OpenWrongModeFile(is_dynamic); + DUMMY_INST1->ctxG = graph; + auto *inst = ApiToCheck(graph, DUMMY_INST1, DUMMY_TYPE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_MODE); + auto* file = graph->ctxI; + impl->DestroyGraphContext(graph); + impl->DestroyInspectContext(file); +} + +} // namespace libabckit::test::helpers_nullptr diff --git a/libabckit/tests/helpers/helpers_mode.h b/libabckit/tests/helpers/helpers_mode.h new file mode 100644 index 0000000000000000000000000000000000000000..5e3a009f2e0e4d08050bc21aa9e15d78234eb970 --- /dev/null +++ b/libabckit/tests/helpers/helpers_mode.h @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2024 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. + */ +#ifndef LIBABCKIT_TESTS_INVALID_HELPERS +#define LIBABCKIT_TESTS_INVALID_HELPERS + +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" + +namespace libabckit::test::helpers_mode { + +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint32_t index), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, int64_t value), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t value), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *inst), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_LiteralArray *inst), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *inst0, abckit_Inst *inst1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, double value), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str, uint64_t imm), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ExportDescriptor *e), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ImportDescriptor *i), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_TypeId typeId), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_ExportDescriptor *e), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_IsaApiDynamicConditionCode cc), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, abckit_Inst *inst1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1, + abckit_Inst *inst1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, abckit_Method *method, + size_t argCount, ...), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, size_t argCount, ...), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, size_t argCount, ...), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, size_t argCount, ...), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Module *m), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass1, abckit_Class *klass2), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass, abckit_Inst *inst), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_LiteralArray *litarr), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *m, abckit_LiteralArray *litarr, uint64_t val, abckit_Inst *inst), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId targetType), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, abckit_Inst *input4), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1, abckit_Inst *input2), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id), bool is_dynamic); +void TestMode(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType), bool is_dynamic); +} // libabckit::test::helpers_nullptr + +#endif /*LIBABCKIT_TESTS_INVALID_HELPERS */ diff --git a/libabckit/tests/helpers/helpers_nullptr.cpp b/libabckit/tests/helpers/helpers_nullptr.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e08d0915abddf6446f85dc1cd0899c4382b5a7da --- /dev/null +++ b/libabckit/tests/helpers/helpers_nullptr.cpp @@ -0,0 +1,2156 @@ +/** + * Copyright (c) 2024 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 "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +namespace libabckit::test::helpers_nullptr { + +static abckit_Module *DUMMY_MODULE = (abckit_Module*)(0x1); +static abckit_String *DUMMY_STRING = (abckit_String*)(0x1); + +static abckit_Graph *DUMMY_GRAPH = (abckit_Graph*)(0x1); +static abckit_Class *DUMMY_CLASS = (abckit_Class*)(0x1); +static abckit_Method *DUMMY_METHOD = (abckit_Method*)(0x1); +static abckit_Literal *DUMMY_LITERAL = (abckit_Literal*)(0x1); +static abckit_LiteralArray *DUMMY_LITARR = (abckit_LiteralArray*)(0x1); +static abckit_BasicBlock *DUMMY_BB = (abckit_BasicBlock*)(0x1); +static abckit_Inst *DUMMY_INST = (abckit_Inst*)(0x1); +static abckit_File *DUMMY_FILE = (abckit_File*)(0x1); +static abckit_Annotation *DUMMY_ANNO = (abckit_Annotation *)(0x1); +static abckit_AnnotationInterface *DUMMY_ANNOIF = (abckit_AnnotationInterface *)(0x1); +static abckit_AnnotationInterfaceField *DUMMY_ANNOIFFIELD = (abckit_AnnotationInterfaceField *)(0x1); +static abckit_AnnotationElement *DUMMY_ANNOELEM = (abckit_AnnotationElement *)(0x1); +static abckit_ModifyContext *DUMMY_CTXM = (abckit_ModifyContext *)(0x1); +static abckit_ImportDescriptor *DUMMY_IMPORT = (abckit_ImportDescriptor*)(0x1); +static abckit_ExportDescriptor *DUMMY_EXPORT = (abckit_ExportDescriptor*)(0x1); +static abckit_Type *DUMMY_TYPE = (abckit_Type*)(0x1); +static abckit_TypeId DUMMY_TYPEID = abckit_TypeId_INVALID; +static abckit_Value *DUMMY_VALUE = (abckit_Value *)(0x1); + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Graph *ctxG)) +{ + abckit_BasicBlock *bb = ApiToCheck(nullptr); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Inst *inst)) +{ + abckit_BasicBlock *bb = ApiToCheck(nullptr); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_BasicBlock *bb, size_t argCount, ...)) +{ + abckit_Inst *bb = ApiToCheck(nullptr, 0x0); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG)) +{ + abckit_Inst *inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Graph *ctxG)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Graph *ctxG, int fd)) +{ + ApiToCheck(nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI, const char *ptr)) +{ + ApiToCheck(nullptr, "dummy string"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI, abckit_Literal *lit)) +{ + ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI, abckit_String *str, char* out, size_t *len)) +{ + ApiToCheck(nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, DUMMY_STRING, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, abckit_ImportDescriptor *i)) +{ + ApiToCheck(nullptr, DUMMY_IMPORT); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, abckit_ExportDescriptor *e)) +{ + ApiToCheck(nullptr, DUMMY_EXPORT); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_LiteralArray *litarr)) +{ + ApiToCheck(nullptr, DUMMY_LITARR); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Module *m)) +{ + ApiToCheck(nullptr, DUMMY_MODULE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_ImportDescriptor *i)) +{ + ApiToCheck(nullptr, DUMMY_IMPORT); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_ExportDescriptor *e)) +{ + ApiToCheck(nullptr, DUMMY_EXPORT); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_IsaApiDynamicConditionCode cc)) +{ + ApiToCheck(nullptr, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_IsaApiStaticConditionCode cc)) +{ + ApiToCheck(nullptr, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_TypeId type)) +{ + ApiToCheck(nullptr, abckit_TypeId_INVALID); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, int fd)) +{ + ApiToCheck(nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_IsaApiDynamicOpcode (*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_IsaApiStaticOpcode (*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_TypeId (*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Inst *inst, uint32_t index)) +{ + auto *inst = ApiToCheck(nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint32_t (*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_Module *m)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Method *(*ApiToCheck)(abckit_Inst *inst)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Method *method)) +{ + ApiToCheck(nullptr, DUMMY_METHOD); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint32_t (*ApiToCheck)(abckit_Graph *ctxG)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(int64_t (*ApiToCheck)(abckit_Inst *input0)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint64_t (*ApiToCheck)(abckit_Inst *input0)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint64_t (*ApiToCheck)(abckit_Inst *inst, size_t val)) +{ + ApiToCheck(nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(double (*ApiToCheck)(abckit_Inst *input0)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Graph *(*ApiToCheck)(abckit_BasicBlock *bb)) +{ + auto *graph = ApiToCheck(nullptr); + ASSERT_EQ(graph, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Graph *(*ApiToCheck)(abckit_File *ctx, abckit_Code *code)) +{ + auto *graph = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(graph, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + graph = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(graph, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_BasicBlock *bb)) +{ + auto *inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_BasicBlock *bb)) +{ + auto *bb = ApiToCheck(nullptr); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_BasicBlock *bb)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint32_t (*ApiToCheck)(abckit_BasicBlock *bb)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint64_t (*ApiToCheck)(abckit_BasicBlock *bb)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Code *(*ApiToCheck)(abckit_Method *method)) +{ + auto *code = ApiToCheck(nullptr); + ASSERT_EQ(code, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Code *(*ApiToCheck)(abckit_Graph *ctx)) +{ + auto *code = ApiToCheck(nullptr); + ASSERT_EQ(code, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Class *klass)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Method *method)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Module *m)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_ExportDescriptor *e)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_ImportDescriptor *i)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_ModifyContext *ctxM, const char *val)) +{ + auto *str = ApiToCheck(nullptr, "dummy string"); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + str = ApiToCheck(DUMMY_CTXM, nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Class *klass)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Method *method)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Module *m)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Annotation *anno)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_ExportDescriptor *e)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_ImportDescriptor *i)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(const char *ptr)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(const char *ptr, bool opt)) +{ + auto *f = ApiToCheck(nullptr, false); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File_Version (*ApiToCheck)(abckit_File *file)) +{ + auto *f = ApiToCheck(nullptr); + ASSERT_EQ(f, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + bool res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(double (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(float (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + bool res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_LiteralArray *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *res = ApiToCheck(nullptr); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_LiteralArray *(*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Literal **lit, size_t sz)) +{ + auto *res = ApiToCheck(nullptr, &DUMMY_LITERAL, 0); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_CTXM, nullptr, 0); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, bool val)) +{ + auto *res = ApiToCheck(nullptr, false); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, double val)) +{ + auto *res = ApiToCheck(nullptr, 0.); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, float val)) +{ + auto *res = ApiToCheck(nullptr, 0.); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, const char *val)) +{ + auto *res = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint8_t val)) +{ + auto *res = ApiToCheck(nullptr, 0); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint16_t val)) +{ + auto *res = ApiToCheck(nullptr, 0); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint32_t val)) +{ + auto *res = ApiToCheck(nullptr, 0); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint64_t val)) +{ + auto *res = ApiToCheck(nullptr, 0); + ASSERT_EQ(res, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_LiteralTag (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + auto res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, abckit_LiteralTag_INVALID); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, abckit_LiteralTag_INVALID); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint8_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + auto res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint16_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + auto res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint32_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + auto res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(uint64_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)) +{ + auto res = ApiToCheck(nullptr, DUMMY_LITERAL); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + res = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(res, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_Class *klass)) +{ + auto *m = ApiToCheck(nullptr); + ASSERT_EQ(m, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_Method *method)) +{ + auto *m = ApiToCheck(nullptr); + ASSERT_EQ(m, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_ExportDescriptor *e)) +{ + auto *m = ApiToCheck(nullptr); + ASSERT_EQ(m, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_ImportDescriptor *i)) +{ + auto *m = ApiToCheck(nullptr); + ASSERT_EQ(m, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint32_t index)) +{ + auto *inst = ApiToCheck(nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, int64_t value)) +{ + int64_t val = 0; + abckit_Inst *inst = ApiToCheck(nullptr, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t value)) +{ + uint64_t val = 0; + abckit_Inst *inst = ApiToCheck(nullptr, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, int32_t value)) +{ + int32_t val = 0; + abckit_Inst *inst = ApiToCheck(nullptr, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1)) +{ + auto *inst = ApiToCheck(nullptr, 0, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *str)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, 0, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_LiteralArray *str)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, 0, DUMMY_LITARR); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t value, abckit_Inst *inst1, abckit_Inst *inst2)) +{ + auto *inst = ApiToCheck(nullptr, 0, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, 0, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, 0, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, 0, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, double value)) +{ + double val = 0; + abckit_Inst *inst = ApiToCheck(nullptr, val); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_STRING); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str, uint64_t imm)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_STRING, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ExportDescriptor *e)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_EXPORT); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ImportDescriptor *i)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_IMPORT); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_TypeId typeId)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, nullptr, abckit_TypeId_INVALID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr, abckit_TypeId_INVALID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, abckit_TypeId_INVALID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_ExportDescriptor *e)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_IsaApiDynamicConditionCode cc)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_INST, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, uint64_t imm1)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, 0, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_INST, 0, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, abckit_Inst *inst1)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0, uint64_t imm1, + abckit_Inst *input1)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, nullptr, 0, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, 0, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0, 0, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, abckit_Method *method, size_t argCount, ...)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr, 1, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, 1, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_METHOD, 1, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + // TODO: test with more arguments +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input, size_t argCount, ...)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 1, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + // TODO: test with more arguments +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, size_t argCount, ...)) +{ + auto *inst = ApiToCheck(nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + // TODO: test with more arguments +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_METHOD, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, size_t argCount, ...)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 1, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_METHOD, 1, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + // TODO: test with more arguments +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Module *m)) +{ + auto *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_MODULE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass)) +{ + auto *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_CLASS); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass1, abckit_Class *klass2)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_CLASS, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_CLASS); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass, abckit_Inst *inst)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_CLASS, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_LiteralArray *litarr)) +{ + auto *inst = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_LITARR); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_TYPE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_TYPE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_TYPE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *m, abckit_LiteralArray *litarr, uint64_t val, abckit_Inst *inst)) +{ + auto *inst = ApiToCheck(nullptr, nullptr, nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_METHOD, nullptr, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_METHOD, DUMMY_LITARR, 0, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_ExportDescriptor *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_ImportDescriptor *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *desc = ApiToCheck(nullptr); + ASSERT_EQ(desc, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_ImportDescriptor *(*ApiToCheck)(abckit_Module *inst, const struct abckit_ImportFromDynamicModuleCreateParams *params)) +{ + auto *desc = ApiToCheck(nullptr, nullptr); + ASSERT_EQ(desc, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + desc = ApiToCheck(DUMMY_MODULE, nullptr); + ASSERT_EQ(desc, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_String *str)) +{ + ApiToCheck(nullptr, DUMMY_STRING); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_IsaApiDynamicConditionCode (*ApiToCheck)(abckit_Inst *inst)) +{ + auto inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_IsaApiStaticConditionCode (*ApiToCheck)(abckit_Inst *inst)) +{ + auto inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, size_t argCount, ...)) +{ + ApiToCheck(nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + // TODO: test with more arguments +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *next)) +{ + ApiToCheck(nullptr, DUMMY_INST); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)) +{ + ApiToCheck(nullptr, DUMMY_BB); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, abckit_Inst *inst)) +{ + ApiToCheck(nullptr, DUMMY_INST); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code)) +{ + ApiToCheck(nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, DUMMY_METHOD, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)) +{ + ApiToCheck(nullptr, DUMMY_BB); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *dominator)) +{ + ApiToCheck(nullptr, DUMMY_INST); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_BasicBlock *bb, int32_t index)) +{ + auto *bb = ApiToCheck(nullptr, 0); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Graph *ctxG, uint32_t id)) +{ + auto *bb = ApiToCheck(nullptr, 0); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Inst *inst, bool val)) +{ + auto *bb = ApiToCheck(nullptr, true); + ASSERT_EQ(bb, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, int val)) +{ + ApiToCheck(nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, size_t argCount, ...)) +{ + ApiToCheck(nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, 1, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + // TODO: test with more arguments +} + +void TestNullptr(void (*ApiToCheck)(abckit_Class *klass, void *data, + bool (*cb)(abckit_Method *method, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Method *method, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CLASS, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_Class *klass, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Class *klass, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_ExportDescriptor *i, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_ExportDescriptor *i, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_ImportDescriptor *i, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_ImportDescriptor *i, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_Method *method, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Method *method, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_ModifyContext *ctxM, abckit_Class *klass, void *data){}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CLASS, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Module *m, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_ModifyContext *ctxM, abckit_Module *m, void *data){}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_File *f, void *data, + bool (*cb)(abckit_Module *m, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Module *m, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_File *file, abckit_LiteralArray *litarr, void *data, + bool (*cb)(abckit_File *f, abckit_Literal *lit, void *data))) +{ + ApiToCheck(nullptr, nullptr, nullptr, [](abckit_File *f, abckit_Literal *lit, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr, nullptr, [](abckit_File *f, abckit_Literal *lit, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, DUMMY_LITARR, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Method *method, void *data, + bool (*cb)(abckit_Annotation *anno, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Annotation *anno, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_METHOD, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, void *data, + void (*cb)(abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data) {}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst0, abckit_Inst *inst1, uint32_t index)) +{ + ApiToCheck(nullptr, DUMMY_INST, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId targetType)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, DUMMY_INST, abckit_TypeId::abckit_TypeId_I8); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, abckit_TypeId::abckit_TypeId_I8); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, abckit_TypeId::abckit_TypeId_INVALID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode)) +{ + abckit_Inst *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, nullptr, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_STRING); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_STRING); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Graph *ctxG, void *data, void (*cb)(abckit_BasicBlock *bb, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_BasicBlock *bb, void *data){}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_GRAPH, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Method *ctx, void *data, void (*cb)(abckit_ModifyContext *ctxM, + abckit_Method *method, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_ModifyContext *ctxM, abckit_Method *method, void *data){}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_METHOD, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, void *data, + void (*cb)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, void *data){}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool val)) +{ + ApiToCheck(nullptr, DUMMY_BB, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, int32_t index)) +{ + ApiToCheck(nullptr, DUMMY_BB, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, abckit_Inst *inst1, abckit_Inst *inst2)) +{ + ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, nullptr, DUMMY_INST); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_BB, DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, size_t idx, uint64_t imm)) +{ + ApiToCheck(nullptr, 0, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, void *data, void (*cb)(abckit_Inst *inst, abckit_Inst *user, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Inst *inst, abckit_Inst *user, void *data){}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_INST, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, abckit_Inst *input4)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, nullptr, DUMMY_INST, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, DUMMY_INST, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, DUMMY_INST, DUMMY_INST, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1, abckit_Inst *input2)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_STRING, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_STRING, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, DUMMY_INST); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_STRING, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, 0); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, abckit_Inst *value, abckit_TypeId value_type_id)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_INST, DUMMY_INST, DUMMY_INST, DUMMY_TYPEID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, nullptr, DUMMY_INST, DUMMY_INST, DUMMY_TYPEID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, nullptr, DUMMY_INST, DUMMY_TYPEID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_GRAPH, DUMMY_INST, DUMMY_INST, nullptr, DUMMY_TYPEID); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Annotation *anno, void *data, bool (*cb)(abckit_AnnotationElement *elem, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_AnnotationElement *elem, void *data) -> bool { return false; }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_ANNO, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_TypeId id)) +{ + auto *inst = ApiToCheck(nullptr, abckit_TypeId::abckit_TypeId_I8); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Class *klass)) +{ + auto *inst = ApiToCheck(nullptr, DUMMY_CLASS); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + inst = ApiToCheck(DUMMY_CTXM, nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_TypeId (*ApiToCheck)(abckit_Type *type)) +{ + ApiToCheck(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Class *(*ApiToCheck)(abckit_Type *type)) +{ + auto *inst = ApiToCheck(nullptr); + ASSERT_EQ(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Value **value, size_t size)) +{ + auto *val = ApiToCheck(nullptr, &DUMMY_VALUE, 0); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + val = ApiToCheck(DUMMY_CTXM, nullptr, 0); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, double value)) +{ + auto *val = ApiToCheck(nullptr, 0); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, const char *value)) +{ + auto *val = ApiToCheck(nullptr, "dummy string"); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + val = ApiToCheck(DUMMY_CTXM, nullptr); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, bool value)) +{ + auto *val = ApiToCheck(nullptr, false); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Annotation *(*ApiToCheck)(abckit_AnnotationElement *ae)) +{ + auto *anno = ApiToCheck(nullptr); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_AnnotationElement *ae)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_AnnotationElement *ae)) +{ + auto *file = ApiToCheck(nullptr); + ASSERT_EQ(file, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_AnnotationElement *ae)) +{ + auto *val = ApiToCheck(nullptr); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_AnnotationInterface *(*ApiToCheck)(abckit_Annotation *ae)) +{ + auto *ai = ApiToCheck(nullptr); + ASSERT_EQ(ai, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_AnnotationInterface *ae)) +{ + auto *file = ApiToCheck(nullptr); + ASSERT_EQ(file, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_AnnotationInterface *ae)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_LiteralArray *(*ApiToCheck)(abckit_File *ctx, abckit_Value *value)) +{ + auto *litarr = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(litarr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + litarr = ApiToCheck(nullptr, DUMMY_VALUE); + ASSERT_EQ(litarr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Class *klass, void *data, + bool (*cb)(abckit_Annotation *anno, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_Annotation *anno, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CLASS, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Class *(*ApiToCheck)(abckit_Method *method)) +{ + auto *klass = ApiToCheck(nullptr); + ASSERT_EQ(klass, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_Method *method)) +{ + auto val = ApiToCheck(nullptr); + ASSERT_EQ(val, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_AnnotationInterface *ai, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_AnnotationInterface *ai, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_MODULE, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(double (*ApiToCheck)(abckit_File *ctx, abckit_Value *value)) +{ + ApiToCheck(nullptr, DUMMY_VALUE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_File *ctx, abckit_Value *value)) +{ + auto *str = ApiToCheck(nullptr, DUMMY_VALUE); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + str = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_File *ctx, abckit_Value *value)) +{ + auto *type = ApiToCheck(nullptr, DUMMY_VALUE); + ASSERT_EQ(type, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + type = ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(type, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(bool (*ApiToCheck)(abckit_File *ctx, abckit_Value *value)) +{ + ApiToCheck(nullptr, DUMMY_VALUE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_FILE, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_AnnotationInterface *ai, void *data, + bool (*cb)(abckit_AnnotationInterfaceField *fld, void *data))) +{ + ApiToCheck(nullptr, nullptr, [](abckit_AnnotationInterfaceField *fld, void *data){return false;}); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_ANNOIF, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)) +{ + auto *val = ApiToCheck(nullptr); + ASSERT_EQ(val, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)) +{ + auto *ctx = ApiToCheck(nullptr); + ASSERT_EQ(ctx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_AnnotationInterface *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)) +{ + auto *annoIf = ApiToCheck(nullptr); + ASSERT_EQ(annoIf, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)) +{ + auto *str = ApiToCheck(nullptr); + ASSERT_EQ(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)) +{ + auto *type = ApiToCheck(nullptr); + ASSERT_EQ(type, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_AnnotationInterface *ai)) +{ + auto *module = ApiToCheck(nullptr); + ASSERT_EQ(module, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_AnnotationElement *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params)) +{ + abckit_AnnotationElementCreateParams dummyParams; + + auto *annoElem = ApiToCheck(nullptr, DUMMY_ANNO, &dummyParams); + ASSERT_EQ(annoElem, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + annoElem = ApiToCheck(DUMMY_CTXM, nullptr, &dummyParams); + ASSERT_EQ(annoElem, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + annoElem = ApiToCheck(DUMMY_CTXM, DUMMY_ANNO, nullptr); + ASSERT_EQ(annoElem, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_AnnotationInterfaceField *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params)) +{ + abckit_AnnotationInterfaceFieldCreateParams dummyParams; + + auto *annoElem = ApiToCheck(nullptr, DUMMY_ANNOIF, &dummyParams); + ASSERT_EQ(annoElem, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + annoElem = ApiToCheck(DUMMY_CTXM, nullptr, &dummyParams); + ASSERT_EQ(annoElem, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + annoElem = ApiToCheck(DUMMY_CTXM, DUMMY_ANNOIF, nullptr); + ASSERT_EQ(annoElem, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + abckit_AnnotationInterfaceField *field)) +{ + ApiToCheck(nullptr, DUMMY_ANNOIF, DUMMY_ANNOIFFIELD); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, nullptr, DUMMY_ANNOIFFIELD); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, DUMMY_ANNOIF, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElement *elem)) +{ + ApiToCheck(nullptr, DUMMY_ANNO, DUMMY_ANNOELEM); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, nullptr, DUMMY_ANNOELEM); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, DUMMY_ANNO, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Annotation *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Class *klass, + const abckit_AnnotationCreateParams *params)) +{ + abckit_AnnotationCreateParams dummyParams; + + auto *anno = ApiToCheck(nullptr, DUMMY_CLASS, &dummyParams); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + anno = ApiToCheck(DUMMY_CTXM, nullptr, &dummyParams); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + anno = ApiToCheck(DUMMY_CTXM, DUMMY_CLASS, nullptr); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Class *klass, + abckit_Annotation *anno)) +{ + ApiToCheck(nullptr, DUMMY_CLASS, DUMMY_ANNO); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, nullptr, DUMMY_ANNO); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, DUMMY_CLASS, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Annotation *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Method *method, + const abckit_AnnotationCreateParams *params)) +{ + abckit_AnnotationCreateParams dummyParams; + + auto *anno = ApiToCheck(nullptr, DUMMY_METHOD, &dummyParams); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + anno = ApiToCheck(DUMMY_CTXM, nullptr, &dummyParams); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + anno = ApiToCheck(DUMMY_CTXM, DUMMY_METHOD, nullptr); + ASSERT_EQ(anno, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno)) +{ + ApiToCheck(nullptr, DUMMY_METHOD, DUMMY_ANNO); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, nullptr, DUMMY_ANNO); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(DUMMY_CTXM, DUMMY_METHOD, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_AnnotationInterface *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Module *m, + const abckit_AnnotationInterfaceCreateParams *params)) +{ + abckit_AnnotationInterfaceCreateParams dummyParams; + + auto *annoI = ApiToCheck(nullptr, DUMMY_MODULE, &dummyParams); + ASSERT_EQ(annoI, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + annoI = ApiToCheck(DUMMY_CTXM, nullptr, &dummyParams); + ASSERT_EQ(annoI, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + annoI = ApiToCheck(DUMMY_CTXM, DUMMY_MODULE, nullptr); + ASSERT_EQ(annoI, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Class *klass)) +{ + ApiToCheck(DUMMY_INST, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + ApiToCheck(nullptr, DUMMY_CLASS); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +void TestNullptr(abckit_Class *(*ApiToCheck)(abckit_Inst *inst)) +{ + auto *klass = ApiToCheck(nullptr); + ASSERT_EQ(klass, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); +} + +} // namespace libabckit::test::helpers_nullptr diff --git a/libabckit/tests/helpers/helpers_nullptr.h b/libabckit/tests/helpers/helpers_nullptr.h new file mode 100644 index 0000000000000000000000000000000000000000..877bc70438d38894252e8c463496c01596c299a5 --- /dev/null +++ b/libabckit/tests/helpers/helpers_nullptr.h @@ -0,0 +1,281 @@ +/** + * Copyright (c) 2024 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. + */ +#ifndef LIBABCKIT_TESTS_INVALID_HELPERS +#define LIBABCKIT_TESTS_INVALID_HELPERS + +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" + +namespace libabckit::test::helpers_nullptr { + +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Graph *ctxG)); +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Inst *inst, uint32_t index)); +void TestNullptr(abckit_IsaApiDynamicOpcode (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_IsaApiStaticOpcode (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_TypeId (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(uint32_t (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(bool (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(bool (*ApiToCheck)(abckit_Module *m)); +void TestNullptr(abckit_Method *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Method *method)); +void TestNullptr(uint32_t (*ApiToCheck)(abckit_Graph *ctxG)); +void TestNullptr(int64_t (*ApiToCheck)(abckit_Inst *input0)); +void TestNullptr(uint64_t (*ApiToCheck)(abckit_Inst *input0)); +void TestNullptr(uint64_t (*ApiToCheck)(abckit_Inst *inst, size_t val)); +void TestNullptr(double (*ApiToCheck)(abckit_Inst *input0)); +void TestNullptr(abckit_Graph *(*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(abckit_Graph *(*ApiToCheck)(abckit_File *ctx, abckit_Code *code)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(bool (*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(uint32_t (*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(uint64_t (*ApiToCheck)(abckit_BasicBlock *bb)); +void TestNullptr(abckit_Code *(*ApiToCheck)(abckit_Method *method)); +void TestNullptr(abckit_Code *(*ApiToCheck)(abckit_Graph *ctx)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Class *klass)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Method *method)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Module *m)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_ExportDescriptor *e)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_ImportDescriptor *i)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_ModifyContext *ctxM, const char *val)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Class *klass)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Method *method)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Module *m)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_Annotation *anno)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_ExportDescriptor *e)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_ImportDescriptor *i)); +void TestNullptr(abckit_File *(*ApiToCheck)(const char *ptr)); +void TestNullptr(abckit_File *(*ApiToCheck)(const char *ptr, bool opt)); +void TestNullptr(abckit_File_Version (*ApiToCheck)(abckit_File *file)); + +void TestNullptr(bool (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(double (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(float (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(abckit_LiteralArray *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_LiteralArray *(*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Literal **lit, size_t sz)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, bool val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, double val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, float val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, const char *val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint8_t val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint16_t val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint32_t val)); +void TestNullptr(abckit_Literal *(*ApiToCheck)(abckit_ModifyContext *ctxM, uint64_t val)); +void TestNullptr(abckit_LiteralTag (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(uint8_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(uint16_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(uint32_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); +void TestNullptr(uint64_t (*ApiToCheck)(abckit_File *file, abckit_Literal *lit)); + +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_Class *klass)); +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_Method *method)); +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_ExportDescriptor *e)); +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_ImportDescriptor *i)); + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint32_t index)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, int64_t value)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, int32_t value)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t value)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm0, uint64_t imm1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *inst)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_LiteralArray *inst)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *inst0, abckit_Inst *inst1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, double value)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_String *str, uint64_t imm)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ExportDescriptor *e)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_ImportDescriptor *i)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_TypeId typeId)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_ExportDescriptor *e)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_IsaApiDynamicConditionCode cc)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, abckit_Inst *inst1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1, + abckit_Inst *inst1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, abckit_Method *method, + size_t argCount, ...)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, size_t argCount, ...)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, size_t argCount, ...)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *arrayRef, abckit_Inst *idx, abckit_Inst *value, abckit_TypeId value_type_id)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, size_t argCount, ...)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Module *m)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass1, abckit_Class *klass2)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass, abckit_Inst *inst)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_LiteralArray *litarr)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctx, abckit_Inst *inputObj, abckit_Type *targetType)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *m, abckit_LiteralArray *litarr, uint64_t val, abckit_Inst *inst)); +void TestNullptr(abckit_ExportDescriptor *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_ImportDescriptor *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_ImportDescriptor *(*ApiToCheck)(abckit_Module *inst, const struct abckit_ImportFromDynamicModuleCreateParams *params)); +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_String *str)); +void TestNullptr(abckit_IsaApiDynamicConditionCode (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(abckit_IsaApiStaticConditionCode (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(void (*ApiToCheck)(abckit_Graph *ctxG)); +void TestNullptr(void (*ApiToCheck)(abckit_Graph *ctxG, int fd)); +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI)); +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI, const char *ptr)); +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI, abckit_Literal *lit)); +void TestNullptr(void (*ApiToCheck)(abckit_File *ctxI, abckit_String *str, char* out, size_t *len)); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, abckit_ImportDescriptor *i)); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, abckit_ExportDescriptor *e)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_LiteralArray *litarr)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Module *m)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_ImportDescriptor *i)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_ExportDescriptor *e)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_IsaApiDynamicConditionCode cc)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_IsaApiStaticConditionCode cc)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_TypeId type)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, int fd)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, size_t argCount, ...)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *next)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_Inst *inst)); +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code)); +void TestNullptr(bool (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)); +void TestNullptr(bool (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *dominator)); +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_BasicBlock *bb, int32_t index)); +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Graph *ctx, uint32_t id)); +void TestNullptr(abckit_BasicBlock *(*ApiToCheck)(abckit_Inst *inst, bool val)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, int val)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, size_t argCount, ...)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_BasicBlock *bb, size_t argCount, ...)); + +void TestNullptr(void (*ApiToCheck)(abckit_Class *klass, void *data, + bool (*cb)(abckit_Method *method, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Class *c, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Class *klass, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_Class *klass, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_ExportDescriptor *e, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_ImportDescriptor *i, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_Method *method, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + void (*cb)(abckit_ModifyContext *ctxM, abckit_Module *m, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_File *file, void *data, + bool (*cb)(abckit_Module *m, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_File *file, abckit_LiteralArray *litarr, void* data, + bool (*cb)(abckit_File *f, abckit_Literal *lit, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Method *method, void *data, + bool (*cb)(abckit_Annotation *anno, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, void *data, + void (*cb)(abckit_Inst *inst, abckit_Inst *input, size_t inputIdx, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *input, uint32_t index)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId targetType)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0)); +void TestNullptr(void (*ApiToCheck)(abckit_Graph *ctx, void *data, void (*cb)(abckit_BasicBlock *bb, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_Method *ctx, void *data, void (*cb)(abckit_ModifyContext *ctxM, + abckit_Method *method, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, void *data, + void (*cb)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, void *data))); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool val)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, int32_t index)); +void TestNullptr(void (*ApiToCheck)(abckit_BasicBlock *bb, abckit_Inst *inst1, abckit_Inst *inst2)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, size_t idx, uint64_t imm)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, void *data, void (*cb)(abckit_Inst *inst, abckit_Inst *user, void *data))); + +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, abckit_Inst *input4)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1, abckit_Inst *input2)); +void TestNullptr(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0)); + +void TestNullptr(void (*ApiToCheck)(abckit_Annotation *anno, void *data, bool (*cb)(abckit_AnnotationElement *elem, void *data))); +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_TypeId id)); +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Class *klass)); + +void TestNullptr(abckit_TypeId (*ApiToCheck)(abckit_Type *type)); +void TestNullptr(abckit_Class *(*ApiToCheck)(abckit_Type *type)); + +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Value **value, size_t size)); +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, double value)); +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, const char *value)); +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_ModifyContext *ctx, bool value)); + +void TestNullptr(abckit_Annotation *(*ApiToCheck)(abckit_AnnotationElement *ae)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_AnnotationElement *ae)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_AnnotationElement *ae)); +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_AnnotationElement *ae)); + +void TestNullptr(abckit_AnnotationInterface *(*ApiToCheck)(abckit_Annotation *ae)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_AnnotationInterface *ae)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_AnnotationInterface *ae)); +void TestNullptr(abckit_LiteralArray *(*ApiToCheck)(abckit_File *ctx, abckit_Value *value)); +void TestNullptr(void (*ApiToCheck)(abckit_Class *klass, void *data, + bool (*cb)(abckit_Annotation *anno, void *data))); + +void TestNullptr(abckit_Class *(*ApiToCheck)(abckit_Method *method)); +void TestNullptr(bool (*ApiToCheck)(abckit_Method *method)); +void TestNullptr(void (*ApiToCheck)(abckit_Module *m, void *data, + bool (*cb)(abckit_AnnotationInterface *ai, void *data))); + +void TestNullptr(double (*ApiToCheck)(abckit_File *ctx, abckit_Value *value)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_File *ctx, abckit_Value *value)); +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_File *ctx, abckit_Value *value)); +void TestNullptr(bool (*ApiToCheck)(abckit_File *ctx, abckit_Value *value)); +void TestNullptr(void (*ApiToCheck)(abckit_AnnotationInterface *ai, void *data, + bool (*cb)(abckit_AnnotationInterfaceField *fld, void *data))); +void TestNullptr(abckit_Value *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)); +void TestNullptr(abckit_File *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)); +void TestNullptr(abckit_AnnotationInterface *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)); +void TestNullptr(abckit_String *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)); +void TestNullptr(abckit_Type *(*ApiToCheck)(abckit_AnnotationInterfaceField *fld)); +void TestNullptr(abckit_Module *(*ApiToCheck)(abckit_AnnotationInterface *ai)); + +void TestNullptr(abckit_AnnotationElement *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElementCreateParams *params)); +void TestNullptr(abckit_AnnotationInterfaceField *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + const abckit_AnnotationInterfaceFieldCreateParams *params)); +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_AnnotationInterface *ai, + abckit_AnnotationInterfaceField *field)); +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Annotation *anno, + abckit_AnnotationElement *elem)); +void TestNullptr(abckit_Annotation *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Class *klass, + const abckit_AnnotationCreateParams *params)); +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Class *klass, + abckit_Annotation *anno)); +void TestNullptr(abckit_Annotation *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Method *method, + const abckit_AnnotationCreateParams *params)); +void TestNullptr(void (*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Method *method, abckit_Annotation *anno)); +void TestNullptr(abckit_AnnotationInterface *(*ApiToCheck)(abckit_ModifyContext *ctx, abckit_Module *m, + const abckit_AnnotationInterfaceCreateParams *params)); +void TestNullptr(void (*ApiToCheck)(abckit_Inst *inst, abckit_Class *klass)); +void TestNullptr(abckit_Class *(*ApiToCheck)(abckit_Inst *inst)); +} // libabckit::test::helpers_nullptr + +#endif /*LIBABCKIT_TESTS_INVALID_HELPERS */ diff --git a/libabckit/tests/helpers/helpers_runtime.h b/libabckit/tests/helpers/helpers_runtime.h new file mode 100644 index 0000000000000000000000000000000000000000..b8df0612c4dfa3874622adf4addfd255dae41bea --- /dev/null +++ b/libabckit/tests/helpers/helpers_runtime.h @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_TESTS_VM_HELPERS +#define LIBABCKIT_TESTS_VM_HELPERS + +#include +#include +#include + +namespace libabckit::test::helpers { + +class CoutRedirect { +public: + CoutRedirect(std::streambuf *newBuffer) + : oldBuffer(std::cout.rdbuf(newBuffer)) {} + + ~CoutRedirect() + { + std::cout.rdbuf(oldBuffer); + } + +private: + std::streambuf *oldBuffer; +}; + +std::string ExecuteDynamicAbc(const std::string &abcPath, const std::string &entry); +std::string ExecuteStaticAbc(const std::string &abcPath, const std::string &klassName, const std::string &methodName); + +} // namespace libabckit::test::helpers + +#endif //LIBABCKIT_TESTS_ETS_VM_HELPERS diff --git a/libabckit/tests/helpers/helpers_wrong_ctx.cpp b/libabckit/tests/helpers/helpers_wrong_ctx.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c282849b500fd8e9c1e5e2a1f51a7385234d1d65 --- /dev/null +++ b/libabckit/tests/helpers/helpers_wrong_ctx.cpp @@ -0,0 +1,640 @@ +/** + * Copyright (c) 2024 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 "libabckit/tests/helpers/helpers_wrong_ctx.h" +#include "helpers/helpers.h" + +#include "abckit.h" +#include "libabckit/include/metadata.h" +#include "metadata.h" +#include "ir_core.h" +#include "metadata_inspect_impl.h" +#include "metadata_modify_impl.h" +#include "ir_impl.h" + +#include + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +namespace libabckit::test::helpers_wrong_ctx { + +static abckit_Module *DUMMY_MODULE1 = new abckit_Module(); +static abckit_Module *DUMMY_MODULE2 = new abckit_Module(); + +static abckit_Code *DUMMY_CODE = new abckit_Code(); + +static abckit_Method *DUMMY_METHOD1 = new abckit_Method(); +static abckit_Method *DUMMY_METHOD2 = new abckit_Method(); + +static abckit_File *DUMMY_FILE1 = (abckit_File*)(0x1); +static abckit_File *DUMMY_FILE2 = (abckit_File*)(0x2); + +static abckit_Graph *DUMMY_GRAPH1 = new abckit_Graph(); +static abckit_Graph *DUMMY_GRAPH2 = new abckit_Graph(); + +static abckit_ModifyContext *DUMMY_CTXM = new abckit_ModifyContext(); + +static abckit_Inst *DUMMY_INST1 = new abckit_Inst(); +static abckit_Inst *DUMMY_INST2 = new abckit_Inst(); + +static abckit_Class *DUMMY_CLASS = new abckit_Class(); + +static abckit_String *DUMMY_STRING = (abckit_String*)(0x1); + +static abckit_BasicBlock *DUMMY_BB1 = new abckit_BasicBlock(); +static abckit_BasicBlock *DUMMY_BB2 = new abckit_BasicBlock(); + +static abckit_LiteralArray *DUMMY_LITARR = (abckit_LiteralArray*)(0x1); + +static abckit_ExportDescriptor *DUMMY_EXPORT = (abckit_ExportDescriptor*)(0x1); + +static abckit_Type *DUMMY_TYPE = (abckit_Type*)(0x1); + +void TestWrongCtx(abckit_Graph *(*ApiToCheck)(abckit_File *ctx, abckit_Code *code)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD2->m = DUMMY_MODULE2; + DUMMY_CODE->method = DUMMY_METHOD2; + + auto *graph = ApiToCheck(DUMMY_FILE1, DUMMY_CODE); + ASSERT_EQ(graph, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_CTXM->ctxI = DUMMY_FILE1; + + DUMMY_METHOD2->m = DUMMY_MODULE2; + + ApiToCheck(DUMMY_CTXM, DUMMY_METHOD2, DUMMY_CODE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_Inst *inst)) +{ + DUMMY_BB1->ctxG = DUMMY_GRAPH1; + DUMMY_BB2->ctxG = DUMMY_GRAPH2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + ApiToCheck(DUMMY_BB1, DUMMY_INST2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(bool (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)) +{ + DUMMY_BB1->ctxG = DUMMY_GRAPH1; + DUMMY_BB2->ctxG = DUMMY_GRAPH2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + ApiToCheck(DUMMY_BB1, DUMMY_BB2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool val)) +{ + DUMMY_BB1->ctxG = DUMMY_GRAPH1; + DUMMY_BB2->ctxG = DUMMY_GRAPH2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + ApiToCheck(DUMMY_BB1, DUMMY_BB2, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)) +{ + DUMMY_BB1->ctxG = DUMMY_GRAPH1; + DUMMY_BB2->ctxG = DUMMY_GRAPH2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + ApiToCheck(DUMMY_BB1, DUMMY_BB2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, int32_t index)) +{ + DUMMY_BB1->ctxG = DUMMY_GRAPH1; + DUMMY_BB2->ctxG = DUMMY_GRAPH2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + ApiToCheck(DUMMY_BB1, DUMMY_BB2, 0x0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(bool (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *dominator)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + bool var = ApiToCheck(DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(var, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, size_t argCount, ...)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD1->m = DUMMY_MODULE1; + DUMMY_METHOD2->m = DUMMY_MODULE2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_METHOD2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + // TODO varargs processing +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId targetType)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, abckit_TypeId_INVALID); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, size_t argCount, ...)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + // TODO varargs processing +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, abckit_Inst *inst1)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, 0x0, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, 0x0, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1, + abckit_Inst *inst1)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, 0x0, 0x0, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, 0x0, 0x0, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *m, abckit_LiteralArray *litarr, uint64_t val, abckit_Inst *inst)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD1->m = DUMMY_MODULE1; + DUMMY_METHOD2->m = DUMMY_MODULE2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_METHOD2, DUMMY_LITARR, 0x0, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_METHOD1, DUMMY_LITARR, 0x0, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, 0x0, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, abckit_Inst *input4)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *inst0, abckit_Inst *inst1)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, 0x0, DUMMY_INST2, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, 0x0, DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1, abckit_Inst *input2)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_STRING, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_STRING, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD1->m = DUMMY_MODULE1; + DUMMY_METHOD2->m = DUMMY_MODULE2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_METHOD2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD1->m = DUMMY_MODULE1; + DUMMY_METHOD2->m = DUMMY_MODULE2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_METHOD1, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_METHOD2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Module *m)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_MODULE2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_IsaApiDynamicConditionCode cc)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, abckit_IsaApiDynamicConditionCode_CC_NONE); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1)) { + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_STRING); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, DUMMY_INST1, abckit_TypeId_INVALID); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, DUMMY_INST1, abckit_TypeId_INVALID); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST1, DUMMY_INST2, abckit_TypeId_INVALID); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_TypeId typeId)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, abckit_TypeId_INVALID); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, abckit_TypeId_INVALID); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_ExportDescriptor *e)) +{ + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_EXPORT); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass)) +{ + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_CLASS->m = DUMMY_MODULE2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + + ApiToCheck(DUMMY_GRAPH1, DUMMY_CLASS); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *next)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + ApiToCheck(DUMMY_INST1, DUMMY_INST2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, abckit_IsaApiStaticConditionCode_CC_NONE); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0)) +{ + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_INST1, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_INST2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass, abckit_Inst *input0)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_CLASS->m = DUMMY_MODULE2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_CLASS, DUMMY_INST1); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + + DUMMY_CLASS->m = DUMMY_MODULE1; + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_CLASS, DUMMY_INST2); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(void (*ApiToCheck)(abckit_Inst *input0, abckit_Method *method)) +{ + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD2->m = DUMMY_MODULE2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + + ApiToCheck(DUMMY_INST1, DUMMY_METHOD2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Type *type)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_CLASS->m = DUMMY_MODULE2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_TYPE); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Method *method, size_t argCount, ...)) +{ + DUMMY_MODULE1->ctxI = DUMMY_FILE1; + DUMMY_MODULE2->ctxI = DUMMY_FILE2; + + DUMMY_METHOD1->m = DUMMY_MODULE1; + DUMMY_METHOD2->m = DUMMY_MODULE2; + + DUMMY_INST1->ctxG = DUMMY_GRAPH1; + DUMMY_INST2->ctxG = DUMMY_GRAPH2; + + DUMMY_GRAPH1->ctxI = DUMMY_FILE1; + DUMMY_GRAPH2->ctxI = DUMMY_FILE2; + + auto *instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST1, DUMMY_METHOD2, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + + instr = ApiToCheck(DUMMY_GRAPH1, DUMMY_INST2, DUMMY_METHOD1, 0x0); + ASSERT_EQ(instr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); +} + +} // namespace libabckit::test::helpers_nullptr diff --git a/libabckit/tests/helpers/helpers_wrong_ctx.h b/libabckit/tests/helpers/helpers_wrong_ctx.h new file mode 100644 index 0000000000000000000000000000000000000000..39534a96702cd77befb2fa735b3ccd8fc43750ec --- /dev/null +++ b/libabckit/tests/helpers/helpers_wrong_ctx.h @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024 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. + */ +#ifndef LIBABCKIT_TESTS_INVALID_HELPERS +#define LIBABCKIT_TESTS_INVALID_HELPERS + +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" + +namespace libabckit::test::helpers_wrong_ctx { + +void TestWrongCtx(abckit_Graph *(*ApiToCheck)(abckit_File *ctx, abckit_Code *code)); +void TestWrongCtx(void (*ApiToCheck)(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Code *code)); +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_Inst *inst)); +void TestWrongCtx(bool (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)); +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, bool val)); +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2)); +void TestWrongCtx(void (*ApiToCheck)(abckit_BasicBlock *bb1, abckit_BasicBlock *bb2, int32_t index)); +void TestWrongCtx(bool (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *dominator)); + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm0)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, size_t argCount, ...)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_TypeId targetType)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_Inst *input2)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, size_t argCount, ...)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, abckit_Inst *inst1)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1, + abckit_Inst *inst1)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *m, abckit_LiteralArray *litarr, uint64_t val, abckit_Inst *inst)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *inst, uint64_t imm0, uint64_t imm1)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_Inst *input2, abckit_Inst *input3, abckit_Inst *input4)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, uint64_t imm, abckit_Inst *inst0, abckit_Inst *inst1)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1, abckit_Inst *input2)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Method *method, uint64_t imm)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *acc, abckit_Method *method, uint64_t imm0)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Module *m)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_IsaApiDynamicConditionCode cc)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_String *input1)); + +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *arrayRef, abckit_Inst *idx, + abckit_Inst *value, abckit_TypeId value_type_id)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, abckit_TypeId typeId)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_ExportDescriptor *e)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass)); +void TestWrongCtx(void (*ApiToCheck)(abckit_Inst *inst, abckit_Inst *next)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, + abckit_IsaApiStaticConditionCode)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1, uint64_t imm0)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Class *klass, abckit_Inst *input0)); +void TestWrongCtx(void (*ApiToCheck)(abckit_Inst *input0, abckit_Method *method)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Type *type)); +void TestWrongCtx(abckit_Inst *(*ApiToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Method *method, size_t argCount, ...)); + +} // libabckit::test::helpers_wrong_ctx + +#endif /*LIBABCKIT_TESTS_INVALID_HELPERS */ diff --git a/libabckit/tests/helpers/visit_helper/visit_helper-inl.h b/libabckit/tests/helpers/visit_helper/visit_helper-inl.h new file mode 100644 index 0000000000000000000000000000000000000000..1fc73c202680617d97c3e9fb8d461d3ba234afa8 --- /dev/null +++ b/libabckit/tests/helpers/visit_helper/visit_helper-inl.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef VISIT_HELPER_INL_H +#define VISIT_HELPER_INL_H + +#include "visit_helper.h" + +template +inline void VisitHelper::EnumerateModules(const ModuleCallBack &cb) +{ + implI_->FileEnumerateModules(ctxI_, (void *)(&cb), [](abckit_Module *mod, void *data) { + const auto &cb = *((ModuleCallBack *)(data)); + cb(mod); + return true; + }); +} + +template +inline void VisitHelper::EnumerateModuleImports(abckit_Module *mod, const ImportCallBack &cb) +{ + implI_->ModuleEnumerateImports(mod, (void *)(&cb), [](abckit_ImportDescriptor *i, void *data) { + const auto &cb = *((ImportCallBack *)(data)); + cb(i); + return true; + }); +} + +template +inline void VisitHelper::EnumerateModuleExports(abckit_Module *mod, const ExportCallBack &cb) +{ + implI_->ModuleEnumerateExports(mod, (void *)(&cb), [](abckit_ExportDescriptor *e, void *data) { + const auto &cb = *((ExportCallBack *)(data)); + cb(e); + return true; + }); +} + +template +inline void VisitHelper::EnumerateModuleClasses(abckit_Module *mod, const ClassCallBack &cb) +{ + implI_->ModuleEnumerateClasses(mod, (void *)(&cb), [](abckit_Class *klass, void *data) { + const auto &cb = *((ClassCallBack *)data); + cb(klass); + return true; + }); +} + +template +inline void VisitHelper::EnumerateClassMethods(abckit_Class *klass, const MethodCallBack &cb) +{ + implI_->ClassEnumerateMethods(klass, (void *)(&cb), [](abckit_Method *method, void *data) { + const auto &cb = *((MethodCallBack *)data); + cb(method); + return true; + }); +} + +template +inline void VisitHelper::EnumerateModuleTopLevelFunctions(abckit_Module *mod, const FunctionCallBack &cb) +{ + implI_->ModuleEnumerateTopLevelFunctions(mod, (void *)(&cb), [](abckit_Method *method, void *data) { + const auto &cb = *((FunctionCallBack *)data); + cb(method); + return true; + }); +} + +template +inline void VisitHelper::EnumerateModuleFunctions(abckit_Module *mod, const FunctionCallBack &cb) +{ + // TODO: currently we can only enumerate class methods and top level functions. need to update. + EnumerateModuleTopLevelFunctions(mod, cb); + EnumerateModuleClasses(mod, [&](abckit_Class *klass) { + EnumerateClassMethods(klass, cb); + }); +} + +template +inline void VisitHelper::EnumerateClassAnnotations(abckit_Class *klass, const AnnotationCallBack &cb) +{ + implI_->ClassEnumerateAnnotations(klass, (void *)(&cb), [](abckit_Annotation *an, void *data) { + const auto &cb = *((AnnotationCallBack *)data); + cb(an); + return true; + }); +} + +template +inline void VisitHelper::EnumerateMethodAnnotations(abckit_Method *m, const AnnotationCallBack &cb) +{ + implI_->MethodEnumerateAnnotations(m, (void *)(&cb), [](abckit_Annotation *an, void *data) { + const auto &cb = *((AnnotationCallBack *)data); + cb(an); + return true; + }); +} + +template +inline void VisitHelper::EnumerateAnnotationElements(abckit_Annotation *an, const AnnotationElementCallBack &cb) +{ + implI_->AnnotationEnumerateElements(an, (void *)(&cb), [](abckit_AnnotationElement *ele, void *data) { + const auto &cb = *((AnnotationElementCallBack *)data); + cb(ele); + return true; + }); +} + +template +inline void VisitHelper::EnumerateFunctionInsts(abckit_Method *func, const InstCallBack &cb) +{ + abckit_Code *code = implI_->MethodGetCode(func); + abckit_Graph *ctxG = impl_->codeToGraph(ctxI_, code); + + EnumerateGraphInsts(ctxG, cb); + + impl_->DestroyGraphContext(ctxG); +} + +template +inline void VisitHelper::EnumerateGraphInsts(abckit_Graph *ctxG, const InstCallBack &cb) +{ + struct CapturedData { + void *callback = nullptr; + const abckit_GraphApi *implG = nullptr; + }; + CapturedData captured { + .callback = (void *)(&cb), + .implG = implG_ + }; + + implG_->GvisitBlocksRPO(ctxG, &captured, [](abckit_BasicBlock *bb, void *data) { + CapturedData *captured = (CapturedData *)data; + const auto &cb = *((InstCallBack *)(captured->callback)); + auto *implG = captured->implG; + for (auto *inst = implG->BBgetFirstInst(bb); inst != nullptr; inst = implG->IgetNext(inst)) { + cb(inst); + } + }); +} + +template +inline abckit_Inst *VisitHelper::GraphInstsFindIf(abckit_Graph *ctxG, const InstCallBack &cb) +{ + abckit_Inst *ret = nullptr; + bool found = false; + EnumerateGraphInsts(ctxG, [&](abckit_Inst *inst) { + if (!found && cb(inst)) { + found = true; + ret = inst; + } + }); + + return ret; +} + +template +inline void VisitHelper::EnumerateInstInputs(abckit_Inst *inst, const InputCallBack &cb) +{ + implG_->IvisitInputs(inst, (void *)(&cb), [](abckit_Inst *inst, abckit_Inst *input, void *data) { + const auto &cb = *((InputCallBack *)data); + cb(input); + }); +} + +template +inline void VisitHelper::EnumerateInstUsers(abckit_Inst *inst, const UserCallBack &cb) +{ + implG_->IvisitUsers(inst, (void *)(&cb), [](abckit_Inst *inst, abckit_Inst *user, void *data) { + const auto &cb = *((UserCallBack *)data); + cb(user); + }); +} + +template +inline void VisitHelper::TransformMethod(abckit_Method *f, const FunctionCallBack &cb) +{ + impl_->TransformMethod(f, (void *)(&cb), [](abckit_ModifyContext *ctxM, abckit_Method *f, void *data) { + const auto &cb = *((FunctionCallBack *)data); + cb(ctxM, f); + }); +} + +#endif /* VISIT_HELPER_INL_H */ diff --git a/libabckit/tests/helpers/visit_helper/visit_helper.cpp b/libabckit/tests/helpers/visit_helper/visit_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7ceb2b8541c24e717ec5479e09032358ee68e553 --- /dev/null +++ b/libabckit/tests/helpers/visit_helper/visit_helper.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 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 + +#include "visit_helper.h" + +VisitHelper::VisitHelper(abckit_File *ctxI, + const abckit_Api *impl, + const abckit_InspectApi *implI, + const abckit_GraphApi *implG, + const abckit_IsaApiDynamic *dynG) : + ctxI_(ctxI), + impl_(impl), + implI_(implI), + implG_(implG), + dynG_(dynG) {}; + +std::string VisitHelper::GetString(abckit_String *str) const +{ + std::size_t len = 0; + + implI_->abckit_StringToString(ctxI_, str, nullptr, &len); + assert(impl_->GetLastError() == abckit_Status_NO_ERROR); + assert(len > 0); + + auto name = new char[len] {}; + implI_->abckit_StringToString(ctxI_, str, name, &len); + assert(impl_->GetLastError() == abckit_Status_NO_ERROR); + + std::string res {name}; + delete[] name; + + return res; +} diff --git a/libabckit/tests/helpers/visit_helper/visit_helper.h b/libabckit/tests/helpers/visit_helper/visit_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..650d580b7cdfd124e124fb6e8900f5dab21ffa94 --- /dev/null +++ b/libabckit/tests/helpers/visit_helper/visit_helper.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef VISIT_HELPER_H +#define VISIT_HELPER_H + +#include + +#include "include/abckit.h" +#include "include/ir_core.h" +#include "include/metadata.h" +#include "isa/isa_dynamic.h" + +class VisitHelper { +public: + VisitHelper() = default; + ~VisitHelper() = default; + VisitHelper(abckit_File *ctxI, + const abckit_Api *impl, + const abckit_InspectApi *implI, + const abckit_GraphApi *implG, + const abckit_IsaApiDynamic *dynG); + + // ModuleCallBack: (abckit_Module *) -> void + template + void EnumerateModules(const ModuleCallBack &cb); + + // ImportCallBack: (abckit_ImportDescriptor *) -> void + template + void EnumerateModuleImports(abckit_Module *mod, const ImportCallBack &cb); + + // ExportCallBack: (abckit_ExportDescriptor *) -> void + template + void EnumerateModuleExports(abckit_Module *mod, const ExportCallBack &cb); + + // FunctionCallBack: (abckit_Method *) -> void + template + void EnumerateModuleTopLevelFunctions(abckit_Module *mod, const FunctionCallBack &cb); + + // enumerate all functions (including methods) in the module + // FunctionCallBack: (abckit_Method *) -> void + template + void EnumerateModuleFunctions(abckit_Module *mod, const FunctionCallBack &cb); + + // ClassCallBack: (abckit_Class *) -> void + template + void EnumerateModuleClasses(abckit_Module *mod, const ClassCallBack &cb); + + // MethodCallBack: (abckit_Method *) -> void + template + void EnumerateClassMethods(abckit_Class *klass, const MethodCallBack &cb); + + // AnnotationCallBack: (abckit_Annotation *) -> void + template + void EnumerateClassAnnotations(abckit_Class *klass, const AnnotationCallBack &cb); + + // AnnotationCallBack: (abckit_Annotation *) -> void + template + void EnumerateMethodAnnotations(abckit_Method *m, const AnnotationCallBack &cb); + + // AnnotationElementCallBack: (abckit_AnnotationElement *) -> void + template + void EnumerateAnnotationElements(abckit_Annotation *an, const AnnotationElementCallBack &cb); + + // InstCallBack: (abckit_Inst *) -> void + // NB: the graph context and Inst pointers will be deleted at the end of enumeration + template + void EnumerateFunctionInsts(abckit_Method *f, const InstCallBack &cb); + + // InstCallBack: (abckit_Inst *) -> void + template + void EnumerateGraphInsts(abckit_Graph *ctxG, const InstCallBack &cb); + + // InstCallBack: (abckit_Inst *) -> bool + template + abckit_Inst *GraphInstsFindIf(abckit_Graph *ctxG, const InstCallBack &cb); + + // InputCallBack: (abckit_Inst *) -> void + template + void EnumerateInstInputs(abckit_Inst *inst, const InputCallBack &cb); + + // UserCallBack: (abckit_Inst *) -> void + template + void EnumerateInstUsers(abckit_Inst *inst, const UserCallBack &cb); + + // FunctionCallBack: (abckit_ModifyContext *, abckit_Method *) -> void + template + void TransformMethod(abckit_Method *f, const FunctionCallBack &cb); + + std::string GetString(abckit_String *str) const; + +private: + abckit_File *ctxI_ = nullptr; + const abckit_Api *impl_ = nullptr; + const abckit_InspectApi *implI_ = nullptr; + const abckit_GraphApi *implG_ = nullptr; + const abckit_IsaApiDynamic *dynG_ = nullptr; +}; + +#endif /* VISIT_HELPER_H */ diff --git a/libabckit/tests/internal/ICSlotAllocator/ICSlotAllocator.cpp b/libabckit/tests/internal/ICSlotAllocator/ICSlotAllocator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac228a0c294afd109092c3a0e1d25b2146b58e9e --- /dev/null +++ b/libabckit/tests/internal/ICSlotAllocator/ICSlotAllocator.cpp @@ -0,0 +1,205 @@ +/** + * Copyright (c) 2024 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 + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +namespace libabckit { +namespace test { + +class LibAbcKitInternalTest : public ::testing::Test {}; + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +struct UserData { + abckit_String *print = nullptr; + abckit_String *date = nullptr; + abckit_String *getTime = nullptr; + abckit_String *str = nullptr; + abckit_String *consume = nullptr; +}; + +struct ICSlotDescription { + abckit_IsaApiDynamicOpcode op_ = abckit_IsaApiDynamicOpcode::abckit_IsaApiDynamicOpcode_INVALID; + int32_t ICSlot_ = -1; +}; + +static void CheckICSlots(abckit_BasicBlock *bb, std::vector ICSlotDescr) +{ + ASSERT_EQ(implG->BBgetNumberOfInstructions(bb), ICSlotDescr.size()); + + uint32_t counter = 0; + for (abckit_Inst *inst = implG->BBgetFirstInst(bb); inst != nullptr; inst = implG->IgetNext(inst), ++counter) { + if (ICSlotDescr[counter].ICSlot_ == -1) { + continue; + } + + ASSERT_EQ(dynG->IgetOpcode(inst), ICSlotDescr[counter].op_); + ASSERT_NE(implG->IgetImmediateCount(inst), 0); + ASSERT_EQ(implG->IgetImmediate(inst, 0), ICSlotDescr[counter].ICSlot_); + } +} + +static void TransformIr(abckit_Graph *ctxG, UserData *userData) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + auto *bb = succBBs[0]; + auto *callInst = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_callarg1); + + // Prolog + auto *str = dynG->IcreateLoadString(ctxG, userData->str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstFront(bb, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *print = dynG->IcreateTryldglobalbyname(ctxG, userData->print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(print, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg = dynG->IcreateCallarg1(ctxG, print, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(callArg, print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *dateClass = dynG->IcreateTryldglobalbyname(ctxG, userData->date); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateClass, callArg); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *dateObj = dynG->IcreateNewobjrange(ctxG, 1, dateClass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateObj, dateClass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *getTime = dynG->IcreateLdobjbyname(ctxG, dateObj, userData->getTime); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(getTime, dateObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *time = dynG->IcreateCallthis0(ctxG, getTime, dateObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(time, getTime); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Epilog + auto *dateClass2 = dynG->IcreateTryldglobalbyname(ctxG, userData->date); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateClass2, callInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *dateObj2 = dynG->IcreateNewobjrange(ctxG, 1, dateClass2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateObj2, dateClass2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *getTime2 = dynG->IcreateLdobjbyname(ctxG, dateObj2, userData->getTime); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(getTime2, dateObj2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *time2 = dynG->IcreateCallthis0(ctxG, getTime2, dateObj2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(time2, getTime2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *consume = dynG->IcreateLoadString(ctxG, userData->consume); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(consume, time2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *print2 = dynG->IcreateTryldglobalbyname(ctxG, userData->print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(print2, consume); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg2 = dynG->IcreateCallarg1(ctxG, print2, consume); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(callArg2, print2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *sub = dynG->IcreateSub2(ctxG, time2, time); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(sub, callArg2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *print3 = dynG->IcreateTryldglobalbyname(ctxG, userData->print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(print3, sub); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg3 = dynG->IcreateCallarg1(ctxG, print3, sub); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(callArg3, print3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=internal, abc-kind=JS, category=internal +TEST_F(LibAbcKitInternalTest, LibAbcKitTestICSlotAllocator) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator.abc", "ICSlotAllocator"); + EXPECT_TRUE(helpers::Match(output, "abckit\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator.abc", + ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator_modified.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + UserData data = {}; + data.print = implM->CreateString(ctxM, "print"); + data.date = implM->CreateString(ctxM, "Date"); + data.getTime = implM->CreateString(ctxM, "getTime"); + data.str = implM->CreateString(ctxM, "file: src/MyClass, function: MyClass.handle"); + data.consume = implM->CreateString(ctxM, "Ellapsed time:"); + TransformIr(ctxG, &data); + }, + [](abckit_Graph *ctxG) { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + CheckICSlots(implG->BBgetTrueBranch(startBB), { + {abckit_IsaApiDynamicOpcode_LoadString, -1}, + {abckit_IsaApiDynamicOpcode_tryldglobalbyname, 0xd}, + {abckit_IsaApiDynamicOpcode_callarg1, 0x0}, + {abckit_IsaApiDynamicOpcode_tryldglobalbyname, 0xe}, + {abckit_IsaApiDynamicOpcode_newobjrange, 0xf}, + {abckit_IsaApiDynamicOpcode_ldobjbyname, 0x11}, + {abckit_IsaApiDynamicOpcode_callthis0, 0x2}, + {abckit_IsaApiDynamicOpcode_tryldglobalbyname, 0x13}, + {abckit_IsaApiDynamicOpcode_LoadString, -1}, + {abckit_IsaApiDynamicOpcode_callarg1, 0x4}, + {abckit_IsaApiDynamicOpcode_tryldglobalbyname, 0x14}, + {abckit_IsaApiDynamicOpcode_newobjrange, 0x15}, + {abckit_IsaApiDynamicOpcode_ldobjbyname, 0x17}, + {abckit_IsaApiDynamicOpcode_callthis0, 0x6}, + {abckit_IsaApiDynamicOpcode_LoadString, -1}, + {abckit_IsaApiDynamicOpcode_tryldglobalbyname, 0x19}, + {abckit_IsaApiDynamicOpcode_callarg1, 0x8}, + {abckit_IsaApiDynamicOpcode_sub2, 0xa}, + {abckit_IsaApiDynamicOpcode_tryldglobalbyname, 0x1a}, + {abckit_IsaApiDynamicOpcode_callarg1, 0xb}, + {abckit_IsaApiDynamicOpcode_ldundefined, -1}, + {abckit_IsaApiDynamicOpcode_returnundefined, -1} + }); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator_modified.abc", "ICSlotAllocator"); + EXPECT_TRUE(helpers::Match(output, + "file: src/MyClass, function: MyClass.handle\n" + "abckit\n" + "Ellapsed time:\n" + "\\d+\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/internal/ICSlotAllocator/ICSlotAllocator.js b/libabckit/tests/internal/ICSlotAllocator/ICSlotAllocator.js new file mode 100644 index 0000000000000000000000000000000000000000..0209680d4fb20f200c6ff6b4dbcea8fb00f6245b --- /dev/null +++ b/libabckit/tests/internal/ICSlotAllocator/ICSlotAllocator.js @@ -0,0 +1,28 @@ +// Before AOP: + +class MyClass { + handle() { + print("abckit") + } + } + + function main() { + let c = new MyClass(); + c.handle(); + } + + main() + + // // After AOP: + // + // class MyClass { + // handle() { + // print("file: har_A/src/MyClass, function: MyClass.handle") + // let t1 = Date.getTime() + // // business logic + // let t2 = Date.getTime() + // print("Ellapsed time:") + // print(t2 - t1) + // } + // } + \ No newline at end of file diff --git a/libabckit/tests/internal/implementation_api/abc_dynamic.js b/libabckit/tests/internal/implementation_api/abc_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..183ec2fc63575a8bda7a777220ffeebef6f14bd1 --- /dev/null +++ b/libabckit/tests/internal/implementation_api/abc_dynamic.js @@ -0,0 +1,17 @@ +class classA { + foo() { + print("foo") + } + bar() { + print("bar") + } +} + +class classB extends classA { + baz() { + print("baz") + } + func() { + print("func") + } +} diff --git a/libabckit/tests/internal/implementation_api/abc_static.ets b/libabckit/tests/internal/implementation_api/abc_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..86e406665244a8fd70c6f01c07c9649f97d0e205 --- /dev/null +++ b/libabckit/tests/internal/implementation_api/abc_static.ets @@ -0,0 +1,17 @@ +class classA { + foo() : void { + console.log("foo") + } + bar() : void { + console.log("bar") + } +} + +class classB extends classA { + baz() : void { + console.log("baz") + } + func() : void { + console.log("func") + } +} diff --git a/libabckit/tests/internal/implementation_api/abc_stuff.cpp b/libabckit/tests/internal/implementation_api/abc_stuff.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cd63ef0287bca08fcdb5102e61ab70c38078fa1b --- /dev/null +++ b/libabckit/tests/internal/implementation_api/abc_stuff.cpp @@ -0,0 +1,189 @@ +/** + * Copyright (c) 2024 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 + +#include "abckit.h" +#include "helpers/helpers.h" + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitAbcStuff: public ::testing::Test {}; + +struct ClassData { + const char * className = nullptr; + std::vector classMethods = {}; +}; + +struct ModuleData { + const char * moduleName = nullptr; + std::vector moduleMethods = {}; +}; + +// Test: test-kind=api, api=ApiImpl::OpenAbc, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitAbcStuff, OpenAbcStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector userData = { + { "classA", {"foo", "bar"}}, + { "classB", {"baz", "func"}} + }; + + implI->FileEnumerateModules(ctxI, &userData, [](abckit_Module *m, void *data) { + EMBED_TEST_START(test) + + auto *userData = reinterpret_cast *>(data); + + for(auto classData : *userData) { + helpers::ClassByNameContext classCtxFinder = {nullptr, classData.className}; + implI->ModuleEnumerateClasses(m, &classCtxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(classCtxFinder.klass, nullptr); + + for(auto *method : classData.classMethods) { + helpers::MethodByNameContext methodCtxFinder = {nullptr, method}; + implI->ClassEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + } + } + + EMBED_TEST_END(test) + return true; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::WriteAbc, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitAbcStuff, WriteAbcStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->WriteAbc(ctxI, ABCKIT_ABC_DIR "internal/implementation_api/abc_static_tmp.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static_tmp.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector userData = { + { "classA", {"foo", "bar"}}, + { "classB", {"baz", "func"}} + }; + + implI->FileEnumerateModules(ctxI, &userData, [](abckit_Module *m, void *data) { + EMBED_TEST_START(test) + + auto *userData = reinterpret_cast *>(data); + + for(auto classData : *userData) { + helpers::ClassByNameContext classCtxFinder = {nullptr, classData.className}; + implI->ModuleEnumerateClasses(m, &classCtxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(classCtxFinder.klass, nullptr); + + for(auto *method : classData.classMethods) { + helpers::MethodByNameContext methodCtxFinder = {nullptr, method}; + implI->ClassEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + } + } + + EMBED_TEST_END(test) + return true; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=ApiImpl::DestroyInspectContext, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitAbcStuff, DestroyInspectContextStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::OpenAbc, abc-kind=JS, category=positive +TEST_F(LibAbcKitAbcStuff, OpenAbcDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + struct ModuleData userData = { "abc_dynamic", {"foo", "bar", "baz", "func"}}; + + helpers::ModuleByNameContext moduleCtxFinder = {nullptr, userData.moduleName}; + implI->FileEnumerateModules(ctxI, &moduleCtxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(moduleCtxFinder.module, nullptr); + + for(auto method : userData.moduleMethods) { + auto *found = helpers::findMethodByName(ctxI, method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(found, nullptr); + } + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::WriteAbc, abc-kind=JS, category=positive +TEST_F(LibAbcKitAbcStuff, WriteAbcDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->WriteAbc(ctxI, ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic_tmp.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic_tmp.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + struct ModuleData userData = { "abc_dynamic", {"foo", "bar", "baz", "func"}}; + + helpers::ModuleByNameContext moduleCtxFinder = {nullptr, userData.moduleName}; + implI->FileEnumerateModules(ctxI, &moduleCtxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(moduleCtxFinder.module, nullptr); + + for(auto method : userData.moduleMethods) { + auto *found = helpers::findMethodByName(ctxI, method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(found, nullptr); + } + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::DestroyInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitAbcStuff, DestroyInspectContextDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/internal/implementation_api/graph_stuff.cpp b/libabckit/tests/internal/implementation_api/graph_stuff.cpp new file mode 100644 index 0000000000000000000000000000000000000000..195cca7475b10fdd984b5470eaa1ee742b7e5526 --- /dev/null +++ b/libabckit/tests/internal/implementation_api/graph_stuff.cpp @@ -0,0 +1,302 @@ +/** + * Copyright (c) 2024 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 + +#include "abckit.h" +#include "helpers/helpers.h" + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitGraphStuff: public ::testing::Test {}; + +struct ClassData { + const char * className = nullptr; + std::vector classMethods = {}; +}; + +struct ModuleData { + const char * moduleName = nullptr; + std::vector moduleMethods = {}; +}; + +// Test: test-kind=api, api=ApiImpl::codeToGraph, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGraphStuff, codeToGraphStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector userData = { + { "classA", {"foo", "bar"}}, + { "classB", {"baz", "func"}} + }; + + implI->FileEnumerateModules(ctxI, &userData, [](abckit_Module *m, void *data) { + EMBED_TEST_START(test) + + auto *userData = reinterpret_cast *>(data); + + for(auto classData : *userData) { + helpers::ClassByNameContext classCtxFinder = {nullptr, classData.className}; + implI->ModuleEnumerateClasses(m, &classCtxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(classCtxFinder.klass, nullptr); + + for(auto *method : classData.classMethods) { + helpers::MethodByNameContext methodCtxFinder = {nullptr, method}; + implI->ClassEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + + auto *ctx = implI->MethodGetInspectContext(methodCtxFinder.method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(methodCtxFinder.method)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newCode = impl->graphToCode(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->TransformMethod(methodCtxFinder.method, newCode, + [](abckit_ModifyContext *ctxM, abckit_Method *m, void* data) { + auto *code = reinterpret_cast(data); + implM->MethodSetCode(ctxM, m, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + } + + EMBED_TEST_END(test) + return true; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::graphToCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGraphStuff, graphToCodeStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector userData = { + { "classA", {"foo", "bar"}}, + { "classB", {"baz", "func"}} + }; + + implI->FileEnumerateModules(ctxI, &userData, [](abckit_Module *m, void *data) { + EMBED_TEST_START(test) + + auto *userData = reinterpret_cast *>(data); + + for(auto classData : *userData) { + helpers::ClassByNameContext classCtxFinder = {nullptr, classData.className}; + implI->ModuleEnumerateClasses(m, &classCtxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(classCtxFinder.klass, nullptr); + + for(auto *method : classData.classMethods) { + helpers::MethodByNameContext methodCtxFinder = {nullptr, method}; + implI->ClassEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + + auto *ctx = implI->MethodGetInspectContext(methodCtxFinder.method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(methodCtxFinder.method)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newCode = impl->graphToCode(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->TransformMethod(methodCtxFinder.method, newCode, + [](abckit_ModifyContext *ctxM, abckit_Method *m, void* data) { + auto *code = reinterpret_cast(data); + implM->MethodSetCode(ctxM, m, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + } + + EMBED_TEST_END(test) + return true; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::DestroyGraphContext, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGraphStuff, DestroyGraphContextStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector userData = { + { "classA", {"foo", "bar"}}, + { "classB", {"baz", "func"}} + }; + + implI->FileEnumerateModules(ctxI, &userData, [](abckit_Module *m, void *data) { + EMBED_TEST_START(test) + + auto *userData = reinterpret_cast *>(data); + + for(auto classData : *userData) { + helpers::ClassByNameContext classCtxFinder = {nullptr, classData.className}; + implI->ModuleEnumerateClasses(m, &classCtxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(classCtxFinder.klass, nullptr); + + for(auto *method : classData.classMethods) { + helpers::MethodByNameContext methodCtxFinder = {nullptr, method}; + implI->ClassEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + + auto *ctx = implI->MethodGetInspectContext(methodCtxFinder.method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(methodCtxFinder.method)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->DestroyGraphContext(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + } + } + + EMBED_TEST_END(test) + return true; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::codeToGraph, abc-kind=JS, category=positive +TEST_F(LibAbcKitGraphStuff, codeToGraphDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + struct ModuleData userData = { "abc_dynamic", {"foo", "bar", "baz", "func"}}; + + helpers::ModuleByNameContext moduleCtxFinder = {nullptr, userData.moduleName}; + implI->FileEnumerateModules(ctxI, &moduleCtxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(moduleCtxFinder.module, nullptr); + + for(auto method : userData.moduleMethods) { + auto *found = helpers::findMethodByName(ctxI, method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(found, nullptr); + + auto *ctx = implI->MethodGetInspectContext(found); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(found)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newCode = impl->graphToCode(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->TransformMethod(found, newCode, + [](abckit_ModifyContext *ctxM, abckit_Method *m, void* data) { + auto *code = reinterpret_cast(data); + implM->MethodSetCode(ctxM, m, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::graphToCode, abc-kind=JS, category=positive +TEST_F(LibAbcKitGraphStuff, graphToCodeDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + struct ModuleData userData = { "abc_dynamic", {"foo", "bar", "baz", "func"}}; + + helpers::ModuleByNameContext moduleCtxFinder = {nullptr, userData.moduleName}; + implI->FileEnumerateModules(ctxI, &moduleCtxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(moduleCtxFinder.module, nullptr); + + for(auto method : userData.moduleMethods) { + auto *found = helpers::findMethodByName(ctxI, method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(found, nullptr); + + auto *ctx = implI->MethodGetInspectContext(found); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(found)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newCode = impl->graphToCode(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->TransformMethod(found, newCode, + [](abckit_ModifyContext *ctxM, abckit_Method *m, void* data) { + auto *code = reinterpret_cast(data); + implM->MethodSetCode(ctxM, m, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::DestroyGraphContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitGraphStuff, DestroyGraphContextDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/implementation_api/abc_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + struct ModuleData userData = { "abc_dynamic", {"foo", "bar", "baz", "func"}}; + + helpers::ModuleByNameContext moduleCtxFinder = {nullptr, userData.moduleName}; + implI->FileEnumerateModules(ctxI, &moduleCtxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(moduleCtxFinder.module, nullptr); + + for(auto method : userData.moduleMethods) { + auto *found = helpers::findMethodByName(ctxI, method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(found, nullptr); + + auto *ctx = implI->MethodGetInspectContext(found); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(found)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->DestroyGraphContext(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + } + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/internal/mem_manager/abc_dynamic_1.js b/libabckit/tests/internal/mem_manager/abc_dynamic_1.js new file mode 100644 index 0000000000000000000000000000000000000000..2ebc5b01efe8ef369da5ccadfbec21a2c2a14a1f --- /dev/null +++ b/libabckit/tests/internal/mem_manager/abc_dynamic_1.js @@ -0,0 +1,23 @@ +class classA { + foo() { + print("foo") + } + bar() { + print("bar") + } +} + +class classB extends classA { + baz() { + print("baz") + } + func() { + print("func") + } +} + +let b = new classB() +b.foo() +b.bar() +b.baz() +b.func() diff --git a/libabckit/tests/internal/mem_manager/abc_dynamic_2.js b/libabckit/tests/internal/mem_manager/abc_dynamic_2.js new file mode 100644 index 0000000000000000000000000000000000000000..2ebc5b01efe8ef369da5ccadfbec21a2c2a14a1f --- /dev/null +++ b/libabckit/tests/internal/mem_manager/abc_dynamic_2.js @@ -0,0 +1,23 @@ +class classA { + foo() { + print("foo") + } + bar() { + print("bar") + } +} + +class classB extends classA { + baz() { + print("baz") + } + func() { + print("func") + } +} + +let b = new classB() +b.foo() +b.bar() +b.baz() +b.func() diff --git a/libabckit/tests/internal/mem_manager/abc_static_1.ets b/libabckit/tests/internal/mem_manager/abc_static_1.ets new file mode 100644 index 0000000000000000000000000000000000000000..f236f7a04bfda6890d9b0c5b88d455ead92a80b9 --- /dev/null +++ b/libabckit/tests/internal/mem_manager/abc_static_1.ets @@ -0,0 +1,25 @@ +class classA { + foo() : void { + console.log("foo") + } + bar() : void { + console.log("bar") + } +} + +class classB extends classA { + baz() : void { + console.log("baz") + } + func() : void { + console.log("func") + } +} + +function main() { + let b = new classB(); + b.foo() + b.bar() + b.baz() + b.func() +} diff --git a/libabckit/tests/internal/mem_manager/abc_static_2.ets b/libabckit/tests/internal/mem_manager/abc_static_2.ets new file mode 100644 index 0000000000000000000000000000000000000000..f236f7a04bfda6890d9b0c5b88d455ead92a80b9 --- /dev/null +++ b/libabckit/tests/internal/mem_manager/abc_static_2.ets @@ -0,0 +1,25 @@ +class classA { + foo() : void { + console.log("foo") + } + bar() : void { + console.log("bar") + } +} + +class classB extends classA { + baz() : void { + console.log("baz") + } + func() : void { + console.log("func") + } +} + +function main() { + let b = new classB(); + b.foo() + b.bar() + b.baz() + b.func() +} diff --git a/libabckit/tests/internal/mem_manager/several_abc.cpp b/libabckit/tests/internal/mem_manager/several_abc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c343e22a50592ff359dd6ecc3c3cbdcdd3904594 --- /dev/null +++ b/libabckit/tests/internal/mem_manager/several_abc.cpp @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2024 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 + +#include "abckit.h" +#include "helpers/helpers.h" + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitMemoryHandling : public ::testing::Test {}; + +// Test: test-kind=api, api=ApiImpl::OpenAbc, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitMemoryHandling, OpenAbcStatic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/mem_manager/abc_static_1.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *ctxI2 = impl->OpenAbc(ABCKIT_ABC_DIR "internal/mem_manager/abc_static_2.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *main = helpers::findMethodByName(ctxI, "main"); + ASSERT_NE(main, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *main2 = helpers::findMethodByName(ctxI2, "main"); + ASSERT_NE(main2, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto transformMain = [] (abckit_ModifyContext *ctxM, abckit_Method *method, void *data) { + auto *ctx = implI->MethodGetInspectContext(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(method)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newCode = impl->graphToCode(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implM->MethodSetCode(ctxM, method, newCode); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }; + + impl->TransformMethod(main, nullptr, transformMain); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->TransformMethod(main2, nullptr, transformMain); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctxI, ABCKIT_ABC_DIR "internal/mem_manager/abc_static_1.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->WriteAbc(ctxI2, ABCKIT_ABC_DIR "internal/mem_manager/abc_static_2.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ApiImpl::OpenAbc, abc-kind=JS, category=positive +TEST_F(LibAbcKitMemoryHandling, OpenAbcDynamic) +{ + auto *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "internal/mem_manager/abc_dynamic_1.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *ctxI2 = impl->OpenAbc(ABCKIT_ABC_DIR "internal/mem_manager/abc_dynamic_2.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *main = helpers::findMethodByName(ctxI, "func_main_0"); + ASSERT_NE(main, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *main2 = helpers::findMethodByName(ctxI2, "func_main_0"); + ASSERT_NE(main2, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto transformMain = [] (abckit_ModifyContext *ctxM, abckit_Method *method, void *data) { + auto *ctx = implI->MethodGetInspectContext(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *graph = impl->codeToGraph(ctx, implI->MethodGetCode(method)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newCode = impl->graphToCode(graph); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implM->MethodSetCode(ctxM, method, newCode); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }; + + impl->TransformMethod(main, nullptr, transformMain); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->TransformMethod(main2, nullptr, transformMain); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctxI, ABCKIT_ABC_DIR "internal/mem_manager/abc_dynamic_1.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->WriteAbc(ctxI2, ABCKIT_ABC_DIR "internal/mem_manager/abc_dynamic_2.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/basic_blocks/basic_blocks_dynamic.js b/libabckit/tests/ir/basic_blocks/basic_blocks_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..359fc7aaa5b87263ed828a36d0548c0144310327 --- /dev/null +++ b/libabckit/tests/ir/basic_blocks/basic_blocks_dynamic.js @@ -0,0 +1,38 @@ +class Test { + test() { + } + + test2(a) { + if(a > 0) { + return 1 + } + return -1; + } + + test3(a) { + try { + if(Math.random() < a){ + throw new Error("Error") + } + } catch(e) { + console.log(e) + return a + } + return -a + } + + test4() { + let counter = 0 + for(let i = 0; i < 5; i++) { + counter++ + } + return counter + } +} + +function main() { + const test = new Test() + test.test() + test.test2(1) + test.test3(1) +} diff --git a/libabckit/tests/ir/basic_blocks/basic_blocks_static.cpp b/libabckit/tests/ir/basic_blocks/basic_blocks_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb200390e271fd5f87302b0429736612483a06b6 --- /dev/null +++ b/libabckit/tests/ir/basic_blocks/basic_blocks_static.cpp @@ -0,0 +1,910 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "statuses.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" + +#include +#include + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitBasicBlocksTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::BBcreateEmpty, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBcreateEmptyBlock_1) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *main = helpers::BBgetSuccBlocks(start)[0]; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *bb = implG->BBcreateEmpty(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->BBdisconnectBlocks(start, main); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(start, bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb, main, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector> bbSchemas({ + {{}, {1}, {}}, + {{0}, {2}, {}}, + {{1}, {3}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{2}, {}, {}} + }); + helpers::VerifyGraph(ctxG, bbSchemas); + + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=GraphApiImpl::BBconnectBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBconnectBlocks_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *main = helpers::BBgetSuccBlocks(start)[0]; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *bb = implG->BBcreateEmpty(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->BBdisconnectBlocks(start, main); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(start, bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb, main, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBconnectBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBconnectBlocks_2) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *main = helpers::BBgetSuccBlocks(start)[0]; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *bb = implG->BBcreateEmpty(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->BBdisconnectBlocks(start, main); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(start, bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb, main, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBconnectBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBconnectBlocks_3) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *main = helpers::BBgetSuccBlocks(start)[0]; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *bb = implG->BBcreateEmpty(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->BBdisconnectBlocks(start, main); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(start, bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb, main, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBconnectBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBconnectBlocks_4) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *main = helpers::BBgetSuccBlocks(start)[0]; + auto *bb1 = implG->BBcreateEmpty(ctxG); + auto *bb2 = implG->BBcreateEmpty(ctxG); + + implG->BBdisconnectBlocks(start, main); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->BBconnectBlocks(start, bb1, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, main, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(bb1, bb2, true); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + LIBABCKIT_LOG_DUMP(implG->Gdump(ctxG, 2), DEBUG); + std::vector> bbSchemas({{{}, + {1}, + {}}, + {{0}, {3, 2}, {}}, + {{1}, {}, {}}, + {{1}, {4}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{3}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::BBdisconnectBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBdisconnectBlocks_4) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *next = helpers::BBgetSuccBlocks(start)[0]; + implG->BBdisconnectBlocks(start, next); + ASSERT_TRUE(helpers::BBgetSuccBlocks(start).empty()); + ASSERT_TRUE(helpers::BBgetPredBlocks(next).empty()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {}, + {}}, + {{}, + {2}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{1}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + + implG->BBconnectBlocks(start, next, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetGraph, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetGraph_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = implG->BBcreateEmpty(ctxG); + auto *end = implG->GgetEndBasicBlock(ctxG); + + implG->BBconnectBlocks(start, bb, false); + implG->BBconnectBlocks(bb, end, false); + auto *graph = implG->BBgetGraph(bb); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {2, 1}, + {}}, + {{0}, {3}, {}}, + {{0}, + {3}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{2, 1}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + ASSERT_EQ(graph, ctxG); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetFirstInst, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetFirstInst_2) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(bb); + + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_ReturnVoid); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetLastInst, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetLastInst_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetLastInst(bb); + + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_ReturnVoid); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetTrueBranch, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetTrueBranch_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *cmp_b = helpers::BBgetSuccBlocks(start)[0]; + auto *true_b = implG->BBgetTrueBranch(cmp_b); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *inst = implG->BBgetFirstInst(true_b); + + ASSERT_NE(inst, nullptr); + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_Neg); + + std::vector> bbSchemas({{{}, + {1}, + { + {1, abckit_IsaApiStaticOpcode_Parameter, {}}, + {3, abckit_IsaApiStaticOpcode_Constant, {}}, + {5, abckit_IsaApiStaticOpcode_Constant, {}}, + }}, + {{0}, + {3, 2}, + { + {4, abckit_IsaApiStaticOpcode_If, {3, 1}}, + }}, + {{1}, + {4}, + { + {6, abckit_IsaApiStaticOpcode_Return, {5}}, + }}, + {{1}, + {4}, + { + {7, abckit_IsaApiStaticOpcode_Neg, {5}}, + {8, abckit_IsaApiStaticOpcode_Return, {7}}, + }}, + {{2, 3}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetFalseBranch, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetFalseBranch_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *cmp_b = helpers::BBgetSuccBlocks(start)[0]; + auto *true_b = implG->BBgetFalseBranch(cmp_b); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *inst = implG->BBgetFirstInst(true_b); + + ASSERT_NE(inst, nullptr); + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_Return); + + std::vector> bbSchemas({{{}, + {1}, + { + {1, abckit_IsaApiStaticOpcode_Parameter, {}}, + {3, abckit_IsaApiStaticOpcode_Constant, {}}, + {5, abckit_IsaApiStaticOpcode_Constant, {}}, + }}, + {{0}, + {3, 2}, + { + {4, abckit_IsaApiStaticOpcode_If, {3, 1}}, + }}, + {{1}, + {4}, + { + {6, abckit_IsaApiStaticOpcode_Return, {5}}, + }}, + {{1}, + {4}, + { + {7, abckit_IsaApiStaticOpcode_Neg, {5}}, + {8, abckit_IsaApiStaticOpcode_Return, {7}}, + }}, + {{2, 3}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstFront, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBaddInstFront_4) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(start); + auto *new_inst = implG->GcreateConstantI64(ctxG, 1U); + auto *neg_inst = statG->IcreateNeg(ctxG, new_inst); + implG->BBaddInstFront(bb, neg_inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {1}, + { + {3, abckit_IsaApiStaticOpcode_Constant, {}} + }}, + {{0}, + {2}, + { + {4, abckit_IsaApiStaticOpcode_Neg, {3}}, + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{1}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + + ASSERT_EQ(inst, implG->IgetNext(new_inst)); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstBack, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBaddInstBack_2) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(start); + auto *new_inst = implG->GcreateConstantI64(ctxG, 1U); + auto *neg_inst = statG->IcreateNeg(ctxG, new_inst); + + implG->BBdisconnectBlocks(start, bb); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *empty = implG->BBcreateEmpty(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(start, empty, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(empty, bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstBack(empty, neg_inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {1}, + { + {3, abckit_IsaApiStaticOpcode_Constant, {}} + }}, + {{0}, {2}, + { + {4, abckit_IsaApiStaticOpcode_Neg, {3}}, + }}, + {{1}, {3}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{2}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + + ASSERT_EQ(inst, implG->IgetNext(new_inst)); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstBack, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBaddInstBack_4) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *new_ins = implG->GcreateConstantI64(ctxG, 1); + + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {1}, + { + {3, abckit_IsaApiStaticOpcode_Constant, {}} + }}, + {{0}, + {2}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{1}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + + ASSERT_EQ(new_ins, implG->BBgetFirstInst(start)); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=GraphApiImpl::BBvisitSuccBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBvisitSuccBlocks_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + + uint32_t counter = 0; + implG->BBvisitSuccBlocks(bb, &counter, [](abckit_BasicBlock *curr_bb, abckit_BasicBlock *succ_bb, void *data) { + (*(reinterpret_cast(data)))++; + }); + + ASSERT_EQ(counter, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBvisitPredBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBvisitPredBlocks_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + + uint32_t counter = 0; + implG->BBvisitPredBlocks(bb, &counter, [](abckit_BasicBlock *curr_bb, abckit_BasicBlock *succ_bb, void *data) { + (*(reinterpret_cast(data)))++; + }); + + ASSERT_EQ(counter, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); +} + +// Test: test-kind=api, api=GraphApiImpl::BBvisitDominatedBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBvisitDominatedBlocks_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = helpers::BBgetSuccBlocks(start)[0]; + + uint32_t counter = 0; + implG->BBvisitDominatedBlocks(bb, &counter, [](abckit_BasicBlock *curr_bb, abckit_BasicBlock *succ_bb, void* data) { + (*(reinterpret_cast(data)))++; + }); + + ASSERT_EQ(counter, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetSuccBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetSuccBlock_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + + ASSERT_EQ(bb, helpers::BBgetSuccBlocks(start)[0]); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisStart, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBisStart_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + + ASSERT_TRUE(implG->BBisStart(start)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisEnd, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBisEnd_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* end = implG->GgetEndBasicBlock(ctxG); + + ASSERT_TRUE(implG->BBisEnd(end)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetImmediateDominator, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetImmediateDominator_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = helpers::BBgetSuccBlocks(start)[0]; + implG->BBgetImmediateDominator(bb); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetSuccBlockCount, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetSuccBlockCount_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + + ASSERT_EQ(implG->BBgetSuccBlockCount(start), 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetPredBlockCount, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetPredBlockCount_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = helpers::BBgetSuccBlocks(start)[0]; + + ASSERT_EQ(implG->BBgetPredBlockCount(bb), 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBdump, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBdump_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + LIBABCKIT_LOG_DUMP(implG->BBdump(start, 0), DEBUG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetNumberOfInstructions, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetNumberOfInstructions_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = helpers::BBgetSuccBlocks(start)[0]; + ASSERT_EQ(implG->BBgetNumberOfInstructions(bb), 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetBasicBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, GgetBasicBlock_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* bb = implG->GgetBasicBlock(ctxG, 1); + ASSERT_EQ(bb, implG->GgetStartBasicBlock(ctxG)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetParameter, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, GgetParameter_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* inst = implG->BBgetFirstInst(start); + ASSERT_EQ(inst, implG->GgetParameter(ctxG, 0)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetNumberOfBasicBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, GgetNumberOfBasicBlocks_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + implG->GgetNumberOfBasicBlocks(ctxG); + ASSERT_EQ(implG->GgetNumberOfBasicBlocks(ctxG), 5); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + + +// Test: test-kind=api, api=GraphApiImpl::BBgetId, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetId_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(implG->BBgetId(start), 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetPredBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBgetPredBlock_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + ASSERT_EQ(implG->BBgetPredBlock(bb, 0), helpers::BBgetPredBlocks(bb)[0]); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetSuccBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBsetSuccBlock_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + auto* empty = implG->BBcreateEmpty(ctxG); + implG->BBsetSuccBlock(bb, empty, 2); + ASSERT_EQ(implG->BBgetSuccBlock(bb, 2), helpers::BBgetSuccBlocks(bb)[2]); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBdisconnectBlocks(bb, empty); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetSuccBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBsetSuccBlocks_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + auto* empty1 = implG->BBcreateEmpty(ctxG); + auto* empty2 = implG->BBcreateEmpty(ctxG); + implG->BBsetSuccBlocks(bb, 2, empty1, empty2); + ASSERT_EQ(implG->BBgetSuccBlockCount(bb), 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBdisconnectBlocks(bb, empty1); + implG->BBdisconnectBlocks(bb, empty2); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetPredBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBsetPredBlock_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + auto* empty = implG->BBcreateEmpty(ctxG); + implG->BBsetPredBlock(bb, empty, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(implG->BBgetPredBlock(bb, 1), helpers::BBgetPredBlocks(bb)[1]); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetPredBlocks, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBsetPredBlocks_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + auto* empty1 = implG->BBcreateEmpty(ctxG); + auto* empty2 = implG->BBcreateEmpty(ctxG); + implG->BBsetPredBlocks(bb, 2, empty1, empty2); + ASSERT_EQ(implG->BBgetPredBlockCount(bb), 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBdisconnectBlocks(empty1, bb); + implG->BBdisconnectBlocks(empty2, bb); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBclear, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBclear_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* empty = implG->BBcreateEmpty(ctxG); + auto *const_inst = implG->GcreateConstantI64(ctxG, 1U); + auto *new_inst = statG->IcreateNeg(ctxG, const_inst); + implG->BBaddInstFront(empty, new_inst); + ASSERT_EQ(implG->BBgetNumberOfInstructions(empty), 1); + implG->BBclear(empty); + ASSERT_EQ(implG->BBgetNumberOfInstructions(empty), 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisLoopPrehead, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBisLoopPrehead_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test4", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + ASSERT_TRUE(implG->BBisLoopPrehead(bb)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisLoopHead, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBisLoopHead_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test4", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + auto* bb2 = implG->BBgetSuccBlock(bb, 0); + ASSERT_TRUE(implG->BBisLoopHead(bb2)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsplitBlockAfterInstruction, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBsplitBlockAfterInstruction_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + auto* bb2 = implG->BBgetSuccBlock(bb, 0); + auto* inst = implG->BBgetFirstInst(bb2); + ASSERT_EQ(implG->GgetNumberOfBasicBlocks(ctxG), 5); + auto* new_bb = implG->BBsplitBlockAfterInstruction(inst, false); + ASSERT_EQ(implG->GgetNumberOfBasicBlocks(ctxG), 6); + implG->BBconnectBlocks(bb2, new_bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcheckDominance, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, BBcheckDominance_1) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto* start = implG->GgetStartBasicBlock(ctxG); + auto* bb = implG->BBgetSuccBlock(start, 0); + ASSERT_TRUE(implG->BBcheckDominance(bb, start)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/basic_blocks/basic_blocks_static.ets b/libabckit/tests/ir/basic_blocks/basic_blocks_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..9e8c9aaf0989134f93b434786238fa4156414195 --- /dev/null +++ b/libabckit/tests/ir/basic_blocks/basic_blocks_static.ets @@ -0,0 +1,38 @@ +class Test { + test() { + } + + test2(a: int) { + if(a > 0) { + return 1 + } + return -1; + } + + test3(a: double) { + try { + if(Math.random() < a){ + throw new Error("Error") + } + } catch(e) { + console.log(e) + return a + } + return -a + } + + test4() { + let counter: int = 0 + for(let i: int = 0; i < 5; i++) { + counter++ + } + return counter + } +} + +function main() { + const test = new Test() + test.test() + test.test2(1) + test.test3(1) +} diff --git a/libabckit/tests/ir/class/classes_api.cpp b/libabckit/tests/ir/class/classes_api.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0d6e0c62db975a1afa92b9fe1ee651332decc704 --- /dev/null +++ b/libabckit/tests/ir/class/classes_api.cpp @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "isa/isa_static.h" +#include "metadata.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + std::vector> CreateBBSchema() + { + return { + { + {}, {1}, { + {} + } + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {2, abckit_IsaApiStaticOpcode_IsInstance, {0}}, + {1, abckit_IsaApiStaticOpcode_Return, {2}}, + + } + }, + { + {1}, {}, {} + } + }; + } + + void IsetClass(abckit_Graph *ctxG, abckit_ModifyContext *ctxM, abckit_Class *klass, abckit_Class *startKlass) + { + abckit_Inst *initObj = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_InitObject); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *type = implM->CreateReferenceType(ctxM, startKlass); + ASSERT_NE(type, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *isInstance = statG->IcreateIsInstance(ctxG, initObj, type); + ASSERT_NE(isInstance, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + statG->IsetClass(isInstance, klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(isInstance, initObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ReplaceInst(ret, statG->IcreateReturn(ctxG, isInstance)); + } + + abckit_Class *IgetClass(abckit_Graph *ctxG, abckit_ModifyContext *ctxM) + { + abckit_Inst *inst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_IsInstance); + assert(inst != nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto *klass = statG->IgetClass(inst); + assert(klass != nullptr); + assert(impl->GetLastError() == abckit_Status_NO_ERROR); + return klass; + } + + void TransformIrForIsetClass(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) + { + auto *module = implI->MethodGetModule(method); + helpers::ClassByNameContext classCtxFinder = {nullptr, "A"}; + implI->ModuleEnumerateClasses(module, &classCtxFinder, helpers::classByNameFinder); + ASSERT_NE(classCtxFinder.klass, nullptr); + helpers::ClassByNameContext startClassCtxFinder = {nullptr, "B"}; + implI->ModuleEnumerateClasses(module, &startClassCtxFinder, helpers::classByNameFinder); + ASSERT_NE(startClassCtxFinder.klass, nullptr); + IsetClass(ctxG, ctxM, classCtxFinder.klass, startClassCtxFinder.klass); + } + + void TransformIrForIgetClass(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) + { + auto *module = implI->MethodGetModule(method); + helpers::ClassByNameContext classCtxFinder = {nullptr, "A"}; + implI->ModuleEnumerateClasses(module, &classCtxFinder, helpers::classByNameFinder); + ASSERT_NE(classCtxFinder.klass, nullptr); + helpers::ClassByNameContext startClassCtxFinder = {nullptr, "B"}; + implI->ModuleEnumerateClasses(module, &startClassCtxFinder, helpers::classByNameFinder); + ASSERT_NE(startClassCtxFinder.klass, nullptr); + IsetClass(ctxG, ctxM, classCtxFinder.klass, startClassCtxFinder.klass); + auto *klass = IgetClass(ctxG, ctxM); + ASSERT_EQ(klass, classCtxFinder.klass); + } + + void TemplateTestFunction(const std::string &inputResult, const std::string &outputResult, const std::string &funcName, + void (*IrTransformer)(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG)) + { + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/class/classes_api.abc", "classes_api/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, inputResult)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/class/classes_api.abc", + ABCKIT_ABC_DIR "ir/class/classes_api_modified.abc", + funcName, + [&IrTransformer](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + IrTransformer(ctxM, method, ctxG); + }, + [](abckit_Graph *ctxG) { + const auto &bbSchemas = CreateBBSchema(); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/class/classes_api_modified.abc", "classes_api/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, outputResult)); + } +} // namespace + +class LibAbcKitClassesAPITest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetClass, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitClassesAPITest, LibAbcKitTestIsetClassIsInstanceTrue) +{ + TemplateTestFunction("false\ntrue\n", + "true\ntrue\n", + "foo", + TransformIrForIsetClass + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetClass, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitClassesAPITest, LibAbcKitTestIsetClassIsInstanceFalse) +{ + TemplateTestFunction("false\ntrue\n", + "false\nfalse\n", + "bar", + TransformIrForIsetClass + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetClass, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitClassesAPITest, LibAbcKitTestIgetClassIsInstance) +{ + TemplateTestFunction("false\ntrue\n", + "true\ntrue\n", + "foo", + TransformIrForIgetClass + ); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/class/classes_api.ets b/libabckit/tests/ir/class/classes_api.ets new file mode 100644 index 0000000000000000000000000000000000000000..314a07b134995d91413b8eb8e656de42bba2276e --- /dev/null +++ b/libabckit/tests/ir/class/classes_api.ets @@ -0,0 +1,18 @@ +class A {} +class B extends A {} +class C {} + +function foo (): boolean { + let a = new B(); + return false; +} + +function bar (): boolean { + let a = new C(); + return true; +} + +function main() { + console.log(foo()) + console.log(bar()) +} \ No newline at end of file diff --git a/libabckit/tests/ir/create_constant/create_constant_dynamic.cpp b/libabckit/tests/ir/create_constant/create_constant_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73edb2fbc35ef244524325558711b6f59d019b42 --- /dev/null +++ b/libabckit/tests/ir/create_constant/create_constant_dynamic.cpp @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2024 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 "helpers/helpers_nullptr.h" +#include "metadata.h" +#include "ir_core.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include +#include + +namespace libabckit::test { + +class LibAbcKitTest : public ::testing::Test {}; + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +static void TransformMethodDynamicValid(abckit_Graph *ctxG, const std::string &typeName) +{ + abckit_Inst *constant = nullptr; + if (typeName == "u64") { + constant = implG->GcreateConstantU64(ctxG, 0xa); + } else if (typeName == "f64") { + constant = implG->GcreateConstantF64(ctxG, 12.16); + } else if (typeName == "i64") { + constant = implG->GcreateConstantI64(ctxG, -5); + } else if (typeName == "i32") { + constant = implG->GcreateConstantI32(ctxG, 5); + } else { + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(retOp, constant, 0); +} + +static void TransformMethodDynamicUnconnected(abckit_Graph *ctxG, const std::string &typeName) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + + abckit_Inst *constant = nullptr; + if (typeName == "u64") { + constant = implG->GcreateConstantU64(ctxG, 0xa); + } else if (typeName == "f64") { + constant = implG->GcreateConstantF64(ctxG, 12.16); + } else if (typeName == "i64") { + constant = implG->GcreateConstantI64(ctxG, -5); + } else if (typeName == "i32") { + constant = implG->GcreateConstantI32(ctxG, 5); + } else { + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + + ASSERT_NE(constant, nullptr); + implG->BBaddInstFront(startBB, constant); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; +} + +static void VerifyTransformations(abckit_Graph* ctxG, std::string functionName) +{ + helpers::InstSchema constantInstr {2, abckit_IsaApiDynamicOpcode_Constant, {}}; + + // Verify graph + std::vector> bbSchemas({ + { + {}, {1}, { + constantInstr, + } + }, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_return, {2}} + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); +} + +class LibAbcKitCreateConstantTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantU64, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantU64Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic_modify.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicValid(ctxG, "u64"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo1"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantF64, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantF64Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic_modified.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicValid(ctxG, "f64"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo1"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI64, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantI64Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic_modified.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicValid(ctxG, "i64"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo1"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI32, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantI32Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic_modified.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicValid(ctxG, "i32"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo1"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantU64, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantU64Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + "foo2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicUnconnected(ctxG, "u64"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI64, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantI64Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + "foo2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicUnconnected(ctxG, "i64"); + } + ); +} + + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantF64, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantF64Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + "foo2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicUnconnected(ctxG, "f64"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI32, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateConstantTest, DynamicCreateConstantI32Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_dynamic.abc", + "foo2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodDynamicUnconnected(ctxG, "i32"); + } + ); +} +} // namespace libabckit::test diff --git a/libabckit/tests/ir/create_constant/create_constant_dynamic.js b/libabckit/tests/ir/create_constant/create_constant_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..ea7b6565734df99765d6dfa7b82cd2b6743a92ee --- /dev/null +++ b/libabckit/tests/ir/create_constant/create_constant_dynamic.js @@ -0,0 +1,11 @@ +// Before AOP: + +class A { + foo1() { + return 5; + } + foo2() { + return; + } + +} \ No newline at end of file diff --git a/libabckit/tests/ir/create_constant/create_constant_static.cpp b/libabckit/tests/ir/create_constant/create_constant_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b6e2e329ace6effa29f66c01f70d46d11813435b --- /dev/null +++ b/libabckit/tests/ir/create_constant/create_constant_static.cpp @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2024 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 "helpers/helpers_nullptr.h" +#include "metadata.h" +#include "ir_core.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include +#include + +namespace libabckit::test { + +class LibAbcKitTest : public ::testing::Test {}; + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +static void TransformMethodStaticValid(abckit_Graph *ctxG, const std::string functionName) +{ + abckit_Inst *constant = nullptr; + if (functionName == "foo1") { + constant = implG->GcreateConstantU64(ctxG, 0xa); + } else if (functionName == "foo2") { + constant = implG->GcreateConstantF64(ctxG, 12.16); + } else if (functionName == "foo3") { + constant = implG->GcreateConstantI64(ctxG, -5); + } else if (functionName == "foo5") { + constant = implG->GcreateConstantI64(ctxG, 5); + } else { + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + implG->IsetInput(retOp, constant, 0); +} + +static void TransformMethodStaticUnconnected(abckit_Graph *ctxG, const std::string &typeName) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + + abckit_Inst *constant = nullptr; + if (typeName == "u64") { + constant = implG->GcreateConstantU64(ctxG, 0xa); + } else if (typeName == "f64") { + constant = implG->GcreateConstantF64(ctxG, 12.16); + } else if (typeName == "i64") { + constant = implG->GcreateConstantI64(ctxG, -5); + } else if (typeName == "i32") { + constant = implG->GcreateConstantI32(ctxG, 5); + } else { + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + + ASSERT_NE(constant, nullptr); + implG->BBaddInstFront(startBB, constant); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; +} + +static void VerifyTransformations(abckit_Graph* ctxG, std::string functionName) +{ + helpers::InstSchema constantInstr {2, abckit_IsaApiStaticOpcode_Constant, {}}; // TODO: need to verify value of constant + + // Verify graph + std::vector> bbSchemas({ + { + {}, {1}, { + constantInstr, + } + }, + { + {0}, {2}, { + {3, abckit_IsaApiStaticOpcode_Return, {2}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); +} + +class LibAbcKitCreateConstantTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantU64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantU64Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static_modify.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo1"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo1"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantF64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantF64Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static_modified.abc", + "foo2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo2"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo2"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantI64Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static_modified.abc", + "foo3", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo3"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo3"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantU64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantU64Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + "foo4", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticUnconnected(ctxG, "u64"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantI64Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + "foo4", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticUnconnected(ctxG, "i64"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantF64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantF64Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + "foo4", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticUnconnected(ctxG, "f64"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI32, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantI32Valid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static_modified.abc", + "foo5", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo5"); + }, + [](abckit_Graph *ctxG) { + VerifyTransformations(ctxG, "foo5"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI32, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateConstantTest, StaticCreateConstantI32Unconnected) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/create_constant/create_constant_static.abc", + "foo4", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformMethodStaticUnconnected(ctxG, "i32"); + } + ); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/create_constant/create_constant_static.ets b/libabckit/tests/ir/create_constant/create_constant_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..4a3fb2ff4f48d6c64dd6757f3062e814c8800678 --- /dev/null +++ b/libabckit/tests/ir/create_constant/create_constant_static.ets @@ -0,0 +1,36 @@ +// Before AOP: + +class A { + foo1() : long { + return 5; + } + foo2() : number { + return 5.0; + } + foo3() : long { + return -5; + } + foo4() : void { + return; + } + foo5() : long { + return 7; + } +} + +// After AOP: + +// class A { +// foo1() : long { +// return 10; +// } +// foo2() : number { +// return 12.16; +// } +// foo3() : long { +// return -4; +// } +// foo4() : void { +// return; +// } +// } diff --git a/libabckit/tests/ir/get_constant_value/get_constant_value_static.cpp b/libabckit/tests/ir/get_constant_value/get_constant_value_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e60244e21e71f06951df780456611c70825ca1a --- /dev/null +++ b/libabckit/tests/ir/get_constant_value/get_constant_value_static.cpp @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_static.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitGetConstantValueTest : public ::testing::Test {}; + +static void TransformMethodStaticValid(abckit_Graph *ctxG, const std::string functionName) +{ + abckit_Inst *firstConst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Constant); + if (functionName == "foo1") { + auto constant = implG->IgetConstantValueU64(firstConst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(constant, 5); + } else if (functionName == "foo2") { + auto constant = implG->IgetConstantValueF64(firstConst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(constant, 7.1); + } else if (functionName == "foo3") { + auto constant = implG->IgetConstantValueI64(firstConst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(constant, -5); + } else { + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } +} + +// Test: test-kind=api, api=GraphApiImpl::IgetConstantValueU64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGetConstantValueTest, GetConstantValueU64Valid) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/get_constant_value/get_constant_value_static.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method* method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo1"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetConstantValueF64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGetConstantValueTest, GetConstantValueF64Valid) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/get_constant_value/get_constant_value_static.abc", + "foo2", + [](abckit_ModifyContext *ctxM, abckit_Method* method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo2"); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetConstantValueI64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGetConstantValueTest, GetConstantValueI64Valid) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/get_constant_value/get_constant_value_static.abc", + "foo3", + [](abckit_ModifyContext *ctxM, abckit_Method* method, abckit_Graph *ctxG) { + TransformMethodStaticValid(ctxG, "foo3"); + } + ); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/get_constant_value/get_constant_value_static.ets b/libabckit/tests/ir/get_constant_value/get_constant_value_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..9d74110dbae2ae732bb17895dc626a4ccb34819a --- /dev/null +++ b/libabckit/tests/ir/get_constant_value/get_constant_value_static.ets @@ -0,0 +1,21 @@ +class A { + foo1() : long { + let a: long = 5; + return a; + } + foo2() : number { + let a: number = 7.1; + return a; + } + foo3() : long { + let a: long = -5; + return a; + } +} + +function main() { + let a = new A() + console.log(a.foo1()) + console.log(a.foo2()) + console.log(a.foo3()) +} \ No newline at end of file diff --git a/libabckit/tests/ir/graph_basic_block/graph_basic_block.ets b/libabckit/tests/ir/graph_basic_block/graph_basic_block.ets new file mode 100644 index 0000000000000000000000000000000000000000..7e0cdc8e7baf26447abead22702f17d7e186d426 --- /dev/null +++ b/libabckit/tests/ir/graph_basic_block/graph_basic_block.ets @@ -0,0 +1,5 @@ +class A { + foo(a: number) : number { + return a; + } +} diff --git a/libabckit/tests/ir/graph_basic_block/graph_basic_block_static.cpp b/libabckit/tests/ir/graph_basic_block/graph_basic_block_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b5c8744a55a700272baad38f28185cb0f41a83d4 --- /dev/null +++ b/libabckit/tests/ir/graph_basic_block/graph_basic_block_static.cpp @@ -0,0 +1,197 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "helpers/helpers.h" +#include "abckit.h" +#include "logger.h" + +#include + +namespace libabckit::test { + +class LibAbcKitBasicBlocksTest : public ::testing::Test {}; + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void VerifyGraphStart(abckit_File *ctxI) +{ + // Find transformed method + abckit_Method *testMethod = helpers::findMethodByName(ctxI, "foo"); + ASSERT_NE(testMethod, nullptr); + + // Get graph + auto code = implI->MethodGetCode(testMethod); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + ASSERT_NE(startBB, nullptr); + + // Verify bb predecessors + ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 0); + + // Verify bb successors + ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1); + + // Verify instructions + auto *inst = implG->BBgetFirstInst(startBB); + + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_Parameter); + ASSERT_EQ(implG->IgetId(inst), 1); + + impl->DestroyGraphContext(ctxG); +} + +static void VerifyGraphEnd(abckit_File *ctxI) +{ + // Find transformed method + abckit_Method *testMethod = helpers::findMethodByName(ctxI, "foo"); + ASSERT_NE(testMethod, nullptr); + + // Get graph + auto code = implI->MethodGetCode(testMethod); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_BasicBlock *endBB = implG->GgetEndBasicBlock(ctxG); + ASSERT_NE(endBB, nullptr); + + // Verify bb predecessors + ASSERT_EQ(helpers::BBgetPredBlocks(endBB).size(), 1); + + // Verify bb successors + ASSERT_EQ(helpers::BBgetSuccBlocks(endBB).size(), 0); + + // Verify instructions + ASSERT_EQ(implG->BBgetFirstInst(endBB), nullptr); + + impl->DestroyGraphContext(ctxG); +} + +static void VerifyGraphVisitBlocks(abckit_File *ctxI) +{ + // Find transformed method + abckit_Method *testMethod = helpers::findMethodByName(ctxI, "foo"); + ASSERT_NE(testMethod, nullptr); + + // Get graph + auto code = implI->MethodGetCode(testMethod); + abckit_Graph *ctxG = impl->codeToGraph(ctxI, code); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::vector bbs; + + // Collect basic blocks + implG->GvisitBlocksRPO(ctxG, &bbs, [](abckit_BasicBlock *bb, void *data) { + ((std::vector *)data)->emplace_back(bb); + }); + + ASSERT_EQ(bbs.size(), 3); + + auto *startBB = bbs[0]; + + // Verify bb predecessors + ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 0); + + // Verify bb successors + ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1); + + // Verify instructions + auto *inst = implG->BBgetFirstInst(startBB); + + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_Parameter); + ASSERT_EQ(implG->IgetId(inst), 1); + + startBB = bbs[1]; + + // Verify bb predecessors + ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 1); + + // Verify bb successors + ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1); + + // Verify instructions + inst = implG->BBgetFirstInst(startBB); + + ASSERT_EQ(statG->IgetOpcode(inst), abckit_IsaApiStaticOpcode_Return); + ASSERT_EQ(implG->IgetId(inst), 2); + + startBB = bbs[2]; + ASSERT_NE(startBB, nullptr); + + // Verify bb predecessors + ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 1); + + // Verify bb successors + ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 0); + + // Verify instructions + inst = implG->BBgetFirstInst(startBB); + ASSERT_EQ(inst, nullptr); + + impl->DestroyGraphContext(ctxG); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetStartBasicBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, GgetStartBasicBlockValid) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/graph_basic_block/graph_basic_block.abc"); + LIBABCKIT_LOG(DEBUG) << "LibAbcKitTestStaticGgetStartBasicBlock: " + << ABCKIT_ABC_DIR "ir/graph_basic_block/graph_basic_block.abc" << std::endl; + + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + VerifyGraphStart(ctxI); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetEndBasicBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, GgetEndBasicBlockValid) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/graph_basic_block/graph_basic_block.abc"); + LIBABCKIT_LOG(DEBUG) << "LibAbcKitTestStaticGgetEndBasicBlock: " + << ABCKIT_ABC_DIR "ir/graph_basic_block/graph_basic_block.abc" << std::endl; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + VerifyGraphEnd(ctxI); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=GraphApiImpl::GvisitBlocksRPO, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBasicBlocksTest, GvisitBlocksRPO) +{ + abckit_File *ctxI = impl->OpenAbc(ABCKIT_ABC_DIR "ir/graph_basic_block/graph_basic_block.abc"); + LIBABCKIT_LOG(DEBUG) << "LibAbcKitTestStaticGgetEndBasicBlock: " + << ABCKIT_ABC_DIR "ir/graph_basic_block/graph_basic_block.abc" << std::endl; + + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + VerifyGraphVisitBlocks(ctxI); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_dynamic.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6fd4fa5ac484cd28f97ba6cd3fddf9e90c3b0538 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_dynamic.cpp @@ -0,0 +1,146 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + abckit_IsaApiDynamicOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_dynamic.abc", "bininst_dynamic"); + EXPECT_TRUE(helpers::Match(output, "60\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, BinaryInstToCheck, 3, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForDynBinary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_dynamic_modified.abc", "bininst_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateDynBinInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAdd2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynAdd2Valid) +{ + ValidTest(dynG->IcreateAdd2, abckit_IsaApiDynamicOpcode_add2, "12\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMul2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynMul2Valid) +{ + ValidTest(dynG->IcreateMul2, abckit_IsaApiDynamicOpcode_mul2, "20\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMod2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynMod2Valid) +{ + ValidTest(dynG->IcreateMod2, abckit_IsaApiDynamicOpcode_mod2, "0\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDiv2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynDiv2Valid) +{ + ValidTest(dynG->IcreateDiv2, abckit_IsaApiDynamicOpcode_div2, "5\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSub2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynSub2Valid) +{ + ValidTest(dynG->IcreateSub2, abckit_IsaApiDynamicOpcode_sub2, "8\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateExp, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynExpValid) +{ + ValidTest(dynG->IcreateExp, abckit_IsaApiDynamicOpcode_exp, "100\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateEq, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynEqValid) +{ + ValidTest(dynG->IcreateEq, abckit_IsaApiDynamicOpcode_eq, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNoteq, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynNoteqValid) +{ + ValidTest(dynG->IcreateNoteq, abckit_IsaApiDynamicOpcode_noteq, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLess, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynLessValid) +{ + ValidTest(dynG->IcreateLess, abckit_IsaApiDynamicOpcode_less, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLesseq, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynLesseqValid) +{ + ValidTest(dynG->IcreateLesseq, abckit_IsaApiDynamicOpcode_lesseq, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreater, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynGreaterValid) +{ + ValidTest(dynG->IcreateGreater, abckit_IsaApiDynamicOpcode_greater, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreatereq, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynGreatereqValid) +{ + ValidTest(dynG->IcreateGreatereq, abckit_IsaApiDynamicOpcode_greatereq, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStrictnoteq, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynStrictnoteqValid) +{ + ValidTest(dynG->IcreateStrictnoteq, abckit_IsaApiDynamicOpcode_strictnoteq, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStricteq, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstTest, CreateDynStricteqValid) +{ + ValidTest(dynG->IcreateStricteq, abckit_IsaApiDynamicOpcode_stricteq, "false\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_dynamic.js b/libabckit/tests/ir/icreate/arithmetic/bininst_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..11141006d589f4d03566cb4fe0609303439fbcbf --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_dynamic.js @@ -0,0 +1,51 @@ +// Before AOP: + +class A { + foo(a, b) { + return 3*a*b; + } +} + +let a = new A() +let res = a.foo(10, 2) +print(res) + +// After AOP 1: + +// class A { +// foo(a: long, b: long) : long { +// return a + b; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: long, b: long) : long { +// return a * b; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: long, b: long) : long { +// return a / b; +// } +// } + +// After AOP 4: + +// class A { +// foo(a: long, b: long) : long { +// return a % b; +// } +// } + +// After AOP 5: + +// class A { +// foo(a: long, b: long) : long { +// return a - b; +// } +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_imm_static.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_imm_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0ce76cf5830f420f3a3a825bb008ca9e19c2f15 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_imm_static.cpp @@ -0,0 +1,90 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" +#include "helpers/helpers_runtime.h" + +#include "helpers/helpers.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm), + abckit_IsaApiStaticOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_imm_static.abc", "bininst_imm_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "100\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_imm_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_imm_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrWithImmValid(ctxG, BinaryInstToCheck); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinaryWithImm(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_imm_static_modified.abc", "bininst_imm_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitBinaryInstImmTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAddI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinaryInstImmTest, CreateAddIValid) +{ + ValidTest(statG->IcreateAddI, abckit_IsaApiStaticOpcode_AddI, "15\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMulI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinaryInstImmTest, CreateMulIValid) +{ + ValidTest(statG->IcreateMulI, abckit_IsaApiStaticOpcode_MulI, "50\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateModI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinaryInstImmTest, CreateModIValid) +{ + ValidTest(statG->IcreateModI, abckit_IsaApiStaticOpcode_ModI, "0\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDivI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinaryInstImmTest, CreateDivIValid) +{ + ValidTest(statG->IcreateDivI, abckit_IsaApiStaticOpcode_DivI, "2\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSubI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinaryInstImmTest, CreateSubIValid) +{ + ValidTest(statG->IcreateSubI, abckit_IsaApiStaticOpcode_SubI, "5\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_imm_static.ets b/libabckit/tests/ir/icreate/arithmetic/bininst_imm_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..25d88fe98955621d5dbb79193856c0b765874f04 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_imm_static.ets @@ -0,0 +1,53 @@ +// Before AOP: + +class A { + foo(a: int) : int { + return a*2*5; + } +} + +function main() { + let a = new A() + let res = a.foo(10) + console.log(res) +} + +// After AOP 1: + +// class A { +// foo(a: int) : int { +// return a + 5; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: int) : int { +// return a * 5; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: int) : int { +// return a / 5; +// } +// } + +// After AOP 4: + +// class A { +// foo(a: int) : int { +// return a % 5; +// } +// } + +// After AOP 5: + +// class A { +// foo(a: int) : int { +// return a - 5; +// } +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_logical_dynamic.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b1cccdf50942bed9d6b64c311186a7d82dcfcb1c --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_dynamic.cpp @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + abckit_IsaApiDynamicOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_dynamic.abc", "bininst_logical_dynamic"); + EXPECT_TRUE(helpers::Match(output, "60\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, BinaryInstToCheck, 3, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForDynBinary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_dynamic_modified.abc", "bininst_logical_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateDynBinInstLogicalTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAnd2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstLogicalTest, CreateDynAnd2Valid) +{ + ValidTest(dynG->IcreateAnd2, abckit_IsaApiDynamicOpcode_and2, "2\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateOr2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstLogicalTest, CreateDynOr2Valid) +{ + ValidTest(dynG->IcreateOr2, abckit_IsaApiDynamicOpcode_or2, "10\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateXor2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstLogicalTest, CreateDynXor2Valid) +{ + ValidTest(dynG->IcreateXor2, abckit_IsaApiDynamicOpcode_xor2, "8\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_logical_dynamic.js b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..cec590d92aed883cd71d1bb01bd3555c10336b79 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_dynamic.js @@ -0,0 +1,35 @@ +// Before AOP: + +class A { + foo(a, b) { + return 3*a*b; + } +} + +let a = new A() +let res = a.foo(10, 2) +print(res) + +// After AOP 1: + +// class A { +// foo(a: long, b: long) : long { +// return a | b; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: long, b: long) : long { +// return a & b; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: long, b: long) : long { +// return a ^ b; +// } +// } diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_logical_imm_static.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_imm_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6732b121feb5702cbc94aef9dc8334d4ce466bd9 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_imm_static.cpp @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" +#include "helpers/helpers_runtime.h" + +#include "helpers/helpers.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm), + abckit_IsaApiStaticOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_imm_static.abc", "bininst_logical_imm_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "9\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_imm_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_imm_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrWithImmValid(ctxG, BinaryInstToCheck); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinaryWithImm(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_imm_static_modified.abc", "bininst_logical_imm_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateBinInstLogicalImmTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOrI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstLogicalImmTest, CreateOrIValid) +{ + ValidTest(statG->IcreateOrI, abckit_IsaApiStaticOpcode_OrI, "5\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXorI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstLogicalImmTest, CreateXorIValid) +{ + ValidTest(statG->IcreateXorI, abckit_IsaApiStaticOpcode_XorI, "1\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAndI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstLogicalImmTest, CreateAndIValid) +{ + ValidTest(statG->IcreateAndI, abckit_IsaApiStaticOpcode_AndI, "4\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_logical_imm_static.ets b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_imm_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..1c00f2e21540aa12a6b636a452627999b4d21a97 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_imm_static.ets @@ -0,0 +1,37 @@ +// Before AOP: + +class A { + foo(a: int) : int { + return a + 5; + } +} + +function main() { + let a = new A() + let res = a.foo(4) + console.log(res) +} + +// After AOP 1: + +// class A { +// foo(a: int) : int { +// return a & 5; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: int) : int { +// return a | 5; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: int) : int { +// return a ^ 5; +// } +// } diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_logical_static.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..44d4ceca108b4f4eb7f736a92937b53e88c664d1 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_static.cpp @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + abckit_IsaApiStaticOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_static.abc", "bininst_logical_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "60\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, BinaryInstToCheck); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_logical_static_modified.abc", "bininst_logical_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateBinInstLogicalTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAnd, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstLogicalTest, CreateAndValid) +{ + ValidTest(statG->IcreateAnd, abckit_IsaApiStaticOpcode_And, "2\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOr, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstLogicalTest, CreateOrValid) +{ + ValidTest(statG->IcreateOr, abckit_IsaApiStaticOpcode_Or, "10\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXor, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstLogicalTest, CreateXorValid) +{ + ValidTest(statG->IcreateXor, abckit_IsaApiStaticOpcode_Xor, "8\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_logical_static.ets b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b0b992e1b0ee5ca4924b9df19f8137458c11438a --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_logical_static.ets @@ -0,0 +1,37 @@ +// Before AOP: + +class A { + foo(a: long, b: long) : long { + return 3*a*b; + } +} + +function main() { + let a = new A() + let res = a.foo(10, 2) + console.log(res) +} + +// After AOP 1: + +// class A { +// foo(a: long, b: long) : long { +// return a | b; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: long, b: long) : long { +// return a & b; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: long, b: long) : long { +// return a ^ b; +// } +// } diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_dynamic.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f7549278d3af5c16bd5e635f420069680a526c6 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_dynamic.cpp @@ -0,0 +1,79 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + abckit_IsaApiDynamicOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_dynamic.abc", "bininst_shifts_dynamic"); + EXPECT_TRUE(helpers::Match(output, "60\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, BinaryInstToCheck, 3, 4); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForDynBinary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_dynamic_modified.abc", "bininst_shifts_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateDynBinInstShiftsTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShl2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstShiftsTest, CreateDynShl2Valid) +{ + ValidTest(dynG->IcreateShl2, abckit_IsaApiDynamicOpcode_shl2, "40\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAshr2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstShiftsTest, CreateDynAshr2Valid) +{ + ValidTest(dynG->IcreateAshr2, abckit_IsaApiDynamicOpcode_ashr2, "2\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShr2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynBinInstShiftsTest, CreateDynShr2Valid) +{ + ValidTest(dynG->IcreateShr2, abckit_IsaApiDynamicOpcode_shr2, "2\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_dynamic.js b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..84041763b8e03cda572a9e077afd3c163773bb21 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_dynamic.js @@ -0,0 +1,35 @@ +// Before AOP: + +class A { + foo(a, b) { + return 3*a*b; + } +} + +let a = new A() +let res = a.foo(10, 2) +print(res) + +// After AOP 1: + +// class A { +// foo(a: long, b: long) : long { +// return a >> b; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: long, b: long) : long { +// return a << b; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: long, b: long) : long { +// return a >>> b; +// } +// } diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_imm_static.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_imm_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b70dbc1c54dcaff49c0650effef432e07b1324bb --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_imm_static.cpp @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_static.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitBinInstShiftsImmTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShrI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinInstShiftsImmTest, CreateAShrIValid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_imm_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_imm_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrWithImmValid(ctxG, statG->IcreateAShrI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinaryWithImm(abckit_IsaApiStaticOpcode_AShrI)); + helpers::VerifyGraph(ctxG, bbSchemas); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShrI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinInstShiftsImmTest, CreateShrIValid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_imm_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_imm_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrWithImmValid(ctxG, statG->IcreateShrI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinaryWithImm(abckit_IsaApiStaticOpcode_ShrI)); + helpers::VerifyGraph(ctxG, bbSchemas); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShlI, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitBinInstShiftsImmTest, CreateShlIValid) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_imm_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_imm_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrWithImmValid(ctxG, statG->IcreateShlI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinaryWithImm(abckit_IsaApiStaticOpcode_ShlI)); + helpers::VerifyGraph(ctxG, bbSchemas); + }, + [](abckit_Graph *ctxG) {} + ); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_imm_static.ets b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_imm_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..c7bea0b090c74223b426e8dab2335005f842b145 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_imm_static.ets @@ -0,0 +1,31 @@ +// Before AOP: + +class A { + foo(a: int) : int { + return a*5; + } +} + +// After AOP 1: + +// class A { +// foo(a: int) : int { +// return a >> 5; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: int) : int { +// return a << 5; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: int) : int { +// return a >>> 5; +// } +// } diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_static.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac348266561f6ebfae8e9dc4b733aa8ef157f81e --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_static.cpp @@ -0,0 +1,78 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + abckit_IsaApiStaticOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_static.abc", "bininst_shifts_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "60\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, BinaryInstToCheck); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_shifts_static_modified.abc", "bininst_shifts_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateBinInstShiftsTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShl, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstShiftsTest, CreateShlValid) +{ + ValidTest(statG->IcreateShl, abckit_IsaApiStaticOpcode_Shl, "40\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShr, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstShiftsTest, CreateAShrValid) +{ + ValidTest(statG->IcreateAShr, abckit_IsaApiStaticOpcode_AShr, "2\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShr, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstShiftsTest, CreateShrValid) +{ + ValidTest(statG->IcreateShr, abckit_IsaApiStaticOpcode_Shr, "2\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_static.ets b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..956c3ef97932d26efec3d70dff09efbc81b7cba5 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_shifts_static.ets @@ -0,0 +1,37 @@ +// Before AOP: + +class A { + foo(a: long, b: long) : long { + return 3*a*b; + } +} + +function main() { + let a = new A() + let res = a.foo(10, 2) + console.log(res) +} + +// After AOP 1: + +// class A { +// foo(a: long, b: long) : long { +// return a >> b; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: long, b: long) : long { +// return a << b; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: long, b: long) : long { +// return a >>> b; +// } +// } diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_static.cpp b/libabckit/tests/ir/icreate/arithmetic/bininst_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..00cfc7312fdab3098bac5d8becfdea940d8d9724 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_static.cpp @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void ValidTest(abckit_Inst *(*BinaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + abckit_IsaApiStaticOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_static.abc", "bininst_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "60\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, BinaryInstToCheck); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForBinary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/bininst_static_modified.abc", "bininst_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitCreateBinInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAdd, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstTest, CreateAddValid) +{ + ValidTest(statG->IcreateAdd, abckit_IsaApiStaticOpcode_Add, "12\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMul, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstTest, CreateMulValid) +{ + ValidTest(statG->IcreateMul, abckit_IsaApiStaticOpcode_Mul, "20\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDiv, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstTest, CreateDivValid) +{ + ValidTest(statG->IcreateDiv, abckit_IsaApiStaticOpcode_Div, "5\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMod, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstTest, CreateModValid) +{ + ValidTest(statG->IcreateMod, abckit_IsaApiStaticOpcode_Mod, "0\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSub, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateBinInstTest, CreateSubValid) +{ + ValidTest(statG->IcreateSub, abckit_IsaApiStaticOpcode_Sub, "8\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/bininst_static.ets b/libabckit/tests/ir/icreate/arithmetic/bininst_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..576901eedd2c869ba6bb5f30301427d304337cf0 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/bininst_static.ets @@ -0,0 +1,53 @@ +// Before AOP: + +class A { + foo(a: long, b: long) : long { + return 3*a*b; + } +} + +function main() { + let a = new A() + let res = a.foo(10, 2) + console.log(res) +} + +// After AOP 1: + +// class A { +// foo(a: long, b: long) : long { +// return a + b; +// } +// } + +// After AOP 2: + +// class A { +// foo(a: long, b: long) : long { +// return a * b; +// } +// } + +// After AOP 3: + +// class A { +// foo(a: long, b: long) : long { +// return a / b; +// } +// } + +// After AOP 4: + +// class A { +// foo(a: long, b: long) : long { +// return a % b; +// } +// } + +// After AOP 5: + +// class A { +// foo(a: long, b: long) : long { +// return a - b; +// } +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/arithmetic/helpers_arithmetic.cpp b/libabckit/tests/ir/icreate/arithmetic/helpers_arithmetic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10c08d4cbf4d5844346fd071b0b65a58aaa9b1c6 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/helpers_arithmetic.cpp @@ -0,0 +1,323 @@ +/** + * Copyright (c) 2024 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 "helpers_arithmetic.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" +#include + +static auto impl = abckit_GetApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +namespace libabckit::test::helpers::arithmetic { + +void TransformIrUnaryInstValid(abckit_Graph *ctxG, abckit_Inst *(*UnaryInstToCheck) + (abckit_Graph *ctxG, abckit_Inst *input0), uint32_t operandId) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + + abckit_Inst *firstInst = nullptr; + while (curInst != nullptr) { + if (implG->IgetId(curInst) == operandId) { + firstInst = curInst; + } + curInst = implG->IgetNext(curInst); + } + + abckit_Inst *retOp = nullptr; + if (implG->GraphGetIsa(ctxG) == abckit_Isa_Type_DYNAMIC) { + retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + } else { + retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + } + ASSERT_NE(retOp, nullptr); + abckit_Inst *mainInst = UnaryInstToCheck(ctxG, firstInst); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(retOp, mainInst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static bool IsMulOrAdd(abckit_Graph *ctxG, abckit_Inst *inst) +{ + if (implG->GraphGetIsa(ctxG) == abckit_Isa_Type_DYNAMIC) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(inst); + if (curOpcode != abckit_IsaApiDynamicOpcode_mul2 && + curOpcode != abckit_IsaApiDynamicOpcode_add2) { + return true; + } + } else if (implG->GraphGetIsa(ctxG) == abckit_Isa_Type_STATIC) { + abckit_IsaApiStaticOpcode curOpcode = statG->IgetOpcode(inst); + if (curOpcode != abckit_IsaApiStaticOpcode_Mul && + curOpcode != abckit_IsaApiStaticOpcode_Add) { + return true; + } + } else { + LIBABCKIT_UNREACHABLE + } + return false; +} + +void TransformIrBinInstrValid(abckit_Graph *ctxG, abckit_Inst *(*BinaryInstToCheck) + (abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + uint32_t lhsId, uint32_t rhsId) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *firstInst = nullptr; + abckit_Inst *secondInst = nullptr; + while (curInst != nullptr) { + if (implG->IgetId(curInst) == lhsId) { + firstInst = curInst; + } + if (implG->IgetId(curInst) == rhsId) { + secondInst = curInst; + } + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + auto* bb = helpers::BBgetSuccBlocks(startBB)[0]; + curInst = implG->BBgetFirstInst(bb); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + curInst = implG->BBgetFirstInst(bb); + while (curInst != nullptr) { + if (IsMulOrAdd(ctxG, curInst)) { + curInst = implG->IgetNext(curInst); + continue; + } + auto extraInst = curInst; + curInst = implG->IgetNext(curInst); + implG->Iremove(extraInst); + } + + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + if (retOp == nullptr) { + retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + } + ASSERT_NE(retOp, nullptr); + abckit_Inst *mainInst = BinaryInstToCheck(ctxG, firstInst, secondInst); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(retOp, mainInst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void TransformIrBinInstrWithImmValid(abckit_Graph *ctxG, abckit_Inst *(*BinaryInstToCheck) + (abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm)) +{ + uint64_t imm = 0x5; + + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + + abckit_Inst *firstInst = nullptr; + abckit_Inst *secondInst = nullptr; + abckit_Inst *mainInst = nullptr; + while (curInst != nullptr) { + if (implG->IgetId(curInst) == 1) { + firstInst = curInst; + } + if (implG->IgetId(curInst) == 2) { + secondInst = curInst; + } + curInst = implG->IgetNext(curInst); + } + curInst = implG->BBgetFirstInst(startBB); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + auto *bb = succBBs[0]; + curInst = implG->BBgetFirstInst(bb); + + while (curInst != nullptr) { + if (IsMulOrAdd(ctxG, curInst)) { + curInst = implG->IgetNext(curInst); + continue; + } + auto extraInst = curInst; + curInst = implG->IgetNext(curInst); + implG->Iremove(extraInst); + } + + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + mainInst = BinaryInstToCheck(ctxG, firstInst, imm); + ASSERT_NE(ctxG, nullptr); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + implG->IsetInput(retOp, mainInst, 0); +} + +std::vector> CreateBBSchemaForBinary(abckit_IsaApiStaticOpcode opcode) +{ + std::vector> instVector {}; + if (opcode != abckit_IsaApiStaticOpcode_Mod && opcode != abckit_IsaApiStaticOpcode_Div) { + instVector = { + {4, opcode, {1, 2}}, + {5, abckit_IsaApiStaticOpcode_Return, {4}}, + }; + } else { + instVector = { + {6, opcode, {1, 2}}, + {7, abckit_IsaApiStaticOpcode_Return, {6}}, + }; + } + return { + { + {}, {1}, { + {1, abckit_IsaApiStaticOpcode_Parameter, {}}, + {2, abckit_IsaApiStaticOpcode_Parameter, {}} + } + }, + { + {0}, {2}, instVector + }, + { + {1}, {}, {} + } + }; +} + +std::vector> CreateBBSchemaForDynBinary(abckit_IsaApiDynamicOpcode opcode) +{ + std::vector> instVector {}; + std::vector> paramInstVector {}; + // if (opcode != abckit_Opcode_Mod && opcode != abckit_Opcode_Div) { + instVector = { + {6, opcode, {3, 4}}, + {7, abckit_IsaApiDynamicOpcode_return, {6}}, + }; + paramInstVector = { + {3, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {4, abckit_IsaApiDynamicOpcode_Parameter, {}} + }; + // } else { + // instVector = { + // {7, opcode, {1, 5}}, + // {8, abckit_DynOpcode_return, {7}}, + // }; + // paramInstVector = { + // {1, abckit_Opcode_Parameter, {}}, + // {5, abckit_Opcode_Constant, {}} + // }; + // } + return { + { + {}, {1}, paramInstVector + }, + { + {0}, {2}, instVector + }, + { + {1}, {}, {} + } + }; +} + +std::vector> CreateBBSchemaForBinaryWithImm(abckit_IsaApiStaticOpcode opcode) +{ + std::vector> instVector {}; + std::vector> startInstVector {}; + if (opcode != abckit_IsaApiStaticOpcode_AddI && opcode != abckit_IsaApiStaticOpcode_SubI && opcode != abckit_IsaApiStaticOpcode_MulI + && opcode != abckit_IsaApiStaticOpcode_DivI && opcode != abckit_IsaApiStaticOpcode_ModI) { + startInstVector = { + {1, abckit_IsaApiStaticOpcode_Parameter, {}}, + {2, abckit_IsaApiStaticOpcode_Constant, {}} + }; + } else { + startInstVector = { + {1, abckit_IsaApiStaticOpcode_Parameter, {}}, + {2, abckit_IsaApiStaticOpcode_Constant, {}}, + {3, abckit_IsaApiStaticOpcode_Constant, {}} + }; + } + if (opcode != abckit_IsaApiStaticOpcode_ModI && opcode != abckit_IsaApiStaticOpcode_DivI) { + instVector = { + {4, opcode, {1}}, + {5, abckit_IsaApiStaticOpcode_Return, {4}}, + }; + } else { + instVector = { + {5, opcode, {1}}, + {4, abckit_IsaApiStaticOpcode_Return, {5}}, + }; + } + return { + { + {}, {1}, startInstVector + }, + { + {0}, {2}, instVector + }, + { + {1}, {}, {} + } + }; +} + +std::vector> CreateBBSchemaForUnary(abckit_IsaApiStaticOpcode opcode) +{ + return { + { + {}, {1}, { + {1, abckit_IsaApiStaticOpcode_Parameter, {}} + } + }, + { + {0}, {2}, { + {3, opcode, {1}}, + {4, abckit_IsaApiStaticOpcode_Return, {3}}, + } + }, + { + {1}, {}, {} + } + }; +} + +std::vector> CreateBBSchemaForDynUnary(abckit_IsaApiDynamicOpcode opcode) +{ + return { + { + {}, {1}, { + {3, abckit_IsaApiDynamicOpcode_Parameter, {}} + } + }, + { + {0}, {2}, { + {5, opcode, {3}}, + {6, abckit_IsaApiDynamicOpcode_return, {5}}, + } + }, + { + {1}, {}, {} + } + }; +} + +} // namespace libabckit::test::helpers::arithmetics diff --git a/libabckit/tests/ir/icreate/arithmetic/helpers_arithmetic.h b/libabckit/tests/ir/icreate/arithmetic/helpers_arithmetic.h new file mode 100644 index 0000000000000000000000000000000000000000..0c03f6226b4b7bbec96b8496d6dbb9c987158517 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/helpers_arithmetic.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2024 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. + */ + +#ifndef LIBABCKIT_TESTS_IR_CREATE_INSTR_HELPER_ARITHMETIC_H +#define LIBABCKIT_TESTS_IR_CREATE_INSTR_HELPER_ARITHMETIC_H + +#include "helpers/helpers.h" + +namespace libabckit::test::helpers::arithmetic { + +void TransformIrBinInstrValid(abckit_Graph *ctxG, abckit_Inst *(*BinaryInstToCheck) + (abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1), + uint32_t lhsId = 1, uint32_t rhsId = 2); +void TransformIrBinInstrWithImmValid(abckit_Graph *ctxG, abckit_Inst *(*BinaryInstToCheck) + (abckit_Graph *ctxG, abckit_Inst *input0, uint64_t imm)); +void TransformIrUnaryInstValid(abckit_Graph *ctxG, abckit_Inst *(*UnaryInstToCheck) + (abckit_Graph *ctxG, abckit_Inst *input0), uint32_t operandId = 1); +std::vector> CreateBBSchemaForBinary(abckit_IsaApiStaticOpcode opcode); +std::vector> CreateBBSchemaForDynBinary(abckit_IsaApiDynamicOpcode opcode); +std::vector> CreateBBSchemaForBinaryWithImm(abckit_IsaApiStaticOpcode opcode); +std::vector> CreateBBSchemaForUnary(abckit_IsaApiStaticOpcode opcode); +std::vector> CreateBBSchemaForDynUnary(abckit_IsaApiDynamicOpcode opcode); + +} // namespace libabckit::test::helpers::arithmetics + +#endif //LIBABCKIT_TESTS_IR_CREATE_INSTR_HELPER_ARITHMETIC_H \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/arithmetic/unaryinst_dynamic.cpp b/libabckit/tests/ir/icreate/arithmetic/unaryinst_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ed55e32f5f8497dd3f838575b47bb89ae87b978 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/unaryinst_dynamic.cpp @@ -0,0 +1,127 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void ValidTest(abckit_Inst *(*UnaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0), + abckit_IsaApiDynamicOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_dynamic.abc", "unaryinst_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrUnaryInstValid(ctxG, UnaryInstToCheck, 3); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForDynUnary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_dynamic_modified.abc", "unaryinst_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitDynUnaryInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNot, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynNotValid) +{ + ValidTest(dynG->IcreateNot, abckit_IsaApiDynamicOpcode_not, "-11\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNeg, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynNegValid) +{ + ValidTest(dynG->IcreateNeg, abckit_IsaApiDynamicOpcode_neg, "-10\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInc, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynIncValid) +{ + ValidTest(dynG->IcreateInc, abckit_IsaApiDynamicOpcode_inc, "11\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDec, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynDecValid) +{ + ValidTest(dynG->IcreateDec, abckit_IsaApiDynamicOpcode_dec, "9\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIstrue, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynIstrueValid) +{ + ValidTest(dynG->IcreateIstrue, abckit_IsaApiDynamicOpcode_istrue, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIstrue, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynCallruntimeIstrueValid) +{ + ValidTest(dynG->IcreateCallruntimeIstrue, abckit_IsaApiDynamicOpcode_callruntime_istrue, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsfalse, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynIsfalseValid) +{ + ValidTest(dynG->IcreateIsfalse, abckit_IsaApiDynamicOpcode_isfalse, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIsfalse, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynCallruntimeIsfalseValid) +{ + ValidTest(dynG->IcreateCallruntimeIsfalse, abckit_IsaApiDynamicOpcode_callruntime_isfalse, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumber, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynTonumberValid) +{ + ValidTest(dynG->IcreateTonumber, abckit_IsaApiDynamicOpcode_tonumber, "10\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumeric, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynTonumericValid) +{ + ValidTest(dynG->IcreateTonumeric, abckit_IsaApiDynamicOpcode_tonumber, "10\n"); // TODO: why IcreateDynTonumeric has "tonumber" opcode +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTypeof, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynUnaryInstTest, CreateDynTypeofValid) +{ + ValidTest(dynG->IcreateTypeof, abckit_IsaApiDynamicOpcode_typeof, "number\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/unaryinst_dynamic.js b/libabckit/tests/ir/icreate/arithmetic/unaryinst_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..56a4e36a2d1132ef334c13186ab696dd8b3f4e98 --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/unaryinst_dynamic.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024 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. + */ + +class A { + foo(a) { + return a; + } +} + +let a = new A() +let res = a.foo(10) +print(res) diff --git a/libabckit/tests/ir/icreate/arithmetic/unaryinst_static.cpp b/libabckit/tests/ir/icreate/arithmetic/unaryinst_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..972c2324168759b558ff3615c169211fe9b66ffa --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/unaryinst_static.cpp @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +static void ValidTest(abckit_Inst *(*UnaryInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0), + abckit_IsaApiStaticOpcode expectedOpcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_static.abc", "unaryinst_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_static.abc", + ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrUnaryInstValid(ctxG, UnaryInstToCheck); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(helpers::arithmetic::CreateBBSchemaForUnary(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arithmetic/unaryinst_static_modified.abc", "unaryinst_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +class LibAbcKitUnaryInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNeg, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitUnaryInstTest, CreateNegValid) +{ + ValidTest(statG->IcreateNeg, abckit_IsaApiStaticOpcode_Neg, "-10\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNot, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitUnaryInstTest, CreateNotValid) +{ + ValidTest(statG->IcreateNot, abckit_IsaApiStaticOpcode_Not, "-11\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/arithmetic/unaryinst_static.ets b/libabckit/tests/ir/icreate/arithmetic/unaryinst_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..230fec6659520c44bd49c9393b9ea411dfba2dfc --- /dev/null +++ b/libabckit/tests/ir/icreate/arithmetic/unaryinst_static.ets @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2024 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. + */ + +class A { + foo(a: long) : long { + return a; + } +} + +function main() { + let a = new A() + let res = a.foo(10) + console.log(res) +} diff --git a/libabckit/tests/ir/icreate/arrays/arrays_static.cpp b/libabckit/tests/ir/icreate/arrays/arrays_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d089899a74a7472b3520cc6b69e431fcc8e1f182 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/arrays_static.cpp @@ -0,0 +1,368 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" +#include "libabckit/src/logger.h" +#include + + +// libabckit::logger *libabckit::logger::logger_ = nullptr; + +namespace libabckit { +namespace test { + +namespace { + + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + static auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformStoreArrayByIdx(abckit_Graph *ctxG, enum abckit_Status expected_status, + abckit_Inst *idx, abckit_Inst* new_value, enum abckit_TypeId value_type_id, + abckit_Inst* (*IcreateStoreArray)(abckit_Graph*, abckit_Inst*, abckit_Inst*, + abckit_Inst*, enum abckit_TypeId)) { + + abckit_Inst *arr = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_NewArray); + ASSERT_NE(arr, nullptr); + + abckit_Inst *store = IcreateStoreArray(ctxG, arr, idx, new_value, value_type_id); + + if (expected_status != abckit_Status_NO_ERROR && impl->GetLastError() == expected_status) + return; + + ASSERT_NE(store, nullptr); + + abckit_Inst *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + + implG->IinsertBefore(store, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} // namespace + +class LibAbcKitArrayStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArrayWide, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestStoreArrayWide) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_wide.abc", "store_array_wide/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_wide.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_wide_modified.abc", + "store_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_TypeId value_type_id = abckit_TypeId::abckit_TypeId_F64; + + abckit_Inst *new_value = implG->GcreateConstantF64(ctxG, 4); + ASSERT_NE(new_value, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *idx = implG->GcreateConstantI64(ctxG, 2); + ASSERT_NE(idx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + TransformStoreArrayByIdx(ctxG, abckit_Status_NO_ERROR, + idx, new_value, value_type_id, statG->IcreateStoreArrayWide); + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_wide_modified.abc", "store_array_wide/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "4\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArrayWide, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestStoreArrayWideNeg) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/store_array.abc", "store_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_modified_neg.abc", + "store_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_TypeId value_type_id = abckit_TypeId::abckit_TypeId_F64; + + abckit_Inst *new_value = implG->GcreateConstantF64(ctxG, 4); + ASSERT_NE(new_value, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *idx = implG->GcreateConstantF64(ctxG, 2); // idx's type should be I64 or I32 + ASSERT_NE(idx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + TransformStoreArrayByIdx(ctxG, abckit_Status_BAD_ARGUMENT, + idx, new_value, value_type_id, statG->IcreateStoreArrayWide); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArray, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestStoreArray) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/store_array.abc", "store_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_modified.abc", + "store_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_TypeId value_type_id = abckit_TypeId::abckit_TypeId_I32; + + abckit_Inst *new_value = implG->GcreateConstantI32(ctxG, 4); + ASSERT_NE(new_value, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *idx = implG->GcreateConstantI32(ctxG, 2); + ASSERT_NE(idx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + TransformStoreArrayByIdx(ctxG, abckit_Status_NO_ERROR, + idx, new_value, value_type_id, statG->IcreateStoreArray); + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_modified.abc", "store_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "4\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArray, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestStoreArrayNeg) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/store_array.abc", "store_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/store_array_modified_neg.abc", + "store_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_TypeId value_type_id = abckit_TypeId::abckit_TypeId_I32; + + abckit_Inst *new_value = implG->GcreateConstantI32(ctxG, 4); + ASSERT_NE(new_value, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *idx = implG->GcreateConstantI64(ctxG, 2); // idx's type should be I32 + ASSERT_NE(idx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + TransformStoreArrayByIdx(ctxG, abckit_Status_BAD_ARGUMENT, + idx, new_value, value_type_id, statG->IcreateStoreArray); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadArray, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestLoadArray) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/load_array.abc", "load_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/load_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/load_array_modified.abc", + "get_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_TypeId return_type_id = abckit_TypeId::abckit_TypeId_F64; + + abckit_Inst *arr = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_NewArray); + ASSERT_NE(arr, nullptr); + + abckit_Inst *idx = implG->GcreateConstantI64(ctxG, 1); + ASSERT_NE(idx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *ld = statG->IcreateLoadArray(ctxG, arr, idx, return_type_id); + ASSERT_NE(ld, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + + implG->IinsertBefore(ld, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(ret, ld, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/load_array_modified.abc", "load_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "2\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadArray, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestLoadArrayNeg) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/load_array.abc", "load_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/load_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/load_array_modified_neg.abc", + "get_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_TypeId return_type_id = abckit_TypeId::abckit_TypeId_F64; + + abckit_Inst *fake_arr = implG->GcreateConstantI64(ctxG, 1); + ASSERT_NE(fake_arr, nullptr); + + abckit_Inst *idx = implG->GcreateConstantI64(ctxG, 1); + ASSERT_NE(idx, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + [[maybe_unused]] abckit_Inst *ld = statG->IcreateLoadArray(ctxG, fake_arr, idx, return_type_id); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLenArray, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestLenArray) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/len_array.abc", "len_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/len_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/len_array_modified.abc", + "get_len", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_Inst *arr = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_NewArray); + ASSERT_NE(arr, nullptr); + + abckit_Inst *len = statG->IcreateLenArray(ctxG, arr); + ASSERT_NE(len, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + + implG->IinsertBefore(len, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(ret, len, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/len_array_modified.abc", "len_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "4\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLenArray, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestLenArrayNeg) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/len_array.abc", "len_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/len_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/len_array_modified_neg.abc", + "get_len", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + abckit_Inst *fake_arr = implG->GcreateConstantI64(ctxG, 1); + ASSERT_NE(fake_arr, nullptr); + + [[maybe_unused]] abckit_Inst *len = statG->IcreateLenArray(ctxG, fake_arr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewArray, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitArrayStaticTest, DISABLED_LibAbcKitTestNewArray) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/new_array.abc", "new_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "0\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/new_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/new_array_modified.abc", + "get_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + // TODO: implemement + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/new_array_modified.abc", "new_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadConstArray, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitArrayStaticTest, LibAbcKitTestLoadConstArray) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/load_const_array.abc", "load_const_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/load_const_array.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/load_const_array_modified.abc", + "get_element", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto arr = std::vector({ + implM->CreateLiteralU32(ctxM, 4), + implM->CreateLiteralU32(ctxM, 2), + implM->CreateLiteralU32(ctxM, 3), + }); + auto litArray = implM->CreateLiteralArray(ctxM, arr.data(), arr.size()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *loadConstArray = statG->IcreateLoadConstArray(ctxG, litArray); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(loadConstArray, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(ret, loadConstArray, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ReplaceInst(ret, statG->IcreateReturn(ctxG, loadConstArray)); + + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/load_const_array_modified.abc", "load_const_array/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "4\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/arrays/create_array_dynamic.cpp b/libabckit/tests/ir/icreate/arrays/create_array_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e467596f4c7042c68175c87c61a8f2dbd32eaaba --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/create_array_dynamic.cpp @@ -0,0 +1,80 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "statuses.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitIcreateArrayTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreatearraywithbuffer, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIcreateArrayTest, IcreateDynCreatearraywithbuffer_1) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/create_array_dynamic.abc", "create_array_dynamic"); + EXPECT_TRUE(helpers::Match(output, "aa,10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/arrays/create_array_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/arrays/create_array_dynamic_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + // FIXME(mredkin): Remove CreateLiteralU8, CreateLiteralU16, CreateLiteralU64, CreateLiteralFloat API + auto arr = std::vector({ + implM->CreateLiteralBool(ctxM, true), + // implM->CreateLiteralU8(ctxM, (uint8_t)((uint8_t)2 << 5) + 1), + // implM->CreateLiteralU16(ctxM, (uint16_t)((uint16_t)2 << 14) + 1), + implM->CreateLiteralU32(ctxM, (uint32_t)((uint32_t)2 << 30) + 1), + // implM->CreateLiteralU64(ctxM, (uint64_t)((uint64_t)2 << 62) + 1), + // implM->CreateLiteralFloat(ctxM, 3.21), + implM->CreateLiteralDouble(ctxM, 3.22), + implM->CreateLiteralString(ctxM, "asdf"), + }); + auto lit_arr = implM->CreateLiteralArray(ctxM, arr.data(), arr.size()); + + auto* inst = dynG->IcreateCreatearraywithbuffer(ctxG, lit_arr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(inst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(ret, nullptr); + implG->IinsertBefore(inst, ret); + implG->IsetInput(ret, inst, 0); + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/arrays/create_array_dynamic_modified.abc", "create_array_dynamic"); + EXPECT_TRUE(helpers::Match(output, "true,2147483649,3.22,asdf\n")); +} + +} +} diff --git a/libabckit/tests/ir/icreate/arrays/create_array_dynamic.js b/libabckit/tests/ir/icreate/arrays/create_array_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..2220b2828b4ddaf930198066e6c11530caa054c5 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/create_array_dynamic.js @@ -0,0 +1,8 @@ +class Test { + test() { + return ['aa', 10] + } +} + +let a = new Test() +print(a.test()) diff --git a/libabckit/tests/ir/icreate/arrays/len_array.ets b/libabckit/tests/ir/icreate/arrays/len_array.ets new file mode 100644 index 0000000000000000000000000000000000000000..919b3e125df09934c9a8ec15efb83380502d7e8b --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/len_array.ets @@ -0,0 +1,26 @@ +// Before AOP: + +function get_len() { + let a = [1, 2, 3, 4]; + let l:int = 1; + return l; +} + +function main() { + let len = get_len(); + console.log(len); +} + +// After AOP: + +// function get_len() { +// let a = [1, 2, 3, 4]; +// let l:int = 1; +// l = a.length +// return l; +// } + +// function main() { +// let len = get_len(); +// console.log(len); +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/arrays/load_array.ets b/libabckit/tests/ir/icreate/arrays/load_array.ets new file mode 100644 index 0000000000000000000000000000000000000000..d6cd37ddb610c1ba03077e0a919dee71b8397052 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/load_array.ets @@ -0,0 +1,23 @@ +// Before AOP: + +function get_element() { + let a = [1, 2, 3]; + return a[0]; +} + +function main() { + let elem = get_element(); + console.log(elem); +} + +// After AOP: + +// function get_element() { +// let a = [1, 2, 3]; +// return a[1]; +// } + +// function main() { +// let elem = get_element(); +// console.log(elem); +// } diff --git a/libabckit/tests/ir/icreate/arrays/load_const_array.ets b/libabckit/tests/ir/icreate/arrays/load_const_array.ets new file mode 100644 index 0000000000000000000000000000000000000000..c89f497bd55de5ba46a3f3858d6b49fce86116c9 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/load_const_array.ets @@ -0,0 +1,7 @@ +function get_element(): int[] { + return [1 as int, 0 as int]; +} + +function main() { + console.log(get_element()[0]); +} diff --git a/libabckit/tests/ir/icreate/arrays/new_array.ets b/libabckit/tests/ir/icreate/arrays/new_array.ets new file mode 100644 index 0000000000000000000000000000000000000000..e84d65bdcee99e5094af34011767aa9dcd2c8bd7 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/new_array.ets @@ -0,0 +1,22 @@ +// Before AOP: + +function get_element() { + return 0; +} + +function main() { + let elem : int = get_element(); + console.log(elem); +} + +// After AOP: + +// function get_element() { +// let a : int[] = [1, 2, 3]; +// return a[0]; +// } + +// function main() { +// let elem : int = get_element(); +// console.log(elem); +// } diff --git a/libabckit/tests/ir/icreate/arrays/store_array.ets b/libabckit/tests/ir/icreate/arrays/store_array.ets new file mode 100644 index 0000000000000000000000000000000000000000..ff93e303ef44f3fa713a4bb5cd9fc6bee6a29374 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/store_array.ets @@ -0,0 +1,24 @@ +// Before AOP: + +function store_element() { + let a:int[] = [1, 2, 3]; + return a; +} + +function main(){ + let ret = store_element(); + console.log(ret[2]); +} + +// After AOP: + +// function store_element() { +// let a:int = [1, 2, 3]; +// a[2] = 4; +// return a; +// } +// +// function main(){ +// let ret = store_element(); +// console.log(ret[2]); +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/arrays/store_array_wide.ets b/libabckit/tests/ir/icreate/arrays/store_array_wide.ets new file mode 100644 index 0000000000000000000000000000000000000000..055804347880f338d29de68ca9f2157290bbf434 --- /dev/null +++ b/libabckit/tests/ir/icreate/arrays/store_array_wide.ets @@ -0,0 +1,24 @@ +// Before AOP: + +function store_element() { + let a = [1, 2, 3]; + return a; +} + +function main(){ + let ret = store_element(); + console.log(ret[2]); +} + +// After AOP: + +// function store_element() { +// let a = [1, 2, 3]; +// a[2] = 4; +// return a; +// } +// +// function main(){ +// let ret = store_element(); +// console.log(ret[2]); +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/call/virtual/call_virtual_static.cpp b/libabckit/tests/ir/icreate/call/virtual/call_virtual_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c58fc43a1113316ee224645c1f7dec120f8b9422 --- /dev/null +++ b/libabckit/tests/ir/icreate/call/virtual/call_virtual_static.cpp @@ -0,0 +1,103 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformCallVirtualIr(abckit_Graph *ctxG, abckit_ModifyContext *ctxM, abckit_Class *classA) + { + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_ReturnVoid); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *initObj = implG->IgetPrev(ret); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::MethodByNameContext methodCtxFinder = {nullptr, "foo"}; + implI->ClassEnumerateMethods(classA, &methodCtxFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + + auto *call = statG->IcreateCallVirtual(ctxG, initObj, methodCtxFinder.method, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(call, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + +} // namespace + +class LibAbcKitCallVirtualStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallVirtual, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCallVirtualStaticTest, LibAbcKitTestCallVirtual) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/call/virtual/call_virtual_static.abc", "call_virtual_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/call/virtual/call_virtual_static.abc", + ABCKIT_ABC_DIR "ir/icreate/call/virtual/call_virtual_static_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *module = implI->MethodGetModule(method); + helpers::ClassByNameContext classCtxFinder = {nullptr, "A"}; + implI->ModuleEnumerateClasses(module, &classCtxFinder, helpers::classByNameFinder); + ASSERT_NE(classCtxFinder.klass, nullptr); + TransformCallVirtualIr(ctxG, ctxM, classCtxFinder.klass); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {} + } + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {2, abckit_IsaApiStaticOpcode_CallVirtual, {0}}, + {1, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/call/virtual/call_virtual_static_modified.abc", "call_virtual_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"foo\"\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/call/virtual/call_virtual_static.ets b/libabckit/tests/ir/icreate/call/virtual/call_virtual_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..2a8106c48c32368118fb07c7a5eff4a1bc4d2861 --- /dev/null +++ b/libabckit/tests/ir/icreate/call/virtual/call_virtual_static.ets @@ -0,0 +1,26 @@ +// Before AOP: + +class A { + foo() { + console.log("foo") + } +} +class B extends A {} + +function main() { + let b = new B(); +} + +// After AOP: +// +// class A { +// foo() { +// console.log("foo") +// } +// } +// class B extends A {} +// +// function main() { +// let b = new B(); +// b.foo() +// } diff --git a/libabckit/tests/ir/icreate/cast/cast_static.cpp b/libabckit/tests/ir/icreate/cast/cast_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19fb82e9c6436cc508025efe1893a4d0f101f756 --- /dev/null +++ b/libabckit/tests/ir/icreate/cast/cast_static.cpp @@ -0,0 +1,143 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformIr(abckit_Graph *ctxG, abckit_Method *ConsoleLogInt) + { + abckit_Inst *callInst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + abckit_Inst *castToInt = statG->IcreateCast(ctxG, implG->IgetInput(callInst, 0), abckit_TypeId::abckit_TypeId_I32); + implG->IinsertAfter(castToInt, callInst); + abckit_Inst *callLogInt = statG->IcreateCallStatic(ctxG, ConsoleLogInt, 1, castToInt); + implG->IinsertAfter(callLogInt, castToInt); + } + + void TransformCheckCastIr(abckit_Graph *ctxG, abckit_ModifyContext *ctxM, abckit_Class *classA) + { + abckit_Inst *initObj = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_InitObject); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *type = implM->CreateReferenceType(ctxM, classA); + ASSERT_NE(type, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *checkCast = statG->IcreateCheckCast(ctxG, initObj, type); + ASSERT_NE(checkCast, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(checkCast, initObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + } +} // namespace + +class LibAbcKitCastStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCast, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestCreateCast) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cast/cast_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cast/cast_static_modified.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Method *ConsoleLogInt = helpers::findMethodByName(implI->MethodGetInspectContext(method), "ConsoleLogInt"); + TransformIr(ctxG, ConsoleLogInt); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {2, abckit_IsaApiStaticOpcode_Constant, {}}, + } + }, + { + {0}, {2}, { + {4, abckit_IsaApiStaticOpcode_CallStatic, {2}}, + {6, abckit_IsaApiStaticOpcode_Cast, {2}}, + {8, abckit_IsaApiStaticOpcode_CallStatic, {6}}, + {10, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCheckCast, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestCheckCast) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cast/checkcast_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cast/checkcast_static_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *module = implI->MethodGetModule(method); + helpers::ClassByNameContext classCtxFinder = {nullptr, "A"}; + implI->ModuleEnumerateClasses(module, &classCtxFinder, helpers::classByNameFinder); + ASSERT_NE(classCtxFinder.klass, nullptr); + TransformCheckCastIr(ctxG, ctxM, classCtxFinder.klass); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {} + } + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {2, abckit_IsaApiStaticOpcode_CheckCast, {0}}, + {1, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cast/checkcast_static_modified.abc", "checkcast_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/cast/cast_static.ets b/libabckit/tests/ir/icreate/cast/cast_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..a94e1d20ebd681c188944ae9e495cd87c47e9c5c --- /dev/null +++ b/libabckit/tests/ir/icreate/cast/cast_static.ets @@ -0,0 +1,44 @@ +// Before AOP: + +function ConsoleLogDouble(a: double) { + console.log(a) +} + +function ConsoleLogInt(a: int) { + console.log(a) +} + +class MyClass { + handle() { + let a: double = 3.14 + ConsoleLogDouble(a) + } +} + +function main() { + let c = new MyClass(); + c.handle(); +} + +// // After AOP: + +// function ConsoleLogDouble(a: double) { +// console.log(a) +// } + +// function ConsoleLogInt(a: int) { +// console.log(a) +// } + +// class MyClass { +// handle() { +// let a: double = 3.14 +// ConsoleLogDouble(a) +// ConsoleLogInt(a as int); +// } +// } + +// function main() { +// let c = new MyClass(); +// c.handle(); +// } diff --git a/libabckit/tests/ir/icreate/cast/checkcast_static.ets b/libabckit/tests/ir/icreate/cast/checkcast_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..692326fa33376bf6794b8cf8b0439f6879ed7cff --- /dev/null +++ b/libabckit/tests/ir/icreate/cast/checkcast_static.ets @@ -0,0 +1,20 @@ +// Before AOP: + +class A {} +class B extends A {} + +function main() { + let a = new B(); + return; +} + +// After AOP: +// +// class A {} +// class B extends A {} +// +// function main() { +// let a = new B(); +// ; +// return; +// } diff --git a/libabckit/tests/ir/icreate/catchphi/catchphi_dynamic.cpp b/libabckit/tests/ir/icreate/catchphi/catchphi_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a91b4bb04ea36f94576d96f02064a498754f436 --- /dev/null +++ b/libabckit/tests/ir/icreate/catchphi/catchphi_dynamic.cpp @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2024 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 "isa/isa_dynamic.h" +#include "metadata.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +class LibAbcKitDynamicCatchPhiTest : public ::testing::Test {}; + +namespace { + auto *impl = abckit_GetApiImpl(1); + auto *implI = abckit_GetInspectApiImpl(1); + auto *implM = abckit_GetModifyApiImpl(1); + auto *implG = abckit_GetGraphApiImpl(1); + auto *dynG = abckit_GetIsaApiDynamicImpl(1); + + enum class tryCatchScenario { + defaultPositive = 0, + }; + + [[maybe_unused]] std::vector> CreateBBSchema(tryCatchScenario scenario) + { + helpers::BBSchema bb0 + { + {}, {1}, {} + }; + + helpers::BBSchema bb2{{1}, {}, {}}; + + switch (scenario) { + case tryCatchScenario::defaultPositive: + return { + bb0, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {8, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + default: + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + } +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCatchPhi, abc-kind=TS, category=positive +TEST_F(LibAbcKitDynamicCatchPhiTest, CatchPhiDynamicValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_dynamic.abc", "catchphi_dynamic"); + EXPECT_TRUE(helpers::Match(output, "CATCH\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_dynamic_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *print = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_callarg1); + auto *catchPhi = dynG->IcreateCatchPhi(ctxG, 0); + implG->BBaddInstFront(implG->IgetBasicBlock(print), catchPhi); + implG->IsetInput(print, catchPhi, 0); + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_dynamic_modified.abc", "catchphi_dynamic"); + EXPECT_TRUE(helpers::Match(output, "Error: abckit_error\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/catchphi/catchphi_dynamic.ts b/libabckit/tests/ir/icreate/catchphi/catchphi_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..0ca1024137c2599461a31e671f0bf7134efbd2da --- /dev/null +++ b/libabckit/tests/ir/icreate/catchphi/catchphi_dynamic.ts @@ -0,0 +1,11 @@ + + +function main() { + try { + throw new Error("abckit_error") + } catch (e) { + print("CATCH") + } +} + +main() diff --git a/libabckit/tests/ir/icreate/catchphi/catchphi_static.cpp b/libabckit/tests/ir/icreate/catchphi/catchphi_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9f5c6f28f1292c3493ac00fd153255fc5c126171 --- /dev/null +++ b/libabckit/tests/ir/icreate/catchphi/catchphi_static.cpp @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2024 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 "isa/isa_static.h" +#include "metadata.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +class LibAbcKitStaticCatchPhiTest : public ::testing::Test {}; + +namespace { + auto *impl = abckit_GetApiImpl(1); + auto *implI = abckit_GetInspectApiImpl(1); + auto *implM = abckit_GetModifyApiImpl(1); + auto *implG = abckit_GetGraphApiImpl(1); + auto *statG = abckit_GetIsaApiStaticImpl(1); + + enum class tryCatchScenario { + defaultPositive = 0, + }; +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCatchPhi, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitStaticCatchPhiTest, CatchPhiStaticValid) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_static.abc", + "catchphi_static/ETSGLOBAL", + "main"); + EXPECT_TRUE(helpers::Match(output, "\"CATCH\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_static.abc", + ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *oldCall = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + EXPECT_NE(oldCall, nullptr); + auto *log = helpers::findMethodByName(implI->MethodGetInspectContext(method), "LogError"); + auto *catchPhi = statG->IcreateCatchPhi(ctxG, 0); + implG->BBaddInstFront(implG->IgetBasicBlock(oldCall), catchPhi); + auto *newCall = statG->IcreateCallStatic(ctxG, log, 1, catchPhi); + implG->IinsertBefore(newCall, oldCall); + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/catchphi/catchphi_static_modified.abc", + "catchphi_static/ETSGLOBAL", + "main"); + EXPECT_TRUE(helpers::Match(output, "Error: abckit_error\n\"CATCH\"\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/catchphi/catchphi_static.ets b/libabckit/tests/ir/icreate/catchphi/catchphi_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..c7524c200b2d001c04e4e0c6d11147f8ad19718e --- /dev/null +++ b/libabckit/tests/ir/icreate/catchphi/catchphi_static.ets @@ -0,0 +1,16 @@ +function LogError(e: Error) { + console.log(e) +} + +function foo() { + try { + throw new Error("abckit_error") + } catch (e) { + console.log("CATCH") + } +} + +function main() { + foo(); +} + diff --git a/libabckit/tests/ir/icreate/cmp/create_cmp_static.cpp b/libabckit/tests/ir/icreate/cmp/create_cmp_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f05c2c56c122b8d60fe62fd251cdc14eb8cb498 --- /dev/null +++ b/libabckit/tests/ir/icreate/cmp/create_cmp_static.cpp @@ -0,0 +1,243 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "isa/isa_static.h" +#include "metadata.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "statuses.h" +#include "statuses_impl.h" + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformIrIcreateCmp(abckit_Graph *ctxG, abckit_Inst *firstConst, abckit_Inst *secondConst) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *firstBB = succBBs[0]; + abckit_Inst *cmp = statG->IcreateCmp(ctxG, firstConst, secondConst); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + implG->BBaddInstFront(firstBB, cmp); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *ret = implG->BBgetLastInst(firstBB); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + implG->IsetInput(ret, cmp, 0); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + } +} // namespace + +class LibAbcKitCreateCmpDynamicTest : public ::testing::Test {}; + +template +static std::vector> GetSchema() { + size_t firstConstIdx = 1; + size_t secondConstIdx = 2; + size_t cmpIdx = 3; + size_t retIdx = 4; + if constexpr (isEqTest) { + secondConstIdx = firstConstIdx; + cmpIdx--; + retIdx--; + } + std::vector> constInsts = {{firstConstIdx, abckit_IsaApiStaticOpcode_Constant, {}}}; + if constexpr (!isEqTest) { + constInsts.push_back({secondConstIdx, abckit_IsaApiStaticOpcode_Constant, {}}); + } + return { + { + {}, {1}, { + constInsts + } + }, + { + {0}, {2}, { + {cmpIdx, abckit_IsaApiStaticOpcode_Cmp, {firstConstIdx, secondConstIdx}}, + {retIdx, abckit_IsaApiStaticOpcode_Return, {cmpIdx}}, + } + }, + { + {1}, {}, {} + } + }; +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpI1) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantI64(ctxG, 10); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *secondConst = implG->GcreateConstantI64(ctxG, 7); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + TransformIrIcreateCmp(ctxG, firstConst, secondConst); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", "create_cmp_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpI2) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantI64(ctxG, 0); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *secondConst = implG->GcreateConstantI64(ctxG, 24); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + TransformIrIcreateCmp(ctxG, firstConst, secondConst); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", "create_cmp_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "-1\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpI3) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantI64(ctxG, 7); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + TransformIrIcreateCmp(ctxG, firstConst, firstConst); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", "create_cmp_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpD1) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantF64(ctxG, 12.4); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *secondConst = implG->GcreateConstantF64(ctxG, 4.5); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + TransformIrIcreateCmp(ctxG, firstConst, secondConst); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", "create_cmp_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpD2) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantF64(ctxG, 4.3); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *secondConst = implG->GcreateConstantF64(ctxG, 13.6); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + TransformIrIcreateCmp(ctxG, firstConst, secondConst); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", "create_cmp_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "-1\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpD3) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantF64(ctxG, 7.6); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + TransformIrIcreateCmp(ctxG, firstConst, firstConst); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", "create_cmp_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitCreateCmpDynamicTest, LibAbcKitTestCmpNegative) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static.abc", + ABCKIT_ABC_DIR "ir/icreate/cmp/create_cmp_static_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_Inst *firstConst = implG->GcreateConstantI64(ctxG, 10); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *secondConst = implG->GcreateConstantF64(ctxG, 7.2); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_NO_ERROR); + abckit_Inst *cmp = statG->IcreateCmp(ctxG, firstConst, secondConst); + EXPECT_TRUE(cmp == nullptr); + EXPECT_TRUE(statuses::GetLastError() == abckit_Status_BAD_ARGUMENT); + }, + [](abckit_Graph *ctxG) {} + ); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/cmp/create_cmp_static.ets b/libabckit/tests/ir/icreate/cmp/create_cmp_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..1e8af63ddf74549e80dccb9f4786832e0c0053b4 --- /dev/null +++ b/libabckit/tests/ir/icreate/cmp/create_cmp_static.ets @@ -0,0 +1,10 @@ +class MyClass { + foo() : int { + return 0; + } +} + +function main() { + let c = new MyClass(); + console.log(c.foo()); +} diff --git a/libabckit/tests/ir/icreate/create_if/create_if_dynamic.cpp b/libabckit/tests/ir/icreate/create_if/create_if_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ce628442f6434fb05af3a0e8105026255ad2748 --- /dev/null +++ b/libabckit/tests/ir/icreate/create_if/create_if_dynamic.cpp @@ -0,0 +1,332 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + auto dynG = abckit_GetIsaApiDynamicImpl(1); + + void TransformIrCreateIfDynamic(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, dynG->IcreateReturnundefined(ctxG)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *intrinsicNoteq = dynG->IcreateNoteq(ctxG, constOne, constZero); + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_NE); + implG->BBaddInstBack(ifBB, intrinsicNoteq); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrCreateIfDynamicNeg(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, dynG->IcreateReturnundefined(ctxG)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *intrinsicNoteq = dynG->IcreateNoteq(ctxG, constOne, constZero); + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_GT); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(ifInst, nullptr); + ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_NE); + implG->BBaddInstBack(ifBB, intrinsicNoteq); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIgetConditionCode(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, dynG->IcreateReturnundefined(ctxG)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *intrinsicNoteq = dynG->IcreateNoteq(ctxG, constOne, constZero); + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_NE); + abckit_IsaApiDynamicConditionCode cc = dynG->IgetConditionCode(ifInst); + ASSERT_EQ(cc, abckit_IsaApiDynamicConditionCode_CC_NE); + implG->BBaddInstBack(ifBB, intrinsicNoteq); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIgetConditionCodeNeg(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, dynG->IcreateReturnundefined(ctxG)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *intrinsicNoteq = dynG->IcreateNoteq(ctxG, constOne, constZero); + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_NE); + abckit_IsaApiDynamicConditionCode cc = dynG->IgetConditionCode(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(cc, abckit_IsaApiDynamicConditionCode_CC_NONE); + implG->BBaddInstBack(ifBB, intrinsicNoteq); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIsetConditionCode(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, dynG->IcreateReturnundefined(ctxG)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *intrinsicNoteq = dynG->IcreateNoteq(ctxG, constOne, constZero); + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_EQ); + dynG->IsetConditionCode(ifInst, abckit_IsaApiDynamicConditionCode_CC_NE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstBack(ifBB, intrinsicNoteq); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIsetConditionCodeNeg(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, dynG->IcreateReturnundefined(ctxG)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *intrinsicNoteq = dynG->IcreateNoteq(ctxG, constOne, constZero); + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicNoteq, abckit_IsaApiDynamicConditionCode_CC_NE); + dynG->IsetConditionCode(nullptr, abckit_IsaApiDynamicConditionCode_CC_NE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + dynG->IsetConditionCode(ifInst, abckit_IsaApiDynamicConditionCode_CC_GT); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + implG->BBaddInstBack(ifBB, intrinsicNoteq); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } +} // namespace + +class LibAbcKitCreateIfDynamicTest : public ::testing::Test {}; + +static std::vector> GetSchema() { + return { + { + {}, {1}, { + {0, abckit_IsaApiDynamicOpcode_Constant, {}}, + {1, abckit_IsaApiDynamicOpcode_Constant, {}}, + {2, abckit_IsaApiDynamicOpcode_Constant, {}}, + } + }, + { + {0}, {3, 2}, { + {3, abckit_IsaApiDynamicOpcode_noteq, {0, 1}}, + {4, abckit_IsaApiDynamicOpcode_if, {3, 2}}, + } + }, + { + {1}, {4}, { + {5, abckit_IsaApiDynamicOpcode_returnundefined, {}}, + } + }, + { + {1}, {4}, { + {6, abckit_IsaApiDynamicOpcode_return, {1}}, + } + }, + { + {2, 3}, {}, {} + } + }; +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIf, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateIfDynamicTest, LibAbcKitTestCreateIfDyn) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateIfDynamic(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified.abc", "create_if_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIf, abc-kind=JS, category=negative +TEST_F(LibAbcKitCreateIfDynamicTest, LibAbcKitTestCreateIfDynNeg) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_neg.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateIfDynamicNeg(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_neg.abc", "create_if_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetConditionCode, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateIfDynamicTest, LibAbcKitTestGetConditionCode) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_get.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIgetConditionCode(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_get.abc", "create_if_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetConditionCode, abc-kind=JS, category=negative +TEST_F(LibAbcKitCreateIfDynamicTest, LibAbcKitTestGetConditionCodeNeg) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_get_neg.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIgetConditionCodeNeg(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_get_neg.abc", "create_if_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetConditionCode, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateIfDynamicTest, LibAbcKitTestSetConditionCode) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_set.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIsetConditionCode(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_set.abc", "create_if_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetConditionCode, abc-kind=JS, category=negative +TEST_F(LibAbcKitCreateIfDynamicTest, LibAbcKitTestSetConditionCodeNeg) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_set_neg.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIsetConditionCodeNeg(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema()); + } + ); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_dynamic_modified_set_neg.abc", "create_if_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/create_if/create_if_dynamic.js b/libabckit/tests/ir/icreate/create_if/create_if_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..ea842650de43a35774d455144c05f20f34b0d11c --- /dev/null +++ b/libabckit/tests/ir/icreate/create_if/create_if_dynamic.js @@ -0,0 +1,26 @@ +class MyClass { + foo() { + return 0; + } +} + +let c = new MyClass(); +print(c.foo()); + +// // After AOP: + +// class MyClass { +// foo() { +// let b = 0 +// let c = 1 +// if (b != c) { +// return 0 +// } +// return undefined +// } +// } + +// +// let c = new MyClass(); +// print(c.foo()); +// diff --git a/libabckit/tests/ir/icreate/create_if/create_if_static.cpp b/libabckit/tests/ir/icreate/create_if/create_if_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc3c8113d710b86f8a06ab918ca68630e64e4852 --- /dev/null +++ b/libabckit/tests/ir/icreate/create_if/create_if_static.cpp @@ -0,0 +1,343 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + auto dynG = abckit_GetIsaApiDynamicImpl(1); + + void TransformIrIcreateIf(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, statG->IcreateReturn(ctxG, constZero)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, constOne, constZero, abckit_IsaApiStaticConditionCode_CC_NE); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIcreateIfNeg(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, statG->IcreateReturn(ctxG, constZero)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, constOne, constZero, abckit_IsaApiStaticConditionCode_CC_EQ); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIsetConditionCode(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, statG->IcreateReturn(ctxG, constZero)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, constOne, constZero, abckit_IsaApiStaticConditionCode_CC_EQ); + statG->IsetConditionCode(ifInst, abckit_IsaApiStaticConditionCode_CC_NE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIsetConditionCodeNeg(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, statG->IcreateReturn(ctxG, constZero)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, constOne, constZero, abckit_IsaApiStaticConditionCode_CC_EQ); + statG->IsetConditionCode(nullptr, abckit_IsaApiStaticConditionCode_CC_NE); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + + void TransformIrIgetConditionCode(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, statG->IcreateReturn(ctxG, constZero)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, constOne, constZero, abckit_IsaApiStaticConditionCode_CC_EQ); + abckit_IsaApiStaticConditionCode cc = statG->IgetConditionCode(ifInst); + ASSERT_EQ(cc, abckit_IsaApiStaticConditionCode_CC_EQ); + statG->IsetConditionCode(ifInst, abckit_IsaApiStaticConditionCode_CC_NE); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } + + void TransformIrIgetConditionCodeNeg(abckit_Graph *ctxG) + { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_Inst *constOne = implG->GcreateConstantU64(ctxG, 1); + abckit_Inst *constZero = implG->GcreateConstantU64(ctxG, 0); + + abckit_BasicBlock *trueBB = succBBs[0]; + implG->BBdisconnectBlocks(startBB, trueBB); + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(falseBB, implG->GgetEndBasicBlock(ctxG), 1); + implG->BBaddInstBack(falseBB, statG->IcreateReturn(ctxG, constZero)); + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, constOne, constZero, abckit_IsaApiStaticConditionCode_CC_EQ); + abckit_IsaApiStaticConditionCode cc = statG->IgetConditionCode(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(cc, abckit_IsaApiStaticConditionCode_CC_NONE); + statG->IsetConditionCode(ifInst, abckit_IsaApiStaticConditionCode_CC_NE); + implG->BBaddInstBack(ifBB, ifInst); + implG->BBconnectBlocks(startBB, ifBB, 0); + implG->BBconnectBlocks(ifBB, trueBB, 1); + implG->BBconnectBlocks(ifBB, falseBB, 0); + } +} // namespace + +class LibAbcKitCreateIfStaticTest : public ::testing::Test {}; + +static std::vector> GetSchema1() { + return { + { + {}, {1}, { + {0, abckit_IsaApiStaticOpcode_Constant, {}}, + {1, abckit_IsaApiStaticOpcode_Constant, {}}, + {2, abckit_IsaApiStaticOpcode_Constant, {}}, + {3, abckit_IsaApiStaticOpcode_Constant, {}}, + {4, abckit_IsaApiStaticOpcode_Constant, {}}, + } + }, + { + {0}, {3, 2}, { + {5, abckit_IsaApiStaticOpcode_Cmp, {1, 0}}, + {6, abckit_IsaApiStaticOpcode_If, {5, 2}}, + } + }, + { + {1}, {4}, { + {7, abckit_IsaApiStaticOpcode_Return, {4}}, + } + }, + { + {1}, {4}, { + {8, abckit_IsaApiStaticOpcode_Return, {3}}, + } + }, + { + {2, 3}, {}, {} + } + }; +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIf, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateIfStaticTest, LibAbcKitTestCreateIf) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIcreateIf(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema1()); + } + ); + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified.abc", "create_if_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3.14\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIf, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitCreateIfStaticTest, LibAbcKitTestCreateIfNeg) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_neg.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIcreateIfNeg(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema1()); + } + ); + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_neg.abc", "create_if_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +static std::vector> GetSchema2() { + return { + { + {}, {1}, { + {0, abckit_IsaApiStaticOpcode_Constant, {}}, + {1, abckit_IsaApiStaticOpcode_Constant, {}}, + {2, abckit_IsaApiStaticOpcode_Constant, {}}, + {3, abckit_IsaApiStaticOpcode_Constant, {}}, + {4, abckit_IsaApiStaticOpcode_Constant, {}}, + } + }, + { + {0}, {3, 2}, { + {5, abckit_IsaApiStaticOpcode_Cmp, {1, 0}}, + {6, abckit_IsaApiStaticOpcode_If, {5, 2}}, + } + }, + { + {1}, {4}, { + {7, abckit_IsaApiStaticOpcode_Return, {4}}, + } + }, + { + {1}, {4}, { + {8, abckit_IsaApiStaticOpcode_Return, {3}}, + } + }, + { + {2, 3}, {}, {} + } + }; +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateIfStaticTest, LibAbcKitTestSetCondidionCodePos) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_set.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIsetConditionCode(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema2()); + } + ); + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_set.abc", "create_if_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3.14\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitCreateIfStaticTest, LibAbcKitTestSetCondidionCodeNeg) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_set_neg.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIsetConditionCodeNeg(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema2()); + } + ); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetConditionCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateIfStaticTest, LibAbcKitTestGetCondidionCodePos) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_get.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIgetConditionCode(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema2()); + } + ); + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_get.abc", "create_if_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "3.14\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetConditionCode, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitCreateIfStaticTest, LibAbcKitTestGetCondidionCodeNeg) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_if/create_if_static_modified_get_neg.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrIgetConditionCodeNeg(ctxG); + }, + [](abckit_Graph *ctxG) { + helpers::VerifyGraph(ctxG, GetSchema2()); + } + ); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/create_if/create_if_static.ets b/libabckit/tests/ir/icreate/create_if/create_if_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..a3a0afd9a223a413a2cf27da5f6a95ee1bffb52b --- /dev/null +++ b/libabckit/tests/ir/icreate/create_if/create_if_static.ets @@ -0,0 +1,32 @@ +// Before AOP: + +class MyClass { + handle(): double { + let a: double = 3.14 + return a + } +} + +function main() { + let c = new MyClass(); + console.log(c.handle()); +} + +// After AOP: + +// class MyClass { +// handle(): double { +// let a: double = 3.14 +// let b: int = 0 +// let c: int = 1 +// if (b == c) { +// return 0; +// } +// return a +// } +// } + +// function main() { +// let c = new MyClass(); +// c.handle(); +// } diff --git a/libabckit/tests/ir/icreate/create_nullptr/create_nullptr_static.cpp b/libabckit/tests/ir/icreate/create_nullptr/create_nullptr_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bd175acf962ebbe44fca816d8584987a3f1d7a24 --- /dev/null +++ b/libabckit/tests/ir/icreate/create_nullptr/create_nullptr_static.cpp @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitCreateNullPtrInstTest : public ::testing::Test {}; + +static void TransformIrCreateNullPtrInstValid(abckit_Graph *ctxG) +{ + abckit_Inst *mainInst = statG->GcreateNullPtr(ctxG); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto callOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + implG->IsetInput(callOp, mainInst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::GcreateNullPtr, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateNullPtrInstTest, CreateNullPtrValid) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/create_nullptr/create_nullptr_static.abc", "create_nullptr_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"10\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/create_nullptr/create_nullptr_static.abc", + ABCKIT_ABC_DIR "ir/icreate/create_nullptr/create_nullptr_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateNullPtrInstValid(ctxG); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {1, abckit_IsaApiStaticOpcode_NullPtr, {}}, + } + }, + { + {0}, {2}, { + {2, abckit_IsaApiStaticOpcode_CallStatic, {1}}, + {3, abckit_IsaApiStaticOpcode_ReturnVoid, {}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/create_nullptr/create_nullptr_static_modified.abc", "create_nullptr_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "null\n")); +} + +} //namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/create_nullptr/create_nullptr_static.ets b/libabckit/tests/ir/icreate/create_nullptr/create_nullptr_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..2f95346953c7f923267ac60f590e1490e53e4bc0 --- /dev/null +++ b/libabckit/tests/ir/icreate/create_nullptr/create_nullptr_static.ets @@ -0,0 +1,24 @@ +// Before AOP: + +function logger(a: string | null) { + console.log(a) +} + +class A { + foo() { + logger("10") + } +} + +function main() { + let a = new A() + a.foo() +} + +// After AOP: + +// class A { +// foo() { +// logger(null) +// } +// } \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/dyn_call/call_dynamic.cpp b/libabckit/tests/ir/icreate/dyn_call/call_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..893a203afe597491b511b4f80d9e242455dad125 --- /dev/null +++ b/libabckit/tests/ir/icreate/dyn_call/call_dynamic.cpp @@ -0,0 +1,276 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynCall : public ::testing::Test {}; + +static std::vector> CreateBBSchemaForDynCall(abckit_IsaApiDynamicOpcode opcode) +{ + helpers::InstSchema callInstSchema = {0, abckit_IsaApiDynamicOpcode_INVALID, {}}; + std::vector> params = {}; + switch(opcode) { + case abckit_IsaApiDynamicOpcode_callarg0: + callInstSchema = {4, opcode, {3}}; + break; + case abckit_IsaApiDynamicOpcode_callarg1: + params = { + {4, abckit_IsaApiDynamicOpcode_Constant, {}} + }; + callInstSchema = {4, opcode, {4, 3}}; + break; + case abckit_IsaApiDynamicOpcode_callargs2: + params = { + {4, abckit_IsaApiDynamicOpcode_Constant, {}}, + {5, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {4, opcode, {4, 5, 3}}; + break; + case abckit_IsaApiDynamicOpcode_callargs3: + params = { + {4, abckit_IsaApiDynamicOpcode_Constant, {}}, + {5, abckit_IsaApiDynamicOpcode_Constant, {}}, + {6, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {4, opcode, {4, 5, 6, 3}}; + break; + case abckit_IsaApiDynamicOpcode_callrange: + case abckit_IsaApiDynamicOpcode_wide_callrange: + params = { + {4, abckit_IsaApiDynamicOpcode_Constant, {}}, + {5, abckit_IsaApiDynamicOpcode_Constant, {}}, + {6, abckit_IsaApiDynamicOpcode_Constant, {}}, + {7, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {4, opcode, {4, 5, 6, 7, 3}}; + break; + case abckit_IsaApiDynamicOpcode_INVALID: + break; + default: + LIBABCKIT_UNREACHABLE_TEST(DEBUG); + } + return { + { + {}, {1}, params + }, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_definefunc, {}}, + callInstSchema, + {8, abckit_IsaApiDynamicOpcode_ldundefined, {}}, + {9, abckit_IsaApiDynamicOpcode_returnundefined, {}}, + } + }, + { + {1}, {}, {} + } + }; +} + +static void TestHelper(void (*TransformIrCall)(abckit_Graph *ctxG), abckit_IsaApiDynamicOpcode opcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/dyn_call/call_dynamic.abc", "call_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/dyn_call/call_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/dyn_call/call_dynamic_modified.abc", + "call_dynamic.func_main_0", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCall(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynCall(opcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/dyn_call/call_dynamic_modified.abc", "call_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +static void TransformIrCallarg0(abckit_Graph *ctxG) +{ + auto func = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definefunc); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call0 = dynG->IcreateCallarg0(ctxG, func); + ASSERT_NE(call0, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call0, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallarg1(abckit_Graph *ctxG) +{ + auto func = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definefunc); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call1 = dynG->IcreateCallarg1(ctxG, func, param0); + ASSERT_NE(call1, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call1, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallargs2(abckit_Graph *ctxG) +{ + auto func = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definefunc); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call2 = dynG->IcreateCallargs2(ctxG, func, param0, param1); + ASSERT_NE(call2, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call2, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallargs3(abckit_Graph *ctxG) +{ + auto func = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definefunc); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param2 = implG->GcreateConstantI64(ctxG, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call3 = dynG->IcreateCallargs3(ctxG, func, param0, param1, param2); + ASSERT_NE(call3, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call3, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallrange(abckit_Graph *ctxG) +{ + auto func = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definefunc); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param2 = implG->GcreateConstantI64(ctxG, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param3 = implG->GcreateConstantI64(ctxG, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call4 = dynG->IcreateCallrange(ctxG, func, 4, param0, param1, param2, param3); + ASSERT_NE(call4, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call4, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrWideCallrange(abckit_Graph *ctxG) +{ + auto func = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definefunc); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param2 = implG->GcreateConstantI64(ctxG, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param3 = implG->GcreateConstantI64(ctxG, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call4 = dynG->IcreateWideCallrange(ctxG, func, 4, param0, param1, param2, param3); + ASSERT_NE(call4, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call4, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg0, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCall, CreateDynCallarg0) +{ + TestHelper(TransformIrCallarg0, abckit_IsaApiDynamicOpcode_callarg0, "func\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg1, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCall, CreateDynCallarg1) +{ + TestHelper(TransformIrCallarg1, abckit_IsaApiDynamicOpcode_callarg1, "func\n1\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCall, CreateDynCallargs2) +{ + TestHelper(TransformIrCallargs2, abckit_IsaApiDynamicOpcode_callargs2, "func\n1\n2\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs3, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCall, CreateDynCallargs3) +{ + TestHelper(TransformIrCallargs3, abckit_IsaApiDynamicOpcode_callargs3, "func\n1\n2\n3\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallrange, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCall, CreateDynCallrange) +{ + TestHelper(TransformIrCallrange, abckit_IsaApiDynamicOpcode_callrange, "func\n1\n2\n3\n4\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallrange, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCall, DISABLED_CreateDynWideCallrange) +{ + // Temporary disabled due to Dynamic VM runtime bug + TestHelper(TransformIrWideCallrange, abckit_IsaApiDynamicOpcode_wide_callrange, "func\n1\n2\n3\n4\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/dyn_call/call_dynamic.js b/libabckit/tests/ir/icreate/dyn_call/call_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..a8e1e6768e10a208a0c5374861a4d73b611925d2 --- /dev/null +++ b/libabckit/tests/ir/icreate/dyn_call/call_dynamic.js @@ -0,0 +1,7 @@ +function func(a, b, c, d) { + print("func") + if (a) print(a) + if (b) print(b) + if (c) print(c) + if (d) print(d) +} diff --git a/libabckit/tests/ir/icreate/dyn_call_this/call_this_dynamic.cpp b/libabckit/tests/ir/icreate/dyn_call_this/call_this_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4f8478d51172740a93ecfbfad9f8e2a71daa580f --- /dev/null +++ b/libabckit/tests/ir/icreate/dyn_call_this/call_this_dynamic.cpp @@ -0,0 +1,267 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynCallThis : public ::testing::Test {}; + +[[maybe_unused]] static std::vector> CreateBBSchemaForDynCallThis(abckit_IsaApiDynamicOpcode opcode) +{ + helpers::InstSchema callInstSchema = {0, abckit_IsaApiDynamicOpcode_INVALID, {}}; + std::vector> params = {}; + switch(opcode) { + case abckit_IsaApiDynamicOpcode_callthis0: + callInstSchema = {10, opcode, {6, 9}}; + break; + case abckit_IsaApiDynamicOpcode_callthis1: + params = { + {10, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {11, opcode, {6, 10, 9}}; + break; + case abckit_IsaApiDynamicOpcode_callthis2: + params = { + {10, abckit_IsaApiDynamicOpcode_Constant, {}}, + {11, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {12, opcode, {6, 10, 11, 9}}; + break; + case abckit_IsaApiDynamicOpcode_callthis3: + params = { + {10, abckit_IsaApiDynamicOpcode_Constant, {}}, + {11, abckit_IsaApiDynamicOpcode_Constant, {}}, + {12, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {13, opcode, {6, 10, 11, 12, 9}}; + break; + case abckit_IsaApiDynamicOpcode_callthisrange: + case abckit_IsaApiDynamicOpcode_wide_callthisrange: + params = { + {10, abckit_IsaApiDynamicOpcode_Constant, {}}, + {11, abckit_IsaApiDynamicOpcode_Constant, {}}, + {12, abckit_IsaApiDynamicOpcode_Constant, {}}, + {13, abckit_IsaApiDynamicOpcode_Constant, {}}, + }; + callInstSchema = {14, opcode, {6, 10, 11, 12, 13, 9}}; + break; + case abckit_IsaApiDynamicOpcode_INVALID: + break; + default: + LIBABCKIT_UNREACHABLE_TEST(DEBUG); + } + return { + { + {}, {1}, params + }, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_ldhole, {}}, + {4, abckit_IsaApiDynamicOpcode_defineclasswithbuffer, {3}}, + {5, abckit_IsaApiDynamicOpcode_ldobjbyname, {4}}, + {6, abckit_IsaApiDynamicOpcode_newobjrange, {4}}, + {9, abckit_IsaApiDynamicOpcode_ldobjbyname, {6}}, + callInstSchema, + {7, abckit_IsaApiDynamicOpcode_ldundefined, {}}, + {8, abckit_IsaApiDynamicOpcode_returnundefined, {}}, + } + }, + { + {1}, {}, {} + } + }; +} + +static void TestHelper(void (*TransformIrCall)(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func), + abckit_IsaApiDynamicOpcode opcode, const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/dyn_call_this/call_this_dynamic.abc", "call_this_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/dyn_call_this/call_this_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/dyn_call_this/call_this_dynamic_modified.abc", + "call_this_dynamic.func_main_0", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + + auto obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_newobjrange); + ASSERT_NE(obj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto func = dynG->IcreateLdobjbyname(ctxG, obj, implM->CreateString(ctxM, "func")); + ASSERT_NE(func, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(func, obj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + TransformIrCall(ctxG, obj, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynCallThis(opcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/dyn_call_this/call_this_dynamic_modified.abc", "call_this_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +static void TransformIrCallThisarg0(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func) +{ + auto call0 = dynG->IcreateCallthis0(ctxG, func, obj); + ASSERT_NE(call0, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call0, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallThisarg1(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func) +{ + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call1 = dynG->IcreateCallthis1(ctxG, func, obj, param0); + ASSERT_NE(call1, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call1, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallThisargs2(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func) +{ + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call2 = dynG->IcreateCallthis2(ctxG, func, obj, param0, param1); + ASSERT_NE(call2, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call2, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallThisargs3(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func) +{ + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param2 = implG->GcreateConstantI64(ctxG, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call3 = dynG->IcreateCallthis3(ctxG, func, obj, param0, param1, param2); + ASSERT_NE(call3, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call3, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCallThisrange(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func) +{ + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param2 = implG->GcreateConstantI64(ctxG, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param3 = implG->GcreateConstantI64(ctxG, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call3 = dynG->IcreateCallthisrange(ctxG, func, 4, obj, param0, param1, param2, param3); + ASSERT_NE(call3, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call3, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrWideCallThisrange(abckit_Graph *ctxG, abckit_Inst *obj, abckit_Inst *func) +{ + auto param0 = implG->GcreateConstantI64(ctxG, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param1 = implG->GcreateConstantI64(ctxG, 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param2 = implG->GcreateConstantI64(ctxG, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto param3 = implG->GcreateConstantI64(ctxG, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto call3 = dynG->IcreateWideCallthisrange(ctxG, func, 4, obj, param0, param1, param2, param3); + ASSERT_NE(call3, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(call3, func); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis0, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis0) +{ + TestHelper(TransformIrCallThisarg0, abckit_IsaApiDynamicOpcode_callthis0, "func\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis1, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis1) +{ + TestHelper(TransformIrCallThisarg1, abckit_IsaApiDynamicOpcode_callthis1, "func\n1\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis2, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis2) +{ + TestHelper(TransformIrCallThisargs2, abckit_IsaApiDynamicOpcode_callthis2, "func\n1\n2\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis3, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis3) +{ + TestHelper(TransformIrCallThisargs3, abckit_IsaApiDynamicOpcode_callthis3, "func\n1\n2\n3\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthisrange, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthisrange) +{ + TestHelper(TransformIrCallThisrange, abckit_IsaApiDynamicOpcode_callthisrange, "func\n1\n2\n3\n4\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallthisrange, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCallThis, CreateDynWideCallthisrange) +{ + TestHelper(TransformIrWideCallThisrange, abckit_IsaApiDynamicOpcode_wide_callthisrange, "func\n1\n2\n3\n4\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/dyn_call_this/call_this_dynamic.js b/libabckit/tests/ir/icreate/dyn_call_this/call_this_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..93259e6f327bd9d3fbd68318d7a6820765706b95 --- /dev/null +++ b/libabckit/tests/ir/icreate/dyn_call_this/call_this_dynamic.js @@ -0,0 +1,11 @@ +class A { + func(a, b, c, d) { + print("func") + if (a) print(a) + if (b) print(b) + if (c) print(c) + if (d) print(d) + } +} + +let a = new A() diff --git a/libabckit/tests/ir/icreate/equals/equals_static.cpp b/libabckit/tests/ir/icreate/equals/equals_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a850ee1650c7290207ce6d10e4ef038cb0eeb363 --- /dev/null +++ b/libabckit/tests/ir/icreate/equals/equals_static.cpp @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformEqualsIr(abckit_Graph *ctxG) + { + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *initObj = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_InitObject); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *initObj2 = implG->IgetNext(initObj); + ASSERT_NE(initObj2, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *equals = statG->IcreateEquals(ctxG, initObj, initObj2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(equals, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetInput(ret, equals, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + +} // namespace + +class LibAbcKitEqualsStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateEquals, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitEqualsStaticTest, LibAbcKitTestEquals) +{ + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/equals/equals_static.abc", "equals_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "true\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/equals/equals_static.abc", + ABCKIT_ABC_DIR "ir/icreate/equals/equals_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformEqualsIr(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, {} + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {1, abckit_IsaApiStaticOpcode_InitObject, {}}, + {3, abckit_IsaApiStaticOpcode_Equals, {0, 1}}, + {2, abckit_IsaApiStaticOpcode_Return, {3}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/equals/equals_static_modified.abc", "equals_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "false\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/equals/equals_static.ets b/libabckit/tests/ir/icreate/equals/equals_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b4df3593feb40126dc224ff2d1c58e3f3feefced --- /dev/null +++ b/libabckit/tests/ir/icreate/equals/equals_static.ets @@ -0,0 +1,27 @@ +// Before AOP: + +class A {} + +function foo() { + let a = new A(); + let b = new A(); + return true; +} + +function main() { + console.log(foo()) +} + +// After AOP: +// +// class A {} +// +// function foo() { +// let a = new A(); +// let b = new A(); +// return true; +// } +// +// function main() { +// console.log(foo()) +// } diff --git a/libabckit/tests/ir/icreate/generators/creategeneratorobj_dynamic.cpp b/libabckit/tests/ir/icreate/generators/creategeneratorobj_dynamic.cpp new file mode 100755 index 0000000000000000000000000000000000000000..71d087221edd4abf9c2426cc7717eb2d185dbdac --- /dev/null +++ b/libabckit/tests/ir/icreate/generators/creategeneratorobj_dynamic.cpp @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynCreateGeneratorObjInstTest : public ::testing::Test {}; + +static void TransformIr(abckit_Graph *ctxG) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + abckit_Inst *firstInst = nullptr; + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_Parameter) { + curInst = implG->IgetNext(curInst); + continue; + } + firstInst = curInst; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + break; + } + + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *first = succBBs[0]; + + curInst = implG->BBgetFirstInst(first); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *inst = dynG->IcreateCreategeneratorobj(ctxG, firstInst); + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_return) { + curInst = implG->IgetNext(curInst); + continue; + } + implG->IinsertBefore(inst, curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetInput(curInst, inst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreategeneratorobj, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCreateGeneratorObjInstTest, CreateDynCreategeneratorobjValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/generators/creategeneratorobj_dynamic.abc", "creategeneratorobj_dynamic"); + EXPECT_TRUE(helpers::Match(output, "Cannot get source code of funtion\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/generators/creategeneratorobj_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/generators/creategeneratorobj_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIr(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {3, abckit_IsaApiDynamicOpcode_Parameter, {}}, + } + }, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_creategeneratorobj, {3}}, + {5, abckit_IsaApiDynamicOpcode_return, {4}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/generators/creategeneratorobj_dynamic_modified.abc", "creategeneratorobj_dynamic"); + EXPECT_TRUE(helpers::Match(output, "\\[object Generator\\]\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/generators/creategeneratorobj_dynamic.js b/libabckit/tests/ir/icreate/generators/creategeneratorobj_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..f03510091a3dded58c9683f6702414454e150920 --- /dev/null +++ b/libabckit/tests/ir/icreate/generators/creategeneratorobj_dynamic.js @@ -0,0 +1,14 @@ +const gen = function* () { + yield 'a'; + yield 'b'; + yield 'c'; +}; + +class A { + foo(generator) { + return generator; + } +} + +let a = new A() +print(a.foo(gen)) \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/instanceof/instanceof_dynamic.cpp b/libabckit/tests/ir/icreate/instanceof/instanceof_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ade02805134adf8b3c6ab8bf3b4378de4022ff9f --- /dev/null +++ b/libabckit/tests/ir/icreate/instanceof/instanceof_dynamic.cpp @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "../arithmetic/helpers_arithmetic.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynInstanceofInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInstanceof, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynInstanceofInstTest, CreateDynInstanceofValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/instanceof/instanceof_dynamic.abc", "instanceof_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/instanceof/instanceof_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/instanceof/instanceof_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, dynG->IcreateInstanceof, 3, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {0, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {1, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {2, abckit_IsaApiDynamicOpcode_Constant, {}}, + {3, abckit_IsaApiDynamicOpcode_Constant, {}}, + } + }, + { + {0}, {3, 2}, { + {4, abckit_IsaApiDynamicOpcode_ldlexvar, {}}, + {5, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {4}}, + {6, abckit_IsaApiDynamicOpcode_eq, {1, 4}}, + {7, abckit_IsaApiDynamicOpcode_if, {6, 2}} + } + }, + { + {1}, {3}, { + {8, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}, + {9, abckit_IsaApiDynamicOpcode_callarg1, {0, 8}}, + {10, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}, + {11, abckit_IsaApiDynamicOpcode_callarg1, {3, 10}} + } + }, + { + {1, 2}, {4}, { + {12, abckit_IsaApiDynamicOpcode_instanceof, {0, 1}}, + {13, abckit_IsaApiDynamicOpcode_return, {12}} + } + }, + { + {3}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/instanceof/instanceof_dynamic_modified.abc", "instanceof_dynamic"); + EXPECT_TRUE(helpers::Match(output, "true\nfalse\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/instanceof/instanceof_dynamic.js b/libabckit/tests/ir/icreate/instanceof/instanceof_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..92069314a73e5f249b50a2d3f8dfae49d159f97a --- /dev/null +++ b/libabckit/tests/ir/icreate/instanceof/instanceof_dynamic.js @@ -0,0 +1,15 @@ +class B {} +class A { + foo(a, klass) { + if (klass == B) { + print(a) + print(1) + } + return 10; + } +} + +let a = new A() +let b = 5 +print(a.foo(a, A)) +print(a.foo(b, A)) diff --git a/libabckit/tests/ir/icreate/is_instance/is_instance.cpp b/libabckit/tests/ir/icreate/is_instance/is_instance.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc48a3b9b8a4e367dd6c91939c60cc6176973ed0 --- /dev/null +++ b/libabckit/tests/ir/icreate/is_instance/is_instance.cpp @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformIsInstanceIr(abckit_Graph *ctxG, abckit_ModifyContext *ctxM, abckit_Class *classA) + { + abckit_Inst *initObj = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_InitObject); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *type = implM->CreateReferenceType(ctxM, classA); + ASSERT_NE(type, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *isInstance = statG->IcreateIsInstance(ctxG, initObj, type); + ASSERT_NE(isInstance, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(isInstance, initObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ReplaceInst(ret, statG->IcreateReturn(ctxG, isInstance)); + + } +} // namespace + +class LibAbcKitIsInstanceStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIsInstance, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIsInstanceStaticTest, LibAbcKitTestIsInstance) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/is_instance/is_instance_static.abc", "is_instance_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "false\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/is_instance/is_instance_static.abc", + ABCKIT_ABC_DIR "ir/icreate/is_instance/is_instance_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *module = implI->MethodGetModule(method); + helpers::ClassByNameContext classCtxFinder = {nullptr, "A"}; + implI->ModuleEnumerateClasses(module, &classCtxFinder, helpers::classByNameFinder); + ASSERT_NE(classCtxFinder.klass, nullptr); + TransformIsInstanceIr(ctxG, ctxM, classCtxFinder.klass); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {} + } + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {2, abckit_IsaApiStaticOpcode_IsInstance, {0}}, + {1, abckit_IsaApiStaticOpcode_Return, {2}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/is_instance/is_instance_static_modified.abc", "is_instance_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "true\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/is_instance/is_instance_static.ets b/libabckit/tests/ir/icreate/is_instance/is_instance_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b619537ff73fbd16851e24897ec1e69b4a217885 --- /dev/null +++ b/libabckit/tests/ir/icreate/is_instance/is_instance_static.ets @@ -0,0 +1,27 @@ +// Before AOP: + +class A {} +class B extends A {} + +function foo (): boolean { + let a = new B(); + return false; +} + +function main() { + console.log(foo()) +} + +// After AOP: +// +// class A {} +// class B extends A {} +// +// function main() { +// let a = new B(); +// return ; // expected to be true +// } +// +// function main() { +// console.log(foo()) +// } diff --git a/libabckit/tests/ir/icreate/is_undefined/is_undefined.cpp b/libabckit/tests/ir/icreate/is_undefined/is_undefined.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b063b88d2dea9d79411168b9bd0492274ec77b89 --- /dev/null +++ b/libabckit/tests/ir/icreate/is_undefined/is_undefined.cpp @@ -0,0 +1,104 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "isa/isa_static.h" +#include "metadata.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit { +namespace test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformIsUndefinedIr(abckit_Graph *ctxG, abckit_ModifyContext *ctxM, abckit_Class *classA) + { + abckit_Inst *initObj = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_InitObject); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(initObj, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *isUndefined = statG->IcreateIsUndefined(ctxG, initObj); + ASSERT_NE(isUndefined, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(isUndefined, initObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ReplaceInst(ret, statG->IcreateReturn(ctxG, isUndefined)); + + } +} // namespace + +class LibAbcKitIsUndefinedStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIsUndefined, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIsUndefinedStaticTest, LibAbcKitTestIsUndefined) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/is_undefined/is_undefined_static.abc", "is_undefined_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "true\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/is_undefined/is_undefined_static.abc", + ABCKIT_ABC_DIR "ir/icreate/is_undefined/is_undefined_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *module = implI->MethodGetModule(method); + helpers::ClassByNameContext classCtxFinder = {nullptr, "A"}; + implI->ModuleEnumerateClasses(module, &classCtxFinder, helpers::classByNameFinder); + ASSERT_NE(classCtxFinder.klass, nullptr); + TransformIsUndefinedIr(ctxG, ctxM, classCtxFinder.klass); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {} + } + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {2, abckit_IsaApiStaticOpcode_IsUndefined, {0}}, + {1, abckit_IsaApiStaticOpcode_Return, {2}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/is_undefined/is_undefined_static_modified.abc", "is_undefined_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "false\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/is_undefined/is_undefined_static.ets b/libabckit/tests/ir/icreate/is_undefined/is_undefined_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..5c25926ac9b99debfd74b98d4ebcf49ec97fd1cb --- /dev/null +++ b/libabckit/tests/ir/icreate/is_undefined/is_undefined_static.ets @@ -0,0 +1,26 @@ +// Before AOP: + +class A {} + +function foo (): boolean { + let a = new A(); + return true; +} + +function main() { + console.log(foo()) +} + +// After AOP: +// +// class A {} +// class B extends A {} +// +// function main() { +// let a = new B(); +// return ; // expected to be true +// } +// +// function main() { +// console.log(foo()) +// } diff --git a/libabckit/tests/ir/icreate/isin/isin_dynamic.cpp b/libabckit/tests/ir/icreate/isin/isin_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3152d7cfcd089d8d58194f9029029bccb2648544 --- /dev/null +++ b/libabckit/tests/ir/icreate/isin/isin_dynamic.cpp @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "../arithmetic/helpers_arithmetic.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynIsinInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsin, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynIsinInstTest, CreateDynIsinValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/isin/isin_dynamic.abc", "isin_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/isin/isin_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/isin/isin_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::arithmetic::TransformIrBinInstrValid(ctxG, dynG->IcreateIsin, 3, 4); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {0, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {1, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {2, abckit_IsaApiDynamicOpcode_Constant, {}}, + {3, abckit_IsaApiDynamicOpcode_Constant, {}}, + } + }, + { + {0}, {3, 2}, { + {4, abckit_IsaApiDynamicOpcode_ldlexvar, {}}, + {5, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {4}}, + {6, abckit_IsaApiDynamicOpcode_eq, {1, 4}}, + {7, abckit_IsaApiDynamicOpcode_if, {6, 2}} + } + }, + { + {1}, {3}, { + {8, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}, + {9, abckit_IsaApiDynamicOpcode_callarg1, {0, 8}}, + {10, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}, + {11, abckit_IsaApiDynamicOpcode_callarg1, {3, 10}} + } + }, + { + {1, 2}, {4}, { + {12, abckit_IsaApiDynamicOpcode_isin, {0, 1}}, + {13, abckit_IsaApiDynamicOpcode_return, {12}} + } + }, + { + {3}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/isin/isin_dynamic_modified.abc", "isin_dynamic"); + EXPECT_TRUE(helpers::Match(output, "true\nfalse\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/isin/isin_dynamic.js b/libabckit/tests/ir/icreate/isin/isin_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..9abd3a6b8613fc97b805cd31cad96869c25308fd --- /dev/null +++ b/libabckit/tests/ir/icreate/isin/isin_dynamic.js @@ -0,0 +1,14 @@ +class B {} +class A { + foo(a, klass) { + if (klass == B) { + print(a) + print(1) + } + return 10; + } +} + +let a = new A() +print(a.foo('foo', new A())) +print(a.foo('foo', A)) diff --git a/libabckit/tests/ir/icreate/iterators/createiterresultobj_dynamic.cpp b/libabckit/tests/ir/icreate/iterators/createiterresultobj_dynamic.cpp new file mode 100755 index 0000000000000000000000000000000000000000..7c4ce8855a46c98a0e26d716bac8837d01e1b5a7 --- /dev/null +++ b/libabckit/tests/ir/icreate/iterators/createiterresultobj_dynamic.cpp @@ -0,0 +1,130 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynCreateIterResultObjInstTest : public ::testing::Test {}; + +static void TransformIr(abckit_Graph *ctxG) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + abckit_Inst *firstInst = nullptr; + abckit_Inst *secondInst = nullptr; + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_Parameter) { + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + continue; + } + firstInst = curInst; + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (curOpcode != abckit_IsaApiDynamicOpcode_Parameter) { + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + continue; + } + secondInst = curInst; + break; + } + + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *first = succBBs[0]; + + curInst = implG->BBgetFirstInst(first); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *inst = dynG->IcreateCreateiterresultobj(ctxG, firstInst, secondInst); + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_return) { + curInst = implG->IgetNext(curInst); + continue; + } + implG->IinsertBefore(inst, curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetInput(curInst, inst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateiterresultobj, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynCreateIterResultObjInstTest, CreateDynCreateiterresultobjValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/iterators/createiterresultobj_dynamic.abc", "createiterresultobj_dynamic"); + EXPECT_TRUE(helpers::Match(output, "1\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/iterators/createiterresultobj_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/iterators/createiterresultobj_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIr(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {3, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {4, abckit_IsaApiDynamicOpcode_Parameter, {}}, + } + }, + { + {0}, {2}, { + {5, abckit_IsaApiDynamicOpcode_add2, {3, 4}}, + {6, abckit_IsaApiDynamicOpcode_createiterresultobj, {3, 4}}, + {7, abckit_IsaApiDynamicOpcode_return, {6}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/iterators/createiterresultobj_dynamic_modified.abc", "createiterresultobj_dynamic"); + EXPECT_TRUE(helpers::Match(output, "\\[object Object\\]\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/iterators/createiterresultobj_dynamic.js b/libabckit/tests/ir/icreate/iterators/createiterresultobj_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..961931d5d67609215eb34818d042951541cbdc4c --- /dev/null +++ b/libabckit/tests/ir/icreate/iterators/createiterresultobj_dynamic.js @@ -0,0 +1,8 @@ +class A { + foo(value, done) { + return value+done; + } +} + +let a = new A() +print(a.foo(1, false)) \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/iterators/getiterator_dynamic.cpp b/libabckit/tests/ir/icreate/iterators/getiterator_dynamic.cpp new file mode 100755 index 0000000000000000000000000000000000000000..e5ba096a574db6f93314da57257371fb0637fb9f --- /dev/null +++ b/libabckit/tests/ir/icreate/iterators/getiterator_dynamic.cpp @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynGetIteratorInstTest : public ::testing::Test {}; + +static void TransformIr(abckit_Graph *ctxG) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + abckit_Inst *firstInst = nullptr; + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_Parameter) { + curInst = implG->IgetNext(curInst); + continue; + } + firstInst = curInst; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + break; + } + + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *first = succBBs[0]; + + curInst = implG->BBgetFirstInst(first); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *inst = dynG->IcreateGetiterator(ctxG, firstInst); + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_return) { + curInst = implG->IgetNext(curInst); + continue; + } + implG->IinsertBefore(inst, curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetInput(curInst, inst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetiterator, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynGetIteratorInstTest, CreateDynGetiteratorValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/iterators/getiterator_dynamic.abc", "getiterator_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/iterators/getiterator_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/iterators/getiterator_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIr(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {3, abckit_IsaApiDynamicOpcode_Parameter, {}}, + } + }, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_getiterator, {3}}, + {5, abckit_IsaApiDynamicOpcode_return, {4}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/iterators/getiterator_dynamic_modified.abc", "getiterator_dynamic"); + EXPECT_TRUE(helpers::Match(output, "\\[object Array Iterator\\]\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/iterators/getiterator_dynamic.js b/libabckit/tests/ir/icreate/iterators/getiterator_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..794ffc26b18efa06812f524100aed649c203cde1 --- /dev/null +++ b/libabckit/tests/ir/icreate/iterators/getiterator_dynamic.js @@ -0,0 +1,8 @@ +class A { + foo(obj) { + return obj + } +} + +let a = new A() +print(a.foo([10])) \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/iterators/getpropiterator_dynamic.cpp b/libabckit/tests/ir/icreate/iterators/getpropiterator_dynamic.cpp new file mode 100755 index 0000000000000000000000000000000000000000..6fff058411adf717aa887f183ce823dac49361ee --- /dev/null +++ b/libabckit/tests/ir/icreate/iterators/getpropiterator_dynamic.cpp @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynGetPropIteratorInstTest : public ::testing::Test {}; + +static void TransformIr(abckit_Graph *ctxG) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *curInst = implG->BBgetFirstInst(startBB); + abckit_Inst *firstInst = nullptr; + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_Parameter) { + curInst = implG->IgetNext(curInst); + continue; + } + firstInst = curInst; + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + break; + } + + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *first = succBBs[0]; + + curInst = implG->BBgetFirstInst(first); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *inst = dynG->IcreateGetpropiterator(ctxG, firstInst); + while (curInst != nullptr) { + abckit_IsaApiDynamicOpcode curOpcode = dynG->IgetOpcode(curInst); + if (curOpcode != abckit_IsaApiDynamicOpcode_return) { + curInst = implG->IgetNext(curInst); + continue; + } + implG->IinsertBefore(inst, curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetInput(curInst, inst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + curInst = implG->IgetNext(curInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetpropiterator, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynGetPropIteratorInstTest, CreateDynGetpropiteratorValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/iterators/getpropiterator_dynamic.abc", "getpropiterator_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/iterators/getpropiterator_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/iterators/getpropiterator_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIr(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {3, abckit_IsaApiDynamicOpcode_Parameter, {}}, + } + }, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_getpropiterator, {3}}, + {5, abckit_IsaApiDynamicOpcode_return, {4}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/iterators/getpropiterator_dynamic_modified.abc", "getpropiterator_dynamic"); + EXPECT_TRUE(helpers::Match(output, "\\[object Object\\]\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/iterators/getpropiterator_dynamic.js b/libabckit/tests/ir/icreate/iterators/getpropiterator_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..794ffc26b18efa06812f524100aed649c203cde1 --- /dev/null +++ b/libabckit/tests/ir/icreate/iterators/getpropiterator_dynamic.js @@ -0,0 +1,8 @@ +class A { + foo(obj) { + return obj + } +} + +let a = new A() +print(a.foo([10])) \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/load_undefined/load_undefined_static.cpp b/libabckit/tests/ir/icreate/load_undefined/load_undefined_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..42bbc731a57e2c13333de55c50a33298ec0e5d7a --- /dev/null +++ b/libabckit/tests/ir/icreate/load_undefined/load_undefined_static.cpp @@ -0,0 +1,94 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformLoadUndefinedIr(abckit_Graph *ctxG) + { + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *undef = statG->IcreateLoadUndefined(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(undef, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetInput(ret, undef, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + +} // namespace + +class LibAbcKitLoadUndefinedStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadUndefined, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitLoadUndefinedStaticTest, LibAbcKitTestLoadUndefined) +{ + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/load_undefined/load_undefined_static.abc", "load_undefined_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "load_undefined_static.A \\{\\}\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/load_undefined/load_undefined_static.abc", + ABCKIT_ABC_DIR "ir/icreate/load_undefined/load_undefined_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformLoadUndefinedIr(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {2, abckit_IsaApiStaticOpcode_LoadUndefined, {}}, + } + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {1, abckit_IsaApiStaticOpcode_Return, {2}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/load_undefined/load_undefined_static_modified.abc", "load_undefined_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "undefined\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/load_undefined/load_undefined_static.ets b/libabckit/tests/ir/icreate/load_undefined/load_undefined_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..a74bfc87efcea554db6423d0aa0667caf96edd59 --- /dev/null +++ b/libabckit/tests/ir/icreate/load_undefined/load_undefined_static.ets @@ -0,0 +1,24 @@ +// Before AOP: + +class A {} + +function foo() { + let a = new A(); + return a; +} + +function main() { + console.log(foo()) +} + +// After AOP: +// +// class A {} +// +// function foo() { +// let a = new A(); +// return undefined; +// } +// function main() { +// console.log(foo()) +// } diff --git a/libabckit/tests/ir/icreate/loadstore/create_ld_dynamic.cpp b/libabckit/tests/ir/icreate/loadstore/create_ld_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8fde9118f6b30e5811a8c6bcee8ac699db8af591 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/create_ld_dynamic.cpp @@ -0,0 +1,163 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void TransformIrDynLdInstValid(abckit_Graph *ctxG, abckit_Inst *(*LdInstToCheck)(abckit_Graph *ctxG)) +{ + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + auto *mainInst = LdInstToCheck(ctxG); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + implG->IsetInput(retOp, mainInst, 0); +} + +static std::vector> CreateBBSchemaForDynLd(abckit_IsaApiDynamicOpcode opcode) +{ + return { + { + {}, {1}, {} + }, + { + {0}, {2}, { + {4, opcode, {}}, + {5, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + { + {1}, {}, {} + } + }; +} + +static void ValidTest(abckit_Inst *(*LdInstToCheck)(abckit_Graph *ctxG), + abckit_IsaApiDynamicOpcode expectedOpcode, + const std::string &expectedOutput, + bool skipExecute = false) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic.abc", "ld_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynLdInstValid(ctxG, LdInstToCheck); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynLd(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + if (!skipExecute) { + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic_modified.abc", "ld_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); + } +} + +class LibAbcKitDynLdInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnan, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdnanValid) +{ + ValidTest(dynG->IcreateLdnan, abckit_IsaApiDynamicOpcode_ldnan, "NaN\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdinfinity, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdinfinityValid) +{ + ValidTest(dynG->IcreateLdinfinity, abckit_IsaApiDynamicOpcode_ldinfinity, "Infinity\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdundefined, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdundefinedValid) +{ + ValidTest(dynG->IcreateLdundefined, abckit_IsaApiDynamicOpcode_ldundefined, "undefined\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnull, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdnullValid) +{ + ValidTest(dynG->IcreateLdnull, abckit_IsaApiDynamicOpcode_ldnull, "null\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsymbol, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdsymbolValid) +{ + ValidTest(dynG->IcreateLdsymbol, abckit_IsaApiDynamicOpcode_ldsymbol, "function Symbol\\(\\) \\{ \\[native code\\] \\}\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobal, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdglobalValid) +{ + ValidTest(dynG->IcreateLdglobal, abckit_IsaApiDynamicOpcode_ldglobal, "\\[object Object\\]\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdtrue, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdtrueValid) +{ + ValidTest(dynG->IcreateLdtrue, abckit_IsaApiDynamicOpcode_ldtrue, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfalse, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdfalseValid) +{ + ValidTest(dynG->IcreateLdfalse, abckit_IsaApiDynamicOpcode_ldfalse, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdhole, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdholeValid) +{ + ValidTest(dynG->IcreateLdhole, abckit_IsaApiDynamicOpcode_ldhole, "\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfunction, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdfunctionValid) +{ + ValidTest(dynG->IcreateLdfunction, abckit_IsaApiDynamicOpcode_ldfunction, "", true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnewtarget, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdnewtargetValid) +{ + ValidTest(dynG->IcreateLdnewtarget, abckit_IsaApiDynamicOpcode_ldnewtarget, "\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthis, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdthisValid) +{ + ValidTest(dynG->IcreateLdthis, abckit_IsaApiDynamicOpcode_ldthis, "\\[object Object\\]\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/loadstore/emptyobj.js b/libabckit/tests/ir/icreate/loadstore/emptyobj.js new file mode 100644 index 0000000000000000000000000000000000000000..d88ec049b62783b43117285f9da8dc32a87e44e2 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/emptyobj.js @@ -0,0 +1,16 @@ +function a() { + return 'abckit_test_value'; +} + +function stown() { + return {}; +} + +let res = stown() +if (res.abckit_test_key == undefined) { + print(res[0] ?? 'initial') +} else if (typeof res.abckit_test_key == 'function') { + print(res.abckit_test_key()) +} else { + print(res.abckit_test_key) +} diff --git a/libabckit/tests/ir/icreate/loadstore/ld_dynamic.cpp b/libabckit/tests/ir/icreate/loadstore/ld_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d0d7aef94da9047c4c749d6352586743eff42954 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/ld_dynamic.cpp @@ -0,0 +1,164 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static void TransformIrDynLdInstValid(abckit_Graph *ctxG, abckit_Inst *(*LdInstToCheck)(abckit_Graph *ctxG)) +{ + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + auto *mainInst = LdInstToCheck(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(retOp, mainInst, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static std::vector> CreateBBSchemaForDynLd(abckit_IsaApiDynamicOpcode opcode) +{ + return { + { + {}, {1}, {} + }, + { + {0}, {2}, { + {4, opcode, {}}, + {5, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + { + {1}, {}, {} + } + }; +} + +static void ValidTest(abckit_Inst *(*LdInstToCheck)(abckit_Graph *ctxG), + abckit_IsaApiDynamicOpcode expectedOpcode, + const std::string &expectedOutput, + bool skipExecute = false) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic.abc", "ld_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynLdInstValid(ctxG, LdInstToCheck); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynLd(expectedOpcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + if (!skipExecute) { + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ld_dynamic_modified.abc", "ld_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); + } +} + +class LibAbcKitDynLdInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnan, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdnanValid) +{ + ValidTest(dynG->IcreateLdnan, abckit_IsaApiDynamicOpcode_ldnan, "NaN\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdinfinity, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdinfinityValid) +{ + ValidTest(dynG->IcreateLdinfinity, abckit_IsaApiDynamicOpcode_ldinfinity, "Infinity\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdundefined, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdundefinedValid) +{ + ValidTest(dynG->IcreateLdundefined, abckit_IsaApiDynamicOpcode_ldundefined, "undefined\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnull, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdnullValid) +{ + ValidTest(dynG->IcreateLdnull, abckit_IsaApiDynamicOpcode_ldnull, "null\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsymbol, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdsymbolValid) +{ + ValidTest(dynG->IcreateLdsymbol, abckit_IsaApiDynamicOpcode_ldsymbol, "function Symbol\\(\\) \\{ \\[native code\\] \\}\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobal, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdglobalValid) +{ + ValidTest(dynG->IcreateLdglobal, abckit_IsaApiDynamicOpcode_ldglobal, "\\[object Object\\]\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdtrue, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdtrueValid) +{ + ValidTest(dynG->IcreateLdtrue, abckit_IsaApiDynamicOpcode_ldtrue, "true\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfalse, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdfalseValid) +{ + ValidTest(dynG->IcreateLdfalse, abckit_IsaApiDynamicOpcode_ldfalse, "false\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdhole, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdholeValid) +{ + ValidTest(dynG->IcreateLdhole, abckit_IsaApiDynamicOpcode_ldhole, "\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfunction, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdfunctionValid) +{ + ValidTest(dynG->IcreateLdfunction, abckit_IsaApiDynamicOpcode_ldfunction, "", true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnewtarget, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdnewtargetValid) +{ + ValidTest(dynG->IcreateLdnewtarget, abckit_IsaApiDynamicOpcode_ldnewtarget, "\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthis, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynLdInstTest, CreateDynLdthisValid) +{ + ValidTest(dynG->IcreateLdthis, abckit_IsaApiDynamicOpcode_ldthis, "\\[object Object\\]\n"); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/loadstore/ld_dynamic.js b/libabckit/tests/ir/icreate/loadstore/ld_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..56a4e36a2d1132ef334c13186ab696dd8b3f4e98 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/ld_dynamic.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) 2024 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. + */ + +class A { + foo(a) { + return a; + } +} + +let a = new A() +let res = a.foo(10) +print(res) diff --git a/libabckit/tests/ir/icreate/loadstore/ldglobalvar.js b/libabckit/tests/ir/icreate/loadstore/ldglobalvar.js new file mode 100644 index 0000000000000000000000000000000000000000..ee7d0f17cc9b976b3bb0a368a3561025b9144111 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/ldglobalvar.js @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 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. + */ + +globalThis.str = "globalvar_data"; + +function foo() { + return "funcfoo_data"; +} + +print(foo()) diff --git a/libabckit/tests/ir/icreate/loadstore/ldobjbyindex.js b/libabckit/tests/ir/icreate/loadstore/ldobjbyindex.js new file mode 100644 index 0000000000000000000000000000000000000000..26f104184405ae45ff45bedee977e92050f613a4 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/ldobjbyindex.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 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. + */ + +function foo() { + let o = { + 0: 'field_data', + } + return "just_data"; +} + +print(foo()) diff --git a/libabckit/tests/ir/icreate/loadstore/ldobjbyname.js b/libabckit/tests/ir/icreate/loadstore/ldobjbyname.js new file mode 100644 index 0000000000000000000000000000000000000000..e1f9710f1e8727e12cf024aa9121fb55ab10f0d4 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/ldobjbyname.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 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. + */ + +function foo() { + let o = { + field: 'field_data', + } + return "just_data"; +} + +print(foo()) diff --git a/libabckit/tests/ir/icreate/loadstore/ldobjbyvalue.js b/libabckit/tests/ir/icreate/loadstore/ldobjbyvalue.js new file mode 100644 index 0000000000000000000000000000000000000000..31316591c6c6b7efe4105de5bf33ec957bbb47c1 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/ldobjbyvalue.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 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. + */ + +function stown() { + let o = { + field: 'field_data', + } + return "just_data" +} + +print(stown()) + diff --git a/libabckit/tests/ir/icreate/loadstore/loadstore.cpp b/libabckit/tests/ir/icreate/loadstore/loadstore.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d9ad4711a1bba667c669b90183b336b411bb57ae --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/loadstore.cpp @@ -0,0 +1,688 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +static std::vector> CreateBBSchema(abckit_IsaApiDynamicOpcode opcode) +{ + helpers::BBSchema bb0 + { + {}, {1}, {} + }; + + helpers::BBSchema bb2{{1}, {}, {}}; + + if (opcode == abckit_IsaApiDynamicOpcode_stownbyname) { + return { + bb0, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {7, opcode, {4, 5}}, + {8, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stownbyvalue) { + return { + bb0, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}},\ + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {6, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {7, opcode, {4, 5, 6}}, + {8, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stownbyindex || opcode == abckit_IsaApiDynamicOpcode_wide_stownbyindex) { + return { + bb0, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_createobjectwithbuffer, {}}, + {5, abckit_IsaApiDynamicOpcode_createarraywithbuffer, {}}, + {6, abckit_IsaApiDynamicOpcode_stownbyindex, {4, 5}}, + {7, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {8, opcode, {4, 7}}, + {9, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stownbyvaluewithnameset) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_definefunc, {}}, + {6, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {7, opcode, {4, 6, 5}}, + {8, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stownbynamewithnameset) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_definefunc, {}}, + {6, opcode, {4, 5}}, + {7, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stobjbyname) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {6, opcode, {4, 5}}, + {7, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stobjbyvalue) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {6, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {7, opcode, {4, 6, 5}}, + {8, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stobjbyindex || opcode == abckit_IsaApiDynamicOpcode_wide_stobjbyindex) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createobjectwithbuffer, {}}, + {4, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {5, opcode, {3, 4}}, + {6, abckit_IsaApiDynamicOpcode_return, {3}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_ldobjbyvalue) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createobjectwithbuffer, {}}, + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {6, opcode, {3, 5}}, + {7, abckit_IsaApiDynamicOpcode_return, {6}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_ldobjbyname) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createobjectwithbuffer, {}}, + {5, opcode, {3}}, + {6, abckit_IsaApiDynamicOpcode_return, {5}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_ldobjbyindex) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_createobjectwithbuffer, {}}, + {5, opcode, {3}}, + {6, abckit_IsaApiDynamicOpcode_return, {5}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_ldglobalvar) { + return { + bb0, + { + {0}, {2}, { + {4, opcode, {}}, + {5, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + } else if (opcode == abckit_IsaApiDynamicOpcode_stglobalvar) { + return { + bb0, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {4, opcode, {3}}, + {5, abckit_IsaApiDynamicOpcode_ldglobal, {}}, + {6, abckit_IsaApiDynamicOpcode_ldobjbyname, {5}}, + {7, abckit_IsaApiDynamicOpcode_return, {6}}, + } + }, + bb2 + }; + } + LIBABCKIT_UNREACHABLE_TEST(DEBUG) +} + +class LibAbcKitCreateDynOwnInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyname, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynStownbynameValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "initial\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newKeyString = implM->CreateString(ctxM, "abckit_test_key"); + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createemptyobject); + abckit_Inst *newStOwn = dynG->IcreateStownbyname(ctxG, obj, newKeyString, newValue); + + implG->IinsertAfter(newValue, obj); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stownbyname); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "abckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvalue, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynStownbyvalueValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "initial\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newKeyString = implM->CreateString(ctxM, "abckit_test_key"); + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + auto *newKey = dynG->IcreateLoadString(ctxG, newKeyString); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createemptyobject); + abckit_Inst *newStOwn = dynG->IcreateStownbyvalue(ctxG, obj, newKey, newValue); + + implG->IinsertAfter(newKey, obj); + implG->IinsertAfter(newValue, newKey); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stownbyvalue); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "abckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyindex, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, DISABLED_CreateDynStownbyindexValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex.abc", "stownbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nundefined\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + + auto *oldStOwn = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_stownbyindex); + ASSERT_NE(oldStOwn, nullptr); + abckit_Inst *newStOwn = dynG->IcreateStownbyindex(ctxG, implG->IgetInput(oldStOwn, 0), newValue, 1); + implG->IinsertAfter(newValue, oldStOwn); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stownbyindex); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex_modified.abc", "stownbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nabckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStownbyindex, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, DISABLED_CreateDynWideStownbyindexValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex.abc", "stownbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nundefined\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + + auto *oldStOwn = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_stownbyindex); + ASSERT_NE(oldStOwn, nullptr); + abckit_Inst *newStOwn = dynG->IcreateWideStownbyindex(ctxG, implG->IgetInput(oldStOwn, 0), newValue, 1); + implG->IinsertAfter(newValue, oldStOwn); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_wide_stownbyindex); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stownbyindex_modified.abc", "stownbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nabckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvaluewithnameset, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynWideStownbyvaluewithnamesetValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "initial\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newKeyString = implM->CreateString(ctxM, "abckit_test_key"); + abckit_Method *funcB = helpers::findMethodByName(implI->MethodGetInspectContext(method), "a"); + auto *obj = dynG->IcreateCreateemptyobject(ctxG); + auto *newKey = dynG->IcreateLoadString(ctxG, newKeyString); + auto *defineB = dynG->IcreateDefinefunc(ctxG, funcB, 0); + abckit_Inst *newStOwn = dynG->IcreateStownbyvaluewithnameset(ctxG, obj, newKey, defineB); + + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, obj, 0); + + implG->IinsertBefore(obj, ret); + implG->IinsertAfter(defineB, obj); + implG->IinsertAfter(newKey, defineB); + implG->IinsertAfter(newStOwn, newKey); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stownbyvaluewithnameset); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "abckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbynamewithnameset, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynWideStownbynamewithnamesetValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "initial\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newKeyString = implM->CreateString(ctxM, "abckit_test_key"); + abckit_Method *funcB = helpers::findMethodByName(implI->MethodGetInspectContext(method), "a"); + auto *obj = dynG->IcreateCreateemptyobject(ctxG); + auto *defineB = dynG->IcreateDefinefunc(ctxG, funcB, 0); + abckit_Inst *newStOwn = dynG->IcreateStownbynamewithnameset(ctxG, obj, newKeyString, defineB); + + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, obj, 0); + + implG->IinsertBefore(obj, ret); + implG->IinsertAfter(defineB, obj); + implG->IinsertAfter(newStOwn, defineB); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stownbynamewithnameset); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "abckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyname, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynStobjbynameValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "initial\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newKeyString = implM->CreateString(ctxM, "abckit_test_key"); + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + auto *obj = dynG->IcreateCreateemptyobject(ctxG); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + abckit_Inst *newStOwn = dynG->IcreateStobjbyname(ctxG, obj, newKeyString, newValue); + + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, obj, 0); + + implG->IinsertBefore(obj, ret); + implG->IinsertAfter(newValue, obj); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stobjbyname); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "abckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyvalue, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynStobjbyvalueValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "initial\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newKeyString = implM->CreateString(ctxM, "abckit_test_key"); + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + + auto *obj = dynG->IcreateCreateemptyobject(ctxG); + auto *newKey = dynG->IcreateLoadString(ctxG, newKeyString); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + abckit_Inst *newStOwn = dynG->IcreateStobjbyvalue(ctxG, obj, newKey, newValue); + + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, obj, 0); + + implG->IinsertBefore(obj, ret); + implG->IinsertAfter(newValue, obj); + implG->IinsertAfter(newKey, newValue); + implG->IinsertAfter(newStOwn, newKey); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stobjbyvalue); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/emptyobj_modified.abc", "emptyobj"); + EXPECT_TRUE(helpers::Match(output, "abckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyindex, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynStobjbyindexValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex.abc", "stobjbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nundefined\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createobjectwithbuffer); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + abckit_Inst *newStOwn = dynG->IcreateStobjbyindex(ctxG, obj, newValue, 1); + + implG->IinsertAfter(newValue, obj); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stobjbyindex); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex_modified.abc", "stobjbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nabckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStobjbyindex, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, CreateDynWideStobjbyindexValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex.abc", "stobjbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nundefined\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *newValueString = implM->CreateString(ctxM, "abckit_test_value"); + + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createobjectwithbuffer); + auto *newValue = dynG->IcreateLoadString(ctxG, newValueString); + abckit_Inst *newStOwn = dynG->IcreateWideStobjbyindex(ctxG, obj, newValue, 1); + + implG->IinsertAfter(newValue, obj); + implG->IinsertAfter(newStOwn, newValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_wide_stobjbyindex); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stobjbyindex_modified.abc", "stobjbyindex"); + EXPECT_TRUE(helpers::Match(output, "a\nabckit_test_value\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyvalue, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, IcreateDynLdobjbyvalueValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyvalue.abc", "ldobjbyvalue"); + EXPECT_TRUE(helpers::Match(output, "just_data\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyvalue.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyvalue_modified.abc", + "stown", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *fieldName = implM->CreateString(ctxM, "field"); + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createobjectwithbuffer); + auto *stringObj = dynG->IcreateLoadString(ctxG, fieldName); + auto *fieldValue = dynG->IcreateLdobjbyvalue(ctxG, obj, stringObj); + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, fieldValue, 0); + implG->IinsertBefore(fieldValue, ret); + implG->IinsertBefore(stringObj, fieldValue); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_ldobjbyvalue); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyvalue_modified.abc", "ldobjbyvalue"); + EXPECT_TRUE(helpers::Match(output, "field_data\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyname, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, IcreateDynLdobjbynameValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyname.abc", "ldobjbyname"); + EXPECT_TRUE(helpers::Match(output, "just_data\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyname.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyname_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *fieldName = implM->CreateString(ctxM, "field"); + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createobjectwithbuffer); + auto *fieldValue = dynG->IcreateLdobjbyname(ctxG, obj, fieldName); + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, fieldValue, 0); + implG->IinsertBefore(fieldValue, ret); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_ldobjbyname); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyname_modified.abc", "ldobjbyname"); + EXPECT_TRUE(helpers::Match(output, "field_data\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyindex, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, IcreateDynLdobjbyindexValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyindex.abc", "ldobjbyindex"); + EXPECT_TRUE(helpers::Match(output, "just_data\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyindex.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyindex_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *obj = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_createobjectwithbuffer); + auto *fieldValue = dynG->IcreateLdobjbyindex(ctxG, obj, 0); + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, fieldValue, 0); + implG->IinsertBefore(fieldValue, ret); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_ldobjbyindex); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldobjbyindex_modified.abc", "ldobjbyindex"); + EXPECT_TRUE(helpers::Match(output, "field_data\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobalvar, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, IcreateDynLdglobalvarValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldglobalvar.abc", "ldglobalvar"); + EXPECT_TRUE(helpers::Match(output, "funcfoo_data\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldglobalvar.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/ldglobalvar_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *varName = implM->CreateString(ctxM, "str"); + auto *globalValue = dynG->IcreateLdglobalvar(ctxG, varName); + auto *ret = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + implG->IsetInput(ret, globalValue, 0); + implG->IinsertBefore(globalValue, ret); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_ldglobalvar); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/ldglobalvar_modified.abc", "ldglobalvar"); + EXPECT_TRUE(helpers::Match(output, "globalvar_data\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStglobalvar, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynOwnInstTest, IcreateDynStglobalvarValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stglobalvar.abc", "stglobalvar"); + EXPECT_TRUE(helpers::Match(output, "globalvar_data\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/loadstore/stglobalvar.abc", + ABCKIT_ABC_DIR "ir/icreate/loadstore/stglobalvar_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *varName = implM->CreateString(ctxM, "str"); + abckit_String *funcfooData = implM->CreateString(ctxM, "funcfoo_data"); + auto *newStr = dynG->IcreateLoadString(ctxG, funcfooData); + auto *stGlobalVar = dynG->IcreateStglobalvar(ctxG, newStr, varName); + auto *ldGlobal = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_ldglobal); + implG->IinsertBefore(stGlobalVar, ldGlobal); + implG->IinsertBefore(newStr, stGlobalVar); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas = CreateBBSchema(abckit_IsaApiDynamicOpcode_stglobalvar); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/loadstore/stglobalvar_modified.abc", "stglobalvar"); + EXPECT_TRUE(helpers::Match(output, "funcfoo_data\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/loadstore/stglobalvar.js b/libabckit/tests/ir/icreate/loadstore/stglobalvar.js new file mode 100644 index 0000000000000000000000000000000000000000..5cf3f60b463137fca7eabab16adc94328ead8180 --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/stglobalvar.js @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 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. + */ + +globalThis.str = "globalvar_data"; + +function foo() { + return globalThis.str; +} + +print(foo()) diff --git a/libabckit/tests/ir/icreate/loadstore/stobjbyindex.js b/libabckit/tests/ir/icreate/loadstore/stobjbyindex.js new file mode 100644 index 0000000000000000000000000000000000000000..20f7ef9a1bd312ff7f4eafe4cdad21a5051908ed --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/stobjbyindex.js @@ -0,0 +1,10 @@ +function stown() { + let o = { + 0: 'a', + } + return o; +} + +let o = stown() +print(o[0]) +print(o[1]) diff --git a/libabckit/tests/ir/icreate/loadstore/stownbyindex.js b/libabckit/tests/ir/icreate/loadstore/stownbyindex.js new file mode 100644 index 0000000000000000000000000000000000000000..d3324c8d7b5f389a583de13af2d6520eb8bb7a3f --- /dev/null +++ b/libabckit/tests/ir/icreate/loadstore/stownbyindex.js @@ -0,0 +1,9 @@ +function stown() { + return { + 0: ['a'] + }; +} + +let res = stown() +print(res[0]) +print(res[1]) diff --git a/libabckit/tests/ir/icreate/modules/inst_modules_dynamic.cpp b/libabckit/tests/ir/icreate/modules/inst_modules_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d144a0230f79e88e7bcf298d1b092386887a58f --- /dev/null +++ b/libabckit/tests/ir/icreate/modules/inst_modules_dynamic.cpp @@ -0,0 +1,455 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "ir_impl.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit { +namespace test { + +auto impl = abckit_GetApiImpl(1); +auto implI = abckit_GetInspectApiImpl(1); +auto implM = abckit_GetModifyApiImpl(1); +auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +void TransformIrGetModuleNamespace(abckit_Graph *ctxG, abckit_String *funcName, bool isWide = false) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module2"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + auto getModuleNamespaceInst = isWide ? dynG->IcreateWideGetmodulenamespace(ctxG, ctxFinder.module) : dynG->IcreateGetmodulenamespace(ctxG, ctxFinder.module); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto ldObjByNameInst = dynG->IcreateLdobjbyname(ctxG, getModuleNamespaceInst, funcName); + auto callInst = dynG->IcreateCallthis0(ctxG, ldObjByNameInst, getModuleNamespaceInst); + implG->IinsertBefore(getModuleNamespaceInst, ldundefI); + implG->IinsertBefore(ldObjByNameInst, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrLdExternalModuleVar(abckit_Graph *ctxG, abckit_String *funcName, bool isWide = false) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "inst_modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + helpers::ImportByAliasContext importFinder = {nullptr, "MF1M2"}; + implI->ModuleEnumerateImports(ctxFinder.module, &importFinder, helpers::importByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(importFinder.id, nullptr); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + auto ldExternalModuleVarInst = isWide ? dynG->IcreateWideLdexternalmodulevar(ctxG, importFinder.id) : dynG->IcreateLdexternalmodulevar(ctxG, importFinder.id); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldExternalModuleVarInst, funcName); + auto callInst = dynG->IcreateCallarg0(ctxG, ldExternalModuleVarInst); + implG->IinsertBefore(ldExternalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrLdLocalModuleVar(abckit_Graph *ctxG, abckit_String *localVarName, abckit_String *funcName, bool isWide = false) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "inst_modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + helpers::ExportByAliasContext exportFinder = {nullptr, "LocalExportLet"}; + implI->ModuleEnumerateExports(ctxFinder.module, &exportFinder, helpers::exportByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(exportFinder.ed, nullptr); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + auto tryLdGlobalByNameInst = dynG->IcreateTryldglobalbyname(ctxG, funcName); + auto ldLocalModuleVarInst = isWide ? dynG->IcreateWideLdlocalmodulevar(ctxG, exportFinder.ed) : dynG->IcreateLdlocalmodulevar(ctxG, exportFinder.ed); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldLocalModuleVarInst, localVarName); + auto callInst = dynG->IcreateCallarg1(ctxG, tryLdGlobalByNameInst, ldLocalModuleVarInst); + implG->IinsertBefore(tryLdGlobalByNameInst, ldundefI); + implG->IinsertBefore(ldLocalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrStModuleVar(abckit_Graph *ctxG, abckit_String *localVarName, abckit_String *funcName, bool isWide = false) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "inst_modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + helpers::ExportByAliasContext exportFinder = {nullptr, "LocalExportConst"}; + implI->ModuleEnumerateExports(ctxFinder.module, &exportFinder, helpers::exportByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(exportFinder.ed, nullptr); + + auto *startBB = implG->GgetStartBasicBlock(ctxG); + auto *const1Inst = implG->BBgetLastInst(startBB); + auto *mainBB = implG->BBgetSuccBlock(startBB, 0); + auto *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + auto tryLdGlobalByNameInst = dynG->IcreateTryldglobalbyname(ctxG, funcName); + auto stModuleVarInst = isWide ? dynG->IcreateWideStmodulevar(ctxG, const1Inst, exportFinder.ed) : dynG->IcreateStmodulevar(ctxG, const1Inst, exportFinder.ed); + auto ldLocalModuleVarInst = isWide ? dynG->IcreateWideLdlocalmodulevar(ctxG, exportFinder.ed) : dynG->IcreateLdlocalmodulevar(ctxG, exportFinder.ed); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldLocalModuleVarInst, localVarName); + auto callInst = dynG->IcreateCallarg1(ctxG, tryLdGlobalByNameInst, ldLocalModuleVarInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(tryLdGlobalByNameInst, ldundefI); + implG->IinsertBefore(stModuleVarInst, ldundefI); + implG->IinsertBefore(ldLocalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +std::vector> CreateBBSchemaForModules() +{ + return { + { + {}, {1}, { + {3, abckit_IsaApiDynamicOpcode_Constant, {}}, + {4, abckit_IsaApiDynamicOpcode_Constant, {}} + } + }, + { + {0}, {2}, { + {10, abckit_IsaApiDynamicOpcode_ldundefined, {}}, + {11, abckit_IsaApiDynamicOpcode_stmodulevar, {10}}, + {12, abckit_IsaApiDynamicOpcode_definefunc, {}}, + {13, abckit_IsaApiDynamicOpcode_stmodulevar, {12}}, + {14, abckit_IsaApiDynamicOpcode_getmodulenamespace, {}}, + {15, abckit_IsaApiDynamicOpcode_getmodulenamespace, {}}, + {16, abckit_IsaApiDynamicOpcode_getmodulenamespace, {}}, + {17, abckit_IsaApiDynamicOpcode_getmodulenamespace, {}}, + {18, abckit_IsaApiDynamicOpcode_stmodulevar, {17}}, + {19, abckit_IsaApiDynamicOpcode_ldhole, {}}, + {20, abckit_IsaApiDynamicOpcode_defineclasswithbuffer, {19}}, + {21, abckit_IsaApiDynamicOpcode_ldobjbyname, {20}}, + {22, abckit_IsaApiDynamicOpcode_stmodulevar, {20}}, + {23, abckit_IsaApiDynamicOpcode_stmodulevar, {3}}, + {24, abckit_IsaApiDynamicOpcode_stmodulevar, {4}}, + {25, abckit_IsaApiDynamicOpcode_ldhole, {}}, + {26, abckit_IsaApiDynamicOpcode_defineclasswithbuffer, {25}}, + {27, abckit_IsaApiDynamicOpcode_ldobjbyname, {26}}, + {28, abckit_IsaApiDynamicOpcode_stmodulevar, {26}}, + {29, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, {}}, + {30, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {29}}, + {31, abckit_IsaApiDynamicOpcode_callarg0, {29}}, + {32, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, {}}, + {33, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {32}}, + {34, abckit_IsaApiDynamicOpcode_callarg0, {32}}, + {35, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, {}}, + {36, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {35}}, + {37, abckit_IsaApiDynamicOpcode_callarg0, {35}}, + {38, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, {}}, + {39, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {38}}, + {40, abckit_IsaApiDynamicOpcode_callarg0, {38}}, + {41, abckit_IsaApiDynamicOpcode_ldobjbyname, {14}}, + {42, abckit_IsaApiDynamicOpcode_callthis0, {14, 41}}, + {43, abckit_IsaApiDynamicOpcode_ldobjbyname, {14}}, + {44, abckit_IsaApiDynamicOpcode_callthis0, {14, 43}}, + {45, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}, + {46, abckit_IsaApiDynamicOpcode_ldlocalmodulevar, {}}, + {47, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {46}}, + {48, abckit_IsaApiDynamicOpcode_callarg1, {46, 45}}, + {49, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}, + {50, abckit_IsaApiDynamicOpcode_ldlocalmodulevar, {}}, + {51, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {50}}, + {52, abckit_IsaApiDynamicOpcode_callarg1, {50, 49}}, + {53, abckit_IsaApiDynamicOpcode_ldobjbyname, {15}}, + {54, abckit_IsaApiDynamicOpcode_callthis0, {15, 53}}, + {55, abckit_IsaApiDynamicOpcode_ldobjbyname, {16}}, + {56, abckit_IsaApiDynamicOpcode_callthis0, {16, 55}}, + {57, abckit_IsaApiDynamicOpcode_ldundefined, {}}, + {58, abckit_IsaApiDynamicOpcode_returnundefined, {}} + }, + }, + { + {1}, {}, {} + } + }; +} + +class LibAbcKitIModulesDynamicTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetmodulenamespace, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynGetmodulenamespace) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "SameFuncInDifferentModules"); + + TransformIrGetModuleNamespace(ctxG, abckit_str); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_getmodulenamespace, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_ldobjbyname, {59}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_callthis0, {59, 60}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "the same func from module2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideGetmodulenamespace, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynWideGetmodulenamespace) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "SameFuncInDifferentModules"); + + TransformIrGetModuleNamespace(ctxG, abckit_str, true); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_wide_getmodulenamespace, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_ldobjbyname, {59}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_callthis0, {59, 60}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "the same func from module2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdexternalmodulevar, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynLdexternalmodulevar) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "MF1M2"); + + TransformIrLdExternalModuleVar(ctxG, abckit_str); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {59}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_callarg0, {59}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "regular import func1 from module2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdexternalmodulevar, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynWideLdexternalmodulevar) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "MF1M2"); + + TransformIrLdExternalModuleVar(ctxG, abckit_str, true); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_wide_ldexternalmodulevar, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {59}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_callarg0, {59}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "regular import func1 from module2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdlocalmodulevar, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynLdlocalmodulevar) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "LocalExportLet"); + abckit_String *abckit_call_str = implM->CreateString(ctxM, "print"); + + TransformIrLdLocalModuleVar(ctxG, abckit_str, abckit_call_str); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_ldlocalmodulevar, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {60}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 50, {62, abckit_IsaApiDynamicOpcode_callarg1, {60, 59}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdlocalmodulevar, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynWideLdlocalmodulevar) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "LocalExportLet"); + abckit_String *abckit_call_str = implM->CreateString(ctxM, "print"); + + TransformIrLdLocalModuleVar(ctxG, abckit_str, abckit_call_str, true); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_wide_ldlocalmodulevar, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {60}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 50, {62, abckit_IsaApiDynamicOpcode_callarg1, {60, 59}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStmodulevar, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynStmodulevar) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "LocalExportConst"); + abckit_String *abckit_call_str = implM->CreateString(ctxM, "print"); + + TransformIrStModuleVar(ctxG, abckit_str, abckit_call_str); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_stmodulevar, {4}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_ldlocalmodulevar, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 50, {62, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {61}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 51, {63, abckit_IsaApiDynamicOpcode_callarg1, {61, 59}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "1\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStmodulevar, abc-kind=JS, category=positive +TEST_F(LibAbcKitIModulesDynamicTest, LibAbcKitTestCreateDynWideStmodulevar) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", "inst_modules_dynamic"); + std::string expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", + "inst_modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *abckit_str = implM->CreateString(ctxM, "LocalExportConst"); + abckit_String *abckit_call_str = implM->CreateString(ctxM, "print"); + + TransformIrStModuleVar(ctxG, abckit_str, abckit_call_str, true); + }, + [](abckit_Graph *ctxG) { + auto BBSchema = CreateBBSchemaForModules(); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 47, {59, abckit_IsaApiDynamicOpcode_tryldglobalbyname, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 48, {60, abckit_IsaApiDynamicOpcode_wide_stmodulevar, {4}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 49, {61, abckit_IsaApiDynamicOpcode_wide_ldlocalmodulevar, {}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 50, {62, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, {61}}); + BBSchema[1].instSchemas.insert(BBSchema[1].instSchemas.begin() + 51, {63, abckit_IsaApiDynamicOpcode_callarg1, {61, 59}}); + helpers::VerifyGraph(ctxG, BBSchema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/modules/inst_modules_dynamic_modified.abc", "inst_modules_dynamic"); + expected += "1\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/modules/inst_modules_dynamic.js b/libabckit/tests/ir/icreate/modules/inst_modules_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..8ab63b5ec65678d085ff5492cb533e0479c3aee7 --- /dev/null +++ b/libabckit/tests/ir/icreate/modules/inst_modules_dynamic.js @@ -0,0 +1,37 @@ +// Regular +import {RegularImportFunc1FromModule1} from "./modules/module1" +import {RegularImportFunc1FromModule2 as MF1M2} from "./modules/module2" +import RegularDefaultImportFunc1FromModule3 from "./modules/module3" +import {default as RegularDefaultImportFunc2FromModule2} from "./modules/module2" + +// Namespace +import * as NS1 from "./modules/module1" +import * as NS2 from "./modules/module2" +import * as NS3 from "./modules/module3" + +// Local export +export function LocalExportFunc() {} +export class LocalExportClass {} +export let LocalExportLet = 2; +export var LocalExportVar; +export const LocalExportConst = 1; +export default class LocalDefaultExportClass {} + +// Indirect export +export {IndirectExportFunc1FromModule1} from "./modules/module1" +export {IndirectExportFunc2FromModule1 as MF2M1} from "./modules/module1" + +// Star export +export * as StarExport from "./modules/module1" +export * from "./modules/module2" + +RegularImportFunc1FromModule1(); +MF1M2(); +RegularDefaultImportFunc1FromModule3(); +RegularDefaultImportFunc2FromModule2(); +NS1.NamespaceImportFunc2FromModule1(); +NS1.NamespaceImportFunc3FromModule1(); +print(LocalExportConst); +print(LocalExportLet); +NS2.NamespaceImportFunc3FromModule2(); +NS3.SameFuncInDifferentModules(); diff --git a/libabckit/tests/ir/icreate/modules/modules/module1.js b/libabckit/tests/ir/icreate/modules/modules/module1.js new file mode 100644 index 0000000000000000000000000000000000000000..ffe5e5a90fba7a904c39666672a3f8b456cfeac4 --- /dev/null +++ b/libabckit/tests/ir/icreate/modules/modules/module1.js @@ -0,0 +1,24 @@ +export function RegularImportFunc1FromModule1() +{ + print("regular import func1 from module1") +} +export function NamespaceImportFunc2FromModule1() +{ + print("namespace import func2 from module1") +} +export function NamespaceImportFunc3FromModule1() +{ + print("namespace import func3 from module1") +} +export function IndirectExportFunc1FromModule1() +{ + print("indirect export func1 from module1") +} +export function IndirectExportFunc2FromModule1() +{ + print("indirect export func2 from module1") +} +export function SameFuncInDifferentModules() +{ + print("the same func from module1") +} \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/modules/modules/module2.js b/libabckit/tests/ir/icreate/modules/modules/module2.js new file mode 100644 index 0000000000000000000000000000000000000000..ee8ce0f48797eff6aa83e5b85ce1fcf9a671407c --- /dev/null +++ b/libabckit/tests/ir/icreate/modules/modules/module2.js @@ -0,0 +1,18 @@ +export function RegularImportFunc1FromModule2() +{ + print("regular import func1 from module2") +} + +export default function RegularDefaultImportFunc2FromModule2() +{ + print("regular default import func2 from module2") +} + +export function NamespaceImportFunc3FromModule2() +{ + print("namespace import func3 from module2") +} +export function SameFuncInDifferentModules() +{ + print("the same func from module2") +} \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/modules/modules/module3.js b/libabckit/tests/ir/icreate/modules/modules/module3.js new file mode 100644 index 0000000000000000000000000000000000000000..d1fedd9fa26a88664757fff3bfa1e5fcd8f6a808 --- /dev/null +++ b/libabckit/tests/ir/icreate/modules/modules/module3.js @@ -0,0 +1,13 @@ + +export default function RegularDefaultImportFunc1FromModule3() +{ + print("regular default import func1 from module3") +} +export function SameFuncInDifferentModules() +{ + print("the same func from module3") +} +export function NewImportedFunc() +{ + print("new imported func from module3") +} \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/objects/objects.cpp b/libabckit/tests/ir/icreate/objects/objects.cpp new file mode 100644 index 0000000000000000000000000000000000000000..76e766f8af77ebedbf1c292e15205e1ae2e9a929 --- /dev/null +++ b/libabckit/tests/ir/icreate/objects/objects.cpp @@ -0,0 +1,276 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "ir_impl.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitICreateObjectsStaticTest : public ::testing::Test {}; + +static void TransformIrCreateNewObject(abckit_Graph *ctxG) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "objects"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "B"}; + implI->ModuleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxClassFinder.klass, nullptr); + + auto method = helpers::findMethodByName(ctxG->ctxI, "bar"); + + abckit_Inst *newObjectInst = statG->IcreateNewObject(ctxG, ctxClassFinder.klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + + implG->IinsertBefore(newObjectInst, lastInst); + abckit_Inst *callInst = statG->IcreateCallStatic(ctxG, method, 1, newObjectInst); + implG->IinsertAfter(callInst, newObjectInst); +} + +static void TransformIrCreateInitObject(abckit_Graph *ctxG, size_t numArg) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "objects"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "C"}; + implI->ModuleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxClassFinder.klass, nullptr); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + abckit_Inst *constantInst = numArg > 0 ? implG->GcreateConstantI64(ctxG, 0x1) : nullptr; + if (constantInst != nullptr) { + implG->IinsertBefore(constantInst, lastInst); + } + abckit_Inst *initObjectInst {nullptr}; + switch (numArg) { + case 0: { + auto method1 = helpers::findMethodByName(ctxG->ctxI, "_ctor_:objects.C;void;"); + ASSERT_NE(method1, nullptr); + initObjectInst = statG->IcreateInitObject(ctxG, method1, 0); + break; + } + case 1: { + auto method1 = helpers::findMethodByName(ctxG->ctxI, "_ctor_:objects.C;i32;void;"); + ASSERT_NE(method1, nullptr); + initObjectInst = statG->IcreateInitObject(ctxG, method1, 1, constantInst); + break; + } + case 2: { + auto method1 = helpers::findMethodByName(ctxG->ctxI, "_ctor_:objects.C;i32;i32;void;"); + ASSERT_NE(method1, nullptr); + initObjectInst = statG->IcreateInitObject(ctxG, method1, 2, constantInst, constantInst); + break; + } + case 3: { + auto method1 = helpers::findMethodByName(ctxG->ctxI, "_ctor_:objects.C;i32;i32;i32;void;"); + ASSERT_NE(method1, nullptr); + initObjectInst = statG->IcreateInitObject(ctxG, method1, 3, constantInst, constantInst, constantInst); + break; + } + case 4: { + auto method1 = helpers::findMethodByName(ctxG->ctxI, "_ctor_:objects.C;i32;i32;i32;i32;void;"); + ASSERT_NE(method1, nullptr); + initObjectInst = statG->IcreateInitObject(ctxG, method1, 4, constantInst, constantInst, constantInst, constantInst); + break; + } + case 5: { + auto method1 = helpers::findMethodByName(ctxG->ctxI, "_ctor_:objects.C;i32;i32;i32;i32;i32;void;"); + ASSERT_NE(method1, nullptr); + initObjectInst = statG->IcreateInitObject(ctxG, method1, 5, constantInst, constantInst, constantInst, constantInst, constantInst); + break; + } + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(initObjectInst, lastInst); +} + +void InitObjectTest(size_t numArg, helpers::InstSchema initObjectInst, std::string expectedOutput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/objects/objects.abc", "objects/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"A\"\n")); + + std::vector> startBB = {}; + if (numArg != 0) { + startBB = {{0, abckit_IsaApiStaticOpcode_Constant, {}}}; + } + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/objects/objects.abc", + ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", + "main", + [numArg](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateInitObject(ctxG, numArg); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchema = { + { + {}, {1}, startBB + }, + { + {0}, {2}, { + {1, abckit_IsaApiStaticOpcode_InitObject, {}}, + {4, abckit_IsaApiStaticOpcode_CallVirtual, {1}}, + initObjectInst, + {6, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + + }, + }, + { + {1}, {}, {} + } + }; + helpers::VerifyGraph(ctxG, bbSchema); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", "objects/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateNewObject) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/objects/objects.abc", "objects/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"A\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/objects/objects.abc", + ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateNewObject(ctxG); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchema = { + { + {}, {1}, {} + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {3, abckit_IsaApiStaticOpcode_CallVirtual, {0}}, + {4, abckit_IsaApiStaticOpcode_NewObject, {}}, + {5, abckit_IsaApiStaticOpcode_CallStatic, {4}}, + {6, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + + }, + }, + { + {1}, {}, {} + } + }; + helpers::VerifyGraph(ctxG, bbSchema); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", "objects/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"A\"\n\"B\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", + ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) {}, + [&](abckit_Graph *ctxG) { + std::vector> bbSchema = { + { + {}, {1}, {} + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_InitObject, {}}, + {3, abckit_IsaApiStaticOpcode_CallVirtual, {0}}, + {4, abckit_IsaApiStaticOpcode_NewObject, {}}, + {5, abckit_IsaApiStaticOpcode_CallStatic, {4}}, + {6, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + + }, + }, + { + {1}, {}, {} + } + }; + helpers::VerifyGraph(ctxG, bbSchema); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/objects/objects_modified.abc", "objects/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"A\"\n\"B\"\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateInitObjectArg0) +{ + InitObjectTest(0, {4, abckit_IsaApiStaticOpcode_InitObject, {}}, "\"A\"\n\"C\"\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateInitObjectArg1) +{ + InitObjectTest(1, {4, abckit_IsaApiStaticOpcode_InitObject, {0}}, "\"A\"\n\"C 1\"\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateInitObjectArg2) +{ + InitObjectTest(2, {4, abckit_IsaApiStaticOpcode_InitObject, {0, 0}}, "\"A\"\n\"C 11\"\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateInitObjectArg3) +{ + InitObjectTest(3, {4, abckit_IsaApiStaticOpcode_InitObject, {0, 0, 0}}, "\"A\"\n\"C 111\"\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateInitObjectArg4) +{ + InitObjectTest(4, {4, abckit_IsaApiStaticOpcode_InitObject, {0, 0, 0, 0}}, "\"A\"\n\"C 1111\"\n"); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitICreateObjectsStaticTest, LibAbcKitTestCreateIcreateInitObjectArg5) +{ + InitObjectTest(5, {4, abckit_IsaApiStaticOpcode_InitObject, {0, 0, 0, 0, 0}}, "\"A\"\n\"C 11111\"\n"); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/icreate/objects/objects.ets b/libabckit/tests/ir/icreate/objects/objects.ets new file mode 100644 index 0000000000000000000000000000000000000000..bdb02e5d52fb30abe4a3a70f7b522c67b974ec6c --- /dev/null +++ b/libabckit/tests/ir/icreate/objects/objects.ets @@ -0,0 +1,41 @@ +class A { + constructor() {} + constructor(a: int, b: int) { + console.log("A " + a + b) + } + foo() { + console.log("A") + } +} + +class B {} + +class C { + constructor() { + console.log("C") + } + constructor(a: int) { + console.log("C " + a) + } + constructor(a: int, b: int) { + console.log("C " + a + b) + } + constructor(a: int, b: int, c: int) { + console.log("C " + a + b + c) + } + constructor(a: int, b: int, c: int, d:int) { + console.log("C " + a + b + c + d) + } + constructor(a: int, b: int, c: int, d: int, e: int) { + console.log("C " + a + b + c + d + e) + } +} + +function bar(b: B) { + console.log("B") +} + +function main() { + let a = new A() + a.foo() +} diff --git a/libabckit/tests/ir/icreate/return/return_dynamic.cpp b/libabckit/tests/ir/icreate/return/return_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2e098d75f0eb8dd4c60d122966bc00d7d5230062 --- /dev/null +++ b/libabckit/tests/ir/icreate/return/return_dynamic.cpp @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +namespace { + void TransformIrDynReturnundefinedInstValid(abckit_Graph *ctxG, abckit_Inst *(*ReturnundefinedInstToCheck)(abckit_Graph *ctxG)) + { + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + + auto *mainInst = ReturnundefinedInstToCheck(ctxG); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + implG->Iremove(retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + void TransformIrDynReturnInstValid(abckit_Graph *ctxG, abckit_Inst *(*ReturnInstToCheck)(abckit_Graph *ctxG, abckit_Inst* acc)) + { + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + + auto *constZero = implG->GcreateConstantU64(ctxG, 0); + auto *mainInst = ReturnInstToCheck(ctxG, constZero); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + implG->Iremove(retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + std::vector> CreateBBSchemaForDynReturnundefined() + { + return { + { + {}, {1}, {} + }, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_returnundefined, {}} + } + }, + { + {1}, {}, {} + } + }; + } + + std::vector> CreateBBSchemaForDynReturn() + { + return { + { + {}, {1}, { + {4, abckit_IsaApiDynamicOpcode_Constant, {}} + } + }, + { + {0}, {2}, { + {5, abckit_IsaApiDynamicOpcode_return, {4}} + } + }, + { + {1}, {}, {} + } + }; + } +} // namespace + +class LibAbcKitCreateDynReturnInstTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturnundefined, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynReturnInstTest, CreateDynReturnundefinedValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic.abc", "return_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynReturnundefinedInstValid(ctxG, dynG->IcreateReturnundefined); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynReturnundefined()); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic_modified.abc", "return_dynamic"); + EXPECT_TRUE(helpers::Match(output, "undefined\n")); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturn, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynReturnInstTest, CreateDynReturnValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic.abc", "return_dynamic"); + EXPECT_TRUE(helpers::Match(output, "10\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic_modified_0.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynReturnInstValid(ctxG, dynG->IcreateReturn); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynReturn()); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_dynamic_modified_0.abc", "return_dynamic"); + EXPECT_TRUE(helpers::Match(output, "0\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/return/return_dynamic.js b/libabckit/tests/ir/icreate/return/return_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..c96b24e87eb8488137f4a0d55537aa361ee040f7 --- /dev/null +++ b/libabckit/tests/ir/icreate/return/return_dynamic.js @@ -0,0 +1,9 @@ +class A { + foo(a) { + return a; + } +} + +let a = new A() +let res = a.foo(10) +print(res) \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/return/return_static.cpp b/libabckit/tests/ir/icreate/return/return_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..05da385eea34f772e39eed6218d3be8f2db29243 --- /dev/null +++ b/libabckit/tests/ir/icreate/return/return_static.cpp @@ -0,0 +1,152 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitCreateReturnInstTest : public ::testing::Test {}; + +static void TransformIrCreateReturnInstValid(abckit_Graph *ctxG) +{ + abckit_Inst *firstInst = implG->GcreateConstantI64(ctxG, 5); + abckit_Inst *mainInst = statG->IcreateReturn(ctxG, firstInst); + ASSERT_NE(mainInst, nullptr); + + auto retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->Iremove(retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrCreateReturnVoidInstValid(abckit_Graph *ctxG) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + abckit_Inst *inputInst = implG->BBgetFirstInst(startBB); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *mainInst = statG->IcreateReturnVoid(ctxG); + ASSERT_NE(mainInst, nullptr); + + auto callVirt = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + ASSERT_NE(callVirt, nullptr); + abckit_Inst *nextInst = implG->IgetNext(callVirt); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->Iremove(nextInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(mainInst, callVirt); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(callVirt, inputInst, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturn, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateReturnInstTest, CreateReturnValid) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_static.abc", "return_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "10\n11\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/return/return_static.abc", + ABCKIT_ABC_DIR "ir/icreate/return/return_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateReturnInstValid(ctxG); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {2, abckit_IsaApiStaticOpcode_Constant, {}} + } + }, + { + {0}, {2}, { + {3, abckit_IsaApiStaticOpcode_Return, {2}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_static_modified.abc", "return_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "5\n11\n")); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturnVoid, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitCreateReturnInstTest, CreateReturnVoidValid) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_static.abc", "return_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "10\n11\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/return/return_static.abc", + ABCKIT_ABC_DIR "ir/icreate/return/return_static_modified.abc", + "foo1", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrCreateReturnVoidInstValid(ctxG); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas( + { + { + {}, {1}, { + {1, abckit_IsaApiStaticOpcode_Parameter, {}} + } + }, + { + {0}, {2}, { + {2, abckit_IsaApiStaticOpcode_LoadStatic, {}}, + {5, abckit_IsaApiStaticOpcode_CallStatic, {2, 1}}, + {6, abckit_IsaApiStaticOpcode_ReturnVoid, {}} + } + }, + { + {1}, {}, {} + } + } + ); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/return/return_static_modified.abc", "return_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "10\n10\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/return/return_static.ets b/libabckit/tests/ir/icreate/return/return_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..d615524a7163828de1f47115da592db80c85baa3 --- /dev/null +++ b/libabckit/tests/ir/icreate/return/return_static.ets @@ -0,0 +1,35 @@ +// Before AOP: + +class A { + foo(a: long) : long { + return a; + } + foo1(a: long) : void { + a++ + console.log(a) + return; + } +} + +function main() { + let a = new A() + console.log(a.foo(10)) + a.foo1(10) +} + +// After AOP 1: + +// class A { +// foo(a: long) : long { +// return 5; +// } +// } + +// After AOP 1: + +// class A { +// foo1(a: long) : void { +// console.log(a) +// return; +// } +// } diff --git a/libabckit/tests/ir/icreate/sendable/definesendableclass_dynamic.cpp b/libabckit/tests/ir/icreate/sendable/definesendableclass_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b8afc01af5cf3cbb96894bb149737a42d5807490 --- /dev/null +++ b/libabckit/tests/ir/icreate/sendable/definesendableclass_dynamic.cpp @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynSendable: public ::testing::Test {}; + +static void TransformIrSendableClass(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) +{ + auto *klass = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_defineclasswithbuffer); + ASSERT_NE(klass, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *m = implG->IgetMethod(klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *litarr = implG->IgetLiteralArray(klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto imm = implG->IgetImmediate(klass, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *input = implG->IgetInput(klass, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // creating new inst + auto *sendableKlass = dynG->IcreateCallruntimeDefinesendableclass(ctxG, m, litarr, imm, input); + ASSERT_NE(sendableKlass, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // getting other insts + auto *ldhole = implG->IgetPrev(klass); + ASSERT_NE(ldhole, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *ldobjbyname = implG->IgetNext(klass); + ASSERT_NE(ldobjbyname, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *newobjrange = implG->IgetNext(ldobjbyname); + ASSERT_NE(ldobjbyname, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // removing old insts + implG->Iremove(klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->Iremove(ldobjbyname); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // setting up insts' inputs + implG->IsetInput(sendableKlass, ldhole, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(newobjrange, sendableKlass, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void VerifyIrSendableClass(abckit_Graph *ctxG) +{ + std::vector> bbSchema = { + { + {}, {1}, {} + }, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_ldhole, {}}, + {4, abckit_IsaApiDynamicOpcode_callruntime_definesendableclass, {3}}, + {5, abckit_IsaApiDynamicOpcode_newobjrange, {4}}, + {6, abckit_IsaApiDynamicOpcode_ldundefined, {}}, + {7, abckit_IsaApiDynamicOpcode_returnundefined, {}}, + } + }, + { + {1}, {}, {} + } + }; + + helpers::VerifyGraph(ctxG, bbSchema); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinesendableclass, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynSendable, DISABLED_DefineSendableClass) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/sendable/definesendableclass_dynamic.abc", "definesendableclass_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/sendable/definesendableclass_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/sendable/definesendableclass_dynamic_modified.abc", + "definesendableclass_dynamic.func_main_0", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrSendableClass(ctxM, method, ctxG); + }, + [&](abckit_Graph *ctxG) { + VerifyIrSendableClass(ctxG); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/sendable/definesendableclass_dynamic_modified.abc", "definesendableclass_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/sendable/definesendableclass_dynamic.js b/libabckit/tests/ir/icreate/sendable/definesendableclass_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..5d362b9eded0547b93ff192bb0cbb6f8e35d99b8 --- /dev/null +++ b/libabckit/tests/ir/icreate/sendable/definesendableclass_dynamic.js @@ -0,0 +1,7 @@ +// making class 'sendable' +class A { + constructor() { + } +} + +let a = new A() diff --git a/libabckit/tests/ir/icreate/throw/throw_dynamic.cpp b/libabckit/tests/ir/icreate/throw/throw_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..95df37a9ec6e300bf07b14f87a6a62a634cc1893 --- /dev/null +++ b/libabckit/tests/ir/icreate/throw/throw_dynamic.cpp @@ -0,0 +1,297 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitCreateDynThrow : public ::testing::Test {}; + +static std::vector> CreateBBSchemaForDynThrow(abckit_IsaApiDynamicOpcode opcode) +{ + std::vector> instVector {{3, abckit_IsaApiDynamicOpcode_LoadString, {}}}; + switch(opcode) { + case abckit_IsaApiDynamicOpcode_throw: + instVector.push_back({4, opcode, {3}}); + break; + case abckit_IsaApiDynamicOpcode_throw_notexists: + case abckit_IsaApiDynamicOpcode_throw_patternnoncoercible: + case abckit_IsaApiDynamicOpcode_throw_deletesuperproperty: + instVector.push_back({4, opcode, {}}); + break; + case abckit_IsaApiDynamicOpcode_throw_ifnotobject: + case abckit_IsaApiDynamicOpcode_throw_constassignment: + instVector.push_back({4, opcode, {3}}); + break; + case abckit_IsaApiDynamicOpcode_throw_undefinedifhole: + instVector.push_back({4, opcode, {3, 3}}); + break; + case abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname: + case abckit_IsaApiDynamicOpcode_throw_ifsupernotcorrectcall: + instVector.push_back({4, opcode, {3}}); + break; + default: + LIBABCKIT_UNREACHABLE_TEST(DEBUG); + } + if (opcode != abckit_IsaApiDynamicOpcode_throw) { + instVector.push_back({5, abckit_IsaApiDynamicOpcode_return, {3}}); + } + return { + { + {}, {1}, {} + }, + { + {0}, {2}, { + instVector + } + }, + { + {1}, {}, {} + } + }; +} + +static void TransformThrowValid(void (*TransformIrThrow)(abckit_Graph *ctxG), abckit_IsaApiDynamicOpcode opcode, + const std::string &expectedOutput) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic.abc", "throw_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic_modified.abc", + "bar", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrThrow(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynThrow(opcode)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic_modified.abc", "throw_dynamic"); + EXPECT_TRUE(helpers::Match(output, expectedOutput)); +} + +static void TransformIr1ArgValid(abckit_Graph *ctxG, abckit_Inst *(*ThrowInstToCheck)(abckit_Graph *ctxG)) +{ + auto retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *mainInst = ThrowInstToCheck(ctxG); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIr2ArgValid(abckit_Graph *ctxG, abckit_Inst *(*ThrowInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0)) +{ + auto loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + + auto retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *mainInst = ThrowInstToCheck(ctxG, loadStr); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIr3ArgValid(abckit_Graph *ctxG, abckit_Inst *(*ThrowInstToCheck)(abckit_Graph *ctxG, abckit_Inst *input0, abckit_Inst *input1)) +{ + auto loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + + auto retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *mainInst = ThrowInstToCheck(ctxG, loadStr, loadStr); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void TransformIrThrowValid(abckit_Graph *ctxG) +{ + TransformIr2ArgValid(ctxG, dynG->IcreateThrow); +} + +void TransformIrThrowConstassignmentValid(abckit_Graph *ctxG) +{ + TransformIr2ArgValid(ctxG, dynG->IcreateThrowConstassignment); +} + +void TransformIrThrowIfnotobjectValid(abckit_Graph *ctxG) +{ + TransformIr2ArgValid(ctxG, dynG->IcreateThrowIfnotobject); +} + +void TransformIrThrowNotexistsValid(abckit_Graph *ctxG) +{ + TransformIr1ArgValid(ctxG, dynG->IcreateThrowNotexists); +} + +void TransformIrThrowPatternnoncoercibleValid(abckit_Graph *ctxG) +{ + TransformIr1ArgValid(ctxG, dynG->IcreateThrowPatternnoncoercible); +} + +void TransformIrThrowDeletesuperpropertyValid(abckit_Graph *ctxG) +{ + TransformIr1ArgValid(ctxG, dynG->IcreateThrowDeletesuperproperty); +} + +void TransformIrThrowUndefinedifholeValid(abckit_Graph *ctxG) +{ + TransformIr3ArgValid(ctxG, dynG->IcreateThrowUndefinedifhole); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrow, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowValid) +{ + TransformThrowValid(TransformIrThrowValid, abckit_IsaApiDynamicOpcode_throw, "Ok\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowNotexists, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowNotexistsValid) +{ + TransformThrowValid(TransformIrThrowNotexistsValid, abckit_IsaApiDynamicOpcode_throw_notexists, "TypeError: Throw method is not defined\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowPatternnoncoercible, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowPatternnoncoercibleValid) +{ + TransformThrowValid(TransformIrThrowPatternnoncoercibleValid, abckit_IsaApiDynamicOpcode_throw_patternnoncoercible, "TypeError: objectnotcoercible\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowDeletesuperproperty, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowDeletesuperpropertyValid) +{ + TransformThrowValid(TransformIrThrowDeletesuperpropertyValid, abckit_IsaApiDynamicOpcode_throw_deletesuperproperty, "ReferenceError: Can not delete super property\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowConstassignment, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowConstassignmentValid) +{ + TransformThrowValid(TransformIrThrowConstassignmentValid, abckit_IsaApiDynamicOpcode_throw_constassignment, "TypeError: Assignment to const variable Ok\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfnotobject, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowIfnotobjectValid) +{ + TransformThrowValid(TransformIrThrowIfnotobjectValid, abckit_IsaApiDynamicOpcode_throw_ifnotobject, "TypeError: Inner return result is not object\n"); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifhole, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowUndefinedifholeValid) +{ + TransformThrowValid(TransformIrThrowUndefinedifholeValid, abckit_IsaApiDynamicOpcode_throw_undefinedifhole, ""); +} +/*--------------------------------------------------------------\ +| Not generalized cases | +\--------------------------------------------------------------*/ + +static void TransformIrThrowIfsupernotcorrectcallValid(abckit_Graph *ctxG) +{ + auto loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + + auto retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *mainInst = dynG->IcreateThrowIfsupernotcorrectcall(ctxG, loadStr, 0); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static void TransformIrThrowUndefinedifholewithnameValid(abckit_Graph *ctxG, abckit_String *str) +{ + auto loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + + auto retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_return); + ASSERT_NE(retOp, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *mainInst = dynG->IcreateThrowUndefinedifholewithname(ctxG, loadStr, str); + ASSERT_NE(mainInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(mainInst, retOp); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfsupernotcorrectcall, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowIfsupernotcorrectcallValid) +{ + TransformThrowValid(TransformIrThrowIfsupernotcorrectcallValid, abckit_IsaApiDynamicOpcode_throw_ifsupernotcorrectcall, ""); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifholewithname, abc-kind=JS, category=positive +TEST_F(LibAbcKitCreateDynThrow, CreateDynThrowUndefinedifholewithnameValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic.abc", "throw_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic.abc", + ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic_modified.abc", + "bar", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_String *str = implM->CreateString(ctxM, "GeneratedStr"); + TransformIrThrowUndefinedifholewithnameValid(ctxG, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas(CreateBBSchemaForDynThrow(abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname)); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/icreate/throw/throw_dynamic_modified.abc", "throw_dynamic"); + EXPECT_TRUE(helpers::Match(output, "")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/icreate/throw/throw_dynamic.js b/libabckit/tests/ir/icreate/throw/throw_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..cdf6ce7288d56e205629352c3d1bb1198f29137d --- /dev/null +++ b/libabckit/tests/ir/icreate/throw/throw_dynamic.js @@ -0,0 +1,16 @@ +class A { + bar() { + let a = "Ok" + return a + } + foo() { + try { + this.bar() + } catch (e) { + print(e) + } + } +} + +let a = new A() +let res = a.foo() diff --git a/libabckit/tests/ir/icreate/throw/throw_static.cpp b/libabckit/tests/ir/icreate/throw/throw_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d812274c4c7dd1068d9cc14fa5db0060eed62e9a --- /dev/null +++ b/libabckit/tests/ir/icreate/throw/throw_static.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "isa/isa_static.h" +#include "metadata.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" +#include "libabckit/src/logger.h" +#include + + +namespace libabckit { +namespace test { + +namespace { + + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); +} // namespace + +class LibAbcKitThrowStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateThrow, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitThrowStaticTest, LibAbcKitTestThrow) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/throw/throw_static.abc", "throw_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "")); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/icreate/throw/throw_static.abc", + ABCKIT_ABC_DIR "ir/icreate/throw/throw_static_modified.abc", + "bar", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto ret = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Return); + ASSERT_NE(ret, nullptr); + + auto input = implG->IgetInput(ret, 0); + ASSERT_NE(ret, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *thr = statG->IcreateThrow(ctxG, input); + ASSERT_NE(thr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertBefore(thr, ret); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/icreate/throw/throw_static_modified.abc", "throw_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"THROW\"\n")); +} + + +} // namespace test +} // namespace libabckit \ No newline at end of file diff --git a/libabckit/tests/ir/icreate/throw/throw_static.ets b/libabckit/tests/ir/icreate/throw/throw_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..3b169928e0ef8c12f49f62edbc531ee4ad27317b --- /dev/null +++ b/libabckit/tests/ir/icreate/throw/throw_static.ets @@ -0,0 +1,20 @@ +class A { + bar() { + let a = new Error("Hello"); + return a + } + foo() { + try { + this.bar() + } catch (a) { + console.log("THROW"); + } + } +} + +function main() { + let a = new A() + let res = a.foo() +} + + diff --git a/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic.cpp b/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5be287912af8fb1f964fc431a7444052b149d360 --- /dev/null +++ b/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic.cpp @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +class LibAbcKitDynamicTryCatchTest : public ::testing::Test {}; + +namespace { + auto *impl = abckit_GetApiImpl(1); + auto *implI = abckit_GetInspectApiImpl(1); + auto *implM = abckit_GetModifyApiImpl(1); + auto *implG = abckit_GetGraphApiImpl(1); + static auto dynG = abckit_GetIsaApiDynamicImpl(1); + + enum class tryCatchScenario { + defaultPositive = 0, + }; + + [[maybe_unused]] std::vector> CreateBBSchema(tryCatchScenario scenario) + { + helpers::BBSchema bb0 + { + {}, {1}, {} + }; + + helpers::BBSchema bb2{{1}, {}, {}}; + + switch (scenario) { + case tryCatchScenario::defaultPositive: + return { + bb0, + { + {0}, {2}, { + {4, abckit_IsaApiDynamicOpcode_createemptyobject, {}}, + {5, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {8, abckit_IsaApiDynamicOpcode_return, {4}}, + } + }, + bb2 + }; + default: + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + } +} + +// Test: test-kind=api, api=GraphApiImpl::GinsertTryCatch, abc-kind=JS, category=positive +TEST_F(LibAbcKitDynamicTryCatchTest, TryCatchWrapPositive) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic_wrapper.abc", + "insert_try_catch_dynamic_wrapper"); + EXPECT_TRUE(helpers::Match(output, "TRY\nTHROW\nOUTER_CATCH\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic_wrapper.abc", + ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic_wrapper_modified.abc", + "bar", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + + abckit_BasicBlock *tryFirstBB = helpers::BBgetSuccBlocks(startBB)[0]; + abckit_BasicBlock *tryLastBB = implG->BBgetTrueBranch(tryFirstBB); + + abckit_BasicBlock *catchFirstBB = implG->BBcreateEmpty(ctxG); + auto *str = dynG->IcreateLoadString(ctxG, implM->CreateString(ctxM, "INNER_CATCH")); + implG->BBaddInstBack(catchFirstBB, str); + auto *print = dynG->IcreateTryldglobalbyname(ctxG, implM->CreateString(ctxM, "print")); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstBack(catchFirstBB, print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg = dynG->IcreateCallarg1(ctxG, print, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstBack(catchFirstBB, callArg); + + implG->GinsertTryCatch(tryFirstBB, tryLastBB, catchFirstBB, catchFirstBB); + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic_wrapper_modified.abc", + "insert_try_catch_dynamic_wrapper"); + EXPECT_TRUE(helpers::Match(output, "TRY\nTHROW\nINNER_CATCH\n")); +} + +// Test: test-kind=internal, abc-kind=JS, category=internal +TEST_F(LibAbcKitDynamicTryCatchTest, InsertTryCatchValid) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic.abc", + "insert_try_catch_dynamic"); + EXPECT_TRUE(helpers::Match(output, "TRY1\nTRY2\nCATCH\nTRY1\nTRY3\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic.abc", + ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_dynamic_modified.abc", + "insert_try_catch_dynamic"); + EXPECT_TRUE(helpers::Match(output, "TRY1\nTRY2\nCATCH\nTRY1\nTRY3\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic.js b/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..d2d332d0a07b5d96536164bb01d93ae6f14a0c6b --- /dev/null +++ b/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic.js @@ -0,0 +1,17 @@ + + +function main(a) { + try { + print("TRY1") + if (a == 0) { + print("TRY2") + throw new Error("aaa") + } + print("TRY3") + } catch (e) { + print("CATCH") + } +} + +main(0) +main(1) diff --git a/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic_wrapper.js b/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic_wrapper.js new file mode 100644 index 0000000000000000000000000000000000000000..7086331ea20b77ce34c7fa913d577c6acb70de29 --- /dev/null +++ b/libabckit/tests/ir/insert_try_catch/insert_try_catch_dynamic_wrapper.js @@ -0,0 +1,17 @@ +function bar(a) { + print("TRY") + if (a == 0) { + print("THROW") + throw new Error("MOCK_ERROR"); + } +} + +function foo() { + try { + bar(0) + } catch(e) { + print("OUTER_CATCH") + } +} + +foo() diff --git a/libabckit/tests/ir/insert_try_catch/insert_try_catch_static.cpp b/libabckit/tests/ir/insert_try_catch/insert_try_catch_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0ce6d01c08a0ac6b8c5d66ead79a1455171ea48 --- /dev/null +++ b/libabckit/tests/ir/insert_try_catch/insert_try_catch_static.cpp @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2024 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 "isa/isa_static.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit::test { + +class LibAbcKitStaticTryCatchTest : public ::testing::Test {}; + +namespace { + auto *impl = abckit_GetApiImpl(1); + auto *implI = abckit_GetInspectApiImpl(1); + auto *implM = abckit_GetModifyApiImpl(1); + auto *implG = abckit_GetGraphApiImpl(1); + static auto dynG = abckit_GetIsaApiDynamicImpl(1); + + enum class tryCatchScenario { + defaultPositive = 0, + }; +} + +// Test: test-kind=internal, abc-kind=ArkTSStatic, category=internal +TEST_F(LibAbcKitStaticTryCatchTest, TryCatchIrbuilder) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_static.abc", + "insert_try_catch_static/ETSGLOBAL", + "main"); + EXPECT_TRUE(helpers::Match(output, "\"TRY1\"\n\"TRY2\"\n\"CATCH\"\n\"TRY1\"\n\"TRY3\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_static.abc", + ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + }, + [&](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/insert_try_catch/insert_try_catch_static_modified.abc", + "insert_try_catch_static/ETSGLOBAL", + "main"); + EXPECT_TRUE(helpers::Match(output, "\"TRY1\"\n\"TRY2\"\n\"CATCH\"\n\"TRY1\"\n\"TRY3\"\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/insert_try_catch/insert_try_catch_static.ets b/libabckit/tests/ir/insert_try_catch/insert_try_catch_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..2ea98404b0a99fcdaaeeedb517ec3a2d3819b4b5 --- /dev/null +++ b/libabckit/tests/ir/insert_try_catch/insert_try_catch_static.ets @@ -0,0 +1,53 @@ +function foo(a: int) { + try { + console.log("TRY1") + if (a == 0) { + console.log("TRY2") + throw new Error("aaa") + } + console.log("TRY3") + } catch (e: Error) { + if (a == 2) { + console.log("CATCH_IF") + } + console.log("CATCH") + } +} + +function print_catch() { + console.log("CATCH"); +} + +function bar(a: int) { + console.log("TRY") + if (a == 0) { + console.log("THROW") + throw new Error("MOCK_ERROR"); + } +} + +function bar0(a: int) { + try { + console.log("TRY") + if (a == 0) { + console.log("THROW") + throw new Error("MOCK_ERROR"); + } + } catch(e: Error) { + print_catch(); + } +} + +function main0() { + try { + bar(0) + } catch(e: Error) { + bar(1); + } +} + +function main() { + foo(0); + foo(1); +} + diff --git a/libabckit/tests/ir/inst_inputs/inst_inputs_dynamic.js b/libabckit/tests/ir/inst_inputs/inst_inputs_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..6a82b166346061751a13e470433b31a6432b7525 --- /dev/null +++ b/libabckit/tests/ir/inst_inputs/inst_inputs_dynamic.js @@ -0,0 +1,28 @@ +function foo(a, b) { + console.log(a) +} + +function main() { + foo(1, 2); +} + +// After AOP: + +// function foo(a:int, b:int) { +// console.log(b) +// } +// +// function main() { +// foo(1, 2); +// } +// +// Or +// +// function foo(a:int, b:int) { +// console.log(a) +// } +// +// function main() { +// foo(10, 20); +// } + diff --git a/libabckit/tests/ir/inst_inputs/inst_inputs_static.ets b/libabckit/tests/ir/inst_inputs/inst_inputs_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..de35a1e25836f70f3b01b8364636f92245159525 --- /dev/null +++ b/libabckit/tests/ir/inst_inputs/inst_inputs_static.ets @@ -0,0 +1,31 @@ +function ConsoleLog(a: long, b: long) { + console.log(a, b) +} + +function foo(a:long, b:long) { + ConsoleLog(a, b) +} + +function main() { + foo(1, 2); +} + +// Before AOP: +// function foo(a:int, b:int) { +// ConsoleLog(a, b) +// } +// +// function main() { +// foo(1, 2); +// } +// +// After AOP: +// +// function foo(a:int, b:int) { +// ConsoleLog(10, 20) +// } +// +// function main() { +// foo(1, 2); +// } + diff --git a/libabckit/tests/ir/inst_inputs/inst_inputs_test.cpp b/libabckit/tests/ir/inst_inputs/inst_inputs_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d2259487b1af2c09bf6ffd18adf78cf4825a9c0 --- /dev/null +++ b/libabckit/tests/ir/inst_inputs/inst_inputs_test.cpp @@ -0,0 +1,212 @@ +/** + * Copyright (c) 2024 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 + +#include "abckit.h" +#include "metadata.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitIrInstInputsTest : public ::testing::Test {}; + +namespace { + + void TransformIrStatic(abckit_Graph *ctxG) + { + auto constant1 = implG->GcreateConstantI64(ctxG, 10); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto constant2 = implG->GcreateConstantI64(ctxG, 20); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *callInst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + ASSERT_NE(callInst, nullptr); + + implG->IsetInput(callInst, constant1, 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetInput(callInst, constant2, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + void TransformIrStatic2(abckit_Graph *ctxG) + { + auto constant1 = implG->GcreateConstantI64(ctxG, 10); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto constant2 = implG->GcreateConstantI64(ctxG, 20); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *callInst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + ASSERT_NE(callInst, nullptr); + + implG->IsetInputs(callInst, 2, constant1, constant2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} + +// Test: test-kind=api, api=GraphApiImpl::IsetInput, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, StaticSetInput) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static.abc", "inst_inputs_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1, 2\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static.abc", + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrStatic(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {0, abckit_IsaApiStaticOpcode_Constant, {}}, + {1, abckit_IsaApiStaticOpcode_Constant, {}}, + } + }, + { + {0}, {2}, { + {2, abckit_IsaApiStaticOpcode_CallStatic, {0, 1}}, + {3, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static_modified.abc", "inst_inputs_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "10, 20\n")); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetInputs, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, StaticSetInputs) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static.abc", "inst_inputs_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "1, 2\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static.abc", + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrStatic2(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {0, abckit_IsaApiStaticOpcode_Constant, {}}, + {1, abckit_IsaApiStaticOpcode_Constant, {}}, + } + }, + { + {0}, {2}, { + {2, abckit_IsaApiStaticOpcode_CallStatic, {0, 1}}, + {3, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_static_modified.abc", "inst_inputs_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "10, 20\n")); +} + +namespace { + void TransformIrDynamic(abckit_Graph *ctxG) + { + [[maybe_unused]] abckit_BasicBlock *paramsBB = implG->GgetStartBasicBlock(ctxG); + return; + } + + void TransformIrDynamic2(abckit_Graph *ctxG) + { + [[maybe_unused]] abckit_BasicBlock *paramsBB = implG->GgetStartBasicBlock(ctxG); + return; + } +} + +// Test: test-kind=api, api=GraphApiImpl::IsetInput, abc-kind=JS, category=positive +TEST_F(LibAbcKitIrInstInputsTest, DISABLED_DynamicSetInput) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_dynamic.abc", + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynamic(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({}); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetInputs, abc-kind=JS, category=positive +TEST_F(LibAbcKitIrInstInputsTest, DISABLED_DynamicSetInputs) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_dynamic.abc", + ABCKIT_ABC_DIR "ir/inst_inputs/inst_inputs_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynamic2(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, { + {0, abckit_IsaApiStaticOpcode_INVALID, {}}, + {1, abckit_IsaApiStaticOpcode_Constant, {}}, // new c1 + {2, abckit_IsaApiStaticOpcode_Constant, {}}, // new c2 + } + }, + { + {0}, {2}, { + {3, abckit_IsaApiStaticOpcode_INVALID, {}}, + {4, abckit_IsaApiStaticOpcode_CallStatic, {1, 2, 3}}, + {5, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/ir/inst_manipulation/inst_manipulation.cpp b/libabckit/tests/ir/inst_manipulation/inst_manipulation.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b108d00ce36a4d54110492a4695d9a57d53f6a36 --- /dev/null +++ b/libabckit/tests/ir/inst_manipulation/inst_manipulation.cpp @@ -0,0 +1,540 @@ +/** + * Copyright (c) 2024 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 + +#include "abckit.h" +#include "adapter_static/ir_static.h" +#include "statuses.h" +#include "metadata.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitIrInstInputsTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::IsetInput, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IsetInput_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *input = implG->IgetNext(implG->BBgetFirstInst(start)); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(bb); + + implG->IsetInput(inst, input, 0); + ASSERT_EQ(implG->IgetInput(inst, 0), input); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetInput, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetInput_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *input = implG->IgetNext(implG->BBgetFirstInst(start)); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(bb); + + ASSERT_EQ(implG->IgetInput(inst, 0), input); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetInput, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitIrInstInputsTest, IgetInput_2) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(bb); + + ASSERT_EQ(implG->IgetInput(inst, -1), nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(implG->IgetInput(inst, 2), nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetInputCount, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetInputCount_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(bb); + + ASSERT_EQ(implG->IgetInputCount(inst), 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetImmediateCount, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetImmediateCount_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto const1 = implG->GcreateConstantU64(ctxG, 1); + auto const2 = implG->GcreateConstantU64(ctxG, 2); + auto *addi = statG->IcreateAddI(ctxG, const1, 2); + auto *add = statG->IcreateAdd(ctxG, const1, const2); + + ASSERT_EQ(implG->IgetImmediateCount(addi), 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(implG->IgetImmediateCount(add), 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetImmediate, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetImmediate_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto const1 = implG->GcreateConstantU64(ctxG, 1); + auto *addi = statG->IcreateAddI(ctxG, const1, 2); + + ASSERT_EQ(implG->IgetImmediate(addi, 0), 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetImmediate, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitIrInstInputsTest, IgetImmediate_2) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto const1 = implG->GcreateConstantU64(ctxG, 1); + auto const2 = implG->GcreateConstantU64(ctxG, 2); + auto *addi = statG->IcreateAddI(ctxG, const1, 2); + auto *add = statG->IcreateAdd(ctxG, const1, const2); + + ASSERT_EQ(implG->IgetImmediate(addi, -1), 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(implG->IgetImmediate(addi, 1), 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(implG->IgetImmediate(add, 0), 0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetImmediate, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IsetImmediate_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto const1 = implG->GcreateConstantU64(ctxG, 1); + auto *addi = statG->IcreateAddI(ctxG, const1, 2); + + ASSERT_EQ(implG->IgetImmediate(addi, 0), 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IsetImmediate(addi, 0, 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(implG->IgetImmediate(addi, 0), 3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetImmediate, abc-kind=ArkTSStatic, category=negative +TEST_F(LibAbcKitIrInstInputsTest, IsetImmediate_2) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto const1 = implG->GcreateConstantU64(ctxG, 1); + auto const2 = implG->GcreateConstantU64(ctxG, 2); + auto *addi = statG->IcreateAddI(ctxG, const1, 2); + auto *add = statG->IcreateAdd(ctxG, const1, const2); + + implG->IsetImmediate(addi, -1, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + implG->IsetImmediate(addi, 1, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + implG->IsetImmediate(add, 0, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetNext, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetNext_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *inst = implG->BBgetFirstInst(start); + auto *next = implG->IgetNext(inst); + ASSERT_EQ(statG->IgetOpcode(next), abckit_IsaApiStaticOpcode_Constant); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetPrev, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetPrev_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *inst = implG->BBgetFirstInst(start); + auto *next = implG->IgetNext(inst); + auto *prev = implG->IgetPrev(next); + ASSERT_EQ(statG->IgetOpcode(prev), abckit_IsaApiStaticOpcode_Parameter); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertBefore, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IinsertBefore_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = helpers::BBgetSuccBlocks(implG->GgetStartBasicBlock(ctxG))[0]; + auto *inst = implG->BBgetLastInst(start); + auto *constOne = implG->GcreateConstantI64(ctxG, 1U); + auto *constZero = implG->GcreateConstantI64(ctxG, 0U); + auto *instAdd = statG->IcreateAdd(ctxG, constOne, constZero); + implG->IinsertBefore(instAdd, inst); + ASSERT_EQ(implG->IgetPrev(inst), instAdd); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertBefore, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IinsertBefore_2) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(start); + auto *inst_2 = implG->BBgetFirstInst(bb); + auto *new_inst = implG->GcreateConstantI64(ctxG, 1U); + auto *neg_inst = statG->IcreateNeg(ctxG, new_inst); + implG->IinsertBefore(neg_inst, inst_2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {1}, + { + {3, abckit_IsaApiStaticOpcode_Constant, {}} + }}, + {{0}, + {2}, + { + {2, abckit_IsaApiStaticOpcode_Neg, {3}}, + {4, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{1}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + + ASSERT_EQ(inst, implG->IgetNext(new_inst)); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertAfter, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IinsertAfter_1) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static.abc", + ABCKIT_ABC_DIR "ir/basic_blocks/basic_blocks_static_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = helpers::BBgetSuccBlocks(start)[0]; + auto *inst = implG->BBgetFirstInst(start); + auto *new_inst = implG->GcreateConstantI64(ctxG, 1U); + auto *neg_inst = statG->IcreateNeg(ctxG, new_inst); + auto *add_inst = statG->IcreateAdd(ctxG, neg_inst, new_inst); + + implG->BBdisconnectBlocks(start, bb); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *empty = implG->BBcreateEmpty(ctxG); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(start, empty, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBconnectBlocks(empty, bb, false); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->BBaddInstBack(empty, neg_inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IinsertAfter(add_inst, neg_inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::vector> bbSchemas({{{}, + {1}, + { + {3, abckit_IsaApiStaticOpcode_Constant, {}} + }}, + {{0}, {2}, + { + {4, abckit_IsaApiStaticOpcode_Neg, {3}}, + {5, abckit_IsaApiStaticOpcode_Add, {4, 3}} + }}, + {{1}, {3}, + { + {2, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + }}, + {{2}, {}, {}}}); + helpers::VerifyGraph(ctxG, bbSchemas); + + ASSERT_EQ(inst, implG->IgetNext(new_inst)); + }, + [](abckit_Graph *ctxG) {} + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetBasicBlock, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetBasicBlock_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *inst = implG->BBgetFirstInst(start); + + ASSERT_EQ(implG->IgetBasicBlock(inst), start); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IcheckDominance, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IcheckDominance_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *inst = implG->BBgetFirstInst(start); + auto *next = implG->IgetNext(inst); + + ASSERT_FALSE(implG->IcheckDominance(next, inst)); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetUserCount, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetUserCount_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *inst = implG->BBgetFirstInst(start); + + ASSERT_EQ(implG->IgetUserCount(inst), 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IvisitUsers, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IvisitUsers_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *inst = implG->BBgetFirstInst(start); + auto *inst_2 = implG->IgetNext(inst); + uint32_t counter = 0; + implG->IvisitUsers(inst_2, &counter, [](abckit_Inst *inst, abckit_Inst *input, void *data) { + (*(reinterpret_cast(data)))++; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR);\ + ASSERT_EQ(counter, 1); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IvisitInputs, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IvisitInputs_1) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_static.abc", + "test2", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = implG->BBgetSuccBlock(start, 0); + auto *inst = implG->BBgetFirstInst(bb); + uint32_t counter = 0; + implG->IvisitUsers(inst, &counter, [](abckit_Inst *inst, abckit_Inst *input, void *data) { + (*(reinterpret_cast(data)))++; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(counter, 0); + } + ); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetLiteralArray, abc-kind=JS, category=negative +TEST_F(LibAbcKitIrInstInputsTest, IsetLiteralArray_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic.abc", &ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *const_inst = implG->GcreateConstantI64(ctxG, 1U); + auto arr = std::vector(); + abckit_Literal *res1 = implM->CreateLiteralString(ctxM, "asdf"); + abckit_Literal *res2 = implM->CreateLiteralDouble(ctxM, 1.0); + arr.emplace_back(res1); + arr.emplace_back(res2); + auto lit_arr = implM->CreateLiteralArray(ctxM, arr.data(), arr.size()); + implG->IsetLiteralArray(const_inst, lit_arr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetLiteralArray, abc-kind=JS, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IsetLiteralArray_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic.abc", &ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic.abc", + ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic_modified.abc", + "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = implG->BBgetSuccBlock(start, 0); + auto *inst = implG->BBgetFirstInst(bb); + auto arr = std::vector(); + abckit_Literal *res1 = implM->CreateLiteralString(ctxM, "asdf"); + abckit_Literal *res2 = implM->CreateLiteralDouble(ctxM, 1.0); + arr.emplace_back(res1); + arr.emplace_back(res2); + auto lit_arr = implM->CreateLiteralArray(ctxM, arr.data(), arr.size()); + implG->IsetLiteralArray(inst, lit_arr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + }, + [&](abckit_Graph *ctxG) {} + ); + impl->DestroyInspectContext(ctxI); + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic_modified.abc", "inst_manipulation_dynamic"); + EXPECT_TRUE(helpers::Match(output, "asdf\n1\n")); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetLiteralArray, abc-kind=JS, category=negative +TEST_F(LibAbcKitIrInstInputsTest, IgetLiteralArray_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic.abc", &ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *const_inst = implG->GcreateConstantI64(ctxG, 1U); + implG->IgetLiteralArray(const_inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetLiteralArray, abc-kind=JS, category=positive +TEST_F(LibAbcKitIrInstInputsTest, IgetLiteralArray_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "ir/inst_manipulation/inst_manipulation_dynamic.abc", &ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "test", + [ctxI](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *start = implG->GgetStartBasicBlock(ctxG); + auto *bb = implG->BBgetSuccBlock(start, 0); + auto *inst = implG->BBgetFirstInst(bb); + auto *lit_arr = implG->IgetLiteralArray(inst); + uint32_t counter = 0; + implI->LiteralArrayEnumerateElements(ctxI, lit_arr, &counter, [](abckit_File *ctx, abckit_Literal *lit, void *data) { + if(*(reinterpret_cast(data)) == 2){ + [[maybe_unused]] auto* str = implI->LiteralGetString(ctx, lit); + assert(helpers::abckit_StringToString(ctx, str) == "aa"); + return true; + } + if(*(reinterpret_cast(data)) == 3){ + [[maybe_unused]] auto val = implI->LiteralGetU32(ctx, lit); + assert(val == 10); + return true; + } + (*(reinterpret_cast(data)))++; + return true; + }); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + ); + impl->DestroyInspectContext(ctxI); +} + +} +} diff --git a/libabckit/tests/ir/inst_manipulation/inst_manipulation_dynamic.js b/libabckit/tests/ir/inst_manipulation/inst_manipulation_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..5dedd66201cbefe31e4f2035b3d8a336abfa2473 --- /dev/null +++ b/libabckit/tests/ir/inst_manipulation/inst_manipulation_dynamic.js @@ -0,0 +1,9 @@ +class Test { + test() { + return ['aa', 10] + } +} + +let a = new Test() +print(a.test()[0]) +print(a.test()[1]) diff --git a/libabckit/tests/ir/inst_manipulation/inst_manipulation_static.ets b/libabckit/tests/ir/inst_manipulation/inst_manipulation_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..9209922f6785fe1dfd2bac8f47e818626682ed4b --- /dev/null +++ b/libabckit/tests/ir/inst_manipulation/inst_manipulation_static.ets @@ -0,0 +1,27 @@ +class Test { + test() { + } + + test2(a: int) { + if(a > 0) { + return 1 + } + return -1; + } + + test3(a: int) { + try { + a = a + 1 + } catch(e){ + a = a - 1 + return a + } + return a + } +} + +function main() { + const test = new Test() + test.test() + test.test2(1) +} diff --git a/libabckit/tests/ir/loops/loop_dynamic.js b/libabckit/tests/ir/loops/loop_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..018ef1c59c6ad176d7e8011450fd50876ef4c936 --- /dev/null +++ b/libabckit/tests/ir/loops/loop_dynamic.js @@ -0,0 +1,7 @@ +function bar() { +// for (let i = 0; i < 10; i++) { +// print(i) +// } +} + +bar() \ No newline at end of file diff --git a/libabckit/tests/ir/loops/loop_static.ets b/libabckit/tests/ir/loops/loop_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..0850a32b40c279a478e5a44fabd44c6884cf9399 --- /dev/null +++ b/libabckit/tests/ir/loops/loop_static.ets @@ -0,0 +1,10 @@ +function console_log_int(a: int) { + console.log(a) +} + +function bar() { +} + +function main() { + bar() +} diff --git a/libabckit/tests/ir/loops/loops.cpp b/libabckit/tests/ir/loops/loops.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c747299fa26907028c5fd0e58bb0e46a5b14d306 --- /dev/null +++ b/libabckit/tests/ir/loops/loops.cpp @@ -0,0 +1,172 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" +#include "libabckit/src/logger.h" +#include + + +namespace libabckit { +namespace test { + +namespace { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +void CreateLoopDynamic(abckit_Graph *ctxG, abckit_ModifyContext *ctxM) { + + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *endBB = implG->GgetEndBasicBlock(ctxG); + + abckit_Inst *forConst = implG->GcreateConstantU64(ctxG, 0xa); + abckit_Inst *zero = implG->GcreateConstantU64(ctxG, 0x0); + abckit_Inst *forStep = implG->GcreateConstantU64(ctxG, 0x2); + + implG->BBaddInstBack(startBB, forConst); + implG->BBaddInstBack(startBB, zero); + implG->BBaddInstBack(startBB, forStep); + implG->BBdisconnectBlocks(startBB, succBBs[0]); + + abckit_BasicBlock *forBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(startBB, forBB, 1); + + abckit_Inst *phi = implG->BBcreatePhi(forBB, 1, zero); + + abckit_Inst *intrinsicLess = dynG->IcreateLess(ctxG, phi, forConst); + implG->BBaddInstBack(forBB, intrinsicLess); + + abckit_Inst *ifInst = dynG->IcreateIf(ctxG, intrinsicLess, abckit_IsaApiDynamicConditionCode_CC_NE); + implG->BBaddInstBack(forBB, ifInst); + + abckit_BasicBlock *trueBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *add = dynG->IcreateAdd2(ctxG, phi, forStep); + + implG->BBaddInstBack(trueBB, add); + implG->IappendInput(phi, add); + + + auto *print = dynG->IcreateTryldglobalbyname(ctxG, implM->CreateString(ctxM, "print")); + implG->BBaddInstBack(trueBB, print); + auto *call = dynG->IcreateCallarg1(ctxG, print, phi); + implG->BBaddInstBack(trueBB, call); + implG->BBconnectBlocks(forBB, trueBB, 1); + + abckit_BasicBlock *retBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(forBB, retBB, 0); + implG->BBconnectBlocks(trueBB, forBB, 1); + implG->BBconnectBlocks(retBB, endBB, 1); + + abckit_Inst *ret = dynG->IcreateReturnundefined(ctxG); + + implG->BBaddInstBack(retBB, ret); +} + +void CreateLoopStatic(abckit_Graph *ctxG, abckit_ModifyContext *ctxM, abckit_Method *ConsoleLogInt) { + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *endBB = implG->GgetEndBasicBlock(ctxG); + + abckit_Inst *forConst = implG->GcreateConstantU64(ctxG, 0xa); + abckit_Inst *zero = implG->GcreateConstantU64(ctxG, 0x0); + abckit_Inst *forStep = implG->GcreateConstantU64(ctxG, 0x1); + + implG->BBaddInstBack(startBB, forConst); + implG->BBaddInstBack(startBB, zero); + implG->BBaddInstBack(startBB, forStep); + + implG->BBdisconnectBlocks(startBB, succBBs[0]); + + abckit_BasicBlock *forBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(startBB, forBB, 1); + + abckit_Inst *phi = implG->BBcreatePhi(forBB, 1, zero); + + abckit_Inst *ifInst = statG->IcreateIf(ctxG, phi, forConst, abckit_IsaApiStaticConditionCode_CC_LT); + implG->BBaddInstBack(forBB, ifInst); + + abckit_BasicBlock *trueBB = implG->BBcreateEmpty(ctxG); + abckit_Inst *add = statG->IcreateAdd(ctxG, phi, forStep); + + implG->BBaddInstBack(trueBB, add); + implG->IappendInput(phi, add); + + abckit_Inst *callLogInt = statG->IcreateCallStatic(ctxG, ConsoleLogInt, 1, phi); + implG->BBaddInstBack(trueBB, callLogInt); + + implG->BBconnectBlocks(forBB, trueBB, 1); + + abckit_BasicBlock *retBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(forBB, retBB, 0); + implG->BBconnectBlocks(trueBB, forBB, 1); + implG->BBconnectBlocks(retBB, endBB, 1); + + abckit_Inst *ret = statG->IcreateReturnVoid(ctxG); + implG->BBaddInstBack(retBB, ret); +} + +} // namespace + +class LibAbcKitLoopStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::BBcreatePhi, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitLoopStaticTest, LibAbcKitLoopTestStatic) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/loops/loop_static.abc", "loop_static/ETSGLOBAL", "main"); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/loops/loop_static.abc", + ABCKIT_ABC_DIR "ir/loops/loop_static_modified.abc", + "bar", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *ConsoleLogInt = helpers::findMethodByName(implI->MethodGetInspectContext(method), "console_log_int"); + CreateLoopStatic(ctxG, ctxM, ConsoleLogInt); + }, + [](abckit_Graph *ctxG) { + + } + ); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/loops/loop_static_modified.abc", "loop_static/ETSGLOBAL", "main"); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcreatePhi, abc-kind=JS, category=positive +TEST_F(LibAbcKitLoopStaticTest, LibAbcKitLoopDynamic) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/loops/loop_dynamic.abc", "loop_dynamic"); + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/loops/loop_dynamic.abc", + ABCKIT_ABC_DIR "ir/loops/loop_dynamic_modified.abc", + "bar", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + CreateLoopDynamic(ctxG, ctxM); + }, + [&](abckit_Graph *ctxG) { + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/loops/loop_dynamic_modified.abc", "loop_dynamic"); +} + +} // namespace test +} // namespace libabckit \ No newline at end of file diff --git a/libabckit/tests/ir/method/method_dynamic.cpp b/libabckit/tests/ir/method/method_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..28221fdae2020840b516d6534041d78fd5262e50 --- /dev/null +++ b/libabckit/tests/ir/method/method_dynamic.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + static auto dynG = abckit_GetIsaApiDynamicImpl(1); + + void TransformSetSetCallMethod(abckit_Graph *ctxG, abckit_Method *foo) + { + auto *defineProp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_definepropertybyname); + ASSERT_NE(defineProp, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *defineFunc = implG->IgetPrev(defineProp); + ASSERT_NE(defineFunc, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(dynG->IgetOpcode(defineFunc), abckit_IsaApiDynamicOpcode_definefunc); + + implG->IsetMethod(defineFunc, foo); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} // namespace + +class LibAbcKitMethodDynamicTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::IsetMethod, abc-kind=JS, category=positive +TEST_F(LibAbcKitMethodDynamicTest, LibAbcKitTestSetCallMethod) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/method/method_dynamic.abc", "method_dynamic"); + EXPECT_TRUE(helpers::Match(output, "function\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/method/method_dynamic.abc", + ABCKIT_ABC_DIR "ir/method/method_dynamic_modified.abc", + "func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *bar = helpers::findMethodByName(implI->MethodGetInspectContext(method), "foo"); + ASSERT_NE(bar, nullptr); + TransformSetSetCallMethod(ctxG, bar); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/method/method_dynamic_modified.abc", "method_dynamic"); + EXPECT_TRUE(helpers::Match(output, "foo\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/method/method_dynamic.js b/libabckit/tests/ir/method/method_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..5027db023f94ad84068b75ae42756e2b705b5ae1 --- /dev/null +++ b/libabckit/tests/ir/method/method_dynamic.js @@ -0,0 +1,23 @@ +// Before AOP + +function foo() { + print("foo") +} + +let res = { + method: function () { + print("function") + } +} +res.method() + +// After AOP + +// function foo() { +// print("foo") +// } +// +// let res = { +// method: foo --> this is invalid construction, but method will be a foo function +// } +// res.method() diff --git a/libabckit/tests/ir/method/method_static.cpp b/libabckit/tests/ir/method/method_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bebcf14dd3116b7d272a6bdcd66595b07ca3021 --- /dev/null +++ b/libabckit/tests/ir/method/method_static.cpp @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformSetSetCallMethod(abckit_Graph *ctxG, abckit_Method *bar) + { + auto *call = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + ASSERT_NE(call, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetMethod(call, bar); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } +} // namespace + +class LibAbcKitMethodStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::IsetMethod, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitMethodStaticTest, LibAbcKitTestSetCallMethod) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/method/method_static.abc", "method_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"foo\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/method/method_static.abc", + ABCKIT_ABC_DIR "ir/method/method_static_modified.abc", + "main", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto *bar = helpers::findMethodByName(implI->MethodGetInspectContext(method), "bar"); + ASSERT_NE(bar, nullptr); + TransformSetSetCallMethod(ctxG, bar); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/method/method_static_modified.abc", "method_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"bar\"\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/method/method_static.ets b/libabckit/tests/ir/method/method_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..88fb188515df5b75d8fa9cac3a6bb0ee7011b8f7 --- /dev/null +++ b/libabckit/tests/ir/method/method_static.ets @@ -0,0 +1,27 @@ +// Before AOP + +function foo() { + console.log("foo") +} + +function bar() { + console.log("bar") +} + +function main() { + foo() +} + +// After AOP +// +// function foo() { +// console.log("foo") +// } +// +// function bar() { +// console.log("bar") +// } +// +// function main() { +// bar() +// } diff --git a/libabckit/tests/ir/phi/phi.cpp b/libabckit/tests/ir/phi/phi.cpp new file mode 100644 index 0000000000000000000000000000000000000000..856fa0d01172d423f86af050534a286da8929629 --- /dev/null +++ b/libabckit/tests/ir/phi/phi.cpp @@ -0,0 +1,215 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitGetPhiTest : public ::testing::Test {}; + +namespace { + +void TransformIR(abckit_Graph *ctxG, bool isDynamic = false) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *endBB = implG->GgetEndBasicBlock(ctxG); + + implG->BBdisconnectBlocks(startBB, succBBs[0]); + + abckit_Inst *param0 = nullptr; + abckit_Inst *param1 = nullptr; + if (isDynamic) { + param0 = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_Parameter); + param1 = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_Parameter, [counter = 0](abckit_Inst* i) mutable {return counter++ > 0;}); + } else { + param0 = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Parameter); + param1 = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Parameter, [counter = 0](abckit_Inst* i) mutable {return counter++ > 0;}); + } + ASSERT_NE(param0, nullptr); + ASSERT_NE(param1, nullptr); + + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(startBB, ifBB, 0); + abckit_Inst *ifInst = nullptr; + if (isDynamic) { + abckit_Inst *intrinsicEq = dynG->IcreateEq(ctxG, param0, param1); + implG->BBaddInstBack(ifBB, intrinsicEq); + ifInst = dynG->IcreateIf(ctxG, intrinsicEq, abckit_IsaApiDynamicConditionCode_CC_EQ); + } else { + ifInst = statG->IcreateIf(ctxG, param0, param1, abckit_IsaApiStaticConditionCode_CC_NE); + } + implG->BBaddInstBack(ifBB, ifInst); + + abckit_BasicBlock *trueBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(ifBB, trueBB, 0); + abckit_Inst *dec = nullptr; + if (isDynamic) { + dec = dynG->IcreateSub2(ctxG, param0, param1); + } else { + dec = statG->IcreateSub(ctxG, param0, param1); + } + implG->BBaddInstBack(trueBB, dec); + + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(ifBB, falseBB, 1); + abckit_Inst *inc = nullptr; + if (isDynamic) { + inc = dynG->IcreateAdd2(ctxG, param0, param1); + } else { + inc = statG->IcreateAdd(ctxG, param0, param1); + } + implG->BBaddInstBack(falseBB, inc); + + abckit_BasicBlock *retBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(trueBB, retBB, 0); + implG->BBconnectBlocks(falseBB, retBB, 0); + implG->BBconnectBlocks(retBB, endBB, 0); + abckit_Inst *phi = implG->BBcreatePhi(retBB, 2, dec, inc); + abckit_Inst *ret = nullptr; + if (isDynamic) { + ret = dynG->IcreateReturn(ctxG, phi); + } else { + ret = statG->IcreateReturn(ctxG, phi); + } + implG->BBaddInstBack(retBB, ret); +} + +} + +// Test: test-kind=api, api=GraphApiImpl::BBcreatePhi, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGetPhiTest, StaticBBcreatePhi) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/phi/phi_static.abc", "phi_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "2\n4\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/phi/phi_static.abc", + ABCKIT_ABC_DIR "ir/phi/phi_static_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIR(ctxG); + }, + [&](abckit_Graph *ctxG) { + std::vector> schema = { + { + {}, {1}, { + {0, abckit_IsaApiStaticOpcode_Parameter, {}}, + {1, abckit_IsaApiStaticOpcode_Parameter, {}}, + } + }, + { + {0}, {3, 2}, { + {2, abckit_IsaApiStaticOpcode_If, {0, 1}}, + } + }, + { + {1}, {4}, { + {3, abckit_IsaApiStaticOpcode_Add, {0, 1}}, + } + }, + { + {1}, {4}, { + {4, abckit_IsaApiStaticOpcode_Sub, {0, 1}}, + } + }, + { + {2, 3}, {5}, { + {5, abckit_IsaApiStaticOpcode_Phi, {3, 4}}, + {6, abckit_IsaApiStaticOpcode_Return, {5}}, + } + }, + { + {4}, {}, {} + } + }; + helpers::VerifyGraph(ctxG, schema); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/phi/phi_static_modified.abc", "phi_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "-1\n4\n")); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcreatePhi, abc-kind=TS, category=positive +TEST_F(LibAbcKitGetPhiTest, DynamicBBcreatePhi) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/phi/phi_dynamic.abc", "phi_dynamic"); + EXPECT_TRUE(helpers::Match(output, "2\n4\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/phi/phi_dynamic.abc", + ABCKIT_ABC_DIR "ir/phi/phi_dynamic_modified.abc", + "foo", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIR(ctxG, true); + }, + [&](abckit_Graph *ctxG) { + std::vector> schema = { + { + {}, {1}, { + {0, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {1, abckit_IsaApiDynamicOpcode_Parameter, {}}, + {2, abckit_IsaApiDynamicOpcode_Constant, {}}, + } + }, + { + {0}, {3, 2}, { + {3, abckit_IsaApiDynamicOpcode_eq, {0, 1}}, + {4, abckit_IsaApiDynamicOpcode_if, {3, 2}}, + } + }, + { + {1}, {4}, { + {5, abckit_IsaApiDynamicOpcode_add2, {0, 1}}, + } + }, + { + {1}, {4}, { + {6, abckit_IsaApiDynamicOpcode_sub2, {0, 1}}, + } + }, + { + {2, 3}, {5}, { + {7, abckit_IsaApiDynamicOpcode_Phi, {5, 6}}, + {8, abckit_IsaApiDynamicOpcode_return, {7}}, + } + }, + { + {4}, {}, {} + } + }; + helpers::VerifyGraph(ctxG, schema); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/phi/phi_dynamic_modified.abc", "phi_dynamic"); + EXPECT_TRUE(helpers::Match(output, "-1\n4\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/phi/phi_dynamic.ts b/libabckit/tests/ir/phi/phi_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..eb0a141b20dc6b441b57b34d794161644da5fa2c --- /dev/null +++ b/libabckit/tests/ir/phi/phi_dynamic.ts @@ -0,0 +1,7 @@ + +function foo(a, b) { + return a * b; +} + +print(foo(1, 2)); +print(foo(2, 2)); diff --git a/libabckit/tests/ir/phi/phi_static.ets b/libabckit/tests/ir/phi/phi_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..94da54a0b52f00f475526cdae250c6be9ca0712b --- /dev/null +++ b/libabckit/tests/ir/phi/phi_static.ets @@ -0,0 +1,9 @@ + +function foo(a: int, b: int) : int { + return a * b; +} + +function main() { + console.log(foo(1, 2)); + console.log(foo(2, 2)); +} diff --git a/libabckit/tests/ir/string/string_dynamic.cpp b/libabckit/tests/ir/string/string_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b13bb898bc0753a0a8e0a041265abc93bf2c4f8 --- /dev/null +++ b/libabckit/tests/ir/string/string_dynamic.cpp @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + + void TransformSetStringIrDynamic(abckit_Graph *ctxG, abckit_ModifyContext *ctxM) + { + auto *loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *newStr = implM->CreateString(ctxM, "STRING"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetString(loadStr, newStr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + void CheckGetStringIrDynamic(abckit_Graph *ctxG, abckit_Method *method) + { + auto *loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *str = implG->IgetString(loadStr); + ASSERT_NE(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(helpers::abckit_StringToString(implI->MethodGetInspectContext(method), str), "string"); + } + + +} // namespace + +class LibAbcKitStringDynamicTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::IsetString, abc-kind=JS, category=positive +TEST_F(LibAbcKitStringDynamicTest, LibAbcKitTestSetString) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/string/string_dynamic.abc", "string_dynamic"); + EXPECT_TRUE(helpers::Match(output, "string\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/string/string_dynamic.abc", + ABCKIT_ABC_DIR "ir/string/string_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformSetStringIrDynamic(ctxG, ctxM); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ir/string/string_dynamic_modified.abc", "string_dynamic"); + EXPECT_TRUE(helpers::Match(output, "STRING\n")); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetString, abc-kind=JS, category=positive +TEST_F(LibAbcKitStringDynamicTest, LibAbcKitTestGetString) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/string/string_dynamic.abc", + ABCKIT_ABC_DIR "ir/string/string_dynamic_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + CheckGetStringIrDynamic(ctxG, method); + } + ); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/string/string_dynamic.js b/libabckit/tests/ir/string/string_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..d41069d844b242d731ee2864f96fe9bc4854b827 --- /dev/null +++ b/libabckit/tests/ir/string/string_dynamic.js @@ -0,0 +1,15 @@ +// Before AOP + +function foo() { + return "string" +} + +print(foo()) + +// After AOP +// +// function foo() { +// return "STRING" +// } +// +// print(foo()) diff --git a/libabckit/tests/ir/string/string_static.cpp b/libabckit/tests/ir/string/string_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..22d4ff0753545657db843e9d10f3cb481f4bb438 --- /dev/null +++ b/libabckit/tests/ir/string/string_static.cpp @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers_runtime.h" +#include "helpers/helpers.h" + +#include + +namespace libabckit::test { + +namespace { + auto impl = abckit_GetApiImpl(1); + auto implI = abckit_GetInspectApiImpl(1); + auto implM = abckit_GetModifyApiImpl(1); + auto implG = abckit_GetGraphApiImpl(1); + auto statG = abckit_GetIsaApiStaticImpl(1); + + void TransformSetStringIrStatic(abckit_Graph *ctxG, abckit_ModifyContext *ctxM) + { + auto *loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *newStr = implM->CreateString(ctxM, "STRING"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implG->IsetString(loadStr, newStr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + } + + void CheckGetStringIrStatic(abckit_Graph *ctxG, abckit_Method *method) + { + auto *loadStr = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_LoadString); + ASSERT_NE(loadStr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *str = implG->IgetString(loadStr); + ASSERT_NE(str, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(helpers::abckit_StringToString(implI->MethodGetInspectContext(method), str), "string"); + } + + +} // namespace + +class LibAbcKitStringStaticTest : public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::IsetString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitStringStaticTest, LibAbcKitTestSetString) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/string/string_static.abc", "string_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"string\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/string/string_static.abc", + ABCKIT_ABC_DIR "ir/string/string_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformSetStringIrStatic(ctxG, ctxM); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ir/string/string_static_modified.abc", "string_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"STRING\"\n")); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitStringStaticTest, LibAbcKitTestGetString) +{ + helpers::TransformMethod( + ABCKIT_ABC_DIR "ir/string/string_static.abc", + ABCKIT_ABC_DIR "ir/string/string_static_modified.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + CheckGetStringIrStatic(ctxG, method); + } + ); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/string/string_static.ets b/libabckit/tests/ir/string/string_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..cb6be8af552c1b05ad6c5e474bbaf65adf9dee2f --- /dev/null +++ b/libabckit/tests/ir/string/string_static.ets @@ -0,0 +1,19 @@ +// Before AOP + +function foo() { + return "string" +} + +function main() { + console.log(foo()) +} + +// After AOP +// +// function foo() { +// return "STRING" +// } +// +// function main() { +// console.log(foo()) +// } diff --git a/libabckit/tests/ir/types_api/get_type_dynamic.cpp b/libabckit/tests/ir/types_api/get_type_dynamic.cpp new file mode 100644 index 0000000000000000000000000000000000000000..69277b055f6d26cb62a9d814060ddba34b6b064c --- /dev/null +++ b/libabckit/tests/ir/types_api/get_type_dynamic.cpp @@ -0,0 +1,69 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitGetTypeDynamicTest : public ::testing::Test {}; + +static void CheckTypeOfInst(abckit_Inst *inst, abckit_TypeId typeId) +{ + abckit_Type *instType = implG->IgetType(inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_TypeId instTypeId = implI->TypeGetTypeId(instType); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(instTypeId, typeId); +} + +static void InspectMethodDynamicValid(abckit_Graph *ctxG) +{ + abckit_Inst *firstInst = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_Constant); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *secondInst = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_add2); + ASSERT_NE(secondInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + CheckTypeOfInst(firstInst, abckit_TypeId_I32); + CheckTypeOfInst(secondInst, abckit_TypeId_ANY); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetType, abc-kind=JS, category=positive +TEST_F(LibAbcKitGetTypeDynamicTest, GetTypeDynamic) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "ir/types_api/get_type_dynamic.abc", &ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::InspectMethod(ctxI, "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + InspectMethodDynamicValid(ctxG); + } + ); + impl->DestroyInspectContext(ctxI); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/types_api/get_type_dynamic.js b/libabckit/tests/ir/types_api/get_type_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..f7163e2bdaad4c000e7cfab60a9297d5c87c6f87 --- /dev/null +++ b/libabckit/tests/ir/types_api/get_type_dynamic.js @@ -0,0 +1,7 @@ +class A { + foo(c) { + let a = 15; + let b = a + c; + return b; + } +} \ No newline at end of file diff --git a/libabckit/tests/ir/types_api/get_type_static.cpp b/libabckit/tests/ir/types_api/get_type_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d84b52ff045ad1a2341927cbf004a20735837c9 --- /dev/null +++ b/libabckit/tests/ir/types_api/get_type_static.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024 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 "metadata.h" +#include "ir_core.h" +#include "abckit.h" +#include "helpers/helpers.h" +#include + +namespace libabckit::test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitGetTypeStaticTest : public ::testing::Test {}; + +static void CheckTypeOfInst(abckit_Inst *inst, abckit_TypeId typeId) +{ + abckit_Type *instType = implG->IgetType(inst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_TypeId instTypeId = implI->TypeGetTypeId(instType); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(instTypeId, typeId); +} + +static void InspectMethodStaticValid(abckit_Graph *ctxG) +{ + abckit_Inst *firstConst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Constant); + ASSERT_NE(firstConst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *secondConst = implG->IgetNext(firstConst); + ASSERT_NE(secondConst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + abckit_Inst *addInst = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_Add); + ASSERT_NE(addInst, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + CheckTypeOfInst(firstConst, abckit_TypeId_F64); + CheckTypeOfInst(secondConst, abckit_TypeId_I64); + CheckTypeOfInst(addInst, abckit_TypeId_F64); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetType, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitGetTypeStaticTest, GetTypeStatic) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "ir/types_api/get_type_static.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method* method, abckit_Graph *ctxG) { + InspectMethodStaticValid(ctxG); + } + ); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ir/types_api/get_type_static.ets b/libabckit/tests/ir/types_api/get_type_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..3a07deeaf6cb0dedbb6fa8e7b7833c7c9c1b2ef3 --- /dev/null +++ b/libabckit/tests/ir/types_api/get_type_static.ets @@ -0,0 +1,8 @@ +class A { + foo() : number { + let a: number = 7.1; + let b: long = -5; + let c: number = a + b; + return c; + } +} \ No newline at end of file diff --git a/libabckit/tests/metadata/inspect_api/annotations/annotations_dynamic.ts b/libabckit/tests/metadata/inspect_api/annotations/annotations_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..6239bd783a91c5a9880e84517e62ce03148f2c99 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/annotations/annotations_dynamic.ts @@ -0,0 +1,12 @@ +@interface Anno { + a: number = 3 + b: number[] = [13, 9] + d: boolean = false + str: string = "Hello" +} + +@__$$ETS_ANNOTATION$$__Anno({a: 20, b: [13, 10], d: true, str: "ABC"}) +class A { + @__$$ETS_ANNOTATION$$__Anno({a: 10, b: [1, 2, 3], d: true, str: "DEF"}) + foo() {} +} diff --git a/libabckit/tests/metadata/inspect_api/annotations/annotations_test.cpp b/libabckit/tests/metadata/inspect_api/annotations/annotations_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..713876e90b13627e2370f986aaa9269be623be0f --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/annotations/annotations_test.cpp @@ -0,0 +1,489 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +class LibAbcKitInspectApiAnnotationsTests : public ::testing::Test {}; + +struct AnnoInfo { + abckit_File *ctx; + abckit_Annotation *anno; + std::string a; + std::string b; + std::string d; +} typedef AnnoInfo; + +struct AnnoInterfaceInfo { + abckit_File *ctx; + abckit_AnnotationInterface *annoIf; + abckit_Annotation *anno; +} typedef AnnoInterfaceInfo; + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +template +static void processAnnotations(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + AnnoInfo newData; + implI->MethodEnumerateAnnotations(method, &newData, [](abckit_Annotation *anno, void *data1) { + AnnoInfo *newData1 = (AnnoInfo *)data1; + newData1->anno = anno; + newData1->ctx = implI->AnnotationGetInspectContext(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + implI->AnnotationEnumerateElements(anno, data1, [](abckit_AnnotationElement *annoElement, void *data2) { + auto ctx = implI->AnnotationElementGetInspectContext(annoElement); + + auto abckit_str = implI->AnnotationElementGetName(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctx, abckit_str); + + AnnoInfo *newData2 = (AnnoInfo *)data2; + + if constexpr (IS_CHECK_ANNOTATION) { + [[maybe_unused]] auto gotAnno = implI->AnnotationElementGetAnnotation(annoElement); + EXPECT_TRUE(newData2->anno == gotAnno); + } + + if constexpr (IS_CHECK_CONTEXT) { + [[maybe_unused]] auto gotCtx = implI->AnnotationElementGetInspectContext(annoElement); + EXPECT_TRUE(newData2->ctx == gotCtx); + } + + EXPECT_TRUE(name == "a" || name == "b" || name == "d" || name == "str" || name == "SlotNumber"); + if (name == "a") { + newData2->a = name; + if constexpr (IS_CHECK_VALUE) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetDouble(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(vs == 10); + } + } + + if (name == "b") { + newData2->b = name; + if constexpr (IS_CHECK_VALUE) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ArrayValueGetLiteralArray(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + implI->LiteralArrayEnumerateElements(ctx, vs, nullptr, [](abckit_File *ctx, abckit_Literal *v, void *data) { + double value = implI->LiteralGetDouble(ctx, v); + EXPECT_TRUE(value == 1 || value == 2 || value == 3); + return true; + }); + } + } + + if (name == "d") { + newData2->d = name; + if constexpr (IS_CHECK_VALUE) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetU1(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(vs == true); + } + } + + if (name == "str") { + if constexpr (IS_CHECK_VALUE) { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->ValueGetString(ctx, val); + auto vs = abckit_StringToString(ctx, str); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(vs == "DEF"); + } + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void processClass(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + AnnoInfo newData; + auto klass = implI->MethodGetParentClass(method); + implI->ClassEnumerateAnnotations(klass, &newData, [](abckit_Annotation *anno, void *data1) { + AnnoInfo *newData1 = (AnnoInfo *)data1; + newData1->anno = anno; + newData1->ctx = implI->AnnotationGetInspectContext(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + implI->AnnotationEnumerateElements(anno, data1, [](abckit_AnnotationElement *annoElement, void *data2) { + auto ctx = implI->AnnotationElementGetInspectContext(annoElement); + + auto abckit_str = implI->AnnotationElementGetName(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctx, abckit_str); + + AnnoInfo *newData2 = (AnnoInfo *)data2; + + EXPECT_TRUE(name == "a" || name == "b" || name == "d" || name == "str" || name == "SlotNumber"); + if (name == "a") { + newData2->a = name; + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetDouble(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(vs == 20); + } + + if (name == "b") { + newData2->b = name; + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ArrayValueGetLiteralArray(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + implI->LiteralArrayEnumerateElements(ctx, vs, nullptr, [](abckit_File *ctx, abckit_Literal *v, void *data) { + [[maybe_unused]] double value = implI->LiteralGetDouble(ctx, v); + EXPECT_TRUE(value == 13 || value == 10); + return true; + }); + } + + if (name == "d") { + newData2->d = name; + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto vs = implI->ValueGetU1(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(vs == true); + } + + if (name == "str") { + abckit_Value *val = implI->AnnotationElementGetValue(annoElement); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->ValueGetString(ctx, val); + auto vs = abckit_StringToString(ctx, str); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(vs == "ABC"); + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +template +static void processAnnotationInterface(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + AnnoInterfaceInfo newData; + implI->MethodEnumerateAnnotations(method, &newData, [](abckit_Annotation *anno, void *data1) { + AnnoInterfaceInfo *newData1 = (AnnoInterfaceInfo *)data1; + newData1->anno = anno; + newData1->annoIf = implI->AnnotationGetInterface(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(newData1->annoIf != nullptr); + auto ctx = implI->AnnotationGetInspectContext(anno); + if constexpr (IS_CHECK_CONTEXT) { + EXPECT_TRUE(ctx == implI->AnnotationInterfaceGetInspectContext(newData1->annoIf)); + } + if constexpr (IS_CHECK_NAME) { + auto str = implI->AnnotationInterfaceGetName(newData1->annoIf); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctx, str); + EXPECT_TRUE(name == "Anno" || name == "_ESSlotNumberAnnotation"); + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +template +static void processModule(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + auto module = implI->MethodGetModule(method); + implI->ModuleEnumerateAnnotationInterfaces(module, module, [](abckit_AnnotationInterface *annoI, void *data) { + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + + if constexpr (IS_CHECK_MODULE) { + auto curModule = implI->AnnotationInterfaceGetModule(annoI); + EXPECT_TRUE(curModule == data); + return true; + } + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || + name == "Anno"); + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +template +static void processAnnotationInterfaceFields(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + AnnoInterfaceInfo newData; + implI->MethodEnumerateAnnotations(method, &newData, [](abckit_Annotation *anno, void *data1) { + AnnoInterfaceInfo *newData1 = (AnnoInterfaceInfo *)data1; + newData1->anno = anno; + newData1->annoIf = implI->AnnotationGetInterface(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(newData1->annoIf != nullptr); + auto ctx = implI->AnnotationInterfaceGetInspectContext(newData1->annoIf); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + newData1->ctx = ctx; + + auto str = implI->AnnotationInterfaceGetName(newData1->annoIf); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctx, str); + + if (name != "Anno") { + return true; + } + + implI->AnnotationInterfaceEnumerateFields(newData1->annoIf, newData1, [](abckit_AnnotationInterfaceField *fld, void *data2) { + AnnoInterfaceInfo *newData2 = (AnnoInterfaceInfo *)data2; + + if constexpr (IS_CHECK_INTERFACE) { + auto annoIf = implI->AnnotationInterfaceFieldGetInterface(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + EXPECT_TRUE(newData2->annoIf == annoIf); + } + + auto ctx = implI->AnnotationInterfaceFieldGetInspectContext(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + if constexpr (IS_CHECK_CONTEXT) { + EXPECT_TRUE(newData2->ctx == ctx); + } + + auto str = implI->AnnotationInterfaceFieldGetName(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(newData2->ctx, str); + if constexpr (IS_CHECK_NAME) { + EXPECT_TRUE(name == "a" || name == "b" || name == "d" || name == "str"); + } + + if constexpr (IS_CHECK_TYPE) { + auto type = implI->AnnotationInterfaceFieldGetType(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + if (name == "a") { + EXPECT_TRUE(abckit_TypeId_F64 == implI->TypeGetTypeId(type)); + } + if (name == "b") { + EXPECT_TRUE(abckit_TypeId_F64 == implI->TypeGetTypeId(type)); + } + if (name == "d") { + EXPECT_TRUE(abckit_TypeId_U1 == implI->TypeGetTypeId(type)); + } + } + + if constexpr (IS_CHECK_VALUE) { + auto val = implI->AnnotationInterfaceFieldGetDefaultValue(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + if (name == "a") { + auto value_db = implI->ValueGetDouble(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(value_db == 3); + } + if (name == "b") { + auto vs = implI->ArrayValueGetLiteralArray(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + implI->LiteralArrayEnumerateElements(ctx, vs, nullptr, [](abckit_File *ctx, abckit_Literal *v, void *data) { + double value = implI->LiteralGetDouble(ctx, v); + EXPECT_TRUE(value == 13 || value == 9); + return true; + }); + } + if (name == "d") { + auto value_b = implI->ValueGetU1(ctx, val); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(value_b == false); + } + if (name == "str") { + auto str = implI->ValueGetString(ctx, val); + auto value_str = abckit_StringToString(ctx, str); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(value_str == "Hello"); + } + } + + return true; + }); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationElementGetName) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotations); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetValue, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationElementGetValue) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotations); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetAnnotation, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationElementGetAnnotation) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotations); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationElementGetInspectContext) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotations); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateAnnotations, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, ClassEnumerateAnnotations) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "A", processClass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationGetInterface, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationGetInterface) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterface); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceGetName) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterface); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceGetInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceGetInspectContext) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterface); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateAnnotationInterfaces, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, ModuleEnumerateAnnotationInterfaces) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processModule); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceGetModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceGetModule) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processModule); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceEnumerateFields, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceEnumerateFields) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterfaceFields); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceFieldGetInspectContext) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterfaceFields); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceFieldGetName) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterfaceFields); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetInterface, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceFieldGetInterface) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterfaceFields); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetType, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceFieldGetType) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterfaceFields); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetDefaultValue, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiAnnotationsTests, AnnotationInterfaceFieldGetDefaultValue) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/inspect_api/annotations/annotations_dynamic.abc", "foo", processAnnotationInterfaceFields); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} +} diff --git a/libabckit/tests/metadata/inspect_api/classes/classes_dynamic.js b/libabckit/tests/metadata/inspect_api/classes/classes_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..a0d83a43acb218e088385f1069f6c6443084e32a --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/classes/classes_dynamic.js @@ -0,0 +1,4 @@ +class C1 { + M1(){} + static M2(){} +} diff --git a/libabckit/tests/metadata/inspect_api/classes/classes_empty_dynamic.js b/libabckit/tests/metadata/inspect_api/classes/classes_empty_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..44f95f7ff5c54dc97e200b113476258c14b72333 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/classes/classes_empty_dynamic.js @@ -0,0 +1,2 @@ +class C1 { +} diff --git a/libabckit/tests/metadata/inspect_api/classes/classes_empty_static.ets b/libabckit/tests/metadata/inspect_api/classes/classes_empty_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..c3df66d11c7136923b9cb20567d8d666447d4ce6 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/classes/classes_empty_static.ets @@ -0,0 +1,6 @@ +class C1 { +} + +function main() { + console.log("hello from classes_empty_static.ets") +} diff --git a/libabckit/tests/metadata/inspect_api/classes/classes_static.ets b/libabckit/tests/metadata/inspect_api/classes/classes_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..f24ee6d0b5b38cec6930d8ed3a858eb24942be24 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/classes/classes_static.ets @@ -0,0 +1,8 @@ +class C1 { + C1M1(){} + static C1M2(){} +} + +function main() { + console.log("hello from classes_static.ets") +} diff --git a/libabckit/tests/metadata/inspect_api/classes/classes_test.cpp b/libabckit/tests/metadata/inspect_api/classes/classes_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0a9d4b6cbcf42bcb954df285b41ac11ee651ff2b --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/classes/classes_test.cpp @@ -0,0 +1,614 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" +#include "logger.h" + + +#define EMBED_TEST_START(name) auto name = [&]() { +#define EMBED_TEST_END(name) \ + } \ + ; \ + name(); + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); + +class LibAbcKitInspectApiClassesTest : public ::testing::Test {}; + +static bool classCountrer(abckit_Class *klass, void *data) +{ + helpers::assertClassVisitor(klass, data); + (*(reinterpret_cast(data)))++; + return true; +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateClasses, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, StaticModuleEnumerateClasses) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static.abc", &ctx); + + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + std::size_t gotNumClasses = 0; + implI->ModuleEnumerateClasses(m, &gotNumClasses, classCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumClasses = 1; + ASSERT_EQ(gotNumClasses, expectedNumClasses); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctx); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateClasses, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, DynamicModuleEnumerateClasses) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_dynamic.abc", &ctx); + + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + std::size_t gotNumClasses = 0; + implI->ModuleEnumerateClasses(m, &gotNumClasses, classCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumClasses = 1; + ASSERT_EQ(gotNumClasses, expectedNumClasses); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctx); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateClasses, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, StaticModuleEnumerateClassesEmpty) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_empty_static.abc", &ctx); + + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + std::size_t gotNumClasses = 0; + implI->ModuleEnumerateClasses(m, &gotNumClasses, classCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumClasses = 1; + ASSERT_EQ(gotNumClasses, expectedNumClasses); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctx); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateClasses, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, DynamicModuleEnumerateClassesEmpty) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_empty_dynamic.abc", &ctx); + + implI->FileEnumerateModules(ctx, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + std::size_t gotNumClasses = 0; + implI->ModuleEnumerateClasses(m, &gotNumClasses, classCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumClasses = 1; + ASSERT_EQ(gotNumClasses, expectedNumClasses); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctx); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetName, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, ClassGetNameSmoke) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + abckit_String *name = nullptr; + name = implI->ClassGetName(nullptr); + ASSERT_EQ(name, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + + name = implI->ClassGetName(ctxFinder.klass); + ASSERT_NE(name, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *ctxI = implI->ModuleGetInspectContext(m); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxI, nullptr); + auto nameStr = helpers::abckit_StringToString(ctxI, name); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(nameStr, "C1"); + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// NOTE: Enable when ModuleEnumerateClasses is implemented +// Test: test-kind=api, api=InspectApiImpl::ClassGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, DISABLED_DynamicClassGetNameSmoke) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_dynamic.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + abckit_String *name = nullptr; + name = implI->ClassGetName(nullptr); + ASSERT_EQ(name, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + + name = implI->ClassGetName(ctxFinder.klass); + ASSERT_EQ(name, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *ctxI = implI->ModuleGetInspectContext(m); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxI, nullptr); + auto nameStr = helpers::abckit_StringToString(ctxI, name); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(nameStr, "C1"); + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, "/tmp/classes_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static bool classNameCollector(abckit_Class *klass, void *data) +{ + helpers::assertClassVisitor(klass, data); + + abckit_File *ctx = implI->ClassGetInspectContext(klass); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(ctx != nullptr); + auto names = reinterpret_cast *>(data); + auto className = implI->ClassGetName(klass); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, className); + LIBABCKIT_LOG(DEBUG) << "class name: " << name << std::endl; + EXPECT_TRUE(names->find(name) == names->end()); + names->insert(name); + + return true; +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetName, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, ClassGetName) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + std::set gotNames; + + implI->ModuleEnumerateClasses(m, &gotNames, classNameCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"C1"}; + ASSERT_EQ(expectedNames.size(), gotNames.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotNames.find(expectedName), gotNames.end()); + } + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetName, abc-kind=JS, category=positive +// NOTE: Enable when ModuleEnumerateClasses is implemented +TEST_F(LibAbcKitInspectApiClassesTest, DISABLED_DynamicClassGetName) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_dynamic.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + std::set gotNames; + implI->ModuleEnumerateClasses(m, &gotNames, classNameCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"_ESModuleRecord", "_ESTypeInfoRecord"}; + ASSERT_EQ(expectedNames.size(), gotNames.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotNames.find(expectedName), gotNames.end()); + } + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, "/tmp/classes_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static bool dummyMethodVisitor(abckit_Method *method, void *data) +{ + EXPECT_TRUE(method != nullptr); + [[maybe_unused]] abckit_File *ctx = implI->MethodGetInspectContext(method); + EXPECT_TRUE(ctx != nullptr); + return true; +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, ClassEnumerateMethodsSmoke) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + auto *klass = ctxFinder.klass; + + implI->ClassEnumerateMethods(nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + implI->ClassEnumerateMethods(klass, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + void *someData = reinterpret_cast(0xcafef00d); + implI->ClassEnumerateMethods(klass, someData, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + implI->ClassEnumerateMethods(ctxFinder.klass, nullptr, dummyMethodVisitor); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implI->ClassEnumerateMethods(ctxFinder.klass, someData, dummyMethodVisitor); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=JS, category=positive +// NOTE: Enable when ModuleEnumerateClasses is implemented +TEST_F(LibAbcKitInspectApiClassesTest, DISABLED_DynamicClassEnumerateMethodsSmoke) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_dynamic.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + + auto *klass = ctxFinder.klass; + + implI->ClassEnumerateMethods(nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + implI->ClassEnumerateMethods(klass, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + void *someData = reinterpret_cast(0xcafef00d); + implI->ClassEnumerateMethods(klass, someData, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + implI->ClassEnumerateMethods(ctxFinder.klass, nullptr, dummyMethodVisitor); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + implI->ClassEnumerateMethods(ctxFinder.klass, someData, dummyMethodVisitor); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, "/tmp/classes_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +static bool methodCountrer(abckit_Method *method, void *data) +{ + helpers::assertMethodVisitor(method, data); + (*(reinterpret_cast(data)))++; + return true; +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, ClassEnumerateMethodsEmpty) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_empty_static.abc", &ctxI); + + // class C1 { + // // Empty body, no explicit methods + // + // } + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + auto *klass = ctxFinder.klass; + + std::size_t gotNumMethods = 0; + implI->ClassEnumerateMethods(klass, &gotNumMethods, methodCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumMethods = 1; + ASSERT_EQ(gotNumMethods, expectedNumMethods); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=JS, category=positive +// NOTE: Enable when ModuleEnumerateClasses is implemented +TEST_F(LibAbcKitInspectApiClassesTest, DISABLED_DynamicClassEnumerateMethodsEmpty) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_empty_dynamic.abc", &ctxI); + + // class C1 { + // // Empty body, no explicit methods + // + // } + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + auto *klass = ctxFinder.klass; + + std::size_t gotNumMethods = 0; + implI->ClassEnumerateMethods(klass, &gotNumMethods, methodCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumMethods = 1; + ASSERT_EQ(gotNumMethods, expectedNumMethods); + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, "/tmp/classes_empty_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, ClassEnumerateMethodsSeveralMethods) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static.abc", &ctxI); + + // class C1 { + // public C1M1() + // static C1M2() + // + // } + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + auto *klass = ctxFinder.klass; + + std::size_t gotNumMethods = 0; + implI->ClassEnumerateMethods(klass, &gotNumMethods, methodCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumMethods = 3; + ASSERT_EQ(gotNumMethods, expectedNumMethods); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=JS, category=positive +// NOTE: Enable when ModuleEnumerateClasses is implemented +TEST_F(LibAbcKitInspectApiClassesTest, DISABLED_DynamicClassEnumerateMethodsSeveralMethods) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_empty_dynamic.abc", &ctxI); + + // class C1 { + // public C1M1() + // static C1M2() + // + // } + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + auto *klass = ctxFinder.klass; + + std::size_t gotNumMethods = 0; + implI->ClassEnumerateMethods(klass, &gotNumMethods, methodCountrer); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + constexpr std::size_t expectedNumMethods = 3; + ASSERT_EQ(gotNumMethods, expectedNumMethods); + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, "/tmp/classes_empty_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetInspectContext, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiClassesTest, ClassGetInspectContext) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_static.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + auto *ctxI1 = implI->ModuleGetInspectContext(m); + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + + auto *ctxI2 = implI->ClassGetInspectContext(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(ctxI2, nullptr); + + ctxI2 = implI->ClassGetInspectContext(ctxFinder.klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(ctxI1, ctxI2); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetInspectContext, abc-kind=JS, category=positive +// NOTE: Enable when ModuleEnumerateClasses is implemented +TEST_F(LibAbcKitInspectApiClassesTest, DISABLED_DynamicClassGetInspectContext) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/classes/classes_dynamic.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + auto *ctxI1 = implI->ModuleGetInspectContext(m); + + helpers::ClassByNameContext ctxFinder = {nullptr, "C1"}; + implI->ModuleEnumerateClasses(m, &ctxFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.klass, nullptr); + + auto *ctxI2 = implI->ClassGetInspectContext(nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + ASSERT_EQ(ctxI2, nullptr); + + ctxI2 = implI->ClassGetInspectContext(ctxFinder.klass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(ctxI1, ctxI2); + + EMBED_TEST_END(test) + + return true; + }); + + impl->WriteAbc(ctxI, "/tmp/classes_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/inspect_api/enumerators/enumerators0_dynamic.ts b/libabckit/tests/metadata/inspect_api/enumerators/enumerators0_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f97191bbb8539f2ec272cb0a3e85a302e9ba7ee --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/enumerators/enumerators0_dynamic.ts @@ -0,0 +1,30 @@ +function M0F0() { + (()=>{console.log(1)})(); + (()=>{console.log(2)})(); +} +function* M0F1() {} +async function M0F2() {} +class M0C0 { + M0C0F0(){} + static M0C0F1(){} + async M0C0F2(){} + // async *M0C0F3(){} +} +enum M0E0 {} + +namespace M0N0 { + function M0N0F0() {} + function* M0N0F1() {} + async function M0N0F2() {} + class M0N0C0 { + M0N0C0F0(){} + static M0N0C0F1(){} + async M0N0C0F2(){} + // async *M0N0C0F3(){} + } + enum M0N0E0 {} + + namespace M0N0N0 { + function M0N0N0F0() {} + } +} diff --git a/libabckit/tests/metadata/inspect_api/enumerators/enumerators_static.ets b/libabckit/tests/metadata/inspect_api/enumerators/enumerators_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..acf3e7263f9e890a6761f298da16d7e5127578fb --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/enumerators/enumerators_static.ets @@ -0,0 +1,30 @@ +function M0F0() { + (()=>{console.log(1)})(); + (()=>{console.log(2)})(); +} +function* M0F1() {} +async function M0F2() {} +class M0C0 { + M0C0F0(){} + static M0C0F1(){} + async M0C0F2(){} + // async *M0C0F3(){} +} +// enum M0E0 {} + +// namespace M0N0 { + function M0N0F0() {} + function* M0N0F1() {} + async function M0N0F2() {} + class M0N0C0 { + M0N0C0F0(){} + static M0N0C0F1(){} + async M0N0C0F2(){} + // async *M0N0C0F3(){} + } + // enum M0N0E0 {} + + // namespace M0N0N0 { + function M0N0N0F0() {} + // } +// } diff --git a/libabckit/tests/metadata/inspect_api/enumerators/modules/enumerators1_dynamic.ts b/libabckit/tests/metadata/inspect_api/enumerators/modules/enumerators1_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..8c87a007ea7cdd40afb37a495c183ae22b67ad16 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/enumerators/modules/enumerators1_dynamic.ts @@ -0,0 +1,23 @@ +function M1F0() { + ()=>{} +} +function* M1F1() {} +class M1C0 { + M1C0F0(){} + static M1C0F1(){} + async M1C0F2(){} + // async *M1C0F3(){} +} +enum M1E0 {} + +namespace M1N0 { + function M1N0F0() {} + function* M1N0F1() {} + class M1N0C0 { + M1N0C0F0(){} + static M1N0C0F1(){} + async M1N0C0F2(){} + // async *M1N0C0F3(){} + } + enum M1N0E0 {} +} diff --git a/libabckit/tests/metadata/inspect_api/enumerators/modules_test.cpp b/libabckit/tests/metadata/inspect_api/enumerators/modules_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..41a3bc553ccc05fe6b7906c02e4bfa52e1acf964 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/enumerators/modules_test.cpp @@ -0,0 +1,238 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" +#include "statuses.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitInspectApiEnumeratorsTest : public ::testing::Test {}; + +static const std::string NO_CLASS = "__NO_CLASS__"; +static std::unordered_map>> NAMES = { + {"enumerators0_dynamic", { + {NO_CLASS, { + "M0N0N0F0", + "M0N0F0", + "M0N0F1", + "M0N0F2", + "M0F0", + "M0F1", + "M0F2", + "", + "^1", + "func_main_0", + }}, + {"M0N0C0", { + "M0N0C0F1", + "M0N0C0", + "M0N0C0F0", + "M0N0C0F2", + }}, + {"M0C0", { + "M0C0F1", + "M0C0", + "M0C0F0", + "M0C0F2", + }} + }}, + {"modules/enumerators1_dynamic", { + {NO_CLASS, { + "M1N0F0", + "M1N0F1", + "M1F0", + "M1F1", + "", + "func_main_0", + }}, + {"M1N0C0", { + "M1N0C0F1", + "M1N0C0", + "M1N0C0F0", + "M1N0C0F2", + }}, + {"M1C0", { + "M1C0F1", + "M1C0", + "M1C0F0", + "M1C0F2", + }} + }}, +}; + +static void EnumerateAllMethods() +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/enumerators/enumerators0_dynamic.abc", &ctxI); + size_t methodsCounter = 0; + + std::string moduleName; + std::string className; + + std::function cbTopLevelFunctions = [&](abckit_Method *m) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(m)); + ASSERT_TRUE(NAMES[moduleName][NO_CLASS].count(methodName) == 1); + methodsCounter++; + }; + + std::function cbClassMethods = [&](abckit_Method *m) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(m)); + ASSERT_TRUE(NAMES[moduleName][className].count(methodName) == 1); + methodsCounter++; + }; + + std::function cbClass = [&](abckit_Class *c) { + className = helpers::abckit_StringToString(ctxI, implI->ClassGetName(c)); + ASSERT_TRUE(NAMES[moduleName].find(className) != NAMES[moduleName].end()); + implI->ClassEnumerateMethods(c, &cbClassMethods, [](abckit_Method *m, void *cbClassMethods) { + (*reinterpret_cast*>(cbClassMethods))(m); + return true; + }); + }; + + std::function cbModule = [&](abckit_Module *m) { + moduleName = helpers::abckit_StringToString(ctxI, implI->ModuleGetName(m)); + ASSERT_TRUE(NAMES.find(moduleName) != NAMES.end()); + implI->ModuleEnumerateClasses(m, &cbClass, [](abckit_Class *c, void *cbClass) { + (*reinterpret_cast*>(cbClass))(c); + return true; + }); + implI->ModuleEnumerateTopLevelFunctions(m, &cbTopLevelFunctions, [](abckit_Method *m, void *cbTopLevelFunctions) { + (*reinterpret_cast*>(cbTopLevelFunctions))(m); + return true; + }); + }; + + implI->FileEnumerateModules(ctxI, &cbModule, [](abckit_Module *m, void *cbModule){ + (*reinterpret_cast*>(cbModule))(m); + return true; + }); + ASSERT_EQ(methodsCounter, 32); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +struct testStructType { + size_t anonFuncsCounter = 0; + size_t anonFuncsNumber; + std::string nameModuleToSearch; + std::vector namesOfAnonFuncs; +}; + +static void EnumerateAnonymousFunctions(const char *abcFilePath, testStructType &testStruct) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(abcFilePath, &ctxI); + + implI->FileEnumerateModules(ctxI, &testStruct, [](abckit_Module *m, void* data) { + auto testStruct = (testStructType*) data; + + auto strModule = implI->ModuleGetName(m); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto ctxModule = implI->ModuleGetInspectContext(m); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto nameModule = helpers::abckit_StringToString(ctxModule, strModule); + if (nameModule != testStruct->nameModuleToSearch) { + return true; + } + implI->ModuleEnumerateAnonymousFunctions(m, data, [](abckit_Method *func, void *data1) { + auto testStruct = (testStructType *)data1; + + auto strFunc = implI->MethodGetName(func); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctxFunc = implI->MethodGetInspectContext(func); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto nameFunc = helpers::abckit_StringToString(ctxFunc, strFunc); + + auto &funcs = testStruct->namesOfAnonFuncs; + + auto iter = std::find_if(funcs.begin(), funcs.end(), [&nameFunc](std::string name){ + return nameFunc == name; + }); + + EXPECT_TRUE(iter != funcs.end()); + testStruct->anonFuncsCounter++; + return true; + }); + return true; + }); + + ASSERT_EQ(testStruct.anonFuncsCounter, testStruct.anonFuncsNumber); + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::FileEnumerateModules, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicFileEnumerateModules) +{ + EnumerateAllMethods(); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateClasses, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicModuleEnumerateClasses) +{ + EnumerateAllMethods(); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateTopLevelFunctions, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicModuleEnumerateTopLevelFunctions) +{ + EnumerateAllMethods(); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicClassEnumerateMethods) +{ + EnumerateAllMethods(); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateAnonymousFunctions, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiEnumeratorsTest, DynamicClassEnumerateAnonymousFunctions) +{ + testStructType testStruct; + testStruct.anonFuncsNumber = 2; + testStruct.nameModuleToSearch = "enumerators0_dynamic"; + testStruct.namesOfAnonFuncs = std::vector {"", "^1"}; + + EnumerateAnonymousFunctions(ABCKIT_ABC_DIR "metadata/inspect_api/enumerators/enumerators0_dynamic.abc", testStruct); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateAnonymousFunctions, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiEnumeratorsTest, StaticClassEnumerateAnonymousFunctions) +{ + testStructType testStruct; + testStruct.anonFuncsNumber = 2; + testStruct.nameModuleToSearch = "enumerators_static"; + testStruct.namesOfAnonFuncs = std::vector {"lambda$invoke$0:void;", "lambda$invoke$1:void;"}; + + EnumerateAnonymousFunctions(ABCKIT_ABC_DIR "metadata/inspect_api/enumerators/enumerators_static.abc", testStruct); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/inspect_api/files/file_static.ets b/libabckit/tests/metadata/inspect_api/files/file_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..c3df66d11c7136923b9cb20567d8d666447d4ce6 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/files/file_static.ets @@ -0,0 +1,6 @@ +class C1 { +} + +function main() { + console.log("hello from classes_empty_static.ets") +} diff --git a/libabckit/tests/metadata/inspect_api/files/files_test.cpp b/libabckit/tests/metadata/inspect_api/files/files_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..66830207737ff82c8aa6fc362cbe3374430044f6 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/files/files_test.cpp @@ -0,0 +1,96 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" +#include "logger.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); + +class LibAbcKitInspectApiFilesTest : public ::testing::Test {}; + +// Test: test-kind=api, api=InspectApiImpl::FileGetVersion, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiFilesTest, StaticFileGetVersion) +{ + LIBABCKIT_LOG(DEBUG) << "StaticFileGetVersion source: " + << ABCKIT_TEST_DIR "metadata/inspect_api/files\n"; + + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/files/file_static.abc", &ctxI); + + abckit_File_Version version = implI->FileGetVersion(ctxI); + uint8_t expected_version[ABCKIT_VERSION_SIZE] = {0, 0, 0, 5}; + + const bool versions_equality = std::memcmp(expected_version, version, sizeof(uint8_t)*ABCKIT_VERSION_SIZE); + ASSERT_EQ(versions_equality, 0); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::FileEnumerateModules, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiFilesTest, DynamicFileEnumerateModules) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + std::unordered_map gotModulesMap; + + implI->FileEnumerateModules(ctx, &gotModulesMap, helpers::nameToModuleCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"modules_dynamic", "modules/module1", "modules/module2", "modules/module3"}; + ASSERT_EQ(expectedNames.size(), gotModulesMap.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotModulesMap.find(expectedName), gotModulesMap.end()); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// TODO: fix after ets2bundle integrated into abckit unit tests +// Test: test-kind=api, api=InspectApiImpl::FileEnumerateExternalModules, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiFilesTest, DISABLED_DynamicFileEnumerateExternalModules) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + std::unordered_map gotModulesMap; + + implI->FileEnumerateExternalModules(ctx, &gotModulesMap, helpers::nameToModuleCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"modules/module1", "modules/module2", "modules/module3"}; + ASSERT_EQ(expectedNames.size(), gotModulesMap.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotModulesMap.find(expectedName), gotModulesMap.end()); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/inspect_api/literals/literals_dynamic.js b/libabckit/tests/metadata/inspect_api/literals/literals_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..df377908ff2209e9aabd2003d2e0865510ca40f7 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/literals/literals_dynamic.js @@ -0,0 +1 @@ +o = [false, 1, "2", 0.4] diff --git a/libabckit/tests/metadata/inspect_api/literals/literals_static.ets b/libabckit/tests/metadata/inspect_api/literals/literals_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5349389c39044e1e87b451e8e209ee801f2f4a5 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/literals/literals_static.ets @@ -0,0 +1,8 @@ +function ConsoleLogStr(a: string) { + console.log(a) +} + +function main() { + let str : string = "testString"; + ConsoleLogStr(str); +} diff --git a/libabckit/tests/metadata/inspect_api/literals/literals_test.cpp b/libabckit/tests/metadata/inspect_api/literals/literals_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1cac2f21dab1311f60b5037898eb27989ee61ad --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/literals/literals_test.cpp @@ -0,0 +1,352 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" +#include "metadata_modify_impl.h" // FIXME(mshimenkov) + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +class LibAbcKitInspectApiLiteralsTest : public ::testing::Test {}; + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetBool, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetBool_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralBool(&ctxM, true); + auto val = implI->LiteralGetBool(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_TRUE(val); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU8, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU8_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU8(&ctxM, 1); + auto val = implI->LiteralGetU8(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU16, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU16_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU16(&ctxM, 1); + auto val = implI->LiteralGetU16(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU32, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU32_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU32(&ctxM, 1); + auto val = implI->LiteralGetU32(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU64, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU64_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU64(&ctxM, 1); + auto val = implI->LiteralGetU64(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetFloat, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetFloat_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralFloat(&ctxM, 1.0); + auto val = implI->LiteralGetFloat(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_FLOAT_EQ(val, 1.0); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetDouble, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetDouble_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralDouble(&ctxM, 1.0); + auto val = implI->LiteralGetDouble(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_DOUBLE_EQ(val, 1.0); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetString, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetString_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralString(&ctxM, "asdf"); + auto val = implI->LiteralGetString(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(helpers::abckit_StringToString(ctxI, val), "asdf"); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetTag, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetTag_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralString(&ctxM, "asdf"); + ASSERT_EQ(implI->LiteralGetTag(ctxI, res), abckit_LiteralTag_STRING); + + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralArrayEnumerateElements, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralArrayEnumerateElements_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto arr = std::vector({ + implM->CreateLiteralBool(&ctxM, true), + implM->CreateLiteralU32(&ctxM, (uint32_t)((uint32_t)2 << 30) + 1), + implM->CreateLiteralDouble(&ctxM, 3.22), + implM->CreateLiteralString(&ctxM, "asdf"), + }); + auto lit_arr = implM->CreateLiteralArray(&ctxM, arr.data(), arr.size()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(lit_arr, nullptr); + + std::vector newArr; + implI->LiteralArrayEnumerateElements(ctxI, lit_arr, &newArr, [](abckit_File *ctx, abckit_Literal *lit, void *data) { + (reinterpret_cast *>(data))->emplace_back(lit); + return true; + }); + + ASSERT_EQ(newArr.size(), 4); + for (auto *lit : newArr) { + auto tag = implI->LiteralGetTag(ctxI, lit); + switch (tag) { + case abckit_LiteralTag_BOOL: + ASSERT_EQ(implI->LiteralGetBool(ctxI, lit), true); + break; + case abckit_LiteralTag_INTEGER: + ASSERT_EQ(implI->LiteralGetU32(ctxI, lit), (uint32_t)((uint32_t)2 << 30) + 1); + break; + case abckit_LiteralTag_DOUBLE: + ASSERT_EQ(implI->LiteralGetDouble(ctxI, lit), 3.22); + break; + case abckit_LiteralTag_STRING: { + abckit_String *str = implI->LiteralGetString(ctxI, lit); + ASSERT_EQ(helpers::abckit_StringToString(ctxI, str), "asdf"); + break; + } + default: + LIBABCKIT_UNREACHABLE_TEST(DEBUG) + } + } + + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetBool, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetBool_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralBool(&ctxM, true); + auto val = implI->LiteralGetBool(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_TRUE(val); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU8, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU8_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU8(&ctxM, 1); + auto val = implI->LiteralGetU8(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU16, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU16_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU16(&ctxM, 1); + auto val = implI->LiteralGetU16(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU32, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU32_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU32(&ctxM, 1); + auto val = implI->LiteralGetU32(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetU64_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU64(&ctxM, 1); + auto val = implI->LiteralGetU64(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetFloat, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetFloat_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralFloat(&ctxM, 1.0); + auto val = implI->LiteralGetFloat(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_FLOAT_EQ(val, 1.0); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetDouble, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetDouble_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralDouble(&ctxM, 1.0); + auto val = implI->LiteralGetDouble(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_DOUBLE_EQ(val, 1.0); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetString_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralString(&ctxM, "asdf"); + auto val = implI->LiteralGetString(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(helpers::abckit_StringToString(ctxI, val), "asdf"); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetTag, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiLiteralsTest, LiteralGetTag_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralString(&ctxM, "asdf"); + ASSERT_EQ(implI->LiteralGetTag(ctxI, res), abckit_LiteralTag_STRING); + + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} +} \ No newline at end of file diff --git a/libabckit/tests/metadata/inspect_api/methods/methods_dynamic.ts b/libabckit/tests/metadata/inspect_api/methods/methods_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f97191bbb8539f2ec272cb0a3e85a302e9ba7ee --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/methods/methods_dynamic.ts @@ -0,0 +1,30 @@ +function M0F0() { + (()=>{console.log(1)})(); + (()=>{console.log(2)})(); +} +function* M0F1() {} +async function M0F2() {} +class M0C0 { + M0C0F0(){} + static M0C0F1(){} + async M0C0F2(){} + // async *M0C0F3(){} +} +enum M0E0 {} + +namespace M0N0 { + function M0N0F0() {} + function* M0N0F1() {} + async function M0N0F2() {} + class M0N0C0 { + M0N0C0F0(){} + static M0N0C0F1(){} + async M0N0C0F2(){} + // async *M0N0C0F3(){} + } + enum M0N0E0 {} + + namespace M0N0N0 { + function M0N0N0F0() {} + } +} diff --git a/libabckit/tests/metadata/inspect_api/methods/methods_static.ets b/libabckit/tests/metadata/inspect_api/methods/methods_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..acf3e7263f9e890a6761f298da16d7e5127578fb --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/methods/methods_static.ets @@ -0,0 +1,30 @@ +function M0F0() { + (()=>{console.log(1)})(); + (()=>{console.log(2)})(); +} +function* M0F1() {} +async function M0F2() {} +class M0C0 { + M0C0F0(){} + static M0C0F1(){} + async M0C0F2(){} + // async *M0C0F3(){} +} +// enum M0E0 {} + +// namespace M0N0 { + function M0N0F0() {} + function* M0N0F1() {} + async function M0N0F2() {} + class M0N0C0 { + M0N0C0F0(){} + static M0N0C0F1(){} + async M0N0C0F2(){} + // async *M0N0C0F3(){} + } + // enum M0N0E0 {} + + // namespace M0N0N0 { + function M0N0N0F0() {} + // } +// } diff --git a/libabckit/tests/metadata/inspect_api/methods/methods_test.cpp b/libabckit/tests/metadata/inspect_api/methods/methods_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4eae4e416cc69dc22e0a6c0e790ab21dcf5277f1 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/methods/methods_test.cpp @@ -0,0 +1,543 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" +#include "helpers/visit_helper/visit_helper-inl.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitInspectApiMethodsTest : public ::testing::Test {}; + +// Test: test-kind=api, api=InspectApiImpl::MethodGetCode, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, StaticMethodGetCode) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "M0C0"}; + implI->ModuleEnumerateClasses(m, &ctxClassFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxClassFinder.klass, nullptr); + + helpers::MethodByNameContext ctxMethodFinder = {nullptr, "M0C0F0"}; + implI->ClassEnumerateMethods(ctxClassFinder.klass, &ctxMethodFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxMethodFinder.method, nullptr); + + auto *method = ctxMethodFinder.method; + auto *mCode = implI->MethodGetCode(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(mCode, nullptr); + + impl->DestroyGraphContext(impl->codeToGraph(implI->ModuleGetInspectContext(m), mCode)); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetCode, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodGetCode) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "M0C0"}; + implI->ModuleEnumerateClasses(m, &ctxClassFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxClassFinder.klass, nullptr); + + helpers::MethodByNameContext ctxMethodFinder = {nullptr, "M0C0F0"}; + implI->ClassEnumerateMethods(ctxClassFinder.klass, &ctxMethodFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxMethodFinder.method, nullptr); + + auto *method = ctxMethodFinder.method; + auto *mCode = implI->MethodGetCode(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(mCode, nullptr); + + impl->DestroyGraphContext(impl->codeToGraph(implI->ModuleGetInspectContext(m), mCode)); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetName, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, StaticMethodGetName) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + std::set names = { + "M0F0:void;", + "M0F1:void;", + "M0F2$asyncimpl:std.core.Object;", + "M0F2:std.core.Promise;", + "M0N0F0:void;", + "M0N0F1:void;", + "M0N0F2$asyncimpl:std.core.Object;", + "M0N0F2:std.core.Promise;", + "M0N0N0F0:void;", + "_cctor_:void;", + "lambda$invoke$0:void;", + "lambda$invoke$1:void;", + "M0C0F0:methods_static.M0C0;void;", + "M0C0F1:void;", + "M0C0F2$asyncimpl:methods_static.M0C0;std.core.Object;", + "M0C0F2:methods_static.M0C0;std.core.Promise;", + "_ctor_:methods_static.M0C0;void;", + "M0N0C0F0:methods_static.M0N0C0;void;", + "M0N0C0F1:void;", + "M0N0C0F2$asyncimpl:methods_static.M0N0C0;std.core.Object;", + "M0N0C0F2:methods_static.M0N0C0;std.core.Promise;", + "_ctor_:methods_static.M0N0C0;void;", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method* m) { + auto *abckitname = implI->MethodGetName(m); + EXPECT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + EXPECT_NE(abckitname, nullptr); + std::string name = helpers::abckit_StringToString(ctxI, abckitname); + EXPECT_EQ(names.count(name), 1); + names.erase(name); + }); + ASSERT_TRUE(names.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetName, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodGetName) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + std::set names = { + "M0C0", + "M0C0F1", + "M0C0F0", + "M0C0F2", + "M0N0C0", + "M0N0C0F1", + "M0N0C0F0", + "M0N0C0F2", + "M0N0N0F0", + "M0N0F0", + "M0N0F1", + "M0N0F2", + "M0F0", + "M0F1", + "M0F2", + "", + "^1", + "func_main_0", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method* m) { + auto *abckitname = implI->MethodGetName(m); + EXPECT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + EXPECT_NE(abckitname, nullptr); + std::string name = helpers::abckit_StringToString(ctxI, abckitname); + EXPECT_EQ(names.count(name), 1); + names.erase(name); + }); + ASSERT_TRUE(names.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + + +// Test: test-kind=api, api=InspectApiImpl::MethodGetInspectContext, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, MethodGetInspectContext) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "M0C0"}; + implI->ModuleEnumerateClasses(m, &ctxClassFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxClassFinder.klass, nullptr); + + helpers::MethodByNameContext ctxMethodFinder = {nullptr, "M0C0F0"}; + implI->ClassEnumerateMethods(ctxClassFinder.klass, &ctxMethodFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxMethodFinder.method, nullptr); + + auto *ctxClass = implI->ClassGetInspectContext(ctxClassFinder.klass); + auto *ctxMethod = implI->MethodGetInspectContext(ctxMethodFinder.method); + ASSERT_EQ(ctxClass, ctxMethod); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetInspectContext, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodGetInspectContext) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + implI->FileEnumerateModules(ctxI, nullptr, [](abckit_Module *m, [[maybe_unused]] void *data) -> bool { + EMBED_TEST_START(test) + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "M0C0"}; + implI->ModuleEnumerateClasses(m, &ctxClassFinder, helpers::classByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxClassFinder.klass, nullptr); + + helpers::MethodByNameContext ctxMethodFinder = {nullptr, "M0C0F0"}; + implI->ClassEnumerateMethods(ctxClassFinder.klass, &ctxMethodFinder, helpers::methodByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxMethodFinder.method, nullptr); + + auto *ctxClass = implI->ClassGetInspectContext(ctxClassFinder.klass); + auto *ctxMethod = implI->MethodGetInspectContext(ctxMethodFinder.method); + ASSERT_EQ(ctxClass, ctxMethod); + + EMBED_TEST_END(test) + + return true; + }); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsCtor, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodIsCtor) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + std::set CtorMethods = { + "M0C0", + "M0N0C0", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + bool isCtor = implI->MethodIsCtor(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (isCtor) { + EXPECT_EQ(CtorMethods.count(methodName), 1); + CtorMethods.erase(methodName); + } else { + EXPECT_EQ(CtorMethods.count(methodName), 0); + } + }); + ASSERT_TRUE(CtorMethods.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsCtor, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, StaticMethodIsCtor) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + std::set CtorMethods = { + "_ctor_:methods_static.M0C0;void;", + "_ctor_:methods_static.M0N0C0;void;" + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + bool isCtor = implI->MethodIsCtor(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (isCtor) { + EXPECT_EQ(CtorMethods.count(methodName), 1); + CtorMethods.erase(methodName); + } else { + EXPECT_EQ(CtorMethods.count(methodName), 0); + } + }); + ASSERT_TRUE(CtorMethods.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsStatic, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodIsStatic) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + std::set StaticMethods = { + "M0C0F1", + "M0N0C0F1", + "M0N0N0F0", + "M0N0F0", + "M0N0F1", + "M0N0F2", + "M0F0", + "M0F1", + "M0F2", + "", + "^1", + "func_main_0", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + bool isStatic = implI->MethodIsStatic(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (isStatic) { + EXPECT_EQ(StaticMethods.count(methodName), 1); + StaticMethods.erase(methodName); + } else { + EXPECT_EQ(StaticMethods.count(methodName), 0); + } + }); + ASSERT_TRUE(StaticMethods.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsStatic, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, StaticMethodIsStatic) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + std::set StaticMethods = { + "M0N0C0F1:void;", + "M0C0F1:void;", + "M0F0:void;", + "M0F1:void;", + "M0F2$asyncimpl:std.core.Object;", + "M0F2:std.core.Promise;", + "M0N0F0:void;", + "M0N0F1:void;", + "M0N0F2$asyncimpl:std.core.Object;", + "M0N0F2:std.core.Promise;", + "M0N0N0F0:void;", + "_cctor_:void;", + "lambda$invoke$0:void;", + "lambda$invoke$1:void;", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + bool isStatic = implI->MethodIsStatic(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (isStatic) { + EXPECT_EQ(StaticMethods.count(methodName), 1); + StaticMethods.erase(methodName); + } else { + EXPECT_EQ(StaticMethods.count(methodName), 0); + } + }); + ASSERT_TRUE(StaticMethods.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsAnonymous, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodIsAnonymous) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + std::set AnonymousMethods = { + "", + "^1", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + bool isAnonymous = implI->MethodIsAnonymous(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (isAnonymous) { + EXPECT_EQ(AnonymousMethods.count(methodName), 1); + AnonymousMethods.erase(methodName); + } else { + EXPECT_EQ(AnonymousMethods.count(methodName), 0); + } + }); + ASSERT_TRUE(AnonymousMethods.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsAnonymous, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, StaticMethodIsAnonymous) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + std::set AnonymousMethods = { + "lambda$invoke$0:void;", + "lambda$invoke$1:void;", + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + bool isAnonymous = implI->MethodIsAnonymous(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (isAnonymous) { + EXPECT_EQ(AnonymousMethods.count(methodName), 1); + AnonymousMethods.erase(methodName); + } else { + EXPECT_EQ(AnonymousMethods.count(methodName), 0); + } + AnonymousMethods.erase(methodName); + }); + ASSERT_TRUE(AnonymousMethods.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetParentClass, abc-kind=TS, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, DynamicMethodGetParentClass) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_dynamic.abc", &ctxI); + + std::unordered_map MethodClasses = { + {"M0C0F1", "M0C0"}, + {"M0C0", "M0C0"}, + {"M0C0F0", "M0C0"}, + {"M0C0F2", "M0C0"}, + {"M0N0C0F1", "M0N0C0"}, + {"M0N0C0", "M0N0C0"}, + {"M0N0C0F0", "M0N0C0"}, + {"M0N0C0F2", "M0N0C0"}, + {"M0N0N0F0", ""}, + {"M0N0F0", ""}, + {"M0N0F1", ""}, + {"M0N0F2", ""}, + {"M0F0", ""}, + {"M0F1", ""}, + {"M0F2", ""}, + {"", ""}, + {"^1", ""}, + {"func_main_0", ""}, + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + ASSERT_EQ(MethodClasses.count(methodName), 1); + abckit_Class *methodClass = implI->MethodGetParentClass(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (methodClass == nullptr) { + ASSERT_EQ(MethodClasses.at(methodName), ""); + } else { + std::string className = helpers::abckit_StringToString(ctxI, implI->ClassGetName(methodClass)); + ASSERT_EQ(MethodClasses.at(methodName), className); + } + MethodClasses.erase(methodName); + }); + ASSERT_TRUE(MethodClasses.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetParentClass, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiMethodsTest, StaticMethodGetParentClass) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/methods/methods_static.abc", &ctxI); + + std::unordered_map MethodClasses = { + {"M0F0:void;", ""}, + {"M0F1:void;", ""}, + {"M0F2$asyncimpl:std.core.Object;", ""}, + {"M0F2:std.core.Promise;", ""}, + {"M0N0F0:void;", ""}, + {"M0N0F1:void;", ""}, + {"M0N0F2$asyncimpl:std.core.Object;", ""}, + {"M0N0F2:std.core.Promise;", ""}, + {"M0N0N0F0:void;", ""}, + {"_cctor_:void;", ""}, + {"lambda$invoke$0:void;", ""}, + {"lambda$invoke$1:void;", ""}, + {"M0C0F0:methods_static.M0C0;void;", "M0C0"}, + {"M0C0F1:void;", "M0C0"}, + {"M0C0F2$asyncimpl:methods_static.M0C0;std.core.Object;", "M0C0"}, + {"M0C0F2:methods_static.M0C0;std.core.Promise;", "M0C0"}, + {"_ctor_:methods_static.M0C0;void;", "M0C0"}, + {"M0N0C0F0:methods_static.M0N0C0;void;", "M0N0C0"}, + {"M0N0C0F1:void;", "M0N0C0"}, + {"M0N0C0F2$asyncimpl:methods_static.M0N0C0;std.core.Object;", "M0N0C0"}, + {"M0N0C0F2:methods_static.M0N0C0;std.core.Promise;", "M0N0C0"}, + {"_ctor_:methods_static.M0N0C0;void;", "M0N0C0"}, + }; + + helpers::EnumerateAllMethods(ctxI, [&](abckit_Method *method) { + std::string methodName = helpers::abckit_StringToString(ctxI, implI->MethodGetName(method)); + ASSERT_EQ(MethodClasses.count(methodName), 1); + abckit_Class *methodClass = implI->MethodGetParentClass(method); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + if (methodClass == nullptr) { + ASSERT_EQ(MethodClasses.at(methodName), ""); + } else { + std::string className = helpers::abckit_StringToString(ctxI, implI->ClassGetName(methodClass)); + ASSERT_EQ(MethodClasses.at(methodName), className); + } + MethodClasses.erase(methodName); + }); + ASSERT_TRUE(MethodClasses.empty()); + + impl->DestroyInspectContext(ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/inspect_api/modules/modules/module1.js b/libabckit/tests/metadata/inspect_api/modules/modules/module1.js new file mode 100644 index 0000000000000000000000000000000000000000..f3b2de3f42d38955f63df1f647a9b8d4c83696d4 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/modules/modules/module1.js @@ -0,0 +1,20 @@ +export function RegularImportFunc1FromModule1() +{ + print("regular import func1 from module1") +} +export function NamespaceImportFunc2FromModule1() +{ + print("namespace import func2 from module1") +} +export function NamespaceImportFunc3FromModule1() +{ + print("namespace import func3 from module1") +} +export function IndirectExportFunc1FromModule1() +{ + print("indirect export func1 from module1") +} +export function IndirectExportFunc2FromModule1() +{ + print("indirect export func2 from module1") +} \ No newline at end of file diff --git a/libabckit/tests/metadata/inspect_api/modules/modules/module2.js b/libabckit/tests/metadata/inspect_api/modules/modules/module2.js new file mode 100644 index 0000000000000000000000000000000000000000..785aed015ba07e821f9d349f6351f14c15c1b6f6 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/modules/modules/module2.js @@ -0,0 +1,9 @@ +export function RegularImportFunc1FromModule2() +{ + print("regular import func1 from module2") +} + +export default function RegularDefaultImportFunc2FromModule2() +{ + print("regular default import func2 from module2") +} \ No newline at end of file diff --git a/libabckit/tests/metadata/inspect_api/modules/modules/module3.js b/libabckit/tests/metadata/inspect_api/modules/modules/module3.js new file mode 100644 index 0000000000000000000000000000000000000000..de6d2b37f0d7d76505bb203d3041e7301e0de910 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/modules/modules/module3.js @@ -0,0 +1,5 @@ + +export default function RegularDefaultImportFunc1FromModule3() +{ + print("regular default import func1 from module3") +} diff --git a/libabckit/tests/metadata/inspect_api/modules/modules_dynamic.js b/libabckit/tests/metadata/inspect_api/modules/modules_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..6dab2f2b70c1df9b4a52824a4bcd2beb14058fef --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/modules/modules_dynamic.js @@ -0,0 +1,32 @@ +// Regular +import {RegularImportFunc1FromModule1} from "./modules/module1" +import {RegularImportFunc1FromModule2 as MF1M2} from "./modules/module2" +import RegularDefaultImportFunc1FromModule3 from "./modules/module3" +import {default as RegularDefaultImportFunc2FromModule2} from "./modules/module2" + +// Namespace +import * as NS from "./modules/module1" + +// Local export +export function LocalExportFunc() {} +export class LocalExportClass {} +export let LocalExportLet = 2; +export var LocalExportVar; +export default class LocalDefaultExportClass {} + +// Indirect export +export {IndirectExportFunc1FromModule1} from "./modules/module1" +export {IndirectExportFunc2FromModule1 as MF2M1} from "./modules/module1" + +// Star export +export * as StarExport from "./modules/module1" +export * as StarExport2 from "./modules/module2" +export * from "./modules/module2" + +RegularImportFunc1FromModule1(); +MF1M2(); +RegularDefaultImportFunc1FromModule3(); +RegularDefaultImportFunc2FromModule2(); +NS.NamespaceImportFunc2FromModule1(); +NS.NamespaceImportFunc3FromModule1(); +print(LocalExportLet); diff --git a/libabckit/tests/metadata/inspect_api/modules/modules_dynamic_external.js b/libabckit/tests/metadata/inspect_api/modules/modules_dynamic_external.js new file mode 100644 index 0000000000000000000000000000000000000000..7cfd9754dfe54b712edfb0579f9ce5f338b93fa9 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/modules/modules_dynamic_external.js @@ -0,0 +1,35 @@ +// Regular +import {RegularImportFunc1FromModule1} from "./modules/module1" +import {RegularImportFunc1FromModule2 as MF1M2} from "./modules/module2" +import RegularDefaultImportFunc1FromModule3 from "./modules/module3" +import {default as RegularDefaultImportFunc2FromModule2} from "./modules/module2" + +// Namespace +import * as NS from "./modules/module1" + +// Local export +export function LocalExportFunc() {} +export class LocalExportClass {} +export let LocalExportLet = 2; +export var LocalExportVar; +export default class LocalDefaultExportClass {} + +// Indirect export +export {IndirectExportFunc1FromModule1} from "./modules/module1" +export {IndirectExportFunc2FromModule1 as MF2M1} from "./modules/module1" + +// Star export +export * as StarExport from "./modules/module1" +export * as StarExport2 from "./modules/module2" +export * from "./modules/module2" + +// External import +import ExternalImport from "external_module" + +RegularImportFunc1FromModule1(); +MF1M2(); +RegularDefaultImportFunc1FromModule3(); +RegularDefaultImportFunc2FromModule2(); +NS.NamespaceImportFunc2FromModule1(); +NS.NamespaceImportFunc3FromModule1(); +print(LocalExportLet); diff --git a/libabckit/tests/metadata/inspect_api/modules/modules_dynamic_test.cpp b/libabckit/tests/metadata/inspect_api/modules/modules_dynamic_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50f982875808e09d900a633b824afa25329124cb --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/modules/modules_dynamic_test.cpp @@ -0,0 +1,956 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "metadata.h" +#include "metadata_inspect_impl.h" +#include "isa/isa_dynamic.h" +#include "ir_impl.h" +#include "logger.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitInspectApiModulesTest : public ::testing::Test {}; + +// ======================================== +// Helpers +// ======================================== + +static bool moduleNamesCollector(abckit_Module *module, void *data) +{ + helpers::assertModuleVisitor(module, data); + + abckit_File *ctx = implI->ModuleGetInspectContext(module); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(ctx != nullptr); + auto names = reinterpret_cast *>(data); + auto moduleName = implI->ModuleGetName(module); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, moduleName); + LIBABCKIT_LOG(DEBUG) << "module name: " << name << std::endl; + EXPECT_TRUE(names->find(name) == names->end()); + names->insert(name); + + return true; +} + +static bool moduleCollector(abckit_Module *module, void *data) +{ + helpers::assertModuleVisitor(module, data); + + auto modules = reinterpret_cast *>(data); + EXPECT_TRUE(modules->find(module) == modules->end()); + modules->insert(module); + + return true; +} + +static bool moduleImportNamesCollector(abckit_ImportDescriptor *id, void *data) +{ + helpers::assertImportVisitor(id, data); + + abckit_File *ctx = implI->ImportDescriptorGetInspectContext(id); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(ctx != nullptr); + auto names = reinterpret_cast *>(data); + auto importName = implI->ImportDescriptorGetName(id); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, importName); + LIBABCKIT_LOG(DEBUG) << "import name: " << name << std::endl; + auto found = names->find(name); + if (found != names->end()) { + found->second += 1; + } else { + names->emplace(name, 1); + } + + return true; +} + +static bool moduleImportAliasCollector(abckit_ImportDescriptor *id, void *data) +{ + helpers::assertImportVisitor(id, data); + + abckit_File *ctx = implI->ImportDescriptorGetInspectContext(id); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(ctx != nullptr); + auto names = reinterpret_cast *>(data); + auto importName = implI->ImportDescriptorGetAlias(id); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, importName); + LIBABCKIT_LOG(DEBUG) << "import alias: " << name << std::endl; + EXPECT_TRUE(names->find(name) == names->end()); + names->insert(name); + + return true; +} + +static bool moduleExportNamesCollector(abckit_ExportDescriptor *ed, void *data) +{ + helpers::assertExportVisitor(ed, data); + + abckit_File *ctx = implI->ExportDescriptorGetInspectContext(ed); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(ctx != nullptr); + auto names = reinterpret_cast *>(data); + auto exportName = implI->ExportDescriptorGetName(ed); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, exportName); + LIBABCKIT_LOG(DEBUG) << "export name: " << name << std::endl; + auto found = names->find(name); + if (found != names->end()) { + found->second += 1; + } else { + names->emplace(name, 1); + } + + return true; +} + +static bool moduleExportAliasCollector(abckit_ExportDescriptor *ed, void *data) +{ + helpers::assertExportVisitor(ed, data); + + abckit_File *ctx = implI->ExportDescriptorGetInspectContext(ed); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(ctx != nullptr); + auto names = reinterpret_cast *>(data); + auto exportName = implI->ExportDescriptorGetAlias(ed); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = helpers::abckit_StringToString(ctx, exportName); + LIBABCKIT_LOG(DEBUG) << "export alias: " << name << std::endl; + EXPECT_TRUE(names->find(name) == names->end()); + names->insert(name); + + return true; +} + +void IgetModuleTest(abckit_Graph *ctxG, abckit_IsaApiDynamicOpcode opcode) +{ + auto MODULE_REQUEST_IDX = 0x0; + abckit_Inst *instWithModule = helpers::FindFirstInst(ctxG, opcode, [&](abckit_Inst *inst){ + auto imm = implG->IgetImmediate(inst, 0); + if (imm == MODULE_REQUEST_IDX) { + return true; + } + return false; + }); + + ASSERT_NE(instWithModule, nullptr); + auto moduleI = dynG->IgetModule(instWithModule); + if (opcode != abckit_IsaApiDynamicOpcode_getmodulenamespace) { + ASSERT_NE(impl->GetLastError(), abckit_Status_NO_ERROR); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module1"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *module = ctxFinder.module; + ASSERT_EQ(moduleI, module); +} + +void IgetImportDescriptorTest(abckit_Graph *ctxG, abckit_Module *m, abckit_IsaApiDynamicOpcode opcode) +{ + auto MODULE_REQUEST_IDX = 0x3; + abckit_Inst *instWithID = helpers::FindFirstInst(ctxG, opcode, [&](abckit_Inst *inst){ + auto imm = implG->IgetImmediate(inst, 0); + if (imm == MODULE_REQUEST_IDX) { + return true; + } + return false; + }); + + ASSERT_NE(instWithID, nullptr); + auto importI = dynG->IgetImportDescriptor(instWithID); + if (opcode != abckit_IsaApiDynamicOpcode_ldexternalmodulevar) { + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ImportByAliasContext importFinder = {nullptr, "RegularImportFunc1FromModule1"}; + implI->ModuleEnumerateImports(m, &importFinder, helpers::importByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(importFinder.id, nullptr); + + ASSERT_EQ(importFinder.id, importI); +} + +void IgetExportDescriptorTest(abckit_Graph *ctxG, abckit_Module *m, abckit_IsaApiDynamicOpcode opcode, size_t moduleRequestIdx) +{ + abckit_Inst *instWithID = helpers::FindFirstInst(ctxG, opcode, [&](abckit_Inst *inst){ + auto imm = implG->IgetImmediate(inst, 0); + if (imm == moduleRequestIdx) { + return true; + } + return false; + }); + + ASSERT_NE(instWithID, nullptr); + auto exportI = dynG->IgetExportDescriptor(instWithID); + if (opcode != abckit_IsaApiDynamicOpcode_ldlocalmodulevar) { + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ExportByAliasContext exportFinder = {nullptr, "LocalExportLet"}; + implI->ModuleEnumerateExports(m, &exportFinder, helpers::exportByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(exportFinder.ed, nullptr); + + ASSERT_EQ(exportFinder.ed, exportI); +} + +// ======================================== +// Modules Tests +// ======================================== + +// Test: test-kind=internal, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicFillModule) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + EXPECT_NE(m->impl.dyn.record, nullptr); + EXPECT_NE(m->impl.dyn.moduleLiteralArray, nullptr); + EXPECT_EQ(m->impl.dyn.ModuleRequestsOffset, 1); + EXPECT_EQ(m->impl.dyn.RegularImportsOffset, 5); + EXPECT_EQ(m->impl.dyn.NamespaceImportsOffset, 18); + EXPECT_EQ(m->impl.dyn.LocalExportsOffset, 25); + EXPECT_EQ(m->impl.dyn.IndirectExportsOffset, 40); + EXPECT_EQ(m->impl.dyn.StarExportsOffset, 47); + + // Request Modules + EXPECT_EQ(m->md.size(), 3); + size_t idx = 0; + EXPECT_EQ(helpers::abckit_StringToString(m->ctxI, m->md[idx]->moduleName), "modules/module1"); + EXPECT_EQ(m->md[idx]->isExternal, false); + idx++; + EXPECT_EQ(helpers::abckit_StringToString(m->ctxI, m->md[idx]->moduleName), "modules/module2"); + EXPECT_EQ(m->md[idx]->isExternal, false); + idx++; + EXPECT_EQ(helpers::abckit_StringToString(m->ctxI, m->md[idx]->moduleName), "modules/module3"); + EXPECT_EQ(m->md[idx]->isExternal, false); + + // Imports + EXPECT_EQ(m->id.size(), 5); + + // Regular imports + idx = 0; + EXPECT_EQ(m->id[idx]->importingModule, m); + EXPECT_EQ(m->id[idx]->importedModule, m->md[1]); + EXPECT_EQ(m->id[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_TRUE(m->id[idx]->payload.dyn.isRegularImport); + EXPECT_EQ(m->id[idx]->payload.dyn.moduleRecordIndexOff, idx); + idx++; + EXPECT_EQ(m->id[idx]->importingModule, m); + EXPECT_EQ(m->id[idx]->importedModule, m->md[2]); + EXPECT_EQ(m->id[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_TRUE(m->id[idx]->payload.dyn.isRegularImport); + EXPECT_EQ(m->id[idx]->payload.dyn.moduleRecordIndexOff, idx); + idx++; + EXPECT_EQ(m->id[idx]->importingModule, m); + EXPECT_EQ(m->id[idx]->importedModule, m->md[1]); + EXPECT_EQ(m->id[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_TRUE(m->id[idx]->payload.dyn.isRegularImport); + EXPECT_EQ(m->id[idx]->payload.dyn.moduleRecordIndexOff, idx); + idx++; + EXPECT_EQ(m->id[idx]->importingModule, m); + EXPECT_EQ(m->id[idx]->importedModule, m->md[0]); + EXPECT_EQ(m->id[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_TRUE(m->id[idx]->payload.dyn.isRegularImport); + EXPECT_EQ(m->id[idx]->payload.dyn.moduleRecordIndexOff, idx); + idx++; + + // Namespace imports + EXPECT_EQ(m->id[idx]->importingModule, m); + EXPECT_EQ(m->id[idx]->importedModule, m->md[0]); + EXPECT_EQ(m->id[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_FALSE(m->id[idx]->payload.dyn.isRegularImport); + EXPECT_EQ(m->id[idx]->payload.dyn.moduleRecordIndexOff, 0); + + // Exports + EXPECT_EQ(m->ed.size(), 10); + + // Local Exports + idx = 0; + + // Combined StarExport + EXPECT_EQ(m->ed[idx]->exportingModule, m); + EXPECT_EQ(m->ed[idx]->exportedModule, m->md[0]); + EXPECT_EQ(m->ed[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_EQ(m->ed[idx]->payload.dyn.kind, abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT); + EXPECT_EQ(m->ed[idx]->payload.dyn.hasServiceImport, true); + EXPECT_EQ(m->ed[idx]->payload.dyn.serviceNamespaceImportIdx, 1); + EXPECT_EQ(m->ed[idx]->payload.dyn.moduleRecordIndexOff, idx); + idx++; + EXPECT_EQ(m->ed[idx]->exportingModule, m); + EXPECT_EQ(m->ed[idx]->exportedModule, m->md[1]); + EXPECT_EQ(m->ed[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_EQ(m->ed[idx]->payload.dyn.kind, abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT); + EXPECT_EQ(m->ed[idx]->payload.dyn.hasServiceImport, true); + EXPECT_EQ(m->ed[idx]->payload.dyn.serviceNamespaceImportIdx, 2); + EXPECT_EQ(m->ed[idx]->payload.dyn.moduleRecordIndexOff, idx); + + idx++; + while (idx < 7) { + EXPECT_EQ(m->ed[idx]->exportingModule, m); + EXPECT_EQ(m->ed[idx]->exportedModule, m); + EXPECT_EQ(m->ed[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_EQ(m->ed[idx]->payload.dyn.kind, abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT); + EXPECT_EQ(m->ed[idx]->payload.dyn.hasServiceImport, false); + EXPECT_EQ(m->ed[idx]->payload.dyn.moduleRecordIndexOff, idx); + idx++; + } + + // Indirect Exports + EXPECT_EQ(m->ed[idx]->exportingModule, m); + EXPECT_EQ(m->ed[idx]->exportedModule, m->md[0]); + EXPECT_EQ(m->ed[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_EQ(m->ed[idx]->payload.dyn.kind, abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT); + EXPECT_EQ(m->ed[idx]->payload.dyn.hasServiceImport, false); + EXPECT_EQ(m->ed[idx]->payload.dyn.moduleRecordIndexOff, 0); + idx++; + EXPECT_EQ(m->ed[idx]->exportingModule, m); + EXPECT_EQ(m->ed[idx]->exportedModule, m->md[0]); + EXPECT_EQ(m->ed[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_EQ(m->ed[idx]->payload.dyn.kind, abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT); + EXPECT_EQ(m->ed[idx]->payload.dyn.hasServiceImport, false); + EXPECT_EQ(m->ed[idx]->payload.dyn.moduleRecordIndexOff, 1); + idx++; + + // Star Exports + EXPECT_EQ(m->ed[idx]->exportingModule, m); + EXPECT_EQ(m->ed[idx]->exportedModule, m->md[1]); + EXPECT_EQ(m->ed[idx]->kind, abckit_ImportExportDescriptorKind::UNTYPED); + EXPECT_EQ(m->ed[idx]->payload.dyn.kind, abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT); + EXPECT_EQ(m->ed[idx]->payload.dyn.hasServiceImport, false); + EXPECT_EQ(m->ed[idx]->payload.dyn.moduleRecordIndexOff, 0); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output2 = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + EXPECT_TRUE(helpers::Match(output2, expected)); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicModuleGetName) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + std::set gotNames; + + implI->FileEnumerateModules(ctx, &gotNames, moduleNamesCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"modules_dynamic", "modules/module1", "modules/module2", "modules/module3"}; + ASSERT_EQ(expectedNames.size(), gotNames.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotNames.find(expectedName), gotNames.end()); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// TODO: fix after ets2bundle integrated into abckit unit tests +// Test: test-kind=api, api=InspectApiImpl::ModuleIsExternal, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicModuleIsExternal) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_external.abc", &ctx); + + std::set gotModules; + + implI->FileEnumerateModules(ctx, &gotModules, moduleCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::unordered_map expected = {{"modules_dynamic_external", false}, {"modules/module1", false}, {"modules/module2", false}, {"modules/module3", false}, {"external_module", true}}; + ASSERT_EQ(expected.size(), gotModules.size()); + for (auto *module : gotModules) { + auto name = helpers::abckit_StringToString(ctx, implI->ModuleGetName(module)); + ASSERT_NE(expected.find(name), expected.end()); + ASSERT_EQ(implI->ModuleIsExternal(module), expected[name]); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_external_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleGetInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicModuleGetInspectContext) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + std::set gotModules; + + implI->FileEnumerateModules(ctx, &gotModules, moduleCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotModules.size(), 4); + for (auto *module : gotModules) { + auto ctxI = implI->ModuleGetInspectContext(module); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(ctxI, ctx); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// ======================================== +// Imports +// ======================================== + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateImports, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicModuleEnumerateImports) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotImports; + implI->ModuleEnumerateImports(m, &gotImports, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotImports.size(), 5); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicImportDescriptorGetName) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::unordered_map gotImportNames; + implI->ModuleEnumerateImports(m, &gotImportNames, moduleImportNamesCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"*", "RegularImportFunc1FromModule1", "RegularImportFunc1FromModule2", "default"}; + ASSERT_EQ(expectedNames.size(), gotImportNames.size()); + for (auto &expectedName : expectedNames) { + [[maybe_unused]] auto found = gotImportNames.find(expectedName); + ASSERT_NE(found, gotImportNames.end()); + if (expectedName == "default") { + ASSERT_EQ(found->second, 2); + } else { + ASSERT_EQ(found->second, 1); + } + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetAlias, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicImportDescriptorGetAlias) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotImportAliases; + implI->ModuleEnumerateImports(m, &gotImportAliases, moduleImportAliasCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"NS", "RegularImportFunc1FromModule1", "RegularDefaultImportFunc2FromModule2", + "RegularDefaultImportFunc1FromModule3", "MF1M2"}; + ASSERT_EQ(expectedNames.size(), gotImportAliases.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE( gotImportAliases.find(expectedName), gotImportAliases.end()); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicImportDescriptorGetInspectContext) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotImports; + implI->ModuleEnumerateImports(m, &gotImports, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotImports.size(), 5); + for (auto &gotImport : gotImports) { + auto ctxI = implI->ImportDescriptorGetInspectContext(gotImport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(ctxI, implI->ModuleGetInspectContext(m)); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetImportingModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicImportDescriptorGetImportingModule) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotImports; + implI->ModuleEnumerateImports(m, &gotImports, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotImports.size(), 5); + for (auto &gotImport : gotImports) { + auto impM = implI->ImportDescriptorGetImportingModule(gotImport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(impM, m); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetImportedModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicImportDescriptorGetImportedModule) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + std::unordered_map gotModulesMap; + + implI->FileEnumerateModules(ctx, &gotModulesMap, helpers::nameToModuleCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"modules_dynamic", "modules/module1", "modules/module2", "modules/module3"}; + ASSERT_EQ(expectedNames.size(), gotModulesMap.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotModulesMap.find(expectedName), gotModulesMap.end()); + } + + std::set gotImports; + implI->ModuleEnumerateImports(gotModulesMap.find("modules_dynamic")->second, &gotImports, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::unordered_map expected = {{"NS", gotModulesMap.find("modules/module1")->second}, + {"RegularImportFunc1FromModule1", gotModulesMap.find("modules/module1")->second}, + {"RegularDefaultImportFunc2FromModule2", gotModulesMap.find("modules/module2")->second}, + {"RegularDefaultImportFunc1FromModule3", gotModulesMap.find("modules/module3")->second}, + {"MF1M2", gotModulesMap.find("modules/module2")->second}}; + + ASSERT_EQ(gotImports.size(), 5); + for (auto &gotImport : gotImports) { + auto impM = implI->ImportDescriptorGetImportedModule(gotImport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto impName = implI->ImportDescriptorGetAlias(gotImport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto strName = helpers::abckit_StringToString(ctx, impName); + ASSERT_NE(expected.find(strName), expected.end()); + ASSERT_EQ(impM, expected.find(strName)->second); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// ======================================== +// Exports +// ======================================== + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateExports, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicModuleEnumerateExports) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotExports; + implI->ModuleEnumerateExports(m, &gotExports, helpers::moduleExportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotExports.size(), 10); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetName, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicExportDescriptorGetName) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::unordered_map gotExportNames; + implI->ModuleEnumerateExports(m, &gotExportNames, moduleExportNamesCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"*", "default", "LocalExportClass", "LocalExportFunc", "LocalExportLet", + "LocalExportVar", "IndirectExportFunc1FromModule1", "IndirectExportFunc2FromModule1"}; + ASSERT_EQ(expectedNames.size(), gotExportNames.size()); + for (auto &expectedName : expectedNames) { + [[maybe_unused]] auto found = gotExportNames.find(expectedName); + ASSERT_NE(found, gotExportNames.end()); + if (expectedName == "*") { + ASSERT_EQ(found->second, 3); + } else { + ASSERT_EQ(found->second, 1); + } + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetAlias, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicExportDescriptorGetAlias) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotExportAliases; + implI->ModuleEnumerateExports(m, &gotExportAliases, moduleExportAliasCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"", "IndirectExportFunc1FromModule1", "LocalDefaultExportClass", + "LocalExportClass", "LocalExportFunc", "LocalExportLet", "LocalExportVar", + "StarExport", "StarExport2", "MF2M1"}; + ASSERT_EQ(expectedNames.size(), gotExportAliases.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotExportAliases.find(expectedName), gotExportAliases.end()); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetInspectContext, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicExportDescriptorGetInspectContext) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotExports; + implI->ModuleEnumerateExports(m, &gotExports, helpers::moduleExportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotExports.size(), 10); + for (auto &gotExport : gotExports) { + auto ctxI = implI->ExportDescriptorGetInspectContext(gotExport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(ctxI, implI->ModuleGetInspectContext(m)); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetExportingModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicExportDescriptorGetExportingModule) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *m = ctxFinder.module; + + std::set gotExports; + implI->ModuleEnumerateExports(m, &gotExports, helpers::moduleExportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_EQ(gotExports.size(), 10); + for (auto &gotExport : gotExports) { + auto expM = implI->ExportDescriptorGetExportingModule(gotExport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(expM, m); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetExportedModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicExportDescriptorGetExportedModule) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", &ctx); + + std::unordered_map gotModulesMap; + + implI->FileEnumerateModules(ctx, &gotModulesMap, helpers::nameToModuleCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set expectedNames = {"modules_dynamic", "modules/module1", "modules/module2", "modules/module3"}; + ASSERT_EQ(expectedNames.size(), gotModulesMap.size()); + for (auto &expectedName : expectedNames) { + ASSERT_NE(gotModulesMap.find(expectedName), gotModulesMap.end()); + } + + std::set gotExports; + implI->ModuleEnumerateExports(gotModulesMap.find("modules_dynamic")->second, &gotExports, helpers::moduleExportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + std::unordered_map expected = {{"", gotModulesMap.find("modules/module2")->second}, + {"IndirectExportFunc1FromModule1", gotModulesMap.find("modules/module1")->second}, + {"MF2M1", gotModulesMap.find("modules/module1")->second}, + {"LocalExportClass", gotModulesMap.find("modules_dynamic")->second}, + {"LocalExportFunc", gotModulesMap.find("modules_dynamic")->second}, + {"LocalExportLet", gotModulesMap.find("modules_dynamic")->second}, + {"LocalExportVar", gotModulesMap.find("modules_dynamic")->second}, + {"StarExport", gotModulesMap.find("modules/module1")->second}, + {"StarExport2", gotModulesMap.find("modules/module2")->second}, + {"LocalDefaultExportClass", gotModulesMap.find("modules_dynamic")->second}}; + + ASSERT_EQ(gotExports.size(), 10); + for (auto &gotExport : gotExports) { + auto impM = implI->ExportDescriptorGetExportedModule(gotExport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto impName = implI->ExportDescriptorGetAlias(gotExport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto strName = helpers::abckit_StringToString(ctx, impName); + ASSERT_NE(expected.find(strName), expected.end()); + ASSERT_EQ(impM, expected.find(strName)->second); + } + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicIgetModule) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", + "modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + IgetModuleTest(ctxG, abckit_IsaApiDynamicOpcode_getmodulenamespace); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetModule, abc-kind=JS, category=negative +TEST_F(LibAbcKitInspectApiModulesTest, DynamicIgetModuleWrongInst) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", + "modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + IgetModuleTest(ctxG, abckit_IsaApiDynamicOpcode_stmodulevar); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetImportDescriptor, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicIgetImportDescriptor) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", + "modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IgetImportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_ldexternalmodulevar); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetImportDescriptor, abc-kind=JS, category=negative +TEST_F(LibAbcKitInspectApiModulesTest, DynamicIgetImportDescriptorWrongInst) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", + "modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IgetImportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_stmodulevar); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetExportDescriptor, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiModulesTest, DynamicIgetExportDescriptor) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", + "modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IgetExportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_ldlocalmodulevar, 0x5); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetExportDescriptor, abc-kind=JS, category=negative +TEST_F(LibAbcKitInspectApiModulesTest, DynamicIgetExportDescriptorWrongInst) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", "modules_dynamic"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic.abc", + ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", + "modules_dynamic.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IgetExportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, 0x3); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/inspect_api/modules/modules_dynamic_modified.abc", "modules_dynamic"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/inspect_api/strings/strings_test.cpp b/libabckit/tests/metadata/inspect_api/strings/strings_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a73c4e79eedd38ba1ad04e022e499e5607532b54 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/strings/strings_test.cpp @@ -0,0 +1,98 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "metadata.h" +#include "metadata_inspect_impl.h" // FIXME(mshimenkov) + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); + +class LibAbcKitInspectApiStringsTest: public ::testing::Test {}; + +// Test: test-kind=api, api=InspectApiImpl::abckit_StringToString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiStringsTest, abckit_StringToStringStatic) +{ + ASSERT_NE(impl, nullptr); + ASSERT_NE(implI, nullptr); + + implI->abckit_StringToString(nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + std::string testString = "testString"; + abckit_File *ctxI = new abckit_File(); + ctxI->mode = Mode::STATIC; + + implI->abckit_StringToString(ctxI, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + abckit_String *abcTestString = new abckit_String {testString}; // FIXME + implI->abckit_StringToString(ctxI, abcTestString, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + size_t len = 0; + implI->abckit_StringToString(ctxI, abcTestString, nullptr, &len); + ASSERT_EQ(len, testString.size()+1); + + char *out = new char [len] {}; + implI->abckit_StringToString(ctxI, abcTestString, out, nullptr); + ASSERT_EQ(std::strncmp(out, testString.c_str(), len), 0); + + delete [] out; + delete abcTestString; + delete ctxI; +} + +// Test: test-kind=api, api=InspectApiImpl::abckit_StringToString, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiStringsTest, abckit_StringToStringDynamic) +{ + ASSERT_NE(impl, nullptr); + ASSERT_NE(implI, nullptr); + + implI->abckit_StringToString(nullptr, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + std::string testString = "testString"; + abckit_File *ctxI = new abckit_File(); + ctxI->mode = Mode::DYNAMIC; + + implI->abckit_StringToString(ctxI, nullptr, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + abckit_String *abcTestString = new abckit_String {testString}; // FIXME + implI->abckit_StringToString(ctxI, abcTestString, nullptr, nullptr); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + + size_t len = 0; + implI->abckit_StringToString(ctxI, abcTestString, nullptr, &len); + ASSERT_EQ(len, testString.size()+1); + + char *out = new char [len] {}; + implI->abckit_StringToString(ctxI, abcTestString, out, nullptr); + ASSERT_EQ(std::strncmp(out, testString.c_str(), len), 0); + + delete [] out; + delete abcTestString; + delete ctxI; +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/inspect_api/values/values_dynamic.js b/libabckit/tests/metadata/inspect_api/values/values_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..6a533184b11b8e5f0adeae5d5568dc6567bcc3c9 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/values/values_dynamic.js @@ -0,0 +1 @@ +o = [false, 1, "2", 0.4] \ No newline at end of file diff --git a/libabckit/tests/metadata/inspect_api/values/values_static.ets b/libabckit/tests/metadata/inspect_api/values/values_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5349389c39044e1e87b451e8e209ee801f2f4a5 --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/values/values_static.ets @@ -0,0 +1,8 @@ +function ConsoleLogStr(a: string) { + console.log(a) +} + +function main() { + let str : string = "testString"; + ConsoleLogStr(str); +} diff --git a/libabckit/tests/metadata/inspect_api/values/values_test.cpp b/libabckit/tests/metadata/inspect_api/values/values_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abbb2a7bfc1a8ecb570b7324fd20f3b63f734d7b --- /dev/null +++ b/libabckit/tests/metadata/inspect_api/values/values_test.cpp @@ -0,0 +1,223 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "libabckit/include/metadata.h" +#include "libabckit/src/metadata_modify_impl.h" // FIXME(mredkin) + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +class LibAbcKitInspectApiValuesTest : public ::testing::Test {}; + +// Test: test-kind=api, api=InspectApiImpl::ValueGetU1, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetU1_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueU1(&ctxM, true); + auto val = implI->ValueGetU1(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_TRUE(val); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetDouble, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetDouble_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueDouble(&ctxM, 1.2); + auto val = implI->ValueGetDouble(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1.2); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetString, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetString_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueString(&ctxM, "test"); + auto val = implI->ValueGetString(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->impl, "test"); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArrayValue, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, CreateLiteralArrayValue_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + std::vector abc_arr; + abc_arr.emplace_back(implM->CreateValueString(&ctxM, "test")); + abc_arr.emplace_back(implM->CreateValueU1(&ctxM, true)); + auto *arr = implM->CreateLiteralArrayValue(&ctxM, abc_arr.data(), 2); + auto *lit_arr = implI->ArrayValueGetLiteralArray(ctxM.ctxI, arr); + std::vector newArr; + implI->LiteralArrayEnumerateElements(ctxI, lit_arr, &newArr, [](abckit_File *ctx, abckit_Literal *lit, void *data) { + (reinterpret_cast *>(data))->emplace_back(lit); + return true; + }); + + ASSERT_EQ(newArr.size(), 2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(arr, nullptr); + + ASSERT_EQ(implI->LiteralGetString(ctxI, newArr[0])->impl, "test"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ASSERT_TRUE(implI->LiteralGetBool(ctxI, newArr[1])); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetType, abc-kind=JS, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetType_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueString(&ctxM, "test"); + auto val = implI->ValueGetType(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->id, abckit_TypeId_STRING); + res = implM->CreateValueU1(&ctxM, true); + val = implI->ValueGetType(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->id, abckit_TypeId_U1); + res = implM->CreateValueDouble(&ctxM, 1.2); + val = implI->ValueGetType(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->id, abckit_TypeId_F64); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + + + +// Test: test-kind=api, api=InspectApiImpl::ValueGetU1, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetU1_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueU1(&ctxM, true); + auto val = implI->ValueGetU1(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_TRUE(val); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetDouble, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetDouble_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueDouble(&ctxM, 1.2); + auto val = implI->ValueGetDouble(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val, 1.2); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetString_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueString(&ctxM, "test"); + auto val = implI->ValueGetString(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->impl, "test"); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArrayValue, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, CreateLiteralArrayValue_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + std::vector abc_arr; + abc_arr.emplace_back(implM->CreateValueString(&ctxM, "test")); + abc_arr.emplace_back(implM->CreateValueU1(&ctxM, true)); + auto *arr = implM->CreateLiteralArrayValue(&ctxM, abc_arr.data(), 2); + + ASSERT_NE(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(arr, nullptr); + + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetType, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitInspectApiValuesTest, ValueGetType_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/inspect_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueString(&ctxM, "test"); + auto val = implI->ValueGetType(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->id, abckit_TypeId_STRING); + res = implM->CreateValueU1(&ctxM, true); + val = implI->ValueGetType(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->id, abckit_TypeId_U1); + res = implM->CreateValueDouble(&ctxM, 1.2); + val = implI->ValueGetType(ctxI, res); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(val->id, abckit_TypeId_F64); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/annotations/annotations_dynamic.ts b/libabckit/tests/metadata/modify_api/annotations/annotations_dynamic.ts new file mode 100644 index 0000000000000000000000000000000000000000..20ef5bfc1e48e7a039c307ec904094d2922cc2ee --- /dev/null +++ b/libabckit/tests/metadata/modify_api/annotations/annotations_dynamic.ts @@ -0,0 +1,19 @@ +@interface Anno1 { + a: number = 3 + b: number[] = [13, 9] + d: boolean = false +} + +@interface Anno2 { + a: number = 5 + b: number[] = [12, 4] + d: boolean = true +} + +@__$$ETS_ANNOTATION$$__Anno1({a: 20, b: [13, 10], d: true}) +class A { + @__$$ETS_ANNOTATION$$__Anno1({a: 10, b: [1, 2, 3], d: true}) + foo() {} + @__$$ETS_ANNOTATION$$__Anno1({a: 5, b: [1, 4]}) + bar() {} +} diff --git a/libabckit/tests/metadata/modify_api/annotations/annotations_test.cpp b/libabckit/tests/metadata/modify_api/annotations/annotations_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a3e452b79e0c3ba59982f86e62cf17089f1715fb --- /dev/null +++ b/libabckit/tests/metadata/modify_api/annotations/annotations_test.cpp @@ -0,0 +1,640 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); + +class LibAbcKitModifyApiAnnotationsTests : public ::testing::Test {}; + +static std::string abckit_StringToString(abckit_File *ctxI, abckit_String *str) +{ + size_t len = 0; + implI->abckit_StringToString(ctxI, str, nullptr, &len); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + char *name = new char[len]; + implI->abckit_StringToString(ctxI, str, name, &len); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + std::string res {name}; + delete[] name; + return res; +} + +static void modifyModule(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + auto module = implI->MethodGetModule(method); + const char *str = "NewAnnotation"; + struct abckit_AnnotationInterfaceCreateParams annoIfParams; + annoIfParams.name = str; + implM->ModuleAddAnnotationInterface(ctxM, module, &annoIfParams); + + + implI->ModuleEnumerateAnnotationInterfaces(module, module, [](abckit_AnnotationInterface *annoI, void *data) { + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || + name == "Anno1" || name == "Anno2" || name == "NewAnnotation"); + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +struct AnnoIFind { + std::string name; + abckit_AnnotationInterface *ai; +}; + +struct AnnoFind { + std::string name; + abckit_Annotation *anno; +}; + +struct AnnoElemFind { + std::string name; + abckit_AnnotationElement *annoElem; +}; + +struct AnnoFieldFind { + std::string name; + abckit_AnnotationInterfaceField *fld; +}; + +static void modifyClassAddAnnotation(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + auto module = implI->MethodGetModule(method); + const char *str = "Anno2"; + AnnoIFind af; + af.name = str; + af.ai = nullptr; + + implI->ModuleEnumerateAnnotationInterfaces(module, &af, [](abckit_AnnotationInterface *annoI, void *data) { + auto af1 = (AnnoIFind *)data; + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || + name == "Anno1" || name == "Anno2"); + + if (name == af1->name) { + af1->ai = annoI; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.ai != nullptr); + EXPECT_TRUE(af.name == str); + + auto klass = implI->MethodGetParentClass(method); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + struct abckit_AnnotationCreateParams annoCreateParams; + annoCreateParams.ai = af.ai; + auto anno = implM->ClassAddAnnotation(ctxM, klass, &annoCreateParams); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto annoI = implI->AnnotationGetInterface(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str1 = implI->AnnotationInterfaceGetName(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctx = implI->AnnotationGetInspectContext(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name1 = abckit_StringToString(ctx, str1); + EXPECT_TRUE(name1 == str); +} + +static void modifyClassRemoveAnnotation(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + const char *str = "Anno1"; + AnnoFind af; + af.name = str; + af.anno = nullptr; + + auto klass = implI->MethodGetParentClass(method); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ClassEnumerateAnnotations(klass, &af, [](abckit_Annotation *anno, void *data) { + auto af1 = (AnnoFind *)data; + + auto ai = implI->AnnotationGetInterface(anno); + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(ai); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(ai); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + if (name == af1->name) { + af1->anno = anno; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.anno != nullptr); + EXPECT_TRUE(af.name == str); + + implM->ClassRemoveAnnotation(ctxM, klass, af.anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->ClassEnumerateAnnotations(klass, &af, [](abckit_Annotation *anno, void *data) { + auto af1 = (AnnoFind *)data; + + auto ai = implI->AnnotationGetInterface(anno); + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(ai); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(ai); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name != af1->name); + + return true; + }); +} + +static void modifyMethodAddAnnotation(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + auto module = implI->MethodGetModule(method); + const char *str = "Anno2"; + AnnoIFind af; + af.name = str; + af.ai = nullptr; + + implI->ModuleEnumerateAnnotationInterfaces(module, &af, [](abckit_AnnotationInterface *annoI, void *data) { + auto af1 = (AnnoIFind *)data; + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || + name == "Anno1" || name == "Anno2"); + + if (name == af1->name) { + af1->ai = annoI; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.ai != nullptr); + EXPECT_TRUE(af.name == str); + + struct abckit_AnnotationCreateParams annoCreateParams; + annoCreateParams.ai = af.ai; + auto anno = implM->MethodAddAnnotation(ctxM, method, &annoCreateParams); + EXPECT_TRUE(anno != nullptr); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto annoI = implI->AnnotationGetInterface(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str1 = implI->AnnotationInterfaceGetName(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctx = implI->AnnotationGetInspectContext(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name1 = abckit_StringToString(ctx, str1); + EXPECT_TRUE(name1 == str); +} + +static void modifyMethodRemoveAnnotation(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + const char *str = "Anno1"; + AnnoFind af; + af.name = str; + af.anno = nullptr; + + implI->MethodEnumerateAnnotations(method, &af, [](abckit_Annotation *anno, void *data) { + auto af1 = (AnnoFind *)data; + + auto ai = implI->AnnotationGetInterface(anno); + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(ai); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(ai); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + if (name == af1->name) { + af1->anno = anno; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.anno != nullptr); + EXPECT_TRUE(af.name == str); + + implM->MethodRemoveAnnotation(ctxM, method, af.anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->MethodEnumerateAnnotations(method, &af, [](abckit_Annotation *anno, void *data) { + auto af1 = (AnnoFind *)data; + + auto ai = implI->AnnotationGetInterface(anno); + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(ai); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(ai); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name != af1->name); + + return true; + }); +} + +static void modifyAnnotationAddAnnotationElement(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + const char *str = "Anno1"; + AnnoFind af; + af.name = str; + af.anno = nullptr; + + implI->MethodEnumerateAnnotations(method, &af, [](abckit_Annotation *anno, void *data) { + auto af1 = (AnnoFind *)data; + + auto annoI = implI->AnnotationGetInterface(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || name == "Anno1"); + + if (name == af1->name) { + af1->anno = anno; + } + + return true; + }); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.anno != nullptr); + EXPECT_TRUE(af.name == str); + + struct abckit_AnnotationElementCreateParams annoElementCreateParams; + auto value = implM->CreateValueDouble(ctxM, 0.12); + annoElementCreateParams.value = value; + annoElementCreateParams.name = "newValue"; + + auto annoElem = implM->AnnotationAddAnnotationElement(ctxM, af.anno, &annoElementCreateParams); + EXPECT_TRUE(annoElem != nullptr); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str1 = implI->AnnotationElementGetName(annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctx = implI->AnnotationElementGetInspectContext(annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name1 = abckit_StringToString(ctx, str1); + + EXPECT_TRUE(name1 == annoElementCreateParams.name); + + double val = implI->ValueGetDouble(ctx, value); + EXPECT_TRUE(val == 0.12); +} + +static void modifyAnnotationRemoveAnnotationElement(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + const char *str = "Anno1"; + AnnoFind af; + af.name = str; + af.anno = nullptr; + + implI->MethodEnumerateAnnotations(method, &af, [](abckit_Annotation *anno, void *data) { + auto af1 = (AnnoFind *)data; + + auto annoI = implI->AnnotationGetInterface(anno); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || name == "Anno1"); + + if (name == af1->name) { + af1->anno = anno; + } + + return true; + }); + + AnnoElemFind aef; + aef.name = "a"; + implI->AnnotationEnumerateElements(af.anno, &aef, [](abckit_AnnotationElement *annoElem, void *data) { + auto aef1 = (AnnoElemFind *)data; + + auto ctxI = implI->AnnotationElementGetInspectContext(annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationElementGetName(annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + EXPECT_TRUE(name == "a" || name == "b"); + + if (name == aef1->name) { + aef1->annoElem = annoElem; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + EXPECT_TRUE(af.anno != nullptr); + EXPECT_TRUE(af.name == str); + + implM->AnnotationRemoveAnnotationElement(ctxM, af.anno, aef.annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + implI->AnnotationEnumerateElements(af.anno, &aef, [](abckit_AnnotationElement *annoElem, void *data) { + auto aef1 = (AnnoElemFind *)data; + + auto ctxI = implI->AnnotationElementGetInspectContext(annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationElementGetName(annoElem); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + EXPECT_TRUE(name != aef1->name); + + return true; + }); +} + +static void modifyAnnotationInterfaceAddField(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + auto module = implI->MethodGetModule(method); + const char *str = "Anno2"; + AnnoIFind af; + af.name = str; + af.ai = nullptr; + + implI->ModuleEnumerateAnnotationInterfaces(module, &af, [](abckit_AnnotationInterface *annoI, void *data) { + auto af1 = (AnnoIFind *)data; + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || + name == "Anno1" || name == "Anno2"); + + if (name == af1->name) { + af1->ai = annoI; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.ai != nullptr); + EXPECT_TRUE(af.name == str); + + struct abckit_AnnotationInterfaceFieldCreateParams annoFieldCreateParams; + abckit_Type *type = implM->CreateType(ctxM, abckit_TypeId_U1); + abckit_Value *value = implM->CreateValueU1(ctxM, false); + annoFieldCreateParams.name = "newField"; + annoFieldCreateParams.type = type; + annoFieldCreateParams.defaultValue = value; + auto field = implM->AnnotationInterfaceAddField(ctxM, af.ai, &annoFieldCreateParams); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto annoI1 = implI->AnnotationInterfaceFieldGetInterface(field); + EXPECT_TRUE(annoI1 == af.ai); + + auto str1 = implI->AnnotationInterfaceFieldGetName(field); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctx = implI->AnnotationInterfaceFieldGetInspectContext(field); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name1 = abckit_StringToString(ctx, str1); + EXPECT_TRUE(name1 == "newField"); + + auto val1 = implI->AnnotationInterfaceFieldGetDefaultValue(field); + bool value1 = implI->ValueGetU1(ctx, val1); + EXPECT_TRUE(value1 == false); + + implI->AnnotationInterfaceEnumerateFields(af.ai, nullptr, [](abckit_AnnotationInterfaceField *fld, void *data) { + auto str = implI->AnnotationInterfaceFieldGetName(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctxI = implI->AnnotationInterfaceFieldGetInspectContext(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "a" || name == "b" || name == "d" || name == "newField"); + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +static void modifyAnnotationInterfaceRemoveField(abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *graph) +{ + auto module = implI->MethodGetModule(method); + const char *str = "Anno2"; + AnnoIFind af; + af.name = str; + af.ai = nullptr; + + implI->ModuleEnumerateAnnotationInterfaces(module, &af, [](abckit_AnnotationInterface *annoI, void *data) { + auto af1 = (AnnoIFind *)data; + + auto ctxI = implI->AnnotationInterfaceGetInspectContext(annoI); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto str = implI->AnnotationInterfaceGetName(annoI); + + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "_ESSlotNumberAnnotation" || name == "_ESConcurrentModuleRequestsAnnotation" || + name == "Anno1" || name == "Anno2"); + + if (name == af1->name) { + af1->ai = annoI; + } + + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + EXPECT_TRUE(af.ai != nullptr); + EXPECT_TRUE(af.name == str); + + AnnoFieldFind aff; + aff.name = "d"; + aff.fld = nullptr; + + implI->AnnotationInterfaceEnumerateFields(af.ai, &aff, [](abckit_AnnotationInterfaceField *fld, void *data) { + auto aff1 = (AnnoFieldFind *)data; + + auto str = implI->AnnotationInterfaceFieldGetName(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctxI = implI->AnnotationInterfaceFieldGetInspectContext(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + + if (name == aff1->name) { + aff1->fld = fld; + } + return true; + }); + + EXPECT_TRUE(aff.name == "d"); + EXPECT_TRUE(aff.fld != nullptr); + + implM->AnnotationInterfaceRemoveField(ctxM, af.ai, aff.fld); + + implI->AnnotationInterfaceEnumerateFields(af.ai, &aff, [](abckit_AnnotationInterfaceField *fld, void *data) { + auto str = implI->AnnotationInterfaceFieldGetName(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto ctxI = implI->AnnotationInterfaceFieldGetInspectContext(fld); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); + + auto name = abckit_StringToString(ctxI, str); + + EXPECT_TRUE(name == "a" || name == "b"); + return true; + }); + EXPECT_TRUE(impl->GetLastError() == abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddAnnotationInterface, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, ModuleAddAnnotationInterface) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "foo", modifyModule); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::ClassAddAnnotation, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, ClassAddAnnotation) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "foo", modifyClassAddAnnotation); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::ClassRemoveAnnotation, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, ClassRemoveAnnotation) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "foo", modifyClassRemoveAnnotation); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::MethodAddAnnotation, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, MethodAddAnnotation) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "foo", modifyMethodAddAnnotation); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::MethodRemoveAnnotation, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, MethodRemoveAnnotation) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "foo", modifyMethodRemoveAnnotation); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationAddAnnotationElement, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, AnnotationAddAnnotationElement) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "bar", modifyAnnotationAddAnnotationElement); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationRemoveAnnotationElement, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, AnnotationRemoveAnnotationElement) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "bar", modifyAnnotationRemoveAnnotationElement); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationInterfaceAddField, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, AnnotationInterfaceAddField) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "bar", modifyAnnotationInterfaceAddField); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationInterfaceRemoveField, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiAnnotationsTests, AnnotationInterfaceRemoveField) +{ + helpers::InspectMethod(ABCKIT_ABC_DIR "metadata/modify_api/annotations/annotations_dynamic.abc", "bar", modifyAnnotationInterfaceRemoveField); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/literals/literals_dynamic.js b/libabckit/tests/metadata/modify_api/literals/literals_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..df377908ff2209e9aabd2003d2e0865510ca40f7 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/literals/literals_dynamic.js @@ -0,0 +1 @@ +o = [false, 1, "2", 0.4] diff --git a/libabckit/tests/metadata/modify_api/literals/literals_static.ets b/libabckit/tests/metadata/modify_api/literals/literals_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5349389c39044e1e87b451e8e209ee801f2f4a5 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/literals/literals_static.ets @@ -0,0 +1,8 @@ +function ConsoleLogStr(a: string) { + console.log(a) +} + +function main() { + let str : string = "testString"; + ConsoleLogStr(str); +} diff --git a/libabckit/tests/metadata/modify_api/literals/literals_test.cpp b/libabckit/tests/metadata/modify_api/literals/literals_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a9e332f5e2430c07ca175691db49cccee5dce49e --- /dev/null +++ b/libabckit/tests/metadata/modify_api/literals/literals_test.cpp @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "metadata.h" +#include "metadata_modify_impl.h" // FIXME(mshimenkov) + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitModifyApiLiteralsTest : public ::testing::Test {}; + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralBool, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralBool_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralBool(&ctxM, true); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU8, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU8_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU8(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU16, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU16_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU16(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU32, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU32_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU32(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU64, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU64_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU64(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralFloat, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralFloat_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralFloat(&ctxM, 1.0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralDouble, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralDouble_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralDouble(&ctxM, 1.0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralString, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralString_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralString(&ctxM, "asdf"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArray, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralArray_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto arr = std::vector(); + abckit_Literal *res1 = implM->CreateLiteralString(&ctxM, "asdf"); + abckit_Literal *res2 = implM->CreateLiteralDouble(&ctxM, 1.0); + arr.emplace_back(res1); + arr.emplace_back(res2); + auto lit_arr = implM->CreateLiteralArray(&ctxM, arr.data(), arr.size()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(lit_arr, nullptr); + + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArray, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralArray_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto arr = std::vector(); + abckit_Literal *res1 = implM->CreateLiteralString(&ctxM, "asdf"); + abckit_Literal *res2 = implM->CreateLiteralDouble(&ctxM, 1.0); + arr.emplace_back(res1); + arr.emplace_back(res2); + auto lit_arr = implM->CreateLiteralArray(&ctxM, arr.data(), arr.size()); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(lit_arr, nullptr); + + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralBool, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralBool_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralBool(&ctxM, true); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU8, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU8_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU8(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU16, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU16_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU16(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU32, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU32_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU32(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU64, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralU64_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralU64(&ctxM, 1); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralFloat, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralFloat_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralFloat(&ctxM, 1.0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralDouble, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralDouble_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralDouble(&ctxM, 1.0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiLiteralsTest, CreateLiteralString_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/literals/literals_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + abckit_Literal *res = implM->CreateLiteralString(&ctxM, "asdf"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/literals_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/modules/modules/module1.js b/libabckit/tests/metadata/modify_api/modules/modules/module1.js new file mode 100644 index 0000000000000000000000000000000000000000..f911165e09385dfa7f097ca9ae50c920c55a231a --- /dev/null +++ b/libabckit/tests/metadata/modify_api/modules/modules/module1.js @@ -0,0 +1,25 @@ +export function RegularImportFunc1FromModule1() +{ + print("regular import func1 from module1") +} +export function NamespaceImportFunc2FromModule1() +{ + print("namespace import func2 from module1") +} +export function NamespaceImportFunc3FromModule1() +{ + print("namespace import func3 from module1") +} +export function IndirectExportFunc1FromModule1() +{ + print("indirect export func1 from module1") +} +export function IndirectExportFunc2FromModule1() +{ + print("indirect export func2 from module1") +} +export function SameFuncInDifferentModules() +{ + print("the same func from module1") +} +export let NewLocalExportLet = 3; \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/modules/modules/module2.js b/libabckit/tests/metadata/modify_api/modules/modules/module2.js new file mode 100644 index 0000000000000000000000000000000000000000..ee8ce0f48797eff6aa83e5b85ce1fcf9a671407c --- /dev/null +++ b/libabckit/tests/metadata/modify_api/modules/modules/module2.js @@ -0,0 +1,18 @@ +export function RegularImportFunc1FromModule2() +{ + print("regular import func1 from module2") +} + +export default function RegularDefaultImportFunc2FromModule2() +{ + print("regular default import func2 from module2") +} + +export function NamespaceImportFunc3FromModule2() +{ + print("namespace import func3 from module2") +} +export function SameFuncInDifferentModules() +{ + print("the same func from module2") +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/modules/modules/module3.js b/libabckit/tests/metadata/modify_api/modules/modules/module3.js new file mode 100644 index 0000000000000000000000000000000000000000..b0ded381b3bc523e5b5ce7a76ecdfbdbda563d92 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/modules/modules/module3.js @@ -0,0 +1,18 @@ +export {NewImportedFuncFromModule4} from "./module4" + +export default function RegularDefaultImportFunc1FromModule3() +{ + print("regular default import func1 from module3") +} +export function SameFuncInDifferentModules() +{ + print("the same func from module3") +} +export function NewImportedFunc() +{ + print("new imported func from module3") +} +export function NewExportedFunc() +{ + print("new exported func from module3") +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/modules/modules/module4.js b/libabckit/tests/metadata/modify_api/modules/modules/module4.js new file mode 100644 index 0000000000000000000000000000000000000000..78688246028f24a16fff6834afb05deaacca0d12 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/modules/modules/module4.js @@ -0,0 +1,16 @@ +export function NewImportedFuncFromModule4() +{ + print("new imported func from module4") +} + +export default function NewImportedDefaultFuncFromModule4() +{ + print("new imported default func from module4") +} + +export function NewExportedFuncFromModule4() +{ + print("new exported func from module4") +} + +export let NewLocalExportVar = 6; \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/modules/modules_dynamic_modify.js b/libabckit/tests/metadata/modify_api/modules/modules_dynamic_modify.js new file mode 100644 index 0000000000000000000000000000000000000000..8ab63b5ec65678d085ff5492cb533e0479c3aee7 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/modules/modules_dynamic_modify.js @@ -0,0 +1,37 @@ +// Regular +import {RegularImportFunc1FromModule1} from "./modules/module1" +import {RegularImportFunc1FromModule2 as MF1M2} from "./modules/module2" +import RegularDefaultImportFunc1FromModule3 from "./modules/module3" +import {default as RegularDefaultImportFunc2FromModule2} from "./modules/module2" + +// Namespace +import * as NS1 from "./modules/module1" +import * as NS2 from "./modules/module2" +import * as NS3 from "./modules/module3" + +// Local export +export function LocalExportFunc() {} +export class LocalExportClass {} +export let LocalExportLet = 2; +export var LocalExportVar; +export const LocalExportConst = 1; +export default class LocalDefaultExportClass {} + +// Indirect export +export {IndirectExportFunc1FromModule1} from "./modules/module1" +export {IndirectExportFunc2FromModule1 as MF2M1} from "./modules/module1" + +// Star export +export * as StarExport from "./modules/module1" +export * from "./modules/module2" + +RegularImportFunc1FromModule1(); +MF1M2(); +RegularDefaultImportFunc1FromModule3(); +RegularDefaultImportFunc2FromModule2(); +NS1.NamespaceImportFunc2FromModule1(); +NS1.NamespaceImportFunc3FromModule1(); +print(LocalExportConst); +print(LocalExportLet); +NS2.NamespaceImportFunc3FromModule2(); +NS3.SameFuncInDifferentModules(); diff --git a/libabckit/tests/metadata/modify_api/modules/modules_dynamic_modify_test.cpp b/libabckit/tests/metadata/modify_api/modules/modules_dynamic_modify_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3233989101f2686e482786e7c8c84830f2933b49 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/modules/modules_dynamic_modify_test.cpp @@ -0,0 +1,1711 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "metadata.h" +#include "ir_impl.h" +#include "isa/isa_dynamic.h" +#include "statuses.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitModifyApiModulesTest : public ::testing::Test {}; + +// ======================================== +// Helpers +// ======================================== + +static void ModifyMetaDynModuleRemoveImport(abckit_ModifyContext *ctxM, abckit_File *ctxI, const std::string &name, bool shouldBeRemoved) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *module = ctxFinder.module; + + std::set gotImports; + implI->ModuleEnumerateImports(module, &gotImports, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(gotImports.empty(), false); + + bool removed = false; + for (auto &gotImport : gotImports) { + auto impName = implI->ImportDescriptorGetAlias(gotImport); + auto strName = helpers::abckit_StringToString(ctxI, impName); + if (strName == name) { + implM->ModuleRemoveImport(module, gotImport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + removed = true; + break; + } + } + + ASSERT_EQ(removed, shouldBeRemoved); + + std::set gotImportsAfter; + implI->ModuleEnumerateImports(module, &gotImportsAfter, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(gotImportsAfter.empty(), false); + + for (auto &gotImportAfter : gotImportsAfter) { + auto impName = implI->ImportDescriptorGetAlias(gotImportAfter); + auto strName = helpers::abckit_StringToString(ctxI, impName); + ASSERT_NE(strName, name); + } +} + +static void ModifyMetaDynModuleRemoveExport(abckit_ModifyContext *ctxM, abckit_File *ctxI, const std::string &exportName, bool shouldBeRemoved) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *module = ctxFinder.module; + + std::set gotExports; + implI->ModuleEnumerateExports(module, &gotExports, helpers::moduleExportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + bool removed = false; + for (auto &gotExport : gotExports) { + auto expName = implI->ExportDescriptorGetAlias(gotExport); + auto strName = helpers::abckit_StringToString(ctxI, expName); + if (strName == exportName) { + implM->ModuleRemoveExport(module, gotExport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + removed = true; + break; + } + } + + ASSERT_EQ(removed, shouldBeRemoved); + + std::set gotExportsAfter; + implI->ModuleEnumerateExports(module, &gotExportsAfter, helpers::moduleExportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + for (auto &gotExportAfter : gotExportsAfter) { + auto expName = implI->ExportDescriptorGetAlias(gotExportAfter); + auto strName = helpers::abckit_StringToString(ctxI, expName); + ASSERT_NE(strName, exportName); + } +} + +void TransformIrDynModuleRemoveImport(abckit_Graph *ctxG, const std::string &name) +{ + abckit_Inst *instWithName = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, [&](abckit_Inst *inst){ + auto nameOffset = implG->IgetImmediate(inst, 0); + auto nameStr = ctxG->irInterface->GetStringIdByOffset(nameOffset); + if (nameStr == name) { + return true; + } + return false; + }); + + ASSERT_NE(instWithName, nullptr); + auto ldExternalModuleVarInst = implG->IgetPrev(instWithName); + ASSERT_NE(ldExternalModuleVarInst, nullptr); + auto callArg0Inst = implG->IgetNext(instWithName); + ASSERT_NE(callArg0Inst, nullptr); + + implG->Iremove(instWithName); + implG->Iremove(ldExternalModuleVarInst); + implG->Iremove(callArg0Inst); +} + +void TransformIrDynModuleRemoveNSImport(abckit_Graph *ctxG, const std::string &name) +{ + abckit_Inst *ldObjByNameInst = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_ldobjbyname, [&](abckit_Inst *inst){ + auto nameOffset = implG->IgetImmediate(inst, 1); + auto nameStr = ctxG->irInterface->GetStringIdByOffset(nameOffset); + if (nameStr == name) { + return true; + } + return false; + }); + + ASSERT_NE(ldObjByNameInst, nullptr); + auto callThis0Inst = implG->IgetNext(ldObjByNameInst); + ASSERT_NE(callThis0Inst, nullptr); + + implG->Iremove(ldObjByNameInst); + implG->Iremove(callThis0Inst); +} + +void TransformIrDynModuleRemoveExport(abckit_Graph *ctxG, const std::string &exportName) +{ + abckit_Inst *instWithName = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname, [&](abckit_Inst *inst){ + auto nameOffset = implG->IgetImmediate(inst, 0); + auto nameStr = ctxG->irInterface->GetStringIdByOffset(nameOffset); + if (nameStr == exportName) { + return true; + } + return false; + }); + + ASSERT_NE(instWithName, nullptr); + auto ldLocalModuleVarInst = implG->IgetPrev(instWithName); + ASSERT_NE(ldLocalModuleVarInst, nullptr); + auto callArg1Inst = implG->IgetNext(instWithName); + ASSERT_NE(callArg1Inst, nullptr); + + implG->Iremove(instWithName); + implG->Iremove(ldLocalModuleVarInst); + implG->Iremove(callArg1Inst); + + abckit_Inst *stModuleVarInst = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_stmodulevar, [&](abckit_Inst *inst){ + if (implG->IgetImmediate(inst, 0) == implG->IgetImmediate(ldLocalModuleVarInst, 0)) { + return true; + } + return false; + }); + + ASSERT_NE(stModuleVarInst, nullptr); + implG->Iremove(stModuleVarInst); +} + +void IsetModuleTest(abckit_Graph *ctxG, abckit_Module *module, abckit_IsaApiDynamicOpcode opcode, bool negative = false, bool wrongCtx = false) +{ + auto MODULE_REQUEST_IDX = 0x2; + abckit_Inst *instWithModule = helpers::FindFirstInst(ctxG, opcode, [&](abckit_Inst *inst){ + auto imm = implG->IgetImmediate(inst, 0); + if (imm == MODULE_REQUEST_IDX) { + return true; + } + return false; + }); + + dynG->IsetModule(instWithModule, module); + if (negative) { + if (wrongCtx) { + ASSERT_EQ(impl->GetLastError(), abckit_Status_WRONG_CTX); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void IsetImportDescriptorTest(abckit_Graph *ctxG, abckit_Module *m, abckit_IsaApiDynamicOpcode opcode, + bool negative = false, abckit_ImportDescriptor *importToRemove = nullptr) +{ + auto MODULE_REQUEST_IDX = 0x2; + abckit_Inst *instWithID = helpers::FindFirstInst(ctxG, opcode, [&](abckit_Inst *inst){ + auto imm = implG->IgetImmediate(inst, 0); + if (imm == MODULE_REQUEST_IDX) { + return true; + } + return false; + }); + ASSERT_NE(instWithID, nullptr); + + if (importToRemove == nullptr) { + helpers::ImportByAliasContext importFinder = {nullptr, "MF1M2"}; + implI->ModuleEnumerateImports(m, &importFinder, helpers::importByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(importFinder.id, nullptr); + importToRemove = importFinder.id; + } + + dynG->IsetImportDescriptor(instWithID, importToRemove); + if (negative) { + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +void IsetExportDescriptorTest(abckit_Graph *ctxG, abckit_Module *m, abckit_IsaApiDynamicOpcode opcode, + bool negative = false, abckit_ExportDescriptor *exportToRemove = nullptr) +{ + auto MODULE_REQUEST_IDX = 0x3; + abckit_Inst *instWithID = helpers::FindFirstInst(ctxG, opcode, [&](abckit_Inst *inst){ + auto imm = implG->IgetImmediate(inst, 0); + if (imm == MODULE_REQUEST_IDX) { + return true; + } + return false; + }); + ASSERT_NE(instWithID, nullptr); + + if (exportToRemove == nullptr) { + helpers::ExportByAliasContext exportFinder = {nullptr, "LocalExportLet"}; + implI->ModuleEnumerateExports(m, &exportFinder, helpers::exportByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(exportFinder.ed, nullptr); + exportToRemove = exportFinder.ed; + } + + dynG->IsetExportDescriptor(instWithID, exportToRemove); + if (negative) { + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + return; + } + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +struct UserTransformerData { + std::string name = ""; + std::string alias = ""; + std::string moduleName = ""; + bool isRegular = false; + abckit_DynamicExportKind kind; +}; + +static void TransformModuleImpl(abckit_ModifyContext *ctxM, abckit_Module *module, void *data) +{ + auto userTransformerData = (UserTransformerData *)data; + abckit_File *ctxI = implI->ModuleGetInspectContext(module); + + std::set gotImports; + implI->ModuleEnumerateImports(module, &gotImports, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + bool removed = false; + for (auto &gotImport : gotImports) { + auto impName = implI->ImportDescriptorGetAlias(gotImport); + auto strName = helpers::abckit_StringToString(ctxI, impName); + if (strName == userTransformerData->name) { + implM->ModuleRemoveImport(module, gotImport); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + removed = true; + break; + } + } + + ASSERT_EQ(removed, true); +} + +static void TransformModuleCheck(abckit_ModifyContext *ctxM, abckit_Module *module, void *data) +{ + auto userTransformerData = (UserTransformerData *)data; + abckit_File *ctxI = implI->ModuleGetInspectContext(module); + + std::set gotImportsAfter; + implI->ModuleEnumerateImports(module, &gotImportsAfter, helpers::moduleImportsCollector); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + for (auto &gotImportAfter : gotImportsAfter) { + auto impName = implI->ImportDescriptorGetAlias(gotImportAfter); + auto strName = helpers::abckit_StringToString(ctxI, impName); + ASSERT_NE(strName, userTransformerData->name); + } +} + +static void AddImportFromDynamicModuleImpl(abckit_ModifyContext *ctxM, abckit_Module *module, void *data) +{ + auto userTransformerData = (UserTransformerData *)data; + abckit_File *ctxI = implI->ModuleGetInspectContext(module); + + helpers::ModuleByNameContext ctxFinder = {nullptr, (userTransformerData->moduleName).c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + abckit_ImportFromDynamicModuleCreateParams params; + params.name = (userTransformerData->name).c_str(); + params.alias = (userTransformerData->alias).c_str(); + params.module = ctxFinder.module; + + auto newImport = implM->ModuleAddImportFromDynamicModule(module, ¶ms); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set gotImports; + implI->ModuleEnumerateImports(module, &gotImports, helpers::moduleImportsCollector); + + bool existed = false; + for (auto &gotImport : gotImports) { + if (gotImport != newImport) { + continue; + } + existed = true; + + auto impName = implI->ImportDescriptorGetName(gotImport); + auto strName = helpers::abckit_StringToString(ctxI, impName); + auto impAlias = implI->ImportDescriptorGetAlias(gotImport); + auto strAlias = helpers::abckit_StringToString(ctxI, impAlias); + ASSERT_EQ(userTransformerData->name, strName); + ASSERT_EQ(userTransformerData->alias, strAlias); + ASSERT_EQ(implI->ImportDescriptorGetImportedModule(gotImport), ctxFinder.module); + ASSERT_EQ(implI->ImportDescriptorGetImportingModule(gotImport), module); + ASSERT_EQ(gotImport->payload.dyn.isRegularImport, userTransformerData->isRegular); + } + + ASSERT_EQ(existed, true); +} + +static void DynamicModuleAddExportImpl(abckit_ModifyContext *ctxM, abckit_Module *module, void *data) +{ + auto userTransformerData = (UserTransformerData *)data; + abckit_File *ctxI = implI->ModuleGetInspectContext(module); + + abckit_DynamicModuleExportCreateParams params; + + if (userTransformerData->moduleName != "") { + helpers::ModuleByNameContext ctxFinder = {nullptr, (userTransformerData->moduleName).c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + params.module = ctxFinder.module; + } else { + params.module = nullptr; + } + params.name = (userTransformerData->name).c_str(); + + if (userTransformerData->alias == "") { + params.alias = nullptr; + } else { + params.alias = (userTransformerData->alias).c_str(); + } + + auto newExport = implM->DynamicModuleAddExport(module, ¶ms); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + std::set gotExports; + implI->ModuleEnumerateExports(module, &gotExports, helpers::moduleExportsCollector); + + bool existed = false; + for (auto &gotExport : gotExports) { + if (gotExport != newExport) { + continue; + } + existed = true; + + auto expName = implI->ExportDescriptorGetName(gotExport); + auto strName = helpers::abckit_StringToString(ctxI, expName); + auto expAlias = implI->ExportDescriptorGetAlias(gotExport); + auto strAlias = helpers::abckit_StringToString(ctxI, expAlias); + ASSERT_EQ(userTransformerData->name, strName); + ASSERT_EQ(userTransformerData->alias, strAlias); + ASSERT_EQ(userTransformerData->kind, gotExport->payload.dyn.kind); + if (userTransformerData->kind == abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT) { + ASSERT_EQ(implI->ExportDescriptorGetExportedModule(gotExport), module); + } else { + ASSERT_EQ(implI->ExportDescriptorGetExportedModule(gotExport), params.module); + } + ASSERT_EQ(implI->ExportDescriptorGetExportingModule(gotExport), module); + } + + ASSERT_EQ(existed, true); +} + +void TransformIrAddImportedFunctionCall(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string funcName) +{ + auto abckitStrName = implM->CreateString(ctxM, funcName.c_str()); + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + helpers::ImportByAliasContext importFinder = {nullptr, funcName.c_str()}; + implI->ModuleEnumerateImports(ctxFinder.module, &importFinder, helpers::importByAliasFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(importFinder.id, nullptr); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + auto ldExternalModuleVarInst = dynG->IcreateLdexternalmodulevar(ctxG, importFinder.id); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldExternalModuleVarInst, abckitStrName); + auto callInst = dynG->IcreateCallarg0(ctxG, ldExternalModuleVarInst); + implG->IinsertBefore(ldExternalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrAddImportedFunctionCallNS(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string funcName, std::string moduleName) +{ + auto abckitStrName = implM->CreateString(ctxM, funcName.c_str()); + helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + auto getModuleNamespaceInst = dynG->IcreateGetmodulenamespace(ctxG, ctxFinder.module); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto ldObjByNameInst = dynG->IcreateLdobjbyname(ctxG, getModuleNamespaceInst, abckitStrName); + auto callInst = dynG->IcreateCallthis0(ctxG, ldObjByNameInst, getModuleNamespaceInst); + implG->IinsertBefore(getModuleNamespaceInst, ldundefI); + implG->IinsertBefore(ldObjByNameInst, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrAddLocalExport(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string varName, std::string moduleName) +{ + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + + abckit_String *abckitStr = implM->CreateString(ctxM, "print"); + auto tryLdGlobalByNameInst = dynG->IcreateTryldglobalbyname(ctxG, abckitStr); + + helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + helpers::ExportByAliasContext exportFinder = {nullptr, varName.c_str()}; + implI->ModuleEnumerateExports(ctxFinder.module, &exportFinder, helpers::exportByAliasFinder); + ASSERT_NE(exportFinder.ed, nullptr); + + auto constant = implG->GcreateConstantI32(ctxG, 5); + auto stModuleVarInst = dynG->IcreateStmodulevar(ctxG, constant, exportFinder.ed); + auto ldLocalModuleVarInst = dynG->IcreateLdlocalmodulevar(ctxG, exportFinder.ed); + abckit_String *varNameStr = implM->CreateString(ctxM, varName.c_str()); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldLocalModuleVarInst, varNameStr); + auto callInst = dynG->IcreateCallarg1(ctxG, tryLdGlobalByNameInst, ldLocalModuleVarInst); + + implG->IinsertBefore(stModuleVarInst, ldundefI); + implG->IinsertBefore(tryLdGlobalByNameInst, ldundefI); + implG->IinsertBefore(ldLocalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrAddIndirectExport(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string varName, std::string moduleName) +{ + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + + abckit_String *abckitStr = implM->CreateString(ctxM, "print"); + auto tryLdGlobalByNameInst = dynG->IcreateTryldglobalbyname(ctxG, abckitStr); + + helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + helpers::ImportByAliasContext importFinder = {nullptr, varName.c_str()}; + implI->ModuleEnumerateImports(ctxFinder.module, &importFinder, helpers::importByAliasFinder); + ASSERT_NE(importFinder.id, nullptr); + + auto ldExternalModuleVarInst = dynG->IcreateLdexternalmodulevar(ctxG, importFinder.id); + abckit_String *varNameStr = implM->CreateString(ctxM, varName.c_str()); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldExternalModuleVarInst, varNameStr); + auto callInst = dynG->IcreateCallarg1(ctxG, tryLdGlobalByNameInst, ldExternalModuleVarInst); + implG->IinsertBefore(tryLdGlobalByNameInst, ldundefI); + implG->IinsertBefore(ldExternalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrAddStarExport(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string funcName, std::string moduleName) +{ + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + + helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + auto getModuleNamespaceInst = dynG->IcreateGetmodulenamespace(ctxG, ctxFinder.module); + abckit_String *funcNameStr = implM->CreateString(ctxM, funcName.c_str()); + auto ldObjByNameInst = dynG->IcreateLdobjbyname(ctxG, getModuleNamespaceInst, funcNameStr); + auto callInst = dynG->IcreateCallthis0(ctxG, ldObjByNameInst, getModuleNamespaceInst); + implG->IinsertBefore(getModuleNamespaceInst, ldundefI); + implG->IinsertBefore(ldObjByNameInst, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +void TransformIrAddStarExportFunc(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string exportName, std::string moduleName) +{ + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + + helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + helpers::ModuleByNameContext ctxFinder2 = {nullptr, "modules/module4"}; + implI->FileEnumerateModules(ctxI, &ctxFinder2, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder2.module, nullptr); + + helpers::ExportByAliasContext exportFinder = {nullptr, exportName.c_str()}; + implI->ModuleEnumerateExports(ctxFinder2.module, &exportFinder, helpers::exportByAliasFinder); + ASSERT_NE(exportFinder.ed, nullptr); + + auto getModuleNamespaceInst = dynG->IcreateGetmodulenamespace(ctxG, ctxFinder.module); //module3 + auto stModuleVarInst = dynG->IcreateStmodulevar(ctxG, getModuleNamespaceInst, exportFinder.ed); // NewStarExport + implG->IinsertBefore(getModuleNamespaceInst, ldundefI); + implG->IinsertBefore(stModuleVarInst, ldundefI); +} + +void TransformIrAddStarExportFunc2(abckit_ModifyContext *ctxM, abckit_Graph *ctxG, abckit_File *ctxI, std::string funcName, std::string moduleName) +{ + abckit_BasicBlock *mainBB = implG->BBgetSuccBlock(implG->GgetStartBasicBlock(ctxG), 0); + abckit_Inst *lastInst = implG->BBgetLastInst(mainBB); + auto ldundefI = implG->IgetPrev(lastInst); + + helpers::ModuleByNameContext ctxFinder = {nullptr, moduleName.c_str()}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + helpers::ImportByAliasContext importFinder = {nullptr, "NewStarExport"}; + implI->ModuleEnumerateImports(ctxFinder.module, &importFinder, helpers::importByAliasFinder); + ASSERT_NE(importFinder.id, nullptr); + + auto ldExternalModuleVarInst = dynG->IcreateLdexternalmodulevar(ctxG, importFinder.id); + auto exportStarName = implM->CreateString(ctxM, "NewStarExport"); + auto throwUndef = dynG->IcreateThrowUndefinedifholewithname(ctxG, ldExternalModuleVarInst, exportStarName); + auto funcNameStr = implM->CreateString(ctxM, funcName.c_str()); + auto ldObjByNameInst = dynG->IcreateLdobjbyname(ctxG, ldExternalModuleVarInst, funcNameStr); + auto callInst = dynG->IcreateCallthis0(ctxG, ldObjByNameInst, ldExternalModuleVarInst); + implG->IinsertBefore(ldExternalModuleVarInst, ldundefI); + implG->IinsertBefore(throwUndef, ldundefI); + implG->IinsertBefore(ldObjByNameInst, ldundefI); + implG->IinsertBefore(callInst, ldundefI); +} + +// ======================================== +// Modules Tests +// ======================================== + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveImport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveImport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynModuleRemoveImport(ctxG, "RegularImportFunc1FromModule1"); + abckit_File *ctxI = implI->MethodGetInspectContext(method); + ModifyMetaDynModuleRemoveImport(ctxM, ctxI, "RegularImportFunc1FromModule1", true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveImport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveNSImport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynModuleRemoveNSImport(ctxG, "NamespaceImportFunc2FromModule1"); + TransformIrDynModuleRemoveNSImport(ctxG, "NamespaceImportFunc3FromModule1"); + abckit_File *ctxI = implI->MethodGetInspectContext(method); + ModifyMetaDynModuleRemoveImport(ctxM, ctxI, "NS1", true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveImport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveImportAndModule) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_File *ctxI = implI->MethodGetInspectContext(method); + TransformIrDynModuleRemoveImport(ctxG, "RegularDefaultImportFunc1FromModule3"); + ModifyMetaDynModuleRemoveImport(ctxM, ctxI, "RegularDefaultImportFunc1FromModule3", true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveImport, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveImportWithWrongName) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_File *ctxI = implI->MethodGetInspectContext(method); + ModifyMetaDynModuleRemoveImport(ctxM, ctxI, "R", false); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveImport, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveWrongImport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_File *ctxI = implI->MethodGetInspectContext(method); + abckit_ImportDescriptor *newID = new abckit_ImportDescriptor(); + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *module = ctxFinder.module; + implM->ModuleRemoveImport(module, newID); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); // just to clear last error + delete newID; + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveExport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrDynModuleRemoveExport(ctxG, "LocalExportConst"); + abckit_File *ctxI = implI->MethodGetInspectContext(method); + ModifyMetaDynModuleRemoveExport(ctxM, ctxI, "LocalExportConst", true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveExport, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveExportWithWrongName) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_File *ctxI = implI->MethodGetInspectContext(method); + ModifyMetaDynModuleRemoveExport(ctxM, ctxI, "R", false); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveExport, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleRemoveWrongExport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_File *ctxI = implI->MethodGetInspectContext(method); + abckit_ExportDescriptor *newED = new abckit_ExportDescriptor(); + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto *module = ctxFinder.module; + implM->ModuleRemoveExport(module, newED); + ASSERT_EQ(impl->GetLastError(), abckit_Status_BAD_ARGUMENT); + implI->FileEnumerateModules(ctxI, &ctxFinder, helpers::moduleByNameFinder); // just to clear last error + delete newED; + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetModule) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module1"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + IsetModuleTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_getmodulenamespace); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module1\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetModule, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetModuleWrongInst) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module1"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + + IsetModuleTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_stmodulevar, true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetModule, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetModuleWrongModule) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto newM = new abckit_Module(); + IsetModuleTest(ctxG, newM, abckit_IsaApiDynamicOpcode_stmodulevar, true, true); + delete newM; + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetImportDescriptor, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetImportDescriptor) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IsetImportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_ldexternalmodulevar); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular import func1 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetImportDescriptor, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetImportDescriptorWrongInst) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IsetImportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_stmodulevar, true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetImportDescriptor, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetImportDescriptorWrongImport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_ImportDescriptor *newID = new abckit_ImportDescriptor(); + IsetImportDescriptorTest(ctxG, nullptr, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, true, newID); + delete newID; + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetExportDescriptor, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetExportDescriptor) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IsetExportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_ldlocalmodulevar); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n2\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetExportDescriptor, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetExportDescriptorWrongInst) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctxG->ctxI, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + IsetExportDescriptorTest(ctxG, ctxFinder.module, abckit_IsaApiDynamicOpcode_ldexternalmodulevar, true); + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetExportDescriptor, abc-kind=JS, category=negative +TEST_F(LibAbcKitModifyApiModulesTest, DynamicIsetExportDescriptorWrongExport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + abckit_ExportDescriptor *newED = new abckit_ExportDescriptor(); + IsetExportDescriptorTest(ctxG, nullptr, abckit_IsaApiDynamicOpcode_ldlocalmodulevar, true, newED); + delete newED; + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ApiImpl::TransformModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicTransformModule) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "RegularImportFunc1FromModule1"; + impl->TransformModule(module, (void *)&utd, TransformModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + impl->TransformModule(module, (void *)&utd, TransformModuleCheck); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewImportedFunc"; + utd.alias = "NewImportedFunc"; + utd.moduleName = "modules/module3"; + utd.isRegular = true; + impl->TransformModule(module, (void *)&utd, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddImportedFunctionCall(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewImportedFunc"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport2) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewImportedFunc"; + utd.alias = "NewImportedFuncAlias"; + utd.moduleName = "modules/module3"; + utd.isRegular = true; + impl->TransformModule(module, (void *)&utd, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddImportedFunctionCall(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewImportedFuncAlias"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport3) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + abckit_File *ctx = nullptr; + + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewImportedFuncFromModule4"; + utd.alias = "NewImportedFuncAlias"; + utd.moduleName = "modules/module4"; + utd.isRegular = true; + impl->TransformModule(module, (void *)&utd, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddImportedFunctionCall(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewImportedFuncAlias"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func from module4\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, ModuleAddImportFromDynamicModule_RegularImport4) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + abckit_File *ctx = nullptr; + + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "default"; + utd.alias = "NewImportedDefaultFuncFromModule4"; + utd.moduleName = "modules/module4"; + utd.isRegular = true; + impl->TransformModule(module, (void *)&utd, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddImportedFunctionCall(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewImportedDefaultFuncFromModule4"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported default func from module4\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, ModuleAddImportFromDynamicModule_NamespaceImport) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + abckit_File *ctx = nullptr; + + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "*"; + utd.alias = "NewImport"; + utd.moduleName = "modules/module3"; + utd.isRegular =false; + impl->TransformModule(module, (void *)&utd, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddImportedFunctionCallNS(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewImportedFunc", "modules/module3"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, ModuleAddImportFromDynamicModule_NamespaceImport2) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + abckit_File *ctx = nullptr; + + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "*"; + utd.alias = "NewImport"; + utd.moduleName = "modules/module4"; + utd.isRegular =false; + impl->TransformModule(module, (void *)&utd, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddImportedFunctionCallNS(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewImportedFuncFromModule4", "modules/module4"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew imported func from module4\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_LocalExport) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewExportedVar"; + utd.alias = "NewExportedVar"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [&utd](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddLocalExport(ctxM, ctxG, implI->MethodGetInspectContext(method), utd.alias, "modules_dynamic_modify"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n5\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_LocalExport2) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewExportedVar"; + utd.alias = "NewExportedVarAlias"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [&utd](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddLocalExport(ctxM, ctxG, implI->MethodGetInspectContext(method), utd.alias, "modules_dynamic_modify"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n5\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_LocalExport3) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "default"; + utd.alias = "NewExportedVarDefault"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_LOCAL_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [&utd](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddLocalExport(ctxM, ctxG, implI->MethodGetInspectContext(method), utd.alias, "modules_dynamic_modify"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n5\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_IndirectExport) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module2"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewLocalExportLet"; + utd.alias = "NewLocalExportLet"; + utd.moduleName = "modules/module1"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + UserTransformerData utd2; + utd2.name = utd.name; + utd2.alias = utd.alias; + utd2.moduleName = "modules/module2"; + utd2.isRegular = true; + ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + impl->TransformModule(ctxFinder.module, (void *)&utd2, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [&utd2](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddIndirectExport(ctxM, ctxG, implI->MethodGetInspectContext(method), utd2.alias, "modules_dynamic_modify"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_IndirectExport2) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module2"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "NewLocalExportVar"; + utd.alias = "NewLocalExportVarAlias"; + utd.moduleName = "modules/module4"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_INDIRECT_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + UserTransformerData utd2; + utd2.name = utd.alias; + utd2.alias = "NewLocalExportVarFromModule4"; + utd2.moduleName = "modules/module2"; + utd2.isRegular = true; + ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + impl->TransformModule(ctxFinder.module, (void *)&utd2, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [&utd2](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddIndirectExport(ctxM, ctxG, implI->MethodGetInspectContext(method), utd2.alias, "modules_dynamic_modify"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n6\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_StarExport) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module4"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "*"; + utd.moduleName = "modules/module3"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + module = ctxFinder.module; + UserTransformerData utd2; + utd2.name = "*"; + utd2.alias = "NS4"; + utd2.moduleName = "modules/module4"; + utd2.isRegular = false; + impl->TransformModule(module, (void *)&utd2, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [&utd2](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddStarExport(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewExportedFunc", utd2.moduleName); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew exported func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_StarExport2) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module3"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "*"; + utd.moduleName = "modules/module4"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddStarExport(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewExportedFuncFromModule4", "modules/module3"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew exported func from module4\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::DynamicModuleAddExport, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, DynamicModuleAddExport_StarExport3) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "modules/module4"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + auto module = ctxFinder.module; + UserTransformerData utd; + utd.name = "*"; + utd.alias = "NewStarExport"; + utd.moduleName = "modules/module3"; + utd.kind = abckit_DynamicExportKind::abckit_DynamicExportKind_STAR_EXPORT; + impl->TransformModule(module, (void *)&utd, DynamicModuleAddExportImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + ctxFinder = {nullptr, "modules_dynamic_modify"}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + module = ctxFinder.module; + UserTransformerData utd2; + utd2.name = "NewStarExport"; + utd2.alias = "NewStarExport"; + utd2.moduleName = "modules/module4"; + utd2.isRegular = true; + impl->TransformModule(module, (void *)&utd2, AddImportFromDynamicModuleImpl); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules/module4.func_main_0", + [&utd2, &utd](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddStarExportFunc(ctxM, ctxG, implI->MethodGetInspectContext(method), utd2.alias, utd.moduleName); + }, + [](abckit_Graph *ctxG) {} + ); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", + "modules_dynamic_modify.func_main_0", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIrAddStarExportFunc2(ctxM, ctxG, implI->MethodGetInspectContext(method), "NewExportedFunc", "modules_dynamic_modify"); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\nnew exported func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +// Test: test-kind=api, api=ModifyApiImpl::FileAddExternalModule, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiModulesTest, FileAddExternalModule) +{ + abckit_File *ctx = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify.abc", &ctx); + + abckit_ExternalModuleCreateParams params; + params.name = "ExternalModule"; + implM->FileAddExternalModule(ctx, ¶ms); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + helpers::ModuleByNameContext ctxFinder = {nullptr, params.name}; + implI->FileEnumerateModules(ctx, &ctxFinder, helpers::moduleByNameFinder); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(ctxFinder.module, nullptr); + ASSERT_EQ(implI->ModuleIsExternal(ctxFinder.module), true); + + impl->WriteAbc(ctx, ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/modules/modules_dynamic_modify_modified.abc", "modules_dynamic_modify"); + auto expected = "regular import func1 from module1\nregular import func1 from module2\nregular default import func1 from module3\nregular default import func2 from module2\nnamespace import func2 from module1\nnamespace import func3 from module1\n1\n2\nnamespace import func3 from module2\nthe same func from module3\n"; + EXPECT_TRUE(helpers::Match(output, expected)); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/modify_api/strings/strings_dynamic.js b/libabckit/tests/metadata/modify_api/strings/strings_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..a19498577ab0f533c86fa440eea14db04d32d66b --- /dev/null +++ b/libabckit/tests/metadata/modify_api/strings/strings_dynamic.js @@ -0,0 +1,10 @@ +function ConsoleLogStr(a) { + print(a); +} + +function main() { + let str = "testString"; + ConsoleLogStr(str); +} + +main(); diff --git a/libabckit/tests/metadata/modify_api/strings/strings_static.ets b/libabckit/tests/metadata/modify_api/strings/strings_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5349389c39044e1e87b451e8e209ee801f2f4a5 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/strings/strings_static.ets @@ -0,0 +1,8 @@ +function ConsoleLogStr(a: string) { + console.log(a) +} + +function main() { + let str : string = "testString"; + ConsoleLogStr(str); +} diff --git a/libabckit/tests/metadata/modify_api/strings/strings_test.cpp b/libabckit/tests/metadata/modify_api/strings/strings_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1dda8181dd61356358cfd45c367314afec0853fd --- /dev/null +++ b/libabckit/tests/metadata/modify_api/strings/strings_test.cpp @@ -0,0 +1,230 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "isa/isa_dynamic.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "metadata.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitModifyApiStringsTest : public ::testing::Test {}; + +struct UserData { + abckit_File *ctxI = nullptr; + abckit_ModifyContext *ctxM = nullptr; +}; + +// Test: test-kind=api, api=ModifyApiImpl::CreateString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiStringsTest, StaticCreateString) +{ + UserData userData = {}; + auto testImpl = [&]() { + + auto abckit_str = implM->CreateString(userData.ctxM, "newString"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(abckit_str, nullptr); + + auto str = helpers::abckit_StringToString(userData.ctxI, abckit_str); + ASSERT_EQ(std::strncmp(str.c_str(), "newString", sizeof("newString")), 0); + }; + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_static.abc", + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_static_modified.abc", + "main", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + userData.ctxI = implI->MethodGetInspectContext(method); + userData.ctxM = ctxM; + testImpl(); + }, + [](abckit_Graph *ctxG) { + } + ); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiStringsTest, StaticCreateString2) +{ + UserData userData = {}; + auto testImpl = [&](abckit_Graph *ctxG) { + + abckit_Inst *callOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + auto ConsoleLogStr = helpers::findMethodByName(userData.ctxI, "ConsoleLogStr"); + + auto str1 = implM->CreateString(userData.ctxM, "string1"); + auto loadString1 = statG->IcreateLoadString(ctxG, str1); + implG->IinsertAfter(loadString1, callOp); + abckit_Inst *log1 = statG->IcreateCallStatic(ctxG, ConsoleLogStr, 1, loadString1); + implG->IinsertAfter(log1, loadString1); + + auto str2 = implM->CreateString(userData.ctxM, "string2"); + auto loadString2 = statG->IcreateLoadString(ctxG, str2); + implG->IinsertAfter(loadString2, log1); + abckit_Inst *log2 = statG->IcreateCallStatic(ctxG, ConsoleLogStr, 1, loadString2); + implG->IinsertAfter(log2, loadString2); + }; + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_static.abc", + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_static_modify.abc", + "main", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + userData.ctxI = implI->MethodGetInspectContext(method); + userData.ctxM = ctxM; + + testImpl(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, {} + }, + { + {0}, {2}, { + {0, abckit_IsaApiStaticOpcode_LoadString, {}}, + {1, abckit_IsaApiStaticOpcode_CallStatic, {0}}, + {2, abckit_IsaApiStaticOpcode_LoadString, {}}, + {3, abckit_IsaApiStaticOpcode_CallStatic, {2}}, + {4, abckit_IsaApiStaticOpcode_LoadString, {}}, + {5, abckit_IsaApiStaticOpcode_CallStatic, {4}}, + {6, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateString, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiStringsTest, DynamicCreateString) +{ + UserData userData = {}; + auto testImpl = [&]() { + + auto abckit_str = implM->CreateString(userData.ctxM, "newString"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(abckit_str, nullptr); + + auto str = helpers::abckit_StringToString(userData.ctxI, abckit_str); + ASSERT_EQ(std::strncmp(str.c_str(), "newString", sizeof("newString")), 0); + }; + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_dynamic.abc", + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_dynamic.abc", + "main", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + userData.ctxI = implI->MethodGetInspectContext(method); + userData.ctxM = ctxM; + + testImpl(); + }, + [](abckit_Graph *ctxG) { + } + ); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateString, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiStringsTest, DynamicCreateString2) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_dynamic.abc", "strings_dynamic"); + EXPECT_TRUE(helpers::Match(output, "testString\n")); + + UserData userData = {}; + auto testImpl = [&](abckit_Graph *ctxG) { + + abckit_Inst *callOp = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_callarg1); + + auto str1 = implM->CreateString(userData.ctxM, "string1"); + auto str2 = implM->CreateString(userData.ctxM, "string2"); + + auto loadString1 = dynG->IcreateLoadString(ctxG, str1); + implG->IinsertAfter(loadString1, callOp); + auto *consoleLog1 = dynG->IcreateLdlexvar(ctxG, 0, 0); + implG->IinsertAfter(consoleLog1, loadString1); + abckit_Inst *log1 = dynG->IcreateCallarg1(ctxG, consoleLog1, loadString1); + implG->IinsertAfter(log1, consoleLog1); + + auto loadString2 = dynG->IcreateLoadString(ctxG, str2); + implG->IinsertAfter(loadString2, log1); + auto *consoleLog2 = dynG->IcreateLdlexvar(ctxG, 0, 0); + implG->IinsertAfter(consoleLog2, loadString2); + abckit_Inst *log2 = dynG->IcreateCallarg1(ctxG, consoleLog2, loadString2); + implG->IinsertAfter(log2, consoleLog2); + }; + + helpers::TransformMethod( + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_dynamic.abc", + ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_dynamic_modified.abc", + "main", + [&](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + userData.ctxI = implI->MethodGetInspectContext(method); + userData.ctxM = ctxM; + + testImpl(ctxG); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, {} + }, + { + {0}, {2}, { + {3, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {4, abckit_IsaApiDynamicOpcode_ldlexvar, {}}, + {5, abckit_IsaApiDynamicOpcode_callarg1, {3, 4}}, + {6, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {7, abckit_IsaApiDynamicOpcode_ldlexvar, {}}, + {8, abckit_IsaApiDynamicOpcode_callarg1, {6, 7}}, + {9, abckit_IsaApiDynamicOpcode_LoadString, {}}, + {10, abckit_IsaApiDynamicOpcode_ldlexvar, {}}, + {11, abckit_IsaApiDynamicOpcode_callarg1, {9, 10}}, + {12, abckit_IsaApiDynamicOpcode_ldundefined, {}}, + {13, abckit_IsaApiDynamicOpcode_returnundefined, {}}, + + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + // FIXME + // output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "metadata/modify_api/strings/strings_dynamic_modified.abc", "strings_dynamic"); + // EXPECT_TRUE(helpers::Match(output, "10\n10\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/metadata/modify_api/types/types_dynamic.js b/libabckit/tests/metadata/modify_api/types/types_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..a3922757f265c08d55bca89bdc4b7683d988086b --- /dev/null +++ b/libabckit/tests/metadata/modify_api/types/types_dynamic.js @@ -0,0 +1,5 @@ +class A { + foo(a) { + return a; + } +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/types/types_static.ets b/libabckit/tests/metadata/modify_api/types/types_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..3a4995edd93111572c81f60d565d0a75cbe92be4 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/types/types_static.ets @@ -0,0 +1,5 @@ +class A { + foo(a: int) : int { + return a; + } +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/types/types_test.cpp b/libabckit/tests/metadata/modify_api/types/types_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19dbe449784e1f9822580bb52f76074dd8070ffe --- /dev/null +++ b/libabckit/tests/metadata/modify_api/types/types_test.cpp @@ -0,0 +1,89 @@ +/** + * Copyright (c) 2024 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 +#include + +#include "abckit.h" +#include "statuses.h" +#include "helpers/helpers.h" +#include "ir_core.h" +#include "metadata.h" + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitModifyApiTypesTest : public ::testing::Test {}; + +static void InspectMethodValid(abckit_ModifyContext *ctxM) +{ + abckit_TypeId vecOfTypes[] = { + abckit_TypeId_VOID, + abckit_TypeId_U1, + abckit_TypeId_I8, + abckit_TypeId_U8, + abckit_TypeId_I16, + abckit_TypeId_U16, + abckit_TypeId_I32, + abckit_TypeId_U32, + abckit_TypeId_F32, + abckit_TypeId_F64, + abckit_TypeId_I64, + abckit_TypeId_U64, + abckit_TypeId_ANY, + abckit_TypeId_LITERALARRAY + }; + for (abckit_TypeId typeId : vecOfTypes) { + abckit_Type *type = implM->CreateType(ctxM, typeId); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + abckit_TypeId gotTypeId = implI->TypeGetTypeId(type); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(gotTypeId, typeId); + } +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateType, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiTypesTest, CreateTypesDynamic) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/types/types_dynamic.abc", &ctxI); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::InspectMethod(ctxI, "foo", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + InspectMethodValid(ctxM); + } + ); + impl->DestroyInspectContext(ctxI); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateType, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiTypesTest, CreateTypeStatic) +{ + helpers::InspectMethod( + ABCKIT_ABC_DIR "metadata/modify_api/types/types_static.abc", + "foo", + [](abckit_ModifyContext *ctxM, abckit_Method* method, abckit_Graph *ctxG) { + InspectMethodValid(ctxM); + } + ); +} + +} +} \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/values/values_dynamic.js b/libabckit/tests/metadata/modify_api/values/values_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..6a533184b11b8e5f0adeae5d5568dc6567bcc3c9 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/values/values_dynamic.js @@ -0,0 +1 @@ +o = [false, 1, "2", 0.4] \ No newline at end of file diff --git a/libabckit/tests/metadata/modify_api/values/values_static.ets b/libabckit/tests/metadata/modify_api/values/values_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..b5349389c39044e1e87b451e8e209ee801f2f4a5 --- /dev/null +++ b/libabckit/tests/metadata/modify_api/values/values_static.ets @@ -0,0 +1,8 @@ +function ConsoleLogStr(a: string) { + console.log(a) +} + +function main() { + let str : string = "testString"; + ConsoleLogStr(str); +} diff --git a/libabckit/tests/metadata/modify_api/values/values_test.cpp b/libabckit/tests/metadata/modify_api/values/values_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b4b1164e66800427a4a3c8d67130ecdf9102533b --- /dev/null +++ b/libabckit/tests/metadata/modify_api/values/values_test.cpp @@ -0,0 +1,157 @@ +/** + * Copyright (c) 2024 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 +#include +#include + +#include "libabckit/include/abckit.h" +#include "helpers/helpers.h" +#include "libabckit/include/metadata.h" +#include "metadata_modify_impl.h" // FIXME(mredkin) + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); + +class LibAbcKitModifyApiValuesTest : public ::testing::Test {}; + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueU1, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateValueU1_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueU1(&ctxM, true); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueDouble, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateValueDouble_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueDouble(&ctxM, 1.0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueString, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateValueString_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueString(&ctxM, "test"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArrayValue, abc-kind=JS, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateLiteralArrayValue_1) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_dynamic.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + std::vector abc_arr; + abc_arr.emplace_back(implM->CreateValueString(&ctxM, "test")); + abc_arr.emplace_back(implM->CreateValueU1(&ctxM, true)); + auto *arr = implM->CreateLiteralArrayValue(&ctxM, abc_arr.data(), 2); + + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(arr, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_dynamic.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueU1, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateValueU1_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueU1(&ctxM, true); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueDouble, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateValueDouble_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueDouble(&ctxM, 1.0); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueString, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateValueString_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + auto *res = implM->CreateValueString(&ctxM, "test"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_NE(res, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArrayValue, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitModifyApiValuesTest, CreateLiteralArrayValue_2) +{ + abckit_File *ctxI = nullptr; + helpers::assertOpenAbc(ABCKIT_ABC_DIR "metadata/modify_api/values/values_static.abc", &ctxI); + abckit_ModifyContext ctxM = {ctxI}; + std::vector abc_arr; + abc_arr.emplace_back(implM->CreateValueString(&ctxM, "test")); + abc_arr.emplace_back(implM->CreateValueU1(&ctxM, true)); + auto *arr = implM->CreateLiteralArrayValue(&ctxM, abc_arr.data(), 2); + + ASSERT_NE(impl->GetLastError(), abckit_Status_NO_ERROR); + ASSERT_EQ(arr, nullptr); + // Write output file + impl->WriteAbc(ctxI, "/tmp/values_static.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +} +} \ No newline at end of file diff --git a/libabckit/tests/null_args_tests/null_args_tests.cpp.erb b/libabckit/tests/null_args_tests/null_args_tests.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..cbee5814b08011e7d10e8bec78aab39be5b1cf93 --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests.cpp.erb @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto <%= domain %> = abckit_Get<%= domain %>(1); + +class LibAbcKitNullptrTests<%=domain%><%=iteration%>: public ::testing::Test {}; + +% slice_start = index +% slice_end = index + slice_size +% api_funcs_arr[slice_start..slice_end].each do |api_func| +// Test: test-kind=api, api=<%= domain %>::<%= api_func %>, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTests<%=domain%><%=iteration%>, <%=domain%><%= api_func %>Nullptr) +{ + helpers_nullptr::TestNullptr(<%= domain %>-><%= api_func %>); +} + +% end +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_ApiImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_ApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..659a9d918f5a35ab61a3ee15aee6aefabc221fd9 --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_ApiImpl_0.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto ApiImpl = abckit_GetApiImpl(1); + +class LibAbcKitNullptrTestsApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=ApiImpl::DestroyGraphContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplDestroyGraphContextNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->DestroyGraphContext); +} + +// Test: test-kind=api, api=ApiImpl::DestroyInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplDestroyInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->DestroyInspectContext); +} + +// Test: test-kind=api, api=ApiImpl::OpenAbc, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplOpenAbcNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->OpenAbc); +} + +// Test: test-kind=api, api=ApiImpl::TransformClass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplTransformClassNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->TransformClass); +} + +// Test: test-kind=api, api=ApiImpl::TransformMethod, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplTransformMethodNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->TransformMethod); +} + +// Test: test-kind=api, api=ApiImpl::TransformModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplTransformModuleNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->TransformModule); +} + +// Test: test-kind=api, api=ApiImpl::WriteAbc, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplWriteAbcNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->WriteAbc); +} + +// Test: test-kind=api, api=ApiImpl::codeToGraph, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplcodeToGraphNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->codeToGraph); +} + +// Test: test-kind=api, api=ApiImpl::graphToCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsApiImpl0, ApiImplgraphToCodeNullptr) +{ + helpers_nullptr::TestNullptr(ApiImpl->graphToCode); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_GraphApiImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_GraphApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a1538f6a46fe987ded9bc437ce5661e1e42ab51 --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_GraphApiImpl_0.cpp @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto GraphApiImpl = abckit_GetGraphApiImpl(1); + +class LibAbcKitNullptrTestsGraphApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstBack, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBaddInstBackNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBaddInstBack); +} + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstFront, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBaddInstFrontNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBaddInstFront); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcheckDominance, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBcheckDominanceNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBcheckDominance); +} + +// Test: test-kind=api, api=GraphApiImpl::BBclear, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBclearNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBclear); +} + +// Test: test-kind=api, api=GraphApiImpl::BBconnectBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBconnectBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBconnectBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcreateEmpty, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBcreateEmptyNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBcreateEmpty); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcreatePhi, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBcreatePhiNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBcreatePhi); +} + +// Test: test-kind=api, api=GraphApiImpl::BBdisconnectBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBdisconnectBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBdisconnectBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBdump, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBdumpNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBdump); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetFalseBranch, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetFalseBranchNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetFalseBranch); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetFirstInst, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetFirstInstNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetFirstInst); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetGraph, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetGraphNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetGraph); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetId, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetIdNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetId); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetImmediateDominator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetImmediateDominatorNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetImmediateDominator); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetLastInst, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetLastInstNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetLastInst); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetNumberOfInstructions, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetNumberOfInstructionsNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetNumberOfInstructions); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetPredBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetPredBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetPredBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetPredBlockCount, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetPredBlockCountNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetPredBlockCount); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetSuccBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetSuccBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetSuccBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetSuccBlockCount, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetSuccBlockCountNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetSuccBlockCount); +} + +// Test: test-kind=api, api=GraphApiImpl::BBgetTrueBranch, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBgetTrueBranchNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBgetTrueBranch); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisCatch, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisCatchNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisCatch); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisCatchBegin, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisCatchBeginNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisCatchBegin); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisEnd, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisEndNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisEnd); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisLoopHead, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisLoopHeadNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisLoopHead); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisLoopPrehead, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisLoopPreheadNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisLoopPrehead); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisStart, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisStartNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisStart); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisTry, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisTryNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisTry); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisTryBegin, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisTryBeginNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisTryBegin); +} + +// Test: test-kind=api, api=GraphApiImpl::BBisTryEnd, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBisTryEndNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBisTryEnd); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetPredBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBsetPredBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBsetPredBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetPredBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBsetPredBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBsetPredBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetSuccBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBsetSuccBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBsetSuccBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetSuccBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBsetSuccBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBsetSuccBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsplitBlockAfterInstruction, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBsplitBlockAfterInstructionNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBsplitBlockAfterInstruction); +} + +// Test: test-kind=api, api=GraphApiImpl::BBvisitDominatedBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBvisitDominatedBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBvisitDominatedBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBvisitPredBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBvisitPredBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBvisitPredBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBvisitSuccBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplBBvisitSuccBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->BBvisitSuccBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantF64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGcreateConstantF64Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GcreateConstantF64); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI32, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGcreateConstantI32Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GcreateConstantI32); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantI64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGcreateConstantI64Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GcreateConstantI64); +} + +// Test: test-kind=api, api=GraphApiImpl::GcreateConstantU64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGcreateConstantU64Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GcreateConstantU64); +} + +// Test: test-kind=api, api=GraphApiImpl::Gdump, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGdumpNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->Gdump); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetBasicBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGgetBasicBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GgetBasicBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetEndBasicBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGgetEndBasicBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GgetEndBasicBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetNumberOfBasicBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGgetNumberOfBasicBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GgetNumberOfBasicBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetParameter, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGgetParameterNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GgetParameter); +} + +// Test: test-kind=api, api=GraphApiImpl::GgetStartBasicBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGgetStartBasicBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GgetStartBasicBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::GrunPassRemoveUnreachableBlocks, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGrunPassRemoveUnreachableBlocksNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GrunPassRemoveUnreachableBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::GvisitBlocksRPO, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplGvisitBlocksRPONullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->GvisitBlocksRPO); +} + +// Test: test-kind=api, api=GraphApiImpl::IappendInput, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIappendInputNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IappendInput); +} + +// Test: test-kind=api, api=GraphApiImpl::IcheckDominance, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIcheckDominanceNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IcheckDominance); +} + +// Test: test-kind=api, api=GraphApiImpl::IcheckIsCall, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIcheckIsCallNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IcheckIsCall); +} + +// Test: test-kind=api, api=GraphApiImpl::Idump, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIdumpNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->Idump); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetBasicBlock, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetBasicBlockNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetBasicBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetConstantValueF64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetConstantValueF64Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetConstantValueF64); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetConstantValueI64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetConstantValueI64Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetConstantValueI64); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetConstantValueU64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetConstantValueU64Nullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetConstantValueU64); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetId, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetIdNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetId); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetImmediate, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetImmediateNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetImmediate); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetImmediateCount, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetImmediateCountNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetImmediateCount); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetInput, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetInputNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetInput); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetInputCount, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetInputCountNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetInputCount); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetLiteralArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetLiteralArrayNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetLiteralArray); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetMethod, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetMethodNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetMethod); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetNext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetNextNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetNext); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetPrev, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetPrevNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetPrev); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetStringNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetString); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetTypeNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetType); +} + +// Test: test-kind=api, api=GraphApiImpl::IgetUserCount, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIgetUserCountNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IgetUserCount); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertAfter, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIinsertAfterNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IinsertAfter); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertBefore, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIinsertBeforeNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IinsertBefore); +} + +// Test: test-kind=api, api=GraphApiImpl::Iremove, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIremoveNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->Iremove); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetImmediate, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIsetImmediateNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IsetImmediate); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetInput, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIsetInputNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IsetInput); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetInputs, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIsetInputsNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IsetInputs); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetLiteralArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIsetLiteralArrayNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IsetLiteralArray); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetMethod, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIsetMethodNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IsetMethod); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIsetStringNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IsetString); +} + +// Test: test-kind=api, api=GraphApiImpl::IvisitInputs, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIvisitInputsNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IvisitInputs); +} + +// Test: test-kind=api, api=GraphApiImpl::IvisitUsers, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsGraphApiImpl0, GraphApiImplIvisitUsersNullptr) +{ + helpers_nullptr::TestNullptr(GraphApiImpl->IvisitUsers); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_InspectApiImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_InspectApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5127098e7ad3e627cfb50b39343741b8e9fcb32f --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_InspectApiImpl_0.cpp @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto InspectApiImpl = abckit_GetInspectApiImpl(1); + +class LibAbcKitNullptrTestsInspectApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetAnnotation, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationElementGetAnnotationNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationElementGetAnnotation); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationElementGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationElementGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationElementGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationElementGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationElementGetValue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationElementGetValueNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationElementGetValue); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationEnumerateElements, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationEnumerateElementsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationEnumerateElements); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationGetInterface, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationGetInterfaceNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationGetInterface); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceEnumerateFields, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceEnumerateFieldsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceEnumerateFields); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetDefaultValue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceFieldGetDefaultValueNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceFieldGetDefaultValue); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceFieldGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceFieldGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetInterface, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceFieldGetInterfaceNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceFieldGetInterface); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceFieldGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceFieldGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceFieldGetType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceFieldGetTypeNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceFieldGetType); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceGetModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceGetModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceGetModule); +} + +// Test: test-kind=api, api=InspectApiImpl::AnnotationInterfaceGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplAnnotationInterfaceGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->AnnotationInterfaceGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::ArrayValueGetLiteralArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplArrayValueGetLiteralArrayNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ArrayValueGetLiteralArray); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateAnnotations, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplClassEnumerateAnnotationsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ClassEnumerateAnnotations); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassEnumerateMethods, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplClassEnumerateMethodsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ClassEnumerateMethods); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplClassGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ClassGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplClassGetModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ClassGetModule); +} + +// Test: test-kind=api, api=InspectApiImpl::ClassGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplClassGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ClassGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetAlias, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplExportDescriptorGetAliasNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ExportDescriptorGetAlias); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetExportedModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplExportDescriptorGetExportedModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ExportDescriptorGetExportedModule); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetExportingModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplExportDescriptorGetExportingModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ExportDescriptorGetExportingModule); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplExportDescriptorGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ExportDescriptorGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::ExportDescriptorGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplExportDescriptorGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ExportDescriptorGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::FileEnumerateExternalModules, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplFileEnumerateExternalModulesNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->FileEnumerateExternalModules); +} + +// Test: test-kind=api, api=InspectApiImpl::FileEnumerateModules, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplFileEnumerateModulesNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->FileEnumerateModules); +} + +// Test: test-kind=api, api=InspectApiImpl::FileGetVersion, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplFileGetVersionNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->FileGetVersion); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetAlias, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplImportDescriptorGetAliasNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ImportDescriptorGetAlias); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetImportedModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplImportDescriptorGetImportedModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ImportDescriptorGetImportedModule); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetImportingModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplImportDescriptorGetImportingModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ImportDescriptorGetImportingModule); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplImportDescriptorGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ImportDescriptorGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::ImportDescriptorGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplImportDescriptorGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ImportDescriptorGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralArrayEnumerateElements, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralArrayEnumerateElementsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralArrayEnumerateElements); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetBool, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetBoolNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetBool); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetDouble, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetDoubleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetDouble); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetFloat, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetFloatNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetFloat); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetStringNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetString); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetTag, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetTagNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetTag); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU16, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetU16Nullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetU16); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU32, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetU32Nullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetU32); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetU64Nullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetU64); +} + +// Test: test-kind=api, api=InspectApiImpl::LiteralGetU8, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplLiteralGetU8Nullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->LiteralGetU8); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodEnumerateAnnotations, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodEnumerateAnnotationsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodEnumerateAnnotations); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodGetCodeNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodGetCode); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodGetModuleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodGetModule); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodGetParentClass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodGetParentClassNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodGetParentClass); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsAbstract, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodIsAbstractNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodIsAbstract); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsAnonymous, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodIsAnonymousNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodIsAnonymous); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsCtor, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodIsCtorNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodIsCtor); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsExternal, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodIsExternalNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodIsExternal); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsNative, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodIsNativeNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodIsNative); +} + +// Test: test-kind=api, api=InspectApiImpl::MethodIsStatic, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplMethodIsStaticNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->MethodIsStatic); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateAnnotationInterfaces, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleEnumerateAnnotationInterfacesNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleEnumerateAnnotationInterfaces); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateAnonymousFunctions, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleEnumerateAnonymousFunctionsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleEnumerateAnonymousFunctions); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateClasses, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleEnumerateClassesNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleEnumerateClasses); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateExports, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleEnumerateExportsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleEnumerateExports); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateImports, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleEnumerateImportsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleEnumerateImports); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleEnumerateTopLevelFunctions, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleEnumerateTopLevelFunctionsNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleEnumerateTopLevelFunctions); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleGetInspectContext, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleGetInspectContextNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleGetInspectContext); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleGetName, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleGetNameNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleGetName); +} + +// Test: test-kind=api, api=InspectApiImpl::ModuleIsExternal, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplModuleIsExternalNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ModuleIsExternal); +} + +// Test: test-kind=api, api=InspectApiImpl::TypeGetReferenceClass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplTypeGetReferenceClassNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->TypeGetReferenceClass); +} + +// Test: test-kind=api, api=InspectApiImpl::TypeGetTypeId, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplTypeGetTypeIdNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->TypeGetTypeId); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetDouble, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplValueGetDoubleNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ValueGetDouble); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplValueGetStringNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ValueGetString); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplValueGetTypeNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ValueGetType); +} + +// Test: test-kind=api, api=InspectApiImpl::ValueGetU1, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplValueGetU1Nullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->ValueGetU1); +} + +// Test: test-kind=api, api=InspectApiImpl::abckit_StringToString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsInspectApiImpl0, InspectApiImplabckit_StringToStringNullptr) +{ + helpers_nullptr::TestNullptr(InspectApiImpl->abckit_StringToString); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_IsaApiDynamicImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_IsaApiDynamicImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e8b5453ed802ae5da6105b24473f1c46cef0d8c --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_IsaApiDynamicImpl_0.cpp @@ -0,0 +1,643 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiDynamicImpl = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitNullptrTestsIsaApiDynamicImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAdd2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAdd2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAdd2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAnd2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAnd2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAnd2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateApply, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateApplyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateApply); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAshr2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAshr2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAshr2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionawaituncaught, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionawaituncaughtNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAsyncfunctionawaituncaught); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionenter, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionenterNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAsyncfunctionenter); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionreject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionrejectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAsyncfunctionreject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionresolve, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionresolveNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAsyncfunctionresolve); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncgeneratorreject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncgeneratorrejectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAsyncgeneratorreject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncgeneratorresolve, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncgeneratorresolveNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateAsyncgeneratorresolve); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg0, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallarg0Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallarg0); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg1, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallarg1Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallarg1); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallargs2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallargs2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs3, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallargs3Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallargs3); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeCallinit, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeCallinitNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeCallinit); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeCreateprivateproperty, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeCreateprivatepropertyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeCreateprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinefieldbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinefieldbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeDefinefieldbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinefieldbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinefieldbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeDefinefieldbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefineprivateproperty, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefineprivatepropertyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeDefineprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinesendableclass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinesendableclassNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeDefinesendableclass); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIsfalse, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeIsfalseNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeIsfalse); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIstrue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeIstrueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeIstrue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeLdsendableclass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeLdsendableclassNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeLdsendableclass); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeLdsendableexternalmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeLdsendableexternalmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeLdsendableexternalmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeLdsendablevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeLdsendablevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeLdsendablevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeNewsendableenv, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeNewsendableenvNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeNewsendableenv); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeNotifyconcurrentresult, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeNotifyconcurrentresultNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeNotifyconcurrentresult); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeStsendablevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeStsendablevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeStsendablevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeTopropertykey, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeTopropertykeyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeTopropertykey); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWideldsendableexternalmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWideldsendableexternalmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeWideldsendableexternalmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWideldsendablevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWideldsendablevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeWideldsendablevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWidenewsendableenv, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWidenewsendableenvNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeWidenewsendableenv); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWidestsendablevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWidestsendablevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallruntimeWidestsendablevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis0, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis0Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallthis0); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis1, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis1Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallthis1); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallthis2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis3, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis3Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallthis3); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthisrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthisrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCallthisrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCatchPhi, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCatchPhiNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCatchPhi); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCloseiterator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCloseiteratorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCloseiterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCmp, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCmpNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCmp); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCopydataproperties, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCopydatapropertiesNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCopydataproperties); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCopyrestargs, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCopyrestargsNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCopyrestargs); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreatearraywithbuffer, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreatearraywithbufferNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreatearraywithbuffer); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateasyncgeneratorobj, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateasyncgeneratorobjNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateasyncgeneratorobj); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateemptyarray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateemptyarrayNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateemptyarray); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateemptyobject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateemptyobjectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateemptyobject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreategeneratorobj, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreategeneratorobjNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreategeneratorobj); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateiterresultobj, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateiterresultobjNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateiterresultobj); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateobjectwithbuffer, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateobjectwithbufferNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateobjectwithbuffer); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateobjectwithexcludedkeys, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateobjectwithexcludedkeysNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateobjectwithexcludedkeys); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateregexpwithliteral, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateregexpwithliteralNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateCreateregexpwithliteral); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDebugger, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDebuggerNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDebugger); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDec, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDecNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDec); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefineclasswithbuffer, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefineclasswithbufferNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDefineclasswithbuffer); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinefieldbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinefieldbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDefinefieldbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinefunc, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinefuncNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDefinefunc); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinegettersetterbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinegettersetterbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDefinegettersetterbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinemethod, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinemethodNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDefinemethod); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDelobjprop, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDelobjpropNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDelobjprop); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDiv2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDiv2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDiv2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDynamicimport, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDynamicimportNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateDynamicimport); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateEq, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateEqNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateEq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateExp, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateExpNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateExp); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetasynciterator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetasynciteratorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetasynciterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetiterator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetiteratorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetiterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetmodulenamespace, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetmodulenamespaceNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetmodulenamespace); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetnextpropname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetnextpropnameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetnextpropname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetpropiterator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetpropiteratorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetpropiterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetresumemode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetresumemodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetresumemode); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGettemplateobject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGettemplateobjectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGettemplateobject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetunmappedargs, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetunmappedargsNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGetunmappedargs); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreater, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGreaterNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGreater); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreatereq, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGreatereqNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateGreatereq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIf, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIfNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateIf); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInc, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIncNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateInc); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInstanceof, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateInstanceofNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateInstanceof); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsfalse, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIsfalseNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateIsfalse); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsin, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIsinNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateIsin); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIstrue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIstrueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateIstrue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdbigint, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdbigintNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdbigint); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdexternalmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdexternalmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdexternalmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfalse, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdfalseNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdfalse); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfunction, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdfunctionNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdfunction); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobal, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdglobalNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdglobal); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobalvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdglobalvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdglobalvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdhole, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdholeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdhole); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdinfinity, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdinfinityNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdinfinity); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdlexvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdlexvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdlexvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdlocalmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdlocalmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdlocalmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnan, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdnanNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdnan); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnewtarget, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdnewtargetNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdnewtarget); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnull, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdnullNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdnull); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdobjbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdobjbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdprivateproperty, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdprivatepropertyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsuperbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsuperbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdsuperbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsuperbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsuperbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdsuperbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsymbol, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsymbolNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdsymbol); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_IsaApiDynamicImpl_1.cpp b/libabckit/tests/null_args_tests/null_args_tests_IsaApiDynamicImpl_1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f055e27b2719f48e4ba5ee19260e0def831ed6f3 --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_IsaApiDynamicImpl_1.cpp @@ -0,0 +1,625 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiDynamicImpl = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitNullptrTestsIsaApiDynamicImpl1: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsymbol, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdsymbolNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdsymbol); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthis, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdthisNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdthis); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthisbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdthisbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdthisbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthisbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdthisbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdthisbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdtrue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdtrueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdtrue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdundefined, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdundefinedNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLdundefined); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLess, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLessNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLess); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLesseq, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLesseqNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLesseq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLoadString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLoadStringNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateLoadString); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMod2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateMod2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateMod2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMul2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateMul2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateMul2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNeg, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNegNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNeg); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewlexenv, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewlexenvNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNewlexenv); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewlexenvwithname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewlexenvwithnameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNewlexenvwithname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewobjapply, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewobjapplyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNewobjapply); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewobjrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewobjrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNewobjrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNot, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNotNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNot); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNoteq, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNoteqNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateNoteq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateOr2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateOr2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateOr2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreatePoplexenv, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreatePoplexenvNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreatePoplexenv); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateResumegenerator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateResumegeneratorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateResumegenerator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturn, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateReturnNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateReturn); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturnundefined, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateReturnundefinedNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateReturnundefined); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSetgeneratorstate, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSetgeneratorstateNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSetgeneratorstate); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSetobjectwithproto, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSetobjectwithprotoNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSetobjectwithproto); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShl2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateShl2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateShl2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShr2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateShr2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateShr2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStarrayspread, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStarrayspreadNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStarrayspread); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStconsttoglobalrecord, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStconsttoglobalrecordNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStconsttoglobalrecord); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStglobalvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStglobalvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStglobalvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStlexvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStlexvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStlexvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStobjbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStobjbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStobjbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStobjbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStobjbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStownbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStownbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbynamewithnameset, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbynamewithnamesetNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStownbynamewithnameset); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStownbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvaluewithnameset, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbyvaluewithnamesetNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStownbyvaluewithnameset); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStprivateproperty, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStprivatepropertyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStricteq, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStricteqNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStricteq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStrictnoteq, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStrictnoteqNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStrictnoteq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStsuperbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStsuperbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStsuperbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStsuperbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStsuperbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStsuperbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStthisbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStthisbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStthisbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStthisbyvalue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStthisbyvalueNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateStthisbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSttoglobalrecord, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSttoglobalrecordNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSttoglobalrecord); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSub2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSub2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSub2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallarrowrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallarrowrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSupercallarrowrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallspread, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallspreadNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSupercallspread); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallthisrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallthisrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSupercallthisrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSuspendgenerator, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSuspendgeneratorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateSuspendgenerator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTestin, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTestinNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateTestin); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrow, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrow); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowConstassignment, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowConstassignmentNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowConstassignment); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowDeletesuperproperty, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowDeletesuperpropertyNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowDeletesuperproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfnotobject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowIfnotobjectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowIfnotobject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfsupernotcorrectcall, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowIfsupernotcorrectcallNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowIfsupernotcorrectcall); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowNotexists, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowNotexistsNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowNotexists); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowPatternnoncoercible, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowPatternnoncoercibleNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowPatternnoncoercible); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifhole, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowUndefinedifholeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowUndefinedifhole); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifholewithname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowUndefinedifholewithnameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateThrowUndefinedifholewithname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumber, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTonumberNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateTonumber); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumeric, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTonumericNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateTonumeric); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTryldglobalbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTryldglobalbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateTryldglobalbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTrystglobalbyname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTrystglobalbynameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateTrystglobalbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTypeof, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTypeofNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateTypeof); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCallrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideCallrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallthisrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCallthisrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideCallthisrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCopyrestargs, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCopyrestargsNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideCopyrestargs); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCreateobjectwithexcludedkeys, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCreateobjectwithexcludedkeysNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideCreateobjectwithexcludedkeys); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideGetmodulenamespace, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideGetmodulenamespaceNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideGetmodulenamespace); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdexternalmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdexternalmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideLdexternalmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdlexvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdlexvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideLdlexvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdlocalmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdlocalmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideLdlocalmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdobjbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdobjbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideLdobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdpatchvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdpatchvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideLdpatchvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideNewlexenv, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideNewlexenvNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideNewlexenv); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideNewlexenvwithname, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideNewlexenvwithnameNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideNewlexenvwithname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideNewobjrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideNewobjrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideNewobjrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStlexvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStlexvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideStlexvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStmodulevar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStmodulevarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideStmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStobjbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStobjbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideStobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStownbyindex, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStownbyindexNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideStownbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStpatchvar, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStpatchvarNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideStpatchvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideSupercallarrowrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideSupercallarrowrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideSupercallarrowrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideSupercallthisrange, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideSupercallthisrangeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateWideSupercallthisrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateXor2, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateXor2Nullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IcreateXor2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetConditionCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIgetConditionCodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IgetConditionCode); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetExportDescriptor, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIgetExportDescriptorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IgetExportDescriptor); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetImportDescriptor, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIgetImportDescriptorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IgetImportDescriptor); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIgetModuleNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IgetModule); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IgetOpcode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIgetOpcodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IgetOpcode); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetConditionCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIsetConditionCodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IsetConditionCode); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetExportDescriptor, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIsetExportDescriptorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IsetExportDescriptor); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetImportDescriptor, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIsetImportDescriptorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IsetImportDescriptor); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IsetModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiDynamicImpl1, IsaApiDynamicImplIsetModuleNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiDynamicImpl->IsetModule); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_IsaApiStaticImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_IsaApiStaticImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..974945b169e740fddcac1d5caac342444e1567ac --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_IsaApiStaticImpl_0.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiStaticImpl = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitNullptrTestsIsaApiStaticImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::GcreateNullPtr, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplGcreateNullPtrNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->GcreateNullPtr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShr, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAShrNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateAShr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShrI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAShrINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateAShrI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAdd, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAddNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateAdd); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAddI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAddINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateAddI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAnd, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAndNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateAnd); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAndI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAndINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateAndI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallStatic, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCallStaticNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateCallStatic); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallVirtual, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCallVirtualNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateCallVirtual); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCast, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCastNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateCast); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCatchPhi, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCatchPhiNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateCatchPhi); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCheckCast, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCheckCastNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateCheckCast); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCmp, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCmpNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateCmp); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDiv, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateDivNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateDiv); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDivI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateDivINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateDivI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateEquals, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateEqualsNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateEquals); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIf, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateIfNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateIf); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateInitObjectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateInitObject); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIsInstance, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateIsInstanceNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateIsInstance); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLenArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLenArrayNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateLenArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadArrayNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateLoadArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadConstArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadConstArrayNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateLoadConstArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadStringNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateLoadString); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadUndefined, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadUndefinedNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateLoadUndefined); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMod, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateModNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateMod); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateModI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateModINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateModI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMul, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateMulNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateMul); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMulI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateMulINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateMulI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNeg, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNegNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateNeg); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNewArrayNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateNewArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewObject, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNewObjectNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateNewObject); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNot, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNotNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateNot); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOr, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateOrNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateOr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOrI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateOrINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateOrI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturn, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateReturnNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateReturn); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturnVoid, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateReturnVoidNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateReturnVoid); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShl, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShlNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateShl); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShlI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShlINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateShlI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShr, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShrNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateShr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShrI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShrINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateShrI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateStoreArrayNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateStoreArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArrayWide, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateStoreArrayWideNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateStoreArrayWide); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSub, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateSubNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateSub); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSubI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateSubINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateSubI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateThrow, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateThrowNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateThrow); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXor, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateXorNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateXor); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXorI, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateXorINullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IcreateXorI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetClass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIgetClassNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IgetClass); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetConditionCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIgetConditionCodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IgetConditionCode); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetOpcode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIgetOpcodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IgetOpcode); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IgetTargetType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIgetTargetTypeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IgetTargetType); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetClass, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIsetClassNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IsetClass); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetConditionCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIsetConditionCodeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IsetConditionCode); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IsetTargetType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsIsaApiStaticImpl0, IsaApiStaticImplIsetTargetTypeNullptr) +{ + helpers_nullptr::TestNullptr(IsaApiStaticImpl->IsetTargetType); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/null_args_tests/null_args_tests_ModifyApiImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_ModifyApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f1e1065678b784fd1a331c4d6b22f7852c8f2d88 --- /dev/null +++ b/libabckit/tests/null_args_tests/null_args_tests_ModifyApiImpl_0.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_nullptr.h" + +#include + +namespace libabckit { +namespace test { + +static auto ModifyApiImpl = abckit_GetModifyApiImpl(1); + +class LibAbcKitNullptrTestsModifyApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationAddAnnotationElement, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplAnnotationAddAnnotationElementNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->AnnotationAddAnnotationElement); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationInterfaceAddField, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplAnnotationInterfaceAddFieldNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->AnnotationInterfaceAddField); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationInterfaceRemoveField, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplAnnotationInterfaceRemoveFieldNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->AnnotationInterfaceRemoveField); +} + +// Test: test-kind=api, api=ModifyApiImpl::AnnotationRemoveAnnotationElement, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplAnnotationRemoveAnnotationElementNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->AnnotationRemoveAnnotationElement); +} + +// Test: test-kind=api, api=ModifyApiImpl::ClassAddAnnotation, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplClassAddAnnotationNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->ClassAddAnnotation); +} + +// Test: test-kind=api, api=ModifyApiImpl::ClassRemoveAnnotation, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplClassRemoveAnnotationNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->ClassRemoveAnnotation); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArray, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralArrayNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralArray); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralArrayValue, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralArrayValueNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralArrayValue); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralBool, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralBoolNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralBool); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralDouble, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralDoubleNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralDouble); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralFloat, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralFloatNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralFloat); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralStringNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralString); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU16, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralU16Nullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralU16); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU32, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralU32Nullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralU32); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU64, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralU64Nullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralU64); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateLiteralU8, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateLiteralU8Nullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateLiteralU8); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateReferenceType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateReferenceTypeNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateReferenceType); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateStringNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateString); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateType, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateTypeNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateType); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueDouble, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateValueDoubleNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateValueDouble); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueString, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateValueStringNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateValueString); +} + +// Test: test-kind=api, api=ModifyApiImpl::CreateValueU1, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplCreateValueU1Nullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->CreateValueU1); +} + +// Test: test-kind=api, api=ModifyApiImpl::MethodAddAnnotation, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplMethodAddAnnotationNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->MethodAddAnnotation); +} + +// Test: test-kind=api, api=ModifyApiImpl::MethodRemoveAnnotation, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplMethodRemoveAnnotationNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->MethodRemoveAnnotation); +} + +// Test: test-kind=api, api=ModifyApiImpl::MethodSetCode, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplMethodSetCodeNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->MethodSetCode); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddAnnotationInterface, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplModuleAddAnnotationInterfaceNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->ModuleAddAnnotationInterface); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleAddImportFromDynamicModule, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplModuleAddImportFromDynamicModuleNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->ModuleAddImportFromDynamicModule); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveExport, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplModuleRemoveExportNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->ModuleRemoveExport); +} + +// Test: test-kind=api, api=ModifyApiImpl::ModuleRemoveImport, abc-kind=NoABC, category=negative-nullptr +TEST_F(LibAbcKitNullptrTestsModifyApiImpl0, ModifyApiImplModuleRemoveImportNullptr) +{ + helpers_nullptr::TestNullptr(ModifyApiImpl->ModuleRemoveImport); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/scenarios/add_log/add_log_dynamic.js b/libabckit/tests/scenarios/add_log/add_log_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..79c7f22e528033ab57ecf10269ff35edbd23d3b9 --- /dev/null +++ b/libabckit/tests/scenarios/add_log/add_log_dynamic.js @@ -0,0 +1,27 @@ +// Before AOP: + +class MyClass { + handle() { + print("abckit") + } +} + +function main() { + let c = new MyClass(); + c.handle(); +} + +main() + +// // After AOP: +// +// class MyClass { +// handle() { +// print("file: har_A/src/MyClass, function: MyClass.handle") +// let t1 = Date.getTime() +// // business logic +// let t2 = Date.getTime() +// print("Ellapsed time:") +// print(t2 - t1) +// } +// } diff --git a/libabckit/tests/scenarios/add_log/add_log_dynamic_test.cpp b/libabckit/tests/scenarios/add_log/add_log_dynamic_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b3f27857dd9da509d6a787cb203887d1b62503a --- /dev/null +++ b/libabckit/tests/scenarios/add_log/add_log_dynamic_test.cpp @@ -0,0 +1,162 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit { +namespace test { + +class LibAbcKitTest : public ::testing::Test {}; + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto dynG = abckit_GetIsaApiDynamicImpl(1); + +struct UserData { + abckit_String *print = nullptr; + abckit_String *date = nullptr; + abckit_String *getTime = nullptr; + abckit_String *str = nullptr; + abckit_String *consume = nullptr; +}; + +static void TransformIr(abckit_Graph *ctxG, UserData *userData) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + auto *bb = succBBs[0]; + abckit_Inst *callInst = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_callarg1); + + // Prolog + auto *str = dynG->IcreateLoadString(ctxG, userData->str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->BBaddInstFront(bb, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *print = dynG->IcreateTryldglobalbyname(ctxG, userData->print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(print, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg = dynG->IcreateCallarg1(ctxG, print, str); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(callArg, print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *dateClass = dynG->IcreateTryldglobalbyname(ctxG, userData->date); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateClass, callArg); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *dateObj = dynG->IcreateNewobjrange(ctxG, 1, dateClass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateObj, dateClass); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *getTime = dynG->IcreateLdobjbyname(ctxG, dateObj, userData->getTime); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(getTime, dateObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *time = dynG->IcreateCallthis0(ctxG, getTime, dateObj); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(time, getTime); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Epilog + auto *dateClass2 = dynG->IcreateTryldglobalbyname(ctxG, userData->date); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateClass2, callInst); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *dateObj2 = dynG->IcreateNewobjrange(ctxG, 1, dateClass2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(dateObj2, dateClass2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *getTime2 = dynG->IcreateLdobjbyname(ctxG, dateObj2, userData->getTime); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(getTime2, dateObj2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *time2 = dynG->IcreateCallthis0(ctxG, getTime2, dateObj2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(time2, getTime2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *consume = dynG->IcreateLoadString(ctxG, userData->consume); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(consume, time2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *print2 = dynG->IcreateTryldglobalbyname(ctxG, userData->print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(print2, consume); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg2 = dynG->IcreateCallarg1(ctxG, print2, consume); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(callArg2, print2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *sub = dynG->IcreateSub2(ctxG, time2, time); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(sub, callArg2); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + auto *print3 = dynG->IcreateTryldglobalbyname(ctxG, userData->print); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(print3, sub); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + auto *callArg3 = dynG->IcreateCallarg1(ctxG, print3, sub); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + implG->IinsertAfter(callArg3, print3); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); +} + +// Test: test-kind=scenario, abc-kind=JS, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestDynamicAddLog) +{ + auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic.abc", "add_log_dynamic"); + EXPECT_TRUE(helpers::Match(output, "abckit\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic.abc", + ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic_modified.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + UserData data = {}; + data.print = implM->CreateString(ctxM, "print"); + data.date = implM->CreateString(ctxM, "Date"); + data.getTime = implM->CreateString(ctxM, "getTime"); + data.str = implM->CreateString(ctxM, "file: src/MyClass, function: MyClass.handle"); + data.consume = implM->CreateString(ctxM, "Ellapsed time:"); + + TransformIr(ctxG, &data); + }, + [](abckit_Graph *ctxG) { + // TODO + } + ); + + output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic_modified.abc", "add_log_dynamic"); + EXPECT_TRUE(helpers::Match(output, + "file: src/MyClass, function: MyClass.handle\n" + "abckit\n" + "Ellapsed time:\n" + "\\d+\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/scenarios/add_log/add_log_static.ets b/libabckit/tests/scenarios/add_log/add_log_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..1bdcb7912f6f8a7c2c2c8716bc11acfa45677de0 --- /dev/null +++ b/libabckit/tests/scenarios/add_log/add_log_static.ets @@ -0,0 +1,45 @@ +// Before AOP: + +function ConsoleLogStr(a: string) { + console.log(a) +} + +function ConsoleLogNum(a: number) { + console.log(a) +} + +function DateGetTime(): number { + return (new Date()).getTime() +} + +class MyClass { + handle() { + ConsoleLogStr("buisiness logic...") + } +} + +function main() { + let c = new MyClass(); + c.handle(); +} + +// // After AOP: +// +// function ConsoleLog(a: string) { +// console.log(a) +// } + +// function DateGetTime(): number { +// return (new Date()).getTime() +// } +// +// class MyClass { +// handle() { +// ConsoleLogStr("file: har_A/src/MyClass; function: MyClass.handle") +// let t1 = DateGetTime() +// // business logic +// let t2 = DateGetTime() +// ConsoleLogStr("time consume: ") +// ConsoleLogNum(t2 - t1) +// } +// } \ No newline at end of file diff --git a/libabckit/tests/scenarios/add_log/add_log_static_test.cpp b/libabckit/tests/scenarios/add_log/add_log_static_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f072459b8edbc41e7c4bfcceff873e74c52ab062 --- /dev/null +++ b/libabckit/tests/scenarios/add_log/add_log_static_test.cpp @@ -0,0 +1,144 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +// TODO: +// * Printed filename is "TODO", should be real name +// * Use actual stdlib calls (instead of user's DateGetTime, ConsoleLogNum, ConsoleLogStr) +// * There are several issues related to SaveState in this test: +// * Start calls are inserted after first SaveState (not at the beginning of function) +// * SaveStates are manipulated by user explicitly +// * SaveStates are "INVALID" operations in validation schema + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +struct UserData { + abckit_Method *ConsoleLogStr = nullptr; + abckit_Method *ConsoleLogNum = nullptr; + abckit_Method *DateGetTime = nullptr; +}; + +static void TransformIr(abckit_Graph *ctxG, UserData *userData, abckit_String *str1, abckit_String *str2) +{ + abckit_Inst *callOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_CallStatic); + abckit_Inst *startTime = nullptr; + + // console.log("file: FileName; function: FunctionName") + abckit_Inst *loadString = statG->IcreateLoadString(ctxG, str1); + implG->IinsertBefore(loadString, callOp); + abckit_Inst *log1 = statG->IcreateCallStatic(ctxG, userData->ConsoleLogStr, 1, loadString); + implG->IinsertAfter(log1, loadString); + + // const start = Date().getTime() + startTime = statG->IcreateCallStatic(ctxG, userData->DateGetTime, 0); + implG->IinsertAfter(startTime, log1); + + // const end = Date().getTime() + abckit_Inst *endTime = statG->IcreateCallStatic(ctxG, userData->DateGetTime, 0); + abckit_Inst *retOp = helpers::FindFirstInst(ctxG, abckit_IsaApiStaticOpcode_ReturnVoid); + implG->IinsertBefore(endTime, retOp); + + // console.log("Elapsed time:") + loadString = statG->IcreateLoadString(ctxG, str2); + implG->IinsertAfter(loadString, endTime); + abckit_Inst *log = statG->IcreateCallStatic(ctxG, userData->ConsoleLogStr, 1, loadString); + implG->IinsertAfter(log, loadString); + + // console.log(end - start) + abckit_Inst *sub = statG->IcreateSub(ctxG, endTime, startTime); + implG->IinsertAfter(sub, log); + abckit_Inst *log2 = statG->IcreateCallStatic(ctxG, userData->ConsoleLogNum, 1, sub); + implG->IinsertAfter(log2, sub); +} + +class LibAbcKitTest : public ::testing::Test {}; + +// Test: test-kind=scenario, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestStaticAddLog) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_static.abc", "add_log_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"buisiness logic...\"\n")); + + helpers::TransformMethod( + ABCKIT_ABC_DIR "scenarios/add_log/add_log_static.abc", + ABCKIT_ABC_DIR "scenarios/add_log/add_log_static_modified.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto ctxI = implI->MethodGetInspectContext(method); + UserData userData; + userData.ConsoleLogStr = helpers::findMethodByName(ctxI, "ConsoleLogStr"); + userData.ConsoleLogNum = helpers::findMethodByName(ctxI, "ConsoleLogNum"); + userData.DateGetTime = helpers::findMethodByName(ctxI, "DateGetTime"); + auto mname = implI->MethodGetName(method); + auto methodName = helpers::GetCropFuncName(helpers::abckit_StringToString(ctxI, mname)); + std::string startMsg = "file: TODO; function: " + methodName; + abckit_String *strValue1 = implM->CreateString(ctxM, startMsg.c_str()); + abckit_String *strValue2 = implM->CreateString(ctxM, "Elapsed time:"); + + TransformIr(ctxG, &userData, strValue1, strValue2); + }, + [](abckit_Graph *ctxG) { + std::vector> bbSchemas({ + { + {}, {1}, {} + }, + { + {0}, {2}, { + {3, abckit_IsaApiStaticOpcode_LoadString, {}}, + {5, abckit_IsaApiStaticOpcode_LoadString, {}}, + {8, abckit_IsaApiStaticOpcode_CallStatic, {5}}, + {11, abckit_IsaApiStaticOpcode_CallStatic, {}}, + {14, abckit_IsaApiStaticOpcode_CallStatic, {3}}, + {17, abckit_IsaApiStaticOpcode_CallStatic, {}}, + {19, abckit_IsaApiStaticOpcode_LoadString, {}}, + {22, abckit_IsaApiStaticOpcode_CallStatic, {19}}, + {23, abckit_IsaApiStaticOpcode_Sub, {17, 11}}, + {26, abckit_IsaApiStaticOpcode_CallStatic, {23}}, + {27, abckit_IsaApiStaticOpcode_ReturnVoid, {}}, + } + }, + { + {1}, {}, {} + } + }); + helpers::VerifyGraph(ctxG, bbSchemas); + } + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_static_modified.abc", "add_log_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, + "\"file: TODO; function: handle\"\n" + "\"buisiness logic...\"\n" + "\"Elapsed time:\"\n" + "\\d+\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.cpp b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.cpp new file mode 100644 index 0000000000000000000000000000000000000000..59c6b354a9046f7c4c56547d65ccb9dabd50ff1d --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2024 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 +#include +#include "abckit.h" + +#include "api_scanner.h" + +ApiScanner::ApiScanner(int version, abckit_File *ctxI, + const std::vector &apiList): + ctxI_(ctxI), apiList_(apiList) +{ + impl_ = abckit_GetApiImpl(version); + implI_ = abckit_GetInspectApiImpl(version); + implG_ = abckit_GetGraphApiImpl(version); + dynG_ = abckit_GetIsaApiDynamicImpl(version); + vh_ = VisitHelper(ctxI_, impl_, implI_, implG_, dynG_); +} + +void ApiScanner::CollectApiUsages() +{ + vh_.EnumerateModules([&](abckit_Module *mod) { + SuspectsMap suspects; + GetSuspects(mod, suspects); + if (suspects.empty()) { + return; + } + vh_.EnumerateModuleFunctions(mod, [&](abckit_Method *method) { + CollectUsageInMethod(method, suspects); + }); + }); +} + +bool ApiScanner::GetSuspects(abckit_Module *mod, SuspectsMap &suspects) +{ + vh_.EnumerateModuleImports(mod, [&](abckit_ImportDescriptor *id) { + std::string importName = vh_.GetString(implI_->ImportDescriptorGetName(id)); + auto *importedModule = implI_->ImportDescriptorGetImportedModule(id); + auto source = vh_.GetString(implI_->ModuleGetName(importedModule)); + for (size_t i = 0; i < apiList_.size(); ++i) { + const auto api = apiList_[i]; + // TODO(qiuyu): replace the if-block with the commented code after ModuleGetName is debugged. + if (source.find(api.source) != 0) { + continue; + } + /* + if (source != api.source) { + continue; + } + */ + // TODO(qiuyu): replace the if-block with the commented code after ImportDescriptorGetName is debugged. + if (importName.find(api.objName) == 0) { + suspects.emplace(id, i); + } + /* + if (importName == api.objName) { + suspects.emplace(id, i); + } + */ + } + }); + return !suspects.empty(); +} + +bool ApiScanner::IsLoadApi(abckit_ImportDescriptor *id, size_t apiIndex, abckit_Inst *inst) +{ + // find the following pattern: + // 1. ldExternalModuleVar (import {ApiNamespace} from "./modules/myApi") + // 2. ldObjByName v1, "foo" (api.propName) + // or + // 1. ldExternalModuleVar (import {bar} from "./modules/myApi") + + if (dynG_->IgetOpcode(inst) != abckit_IsaApiDynamicOpcode_ldexternalmodulevar) { + return false; + } + + // TODO(qiuyu): enable the following commented code after IgetImportDescriptor is implemented + /* + if (implG_->IgetImportDescriptor(inst) != id) { + return false; + } + */ + + const auto &prop = apiList_[apiIndex].propName; + if (prop.empty()) { + return true; + } + + bool found = false; + vh_.EnumerateInstUsers(inst, [&](abckit_Inst *user) { + if (!found && dynG_->IgetOpcode(user) == abckit_IsaApiDynamicOpcode_ldobjbyname) { + // TODO(qiuyu): replace the following line with the commented code after IgetString is implemented + std::string str = "foo"; + /* + * auto str = vh_.GetString(implG_->IgetString(user)); + */ + found = str == prop; + } + }); + + return found; +} + +void ApiScanner::CollectUsageInMethod(abckit_Method *method, SuspectsMap &suspects) +{ + // TODO(qiuyu): need to check after MethodGetName is debugged. + auto methodName = vh_.GetString(implI_->MethodGetName(method)); + auto *sourceRaw = implI_->ModuleGetName(implI_->MethodGetModule(method)); + auto source = vh_.GetString(sourceRaw); + UsageInfo usage = { + .source = source, + .funcName = methodName + }; + vh_.EnumerateFunctionInsts(method, [&](abckit_Inst *inst) { + for (const auto &[id, apiIndex] : suspects) { + if (IsLoadApi(id, apiIndex, inst)) { + AddApiUsage(apiIndex, usage); + } + } + }); +} + +static std::string GetQuatatedStr(const std::string str) +{ + const static std::string QUOTATION = "\""; + return QUOTATION + str + QUOTATION; +} + +std::string ApiScanner::ApiUsageMapGetString() const +{ + std::stringstream ss; + const static std::string INDENT_1 = " "; + const static std::string INDENT_2 = INDENT_1 + INDENT_1; + const static std::string INDENT_3 = INDENT_1 + INDENT_2; + const static std::string INDENT_4 = INDENT_1 + INDENT_3; + const static std::string LEFT_BRACKET = "{"; + const static std::string RIGHT_BRACKET = "}"; + const static std::string COLON = ": "; + const static std::string COMMA = ","; + const static std::string APIINFO = "APIInfo"; + const static std::string APIINFO_SOURCE = "source"; + const static std::string APIINFO_OBJNAME = "objName"; + const static std::string APIINFO_PROPNAME = "propName"; + const static std::string USAGES = "Usages"; + const static std::string USAGES_SOURCE = "source"; + const static std::string USAGES_FUNCNAME = "funcName"; + + ss << LEFT_BRACKET << std::endl; + for (const auto &[index, usageInfos] : apiUsages_) { + ss << INDENT_1 << LEFT_BRACKET << std::endl; + + if (usageInfos.empty()) { + continue; + } + const auto &apiInfo = apiList_[index]; + ss << INDENT_2 << APIINFO << COLON << LEFT_BRACKET << std::endl; + ss << INDENT_3 << APIINFO_SOURCE << COLON << GetQuatatedStr(apiInfo.source) << COMMA << std::endl; + ss << INDENT_3 << APIINFO_OBJNAME << COLON << GetQuatatedStr(apiInfo.objName) << COMMA << std::endl; + ss << INDENT_3 << APIINFO_PROPNAME << COLON << GetQuatatedStr(apiInfo.propName) << COMMA << std::endl; + ss << INDENT_2 << RIGHT_BRACKET << COMMA << std::endl; + + ss << INDENT_2 << USAGES << COLON << LEFT_BRACKET << std::endl; + for (const auto &usage : usageInfos) { + ss << INDENT_3 << LEFT_BRACKET << std::endl; + ss << INDENT_4 << USAGES_SOURCE << COLON << GetQuatatedStr(usage.source) << COMMA + << std::endl; + ss << INDENT_4 << USAGES_FUNCNAME << COLON << GetQuatatedStr(usage.funcName) << COMMA << std::endl; + ss << INDENT_3 << RIGHT_BRACKET << COMMA << std::endl; + } + ss << INDENT_2 << RIGHT_BRACKET << std::endl; + + ss << INDENT_1 << RIGHT_BRACKET << COMMA << std::endl; + } + ss << RIGHT_BRACKET << std::endl; + + return ss.str(); +} diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.h b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.h new file mode 100644 index 0000000000000000000000000000000000000000..57b0c3b396ff86697ba0204d3b3ec3ce95c46c1d --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef API_SCANNER_H +#define API_SCANNER_H + +#include +#include +#include + +#include "helpers/visit_helper/visit_helper-inl.h" +#include "include/abckit.h" +#include "include/ir_core.h" +#include "include/metadata.h" +#include "isa/isa_dynamic.h" + +// Suppose that we have a list of privacy APIs. We want to detect all the functions which invoke these APIs. +// +// APP source code example: +// // api_scanner.js +// import {ApiNamespace} from "./modules/apiNamespace"; +// import {bar} from "./modules/toplevelApi"; +// +// function useFoo() { +// ApiNamespace.foo(); +// } +// +// class Person { +// personUseBar() { +// bar(); +// } +// } +// +// Input: list of APIs, example: +// { +// { +// source: "./modules/apiNamespace", +// objName: "ApiNamespace", +// propName: "foo", +// }, +// { +// source: "./modules/toplevelApi", +// objName: "bar", +// propName: "", +// }, +// // ... +// } +// +// Output: list of API usage info, example: +// { +// { +// APIInfo: { +// source: "./modules/apiNamespace", +// objName: "ApiNamespace", +// propName: "foo", +// }, +// Usages: { +// { +// source: "api_scanner", +// funcName: "useFoo", +// }, +// // ... +// } +// }, +// { +// APIInfo: { +// source: "./modules/toplevelApi", +// objName: "bar", +// propName: "", +// }, +// Usages: { +// { +// source: "api_scanner", +// funcName: "useBar", +// }, +// // ... +// } +// }, +// // ... +// } + +struct ApiInfo { + std::string source; + std::string objName; + std::string propName; +}; + +struct UsageInfo { + std::string source; + std::string funcName; +}; + + +typedef std::unordered_map> ApiUsageMap; + +typedef std::unordered_map SuspectsMap; + +class ApiScanner { +public: + ApiScanner(int version, abckit_File *ctxI, + const std::vector &apiList); + + const ApiUsageMap &GetApiUsages() + { + CollectApiUsages(); + return apiUsages_; + } + + std::string ApiUsageMapGetString() const; + +private: + void CollectApiUsages(); + + void CollectUsageInMethod(abckit_Method *method, SuspectsMap &suspects); + + std::string GetString(abckit_String *str) const; + + void AddApiUsage(size_t apiIndex, + const UsageInfo &usage) + { + auto iter = apiUsages_.find(apiIndex); + if (iter == apiUsages_.end()) { + std::vector usages; + usages.emplace_back(usage); + apiUsages_.emplace(apiIndex, usages); + } else { + iter->second.emplace_back(usage); + } + } + + bool GetSuspects(abckit_Module* mod, SuspectsMap &suspects); + bool IsLoadApi(abckit_ImportDescriptor *id, size_t apiIndex, abckit_Inst *inst); + +private: + const abckit_Api *impl_ = nullptr; + const abckit_InspectApi *implI_ = nullptr; + const abckit_GraphApi *implG_ = nullptr; + const abckit_IsaApiDynamic *dynG_ = nullptr; + abckit_File *ctxI_ = nullptr; + VisitHelper vh_; + const std::vector &apiList_; + ApiUsageMap apiUsages_; +}; + +#endif /* API_SCANNER_H */ diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.js b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.js new file mode 100644 index 0000000000000000000000000000000000000000..2aa5c868ca8fbea1d6fd0faaaf2ec67bed2e7c72 --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner.js @@ -0,0 +1,57 @@ +import {ApiNamespace} from "./modules/apiNamespace"; +import {bar} from "./modules/toplevelApi"; +import {geolocation} from "@ohos.geolocation"; + +class Person { + personUseFoo() { + ApiNamespace.foo(); + } + /* + personUseBar() { + bar(); + } + personUseClass() { + return new ApiNamespace.MyClass(); + } + personUseAll() { + ApiNamespace.foo(); + bar(); + return new ApiNamespace.MyClass(); + } + personUseLocation() { + geolocation.getCurrentLocation(); + } + personUseOther() { + geolocation.getLastLocation(); + } + */ + personNoUse() { + } +} + +function useFoo() { + ApiNamespace.foo(); +} + +/* +function useBar() { + bar(); +} +function useClass() { + return new ApiNamespace.MyClass(); +} + +function useLocation() { + geolocation.getCurrentLocation(); +} + +function useAll() { + ApiNamespace.foo(); + bar(); + geolocation.getCurrentLocation(); + return new ApiNamespace.MyClass(); +} +*/ + +function noUse() { +} diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner_test.cpp b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5c6c83db0ebfa818a2dcd43fd59990a54b6aa247 --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/api_scanner_test.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 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 + +#include "api_scanner.h" + +namespace libabckit { +namespace test { + +class LibAbcKitTest : public ::testing::Test {}; + +// Test: test-kind=scenario, abc-kind=JS, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestApiScannerDynamic) +{ + int version = 1; + auto *impl = abckit_GetApiImpl(version); + auto filePath = ABCKIT_ABC_DIR "scenarios/api_scanner/dynamic/api_scanner.abc"; + // TODO(qiuyu): should use OpenAbc when it is ready + abckit_File *ctxI = impl->OpenAbc(filePath); + // TODO(qiuyu): complement more api info when OpenAbc is ready (current MethodGetName does not return correct name for top-level functions) + std::vector apiList = { + { + .source = "modules/apiNamespace", + .objName = "ApiNamespace", + .propName = "foo" + }, + /* + { + .source = "modules/toplevelApi", + .objName = "bar", + .propName = "" + } + */ + }; + ApiScanner a(version, ctxI, apiList); + + const auto &usages = a.GetApiUsages(); + EXPECT_FALSE(usages.empty()); + + auto usagesStr = a.ApiUsageMapGetString(); + //TODO(qiuyu): complement expected output after other todos are done + std::cout << "====================================\n"; + std::cout << usagesStr; + + impl->DestroyInspectContext(ctxI); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/modules/apiNamespace.js b/libabckit/tests/scenarios/api_scanner/dynamic/modules/apiNamespace.js new file mode 100644 index 0000000000000000000000000000000000000000..301af660d8930d846573839b26bcbaad6aed72e5 --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/modules/apiNamespace.js @@ -0,0 +1,6 @@ +export let ApiNamespace = { + foo: () => {}, + MyClass: class MyClass {} +}; + +export let bar = () => {}; diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/modules/src2.js b/libabckit/tests/scenarios/api_scanner/dynamic/modules/src2.js new file mode 100644 index 0000000000000000000000000000000000000000..cb5aa7aeeeb0e27a1998e7ee487b92aa2782a211 --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/modules/src2.js @@ -0,0 +1,39 @@ +import {ApiNamespace} from "./apiNamespace"; + +class Animal { + animalUseFoo() { + ApiNamespace.foo(); + } + animalUseBar() { + ApiNamespace.bar(); + } + animalUseClass() { + return new ApiNamespace.MyClass(); + } + animalUseAll() { + ApiNamespace.foo(); + ApiNamespace.bar(); + return new ApiNamespace.MyClass(); + } +} + +function src2UseFoo() { + ApiNamespace.foo(); +} + +function src2UseBar() { + ApiNamespace.bar(); +} + +function src2UseClass() { + return new ApiNamespace.MyClass(); +} + +function src2UseAll() { + ApiNamespace.foo(); + ApiNamespace.bar(); + return new ApiNamespace.MyClass(); +} + +function src2NoUse() { +} diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/modules/src3.js b/libabckit/tests/scenarios/api_scanner/dynamic/modules/src3.js new file mode 100644 index 0000000000000000000000000000000000000000..7520111ed0f7900b4a0e17652add679b924a1cce --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/modules/src3.js @@ -0,0 +1,18 @@ +import {geolocation} from "@ohos.geolocation"; + +export function src3UseLocation() { + geolocation.getCurrentLocation(); +} + +function src3UseOther() { + geolocation.getLastLocation(); +} + +export class Cat { + catUseLocation() { + geolocation.getCurrentLocation(); + } + catUseUseOther() { + geolocation.getLastLocation(); + } +} diff --git a/libabckit/tests/scenarios/api_scanner/dynamic/modules/toplevelApi.js b/libabckit/tests/scenarios/api_scanner/dynamic/modules/toplevelApi.js new file mode 100644 index 0000000000000000000000000000000000000000..ebcfd22baf81119a45437363b79ca1652e28eb6d --- /dev/null +++ b/libabckit/tests/scenarios/api_scanner/dynamic/modules/toplevelApi.js @@ -0,0 +1 @@ +export let bar = () => {}; diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.cpp b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..542f610154c94c3281020a3ad67a442f66fe4b9a --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.cpp @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2024 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 +#include "abckit.h" + +#include "branch_eliminator.h" + +BranchEliminator::BranchEliminator(int version, abckit_File *ctxI, + const std::vector &constants): + ctxI_(ctxI), constants_(constants) +{ + impl_ = abckit_GetApiImpl(version); + implI_ = abckit_GetInspectApiImpl(version); + implG_ = abckit_GetGraphApiImpl(version); + dynG_ = abckit_GetIsaApiDynamicImpl(version); + implM_ = abckit_GetModifyApiImpl(version); + vh_ = VisitHelper(ctxI_, impl_, implI_, implG_, dynG_); +} + +void BranchEliminator::Run() { + if (constants_.empty()) { + return; + } + vh_.EnumerateModules([&](abckit_Module *mod) { + SuspectsType suspects; + if (!GetSuspects(mod, suspects)) { + return; + } + vh_.EnumerateModuleFunctions(mod, [&](abckit_Method *func) { + EliminateBranchWithSuspect(func, suspects); + }); + }); +} + +bool BranchEliminator::GetSuspects(abckit_Module *mod, SuspectsType &suspects) +{ + vh_.EnumerateModuleImports(mod, [&](abckit_ImportDescriptor *id) { + auto importName = vh_.GetString(implI_->ImportDescriptorGetName(id)); + auto *importedModule = implI_->ImportDescriptorGetImportedModule(id); + auto path = vh_.GetString(implI_->ModuleGetName(importedModule)); + for (ConstantInfoIndexType i = 0; i < constants_.size(); ++i) { + const auto &constInfo = constants_[i]; + if (constInfo.path != path || constInfo.objName != importName) { + continue; + } + auto iter = suspects.find(id); + if (iter == suspects.end()) { + std::vector vec = {i}; + suspects.emplace(id, vec); + } else { + iter->second.push_back(i); + } + } + }); + return !suspects.empty(); +} + +bool BranchEliminator::IsEliminatableIfInst(abckit_Inst *inst) +{ + if (dynG_->IgetOpcode(inst) != abckit_IsaApiDynamicOpcode_if || implG_->IgetInputCount(inst) != 2) { + return false; + } + auto *ldBool = implG_->IgetInput(inst, 0); + auto op = dynG_->IgetOpcode(ldBool); + if (op != abckit_IsaApiDynamicOpcode_ldtrue && op != abckit_IsaApiDynamicOpcode_ldfalse) { + return false; + } + auto *constInst = implG_->IgetInput(inst, 1); + if (dynG_->IgetOpcode(constInst) != abckit_IsaApiDynamicOpcode_Constant) { + return false; + } + return true; +} + +void BranchEliminator::EliminateBranchWithSuspect(abckit_Method *method, const SuspectsType &suspects) +{ + vh_.TransformMethod(method, [&](abckit_ModifyContext *ctxM, abckit_Method *method) { + auto oldCode = implI_->MethodGetCode(method); + abckit_Graph *ctxG = impl_->codeToGraph(ctxI_, oldCode); + bool hasGraphChanged = ReplaceModuleVarByConstant(ctxG, suspects); + + do { + hasGraphChanged |= LoweringConstants(ctxG); + + auto *ifInst = vh_.GraphInstsFindIf(ctxG, [&](abckit_Inst *inst) { + return IsEliminatableIfInst(inst); + }); + + if (ifInst == nullptr) { + break; + } + + DeleteUnreachableBranch(ifInst); + + hasGraphChanged = true; + + } while (true); // until no branch can be eliminated, i.e., there is no such If inst + + if (hasGraphChanged) { + abckit_Code *newCode = impl_->graphToCode(ctxG); + implM_->MethodSetCode(ctxM, method, newCode); + } else { + impl_->DestroyGraphContext(ctxG); + } + }); +} + +bool BranchEliminator::ReplaceModuleVarByConstant(abckit_Graph *ctxG, const SuspectsType &suspects) +{ + // find the following patter: + // ... + // 1. ldExternalModuleVar (importdescriptor) + // 2. ldObjByName v1, "isDebug" + // + // and replace it by + // 3. ldtrue + + std::unordered_map moduleVars; + vh_.EnumerateGraphInsts(ctxG, [&](abckit_Inst *inst) { + auto constInfoIndex = GetConstantInfoIndex(inst, suspects); + if (constInfoIndex != INVALID_INDEX) { + moduleVars.emplace(inst, constInfoIndex); + } + }); + for (auto &[ldObjByName, constInfoIndex] : moduleVars) { + assert(ldObjByName != nullptr); + assert(constInfoIndex != INVALID_INDEX); + ReplaceLdObjByNameWithBoolean(ldObjByName, constInfoIndex); + } + + return !moduleVars.empty(); +} + +ConstantInfoIndexType BranchEliminator::GetConstantInfoIndex(abckit_Inst *ldObjByName, const SuspectsType &suspects) const +{ + if (dynG_->IgetOpcode(ldObjByName) != abckit_IsaApiDynamicOpcode_ldobjbyname) { + return INVALID_INDEX; + } + auto *ldExternalModuleVar = implG_->IgetInput(ldObjByName, 0); + if (dynG_->IgetOpcode(ldExternalModuleVar) != abckit_IsaApiDynamicOpcode_ldexternalmodulevar) { + return INVALID_INDEX; + } +// TODO(qiuyu): replace the following code by the commented code after IgetImportDescriptor is implemented. + return 0; +/* + auto *id = implG_->IgetImportDescriptor(ldExternalModuleVar); + auto iter = suspects.find(id); + if (iter == suspects.end()) { + return INVALID_INDEX; + } + const auto &constInfoIndexes = iter->second; + const auto propName = vh_.GetString(implG_->IgetString(ldObjByName)); // "isDebug" + for (size_t i = 0; i < constInfoIndexes.size(); ++i) { + const auto index = constInfoIndexes[i]; + assert(index >= 0); + assert(index < constants_.size()); + if (constants_[index].fieldName == propName) { + return index; + } + } + + return INVALID_INDEX; +*/ +} + +void BranchEliminator::ReplaceLdObjByNameWithBoolean(abckit_Inst *ldObjByName, ConstantInfoIndexType constInfoIndex) +{ + bool fieldVal = constants_[constInfoIndex].fieldValue; + auto *bb = implG_->IgetBasicBlock(ldObjByName); + auto *ctxG = implG_->BBgetGraph(bb); + auto *value = fieldVal ? dynG_->IcreateLdtrue(ctxG) : dynG_->IcreateLdfalse(ctxG); + implG_->IinsertAfter(value, ldObjByName); + ReplaceUsers(ldObjByName, value); + + auto *ldExternalModuleVar = implG_->IgetInput(ldObjByName, 0); + bool isRemovable = true; + std::vector checks; + vh_.EnumerateInstUsers(ldExternalModuleVar, [&](abckit_Inst *inst) { + if (inst != ldObjByName) { + if (dynG_->IgetOpcode(inst) != abckit_IsaApiDynamicOpcode_throw_undefinedifholewithname) { + isRemovable = false; + } else { + checks.emplace_back(inst); + } + } + }); + + if (isRemovable) { + for (auto *check : checks) { + implG_->Iremove(check); + } + implG_->Iremove(ldExternalModuleVar); + } + implG_->Iremove(ldObjByName); +} + +void BranchEliminator::ReplaceUsers(abckit_Inst *oldInst, abckit_Inst *newInst) +{ + vh_.EnumerateInstUsers(oldInst, [&](abckit_Inst *user) { + auto inputCount = implG_->IgetInputCount(user); + for (uint64_t i = 0; i < inputCount; ++i) { + if (implG_->IgetInput(user, i) == oldInst) { + implG_->IsetInput(user, newInst, i); + } + } + }); +} + +bool BranchEliminator::GetInstAsBool(abckit_Inst *inst) const +{ + switch (dynG_->IgetOpcode(inst)) { + case abckit_IsaApiDynamicOpcode_Constant: + return implG_->IgetConstantValueI64(inst) != 0; + case abckit_IsaApiDynamicOpcode_ldtrue: + case abckit_IsaApiDynamicOpcode_istrue: + case abckit_IsaApiDynamicOpcode_callruntime_istrue: + return true; + case abckit_IsaApiDynamicOpcode_ldfalse: + case abckit_IsaApiDynamicOpcode_isfalse: + case abckit_IsaApiDynamicOpcode_callruntime_isfalse: + return false; + default: + assert(false); // UNREACHABLE + } + return false; +} + +void BranchEliminator::DeleteUnreachableBranch(abckit_Inst *ifInst) const +{ + // compute result of If compare + auto *ldBool = implG_->IgetInput(ifInst, 0); // 0: ldtrue or ldfalse + auto *constInst = implG_->IgetInput(ifInst, 1); // 1: ConstantInst + auto valLeft = GetInstAsBool(ldBool); + auto valRight = GetInstAsBool(constInst); + // TODO(qiuyu): replace RHS with "implG_->IgetConditionCode(ifInst);" after IgetConditionCode is ready + auto conditionCode = abckit_IsaApiDynamicConditionCode_CC_NE; + + assert(conditionCode == abckit_IsaApiDynamicConditionCode_CC_EQ || conditionCode == abckit_IsaApiDynamicConditionCode_CC_NE); + bool result = (conditionCode == abckit_IsaApiDynamicConditionCode_CC_EQ && valLeft == valRight) || + (conditionCode == abckit_IsaApiDynamicConditionCode_CC_NE && valLeft != valRight); + + auto *bb = implG_->IgetBasicBlock(ifInst); + // if (true) ==> delete false branch + abckit_BasicBlock *deleteBranch = result ? implG_->BBgetFalseBranch(bb) : implG_->BBgetTrueBranch(bb); + implG_->Iremove(ifInst); + + implG_->BBdisconnectBlocks(bb, deleteBranch); + implG_->GrunPassRemoveUnreachableBlocks(implG_->BBgetGraph(bb)); +} + +bool BranchEliminator::LoweringConstants(abckit_Graph *ctxG) +{ + bool hasGraphChanged = false; + do { + std::vector users; + abckit_Inst *ldBool = vh_.GraphInstsFindIf(ctxG, [&](abckit_Inst *inst) { + auto op = dynG_->IgetOpcode(inst); + if (op != abckit_IsaApiDynamicOpcode_ldtrue && op != abckit_IsaApiDynamicOpcode_ldfalse) { + return false; + } + vh_.EnumerateInstUsers(inst, [&](abckit_Inst *user) { + auto userOp = dynG_->IgetOpcode(user); + if (userOp == abckit_IsaApiDynamicOpcode_istrue || userOp == abckit_IsaApiDynamicOpcode_isfalse || + userOp == abckit_IsaApiDynamicOpcode_callruntime_istrue || userOp == abckit_IsaApiDynamicOpcode_callruntime_isfalse) { + users.emplace_back(user); + } + }); + return !users.empty(); + }); + + if (ldBool == nullptr) { + break; + } + + auto ldBoolVal = GetInstAsBool(ldBool); + for (auto *isBool : users) { + auto isBoolVal = GetInstAsBool(isBool); + auto *ldBool = ldBoolVal == isBoolVal ? dynG_->IcreateLdtrue(ctxG) : dynG_->IcreateLdfalse(ctxG); + implG_->IinsertAfter(ldBool, isBool); + ReplaceUsers(isBool, ldBool); + implG_->Iremove(isBool); + } + + hasGraphChanged = true; + + } while (true); + + hasGraphChanged |= RemoveUnusedInsts(ctxG); + + return hasGraphChanged; +} + +bool BranchEliminator::RemoveUnusedInsts(abckit_Graph *ctxG) +{ + bool hasGraphChanged = false; + do { + std::vector removableInsts; + vh_.EnumerateGraphInsts(ctxG, [&](abckit_Inst *inst) { + if (implG_->IgetUserCount(inst) == 0 && CanBeRemoved(inst)) { + removableInsts.emplace_back(inst); + } + }); + + if (removableInsts.empty()) { + break; + } + + assert(!removableInsts.empty()); + for (auto *inst : removableInsts) { + implG_->Iremove(inst); + } + + hasGraphChanged = true; + + } while (true); + + return hasGraphChanged; +} + +bool BranchEliminator::CanBeRemoved(abckit_Inst *inst) +{ + switch (dynG_->IgetOpcode(inst)) { + case abckit_IsaApiDynamicOpcode_Constant: + case abckit_IsaApiDynamicOpcode_ldtrue: + case abckit_IsaApiDynamicOpcode_istrue: + case abckit_IsaApiDynamicOpcode_ldfalse: + case abckit_IsaApiDynamicOpcode_isfalse: + return true; + default: + return false; + } +} diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.h b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.h new file mode 100644 index 0000000000000000000000000000000000000000..5401fe241a2d61e0d014d98662f0abe157545930 --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef BRANCH_ELIMINATOR_H +#define BRANCH_ELIMINATOR_H + +#include +#include +#include +#include + +#include "helpers/visit_helper/visit_helper-inl.h" +#include "include/abckit.h" +#include "include/ir_core.h" +#include "include/metadata.h" +#include "isa/isa_dynamic.h" + +struct ConstantInfo { + std::string path; + std::string objName; // Config + std::string fieldName; // isDebug + bool fieldValue; // field is constant true or false +}; + +typedef uint32_t ConstantInfoIndexType; + +typedef std::unordered_map> SuspectsType; + +constexpr static ConstantInfoIndexType INVALID_INDEX = std::numeric_limits::max(); + +class BranchEliminator { +public: + BranchEliminator(int version, abckit_File *ctxI, const std::vector &constants); + + void Run(); + +private: + bool GetInstAsBool(abckit_Inst *inst) const; + bool GetSuspects(abckit_Module *mod, SuspectsType &suspects); + void EliminateBranchWithSuspect(abckit_Method *method, const SuspectsType &suspects); + ConstantInfoIndexType GetConstantInfoIndex(abckit_Inst *inst, const SuspectsType &suspects) const; + void ReplaceUsers(abckit_Inst *oldInst, abckit_Inst *newInst); + bool ReplaceModuleVarByConstant(abckit_Graph *ctxG, const SuspectsType &suspects); + void ReplaceLdObjByNameWithBoolean(abckit_Inst *ldObjByName, ConstantInfoIndexType constInfoIndex); + void DeleteUnreachableBranch(abckit_Inst *ifInst) const; + bool LoweringConstants(abckit_Graph *graph); + bool RemoveUnusedInsts(abckit_Graph *ctxG); + bool CanBeRemoved(abckit_Inst *inst); + bool IsEliminatableIfInst(abckit_Inst *ifInst); + +private: + const abckit_Api *impl_ = nullptr; + const abckit_InspectApi *implI_ = nullptr; + const abckit_GraphApi *implG_ = nullptr; + const abckit_IsaApiDynamic *dynG_ = nullptr; + const abckit_ModifyApi *implM_ = nullptr; + abckit_File *ctxI_ = nullptr; + VisitHelper vh_; + + const std::vector &constants_; +}; + +#endif /* BRANCH_ELIMINATOR_H */ diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.js b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.js new file mode 100644 index 0000000000000000000000000000000000000000..d44544ad8a5e6522919ed990081ea42efaa48e22 --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator.js @@ -0,0 +1,46 @@ +import {myfoo} from "./modules/myfoo"; +import {mybar} from "./modules/mybar"; +import {Config} from "./modules/config"; +export function foo() { + print("Config.isDebug = " + Config.isDebug); + if (Config.isDebug) { + print("foo: Config.isDebug is true"); + } else { + print("foo: Config.isDebug is false"); + } +} + +export class bar { + static test1() { + if (Config.isDebug) { + print("bar.test1: Config.isDebug is true"); + } else { + print("bar.test1: Config.isDebug is false"); + } + } + + test2() { + if (!Config.isDebug) { + print("bar.test2: Config.isDebug is false"); + } else { + print("bar.test2: Config.isDebug is true"); + } + } +} + +function nonCrossFile() { + foo(); + bar.test1(); + let b = new bar(); + b.test2(); +} +// TODO(qiuyu) call this function when we can enumerate functions from other modules. +// Currently we can only enumerate functions defined in this file. +function crossFile() { + myfoo(); + mybar.test1(); // there is bug for static method, should have been resolved in mainline; + let m = new mybar(); + m.test2(); +} + +nonCrossFile(); diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator_test.cpp b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5600792bcd7dc29a810fbd53cb7527347408013c --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/branch_eliminator_test.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2024 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 + +#include + +#include "abckit.h" +#include "isa/isa_dynamic.h" +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include "branch_eliminator.h" + +namespace libabckit { +namespace test { + +static constexpr int version = 1; +static const abckit_Api *impl = abckit_GetApiImpl(version); +static const abckit_InspectApi *implI = abckit_GetInspectApiImpl(version); +static const abckit_GraphApi *implG = abckit_GetGraphApiImpl(version); +static const abckit_IsaApiDynamic *dynG = abckit_GetIsaApiDynamicImpl(version); + +static bool MethodHasBranch(const std::string &moduleName, const std::string &methodName, abckit_File *ctxI) +{ + EXPECT_NE(ctxI, nullptr); + EXPECT_NE(impl, nullptr); + EXPECT_NE(implI, nullptr); + EXPECT_NE(implG, nullptr); + EXPECT_NE(dynG, nullptr); + VisitHelper vh = VisitHelper(ctxI, impl, implI, implG, dynG); + bool found = false; + bool ret = false; + vh.EnumerateModules([&](abckit_Module *mod) { + // TODO(qiuyu): replace if-condition by the commented code after ModuleGetName is debugged + if (vh.GetString(implI->ModuleGetName(mod)).find(moduleName) != 0) { + // if (vh.GetString(implI->ModuleGetName(mod)) != moduleName) { + return; + } + vh.EnumerateModuleFunctions(mod, [&](abckit_Method *func) { + // TODO(qiuyu): replace if-condition by the commented code after MethodGetName is debugged + if (found || vh.GetString(implI->MethodGetName(func)).find(methodName) != 0) { + // if (!found && vh.GetString(implI->MethodGetName(func)) != methodName) { + return; + } + found = true; + auto *code = implI->MethodGetCode(func); + auto *ctxG = impl->codeToGraph(ctxI, code); + auto *ifInst = vh.GraphInstsFindIf(ctxG, [&](abckit_Inst *inst) { + return dynG->IgetOpcode(inst) == abckit_IsaApiDynamicOpcode_if; + }); + ret = ifInst != nullptr; + impl->DestroyGraphContext(ctxG); + }); + }); + + EXPECT_TRUE(found); + return ret; +} + +class LibAbcKitTest : public ::testing::Test { }; + +static const std::string dir = std::string(ABCKIT_ABC_DIR "scenarios/branch_eliminator/dynamic/"); +static const std::string input = dir + "branch_eliminator.abc"; +static constexpr bool configIsDebugOriginValue = false; + +/* + * @param value: the value of isDebug when we handle, it can be different from configIsDebugOriginValue + */ +static std::string GetExpectOutput(bool value) +{ + std::stringstream expectOutput; + expectOutput << std::boolalpha; + expectOutput << "Config.isDebug = " << value << std::endl; + expectOutput << "foo: Config.isDebug is " << value << std::endl; + expectOutput << "bar.test1: Config.isDebug is " << value << std::endl; + expectOutput << "bar.test2: Config.isDebug is " << value << std::endl; + return expectOutput.str(); +} + +// Test: test-kind=scenario, abc-kind=JS, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestBranchEliminatorDynamic1) +{ + auto *impl = abckit_GetApiImpl(version); + abckit_File *ctxI = nullptr; + // TODO(qiuyu): shoule use OpenAbc when it is ready + helpers::assertOpenAbc(input.c_str(), &ctxI); + ASSERT_NE(ctxI, nullptr); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test1", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test2", ctxI)); + const auto originPath = dir + "branch_eliminator_origin.abc"; + impl->WriteAbc(ctxI, originPath.c_str()); + const auto originOutput = helpers::ExecuteDynamicAbc(originPath, "branch_eliminator"); + + auto expectOutput = GetExpectOutput(configIsDebugOriginValue); + ASSERT_EQ(originOutput, expectOutput); + + ctxI = nullptr; + helpers::assertOpenAbc(input.c_str(), &ctxI); + ASSERT_NE(ctxI, nullptr); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test1", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test2", ctxI)); + + const std::vector infos = { + { + .path = "modules/config", + .objName = "Config", + .fieldName = "isDebug", + .fieldValue = configIsDebugOriginValue // delete true branch + }, + { + .path = "/config", + .objName = "Config", + .fieldName = "isDebug", + .fieldValue = configIsDebugOriginValue // delete true branch + } + }; + BranchEliminator b(version, ctxI, infos); + b.Run(); + + ASSERT_FALSE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_FALSE(MethodHasBranch("branch_eliminator", "test1", ctxI)); + ASSERT_FALSE(MethodHasBranch("branch_eliminator", "test2", ctxI)); + const auto modifiedPath = dir + "branch_eliminator_modified1.abc"; + impl->WriteAbc(ctxI, modifiedPath.c_str()); + const auto output = helpers::ExecuteDynamicAbc(modifiedPath, "branch_eliminator"); + ASSERT_EQ(output, expectOutput); +} + +// Test: test-kind=scenario, abc-kind=JS, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestBranchEliminatorDynamic2) +{ + auto *impl = abckit_GetApiImpl(version); + abckit_File *ctxI = nullptr; + // TODO(qiuyu): shoule use OpenAbc when it is ready + helpers::assertOpenAbc(input.c_str(), &ctxI); + ASSERT_NE(ctxI, nullptr); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test1", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test2", ctxI)); + + const auto originPath = dir + "branch_eliminator_origin.abc"; + impl->WriteAbc(ctxI, originPath.c_str()); + const auto originOutput = helpers::ExecuteDynamicAbc(originPath, "branch_eliminator"); + auto expectOutput = GetExpectOutput(configIsDebugOriginValue); + ASSERT_EQ(originOutput, expectOutput); + + ctxI = nullptr; + helpers::assertOpenAbc(input.c_str(), &ctxI); + ASSERT_NE(ctxI, nullptr); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test1", ctxI)); + ASSERT_TRUE(MethodHasBranch("branch_eliminator", "test2", ctxI)); + const std::vector infos = { + { + .path = "modules/config", + .objName = "Config", + .fieldName = "isDebug", + .fieldValue = !configIsDebugOriginValue // delete false branch + }, + { + .path = "./config", + .objName = "Config", + .fieldName = "isDebug", + .fieldValue = !configIsDebugOriginValue // delete false branch + } + }; + BranchEliminator b(version, ctxI, infos); + b.Run(); + ASSERT_FALSE(MethodHasBranch("branch_eliminator", "foo", ctxI)); + ASSERT_FALSE(MethodHasBranch("branch_eliminator", "test1", ctxI)); + ASSERT_FALSE(MethodHasBranch("branch_eliminator", "test2", ctxI)); + + const auto modifiedPath = dir + "branch_eliminator_modified2.abc"; + impl->WriteAbc(ctxI, modifiedPath.c_str()); + const auto output = helpers::ExecuteDynamicAbc(modifiedPath, "branch_eliminator"); + auto expectOutput2 = GetExpectOutput(!configIsDebugOriginValue); + ASSERT_EQ(output, expectOutput2); + ASSERT_NE(expectOutput2, expectOutput); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/config.js b/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/config.js new file mode 100644 index 0000000000000000000000000000000000000000..ab06319dcc599e7fd8ddfb6d2494f2e8fc25b87b --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/config.js @@ -0,0 +1,3 @@ +export let Config = { + isDebug: false +}; diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/mybar.js b/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/mybar.js new file mode 100644 index 0000000000000000000000000000000000000000..c3bd4716bdb8669bf0a6b56f5f04f898efc61f9a --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/mybar.js @@ -0,0 +1,19 @@ +import {Config} from "./config"; + +export class mybar { + static test1() { + if (Config.isDebug) { + print("bar.test1: Config.isDebug is true"); + } else { + print("bar.test1: Config.isDebug is false"); + } + } + + test2() { + if (!Config.isDebug) { + print("bar.test2: Config.isDebug is false"); + } else { + print("bar.test2: Config.isDebug is true"); + } + } +} diff --git a/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/myfoo.js b/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/myfoo.js new file mode 100644 index 0000000000000000000000000000000000000000..533635d1e8857229483f5079f7f31c6351ad693f --- /dev/null +++ b/libabckit/tests/scenarios/branch_eliminator/dynamic/modules/myfoo.js @@ -0,0 +1,10 @@ +import {Config} from "./config"; + +export function myfoo() { + print("Config.isDebug = " + Config.isDebug); + if (Config.isDebug) { + print("foo: Config.isDebug is true"); + } else { + print("foo: Config.isDebug is false"); + } +} diff --git a/libabckit/tests/scenarios/parameter_check/parameter_check_static.cpp b/libabckit/tests/scenarios/parameter_check/parameter_check_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca66e1cc4fa1ceb287f7e4595e93259305d100c5 --- /dev/null +++ b/libabckit/tests/scenarios/parameter_check/parameter_check_static.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "isa/isa_static.h" +#include "metadata.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +void TransformIR(abckit_Graph *ctxG) +{ + abckit_BasicBlock *startBB = implG->GgetStartBasicBlock(ctxG); + std::vector succBBs = helpers::BBgetSuccBlocks(startBB); + abckit_BasicBlock *endBB = implG->GgetEndBasicBlock(ctxG); + + implG->BBdisconnectBlocks(startBB, succBBs[0]); + + abckit_Inst *param0 = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_Parameter); + ASSERT_NE(param0, nullptr); + abckit_Inst *param1 = helpers::FindFirstInst(ctxG, abckit_IsaApiDynamicOpcode_Parameter, [counter = 0](abckit_Inst* i) mutable {return counter++ > 0;}); + ASSERT_NE(param1, nullptr); + + abckit_BasicBlock *ifBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(startBB, ifBB, 0); + abckit_Inst *len = statG->IcreateLenArray(ctxG, param0); + implG->BBaddInstBack(ifBB, len); + abckit_Inst *ifInst = statG->IcreateIf(ctxG, len, param1, abckit_IsaApiStaticConditionCode_CC_GT); + + implG->BBaddInstBack(ifBB, ifInst); + + implG->BBconnectBlocks(ifBB, succBBs[0], 0); + + abckit_BasicBlock *falseBB = implG->BBcreateEmpty(ctxG); + implG->BBconnectBlocks(ifBB, falseBB, 1); + auto* constm1 = implG->GcreateConstantI32(ctxG, -1); + + implG->BBconnectBlocks(falseBB, endBB, 0); + + abckit_Inst *ret = statG->IcreateReturn(ctxG, constm1); + + implG->BBaddInstBack(falseBB, ret); +} + +class LibAbcKitTest : public ::testing::Test {}; + +// Test: test-kind=scenario, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestStaticParameterCheck) +{ + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "scenarios/parameter_check/parameter_check_static.abc", "parameter_check_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, "\"buisiness logic...\"\n" + "1\n" + "\"buisiness logic...\"\n" + "2\n" + "\"buisiness logic...\"\n" + "3\n")); + // TODO: Add method search + helpers::TransformMethod( + ABCKIT_ABC_DIR "scenarios/parameter_check/parameter_check_static.abc", + ABCKIT_ABC_DIR "scenarios/parameter_check/parameter_check_static_modified.abc", + "handle", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + TransformIR(ctxG); + }, + [](abckit_Graph *ctxG) {} + ); + + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "scenarios/parameter_check/parameter_check_static_modified.abc", "parameter_check_static/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, + "\"buisiness logic...\"\n" + "1\n" + "-1\n" + "-1\n")); +} + +} +} diff --git a/libabckit/tests/scenarios/parameter_check/parameter_check_static.ets b/libabckit/tests/scenarios/parameter_check/parameter_check_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..20644c5cb841ea367f3ff1c8994da988bf6ecbf1 --- /dev/null +++ b/libabckit/tests/scenarios/parameter_check/parameter_check_static.ets @@ -0,0 +1,14 @@ +class MyClass { + handle(arr: string[], idx: int): int { + console.log("buisiness logic...") + arr[0] = "b" + return idx + } +} + +function main() { + let c = new MyClass(); + console.log(c.handle(["a", "a"], 1)); + console.log(c.handle(["a", "a"], 2)); + console.log(c.handle(["a", "a"], 3)); +} \ No newline at end of file diff --git a/libabckit/tests/scenarios/router_map_generator/router_map_generator.cpp b/libabckit/tests/scenarios/router_map_generator/router_map_generator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..73d7294e2011769176407219a795f85d83a2b472 --- /dev/null +++ b/libabckit/tests/scenarios/router_map_generator/router_map_generator.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2024 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 +#include "abckit.h" + +#include "router_map_generator.h" + +RouterMapGenerator::RouterMapGenerator(int version, abckit_File *ctxI): + ctxI_(ctxI) +{ + impl_ = abckit_GetApiImpl(version); + implI_ = abckit_GetInspectApiImpl(version); + implG_ = abckit_GetGraphApiImpl(version); + dynG_ = abckit_GetIsaApiDynamicImpl(version); + implM_ = abckit_GetModifyApiImpl(version); + vh_ = VisitHelper(ctxI_, impl_, implI_, implG_, dynG_); +} + +void RouterMapGenerator::Run() +{ + CollectAnnoInfoInClasses(); + GenerateRouterMap(); +} + +void RouterMapGenerator::CollectAnnoInfoInClasses() +{ + vh_.EnumerateModules([&](abckit_Module *mod) { + auto moduleName = vh_.GetString(implI_->ModuleGetName(mod)); + if (ROUTER_MAP_FILE_MODULE_NAME == moduleName) { + routerMapModule_ = mod; + } + vh_.EnumerateModuleClasses(mod, [&](abckit_Class *klass) { + vh_.EnumerateClassAnnotations(klass, [&](abckit_Annotation *anno) { + auto *annoClass = implI_->AnnotationGetInterface(anno); + auto annoName = vh_.GetString(implI_->AnnotationInterfaceGetName(annoClass)); + if (ANNOTATION_NAME == annoName) { + CollectAnnoInfoInAnnotation(klass, anno, mod); + } + }); + }); + }); +} + +void RouterMapGenerator::CollectAnnoInfoInAnnotation(abckit_Class *klass, abckit_Annotation *anno, abckit_Module *mod) +{ + AnnoInfo info { + .exportModule = mod + }; + vh_.EnumerateAnnotationElements(anno, [&](abckit_AnnotationElement *ele) { + auto eleName = vh_.GetString(implI_->AnnotationElementGetName(ele)); + assert(ANNO_FIELD_SCHEMA_NAME == eleName || ANNO_FIELD_PATH_NAME == eleName); + auto *val = implI_->AnnotationElementGetValue(ele); + auto varStr = vh_.GetString(implI_->ValueGetString(ctxI_, val)); + if (ANNO_FIELD_SCHEMA_NAME == eleName) { + info.schema = varStr; + } else { + info.path = varStr; + } + }); + info.exportName = GetExportNameOfClass(klass); + annoInfo_.emplace_back(info); +} + +std::string RouterMapGenerator::GetExportNameOfClass(abckit_Class *klass) +{ + // NB: only works for top-level exported classes, not work for exported classes in namespace + auto className = vh_.GetString(implI_->ClassGetName(klass)); + auto *mod = implI_->ClassGetModule(klass); + std::string ret; + vh_.EnumerateModuleExports(mod, [&](abckit_ExportDescriptor *ed) { + if (!ret.empty()) { + return; + } + auto name = vh_.GetString(implI_->ExportDescriptorGetName(ed)); + if (name == className) { + ret = vh_.GetString(implI_->ExportDescriptorGetAlias(ed)); + } + }); + + assert(!ret.empty()); + return ret; +} + +void RouterMapGenerator::GenerateRouterMap() +{ + assert(routerMapModule_ != nullptr); + vh_.EnumerateModuleTopLevelFunctions(routerMapModule_, [&](abckit_Method *m) { + auto name = vh_.GetString(implI_->MethodGetName(m)); + if (FUNC_MAIN_0 == name) { + AddImportDescriptor(); + InsertCode(m); + } + }); +} + +void RouterMapGenerator::AddImportDescriptor() +{ + for (auto &info : annoInfo_) { + auto *namePtr = info.exportName.c_str(); + abckit_ImportFromDynamicModuleCreateParams param = { + .name = namePtr, + .alias = namePtr, + .module = info.exportModule + }; + info.importDesc = implM_->ModuleAddImportFromDynamicModule(routerMapModule_, ¶m); + } +} + +void RouterMapGenerator::InsertCode(abckit_Method *m) +{ + abckit_ExportDescriptor *routerMapDescriptor = nullptr; + vh_.EnumerateModuleExports(routerMapModule_, [&](abckit_ExportDescriptor *ed) { + if (ROUTER_MAP == vh_.GetString(implI_->ExportDescriptorGetName(ed))) { + routerMapDescriptor = ed; + } + }); + + assert(routerMapDescriptor != nullptr); + + vh_.TransformMethod(m, [&](abckit_ModifyContext *ctxM, abckit_Method *m) { + auto oldCode = implI_->MethodGetCode(m); + abckit_Graph *ctxG = impl_->codeToGraph(ctxI_, oldCode); + auto *stModuleVar = vh_.GraphInstsFindIf(ctxG, [&](abckit_Inst *inst) { + if (dynG_->IgetOpcode(inst) != abckit_IsaApiDynamicOpcode_stmodulevar) { + return false; + } + return dynG_->IgetExportDescriptor(inst) == routerMapDescriptor; + }); + assert(stModuleVar != nullptr); + + // routerMap.set + auto *ldRouterMap = dynG_->IcreateLdlocalmodulevar(ctxG, routerMapDescriptor); + auto *ldSetMethod = dynG_->IcreateLdobjbyname(ctxG, ldRouterMap, implM_->CreateString(ctxM, "set")); + implG_->IinsertAfter(ldRouterMap, stModuleVar); + implG_->IinsertAfter(ldSetMethod, ldRouterMap); + + auto *currentInst = ldSetMethod; + // routerMap.set("xxx", new xxxHandler()) + for (const auto &info : annoInfo_) { + auto keyStr = info.schema + info.path; + auto *ldKey = dynG_->IcreateLoadString(ctxG, implM_->CreateString(ctxM, keyStr.c_str())); + auto *ldClass = dynG_->IcreateLdexternalmodulevar(ctxG, info.importDesc); + auto *newClass = dynG_->IcreateNewobjrange(ctxG, 0x1, ldClass); // 0x1: 1 + num of ctor args + auto *callSet = dynG_->IcreateCallthis2(ctxG, ldSetMethod, ldRouterMap, ldKey, newClass); + implG_->IinsertAfter(ldKey, currentInst); + implG_->IinsertAfter(ldClass, ldKey); + implG_->IinsertAfter(newClass, ldClass); + implG_->IinsertAfter(callSet, newClass); + + currentInst = callSet; + } + + auto *newCode = impl_->graphToCode(ctxG); + implM_->MethodSetCode(ctxM, m, newCode); + }); +} diff --git a/libabckit/tests/scenarios/router_map_generator/router_map_generator.h b/libabckit/tests/scenarios/router_map_generator/router_map_generator.h new file mode 100644 index 0000000000000000000000000000000000000000..d9da11db12bfde10023983faefda25e06f8fb9eb --- /dev/null +++ b/libabckit/tests/scenarios/router_map_generator/router_map_generator.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef ROUTER_TABLE_GENERATOR_H +#define ROUTER_TABLE_GENERATOR_H + +#include +#include + +#include "helpers/visit_helper/visit_helper-inl.h" +#include "include/abckit.h" +#include "include/ir_core.h" +#include "include/metadata.h" +#include "isa/isa_dynamic.h" + +/* +// before AOP + +// IRouterHandler.ets + export interface IRouterHandler { + handle(): void; + } + + export @interface Router { + schema: string; + path: string; + thread: Thread; + } + +// xxxHandler.ets // we have many such classes + import {Router, IRouterHandler} from "./IRouterHandler" + @Router({schema: "xxx", path: "/yyy"}) + export class xxxHandler implements IRouterHandler { + void handle() { + // business logic + } + } + +// routerMap.ets + import {IRouterHandler} from "./IRouterHandler" + export let routerMap = new Map(); + +// after AOP + +// routerMap.ets + import {IRouterHandler} from "./IRouterHandler"; + + import {xxxHandler} from "./xxxHandler"; +// we have many such imports + + export let routerMap = new Map(); +// inserted code + + routerMap.set("xxx/yyy", new xxxHandler()); // [schema + path, new handler()] + // ... // we have many such pairs + + +// xxxHandler.ets // we have many such classes + import {Router, IRouterHandler, Thread} from "./IRouterHandler" + export class xxxHandler implements IRouterHandler { // annotation is removed + void handle() { + // business logic + } + } +*/ + +struct AnnoInfo { + // for routerMap key + std::string schema; + std::string path; + // for routerMap value + abckit_Module *exportModule = nullptr; + std::string exportName; + abckit_ImportDescriptor *importDesc = nullptr; +}; + +static const std::string ANNOTATION_NAME = "Router"; +static const std::string ANNO_FIELD_SCHEMA_NAME = "schema"; +static const std::string ANNO_FIELD_PATH_NAME = "path"; +static const std::string ROUTER_MAP_FILE_MODULE_NAME = "routerPkg.src.main.ets.router.RouterMap"; +static const std::string FUNC_MAIN_0 = "func_main_0"; +static const std::string ROUTER_MAP = "routerMap"; + +class RouterMapGenerator { +public: + RouterMapGenerator(int version, abckit_File *ctxI); + + void Run(); + +private: + void CollectAnnoInfoInClasses(); + void GenerateRouterMap(); + + void CollectAnnoInfoInAnnotation(abckit_Class *klass, abckit_Annotation *anno, abckit_Module *mod); + std::string GetExportNameOfClass(abckit_Class *klass); + + void AddImportDescriptor(); + void InsertCode(abckit_Method *m); + +private: + const abckit_Api *impl_ = nullptr; + const abckit_InspectApi *implI_ = nullptr; + const abckit_GraphApi *implG_ = nullptr; + const abckit_IsaApiDynamic *dynG_ = nullptr; + const abckit_ModifyApi *implM_ = nullptr; + abckit_File *ctxI_ = nullptr; + VisitHelper vh_; + + std::vector annoInfo_; + abckit_Module *routerMapModule_ = nullptr; +}; + +#endif /* ROUTER_TABLE_GENERATOR_H */ diff --git a/libabckit/tests/scenarios/static_branch_elimination/static_branch_elimination.cpp b/libabckit/tests/scenarios/static_branch_elimination/static_branch_elimination.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd85d0788ec229d97a08acdda5d3f9346b1ea2b6 --- /dev/null +++ b/libabckit/tests/scenarios/static_branch_elimination/static_branch_elimination.cpp @@ -0,0 +1,133 @@ +/** + * Copyright (c) 2024 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 "abckit.h" +#include "metadata.h" +#include "logger.h" +#include "ir_core.h" +#include "isa/isa_static.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" + +#include + +namespace libabckit { +namespace test { + +static auto impl = abckit_GetApiImpl(1); +static auto implI = abckit_GetInspectApiImpl(1); +static auto implM = abckit_GetModifyApiImpl(1); +static auto implG = abckit_GetGraphApiImpl(1); +static auto statG = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitTest : public ::testing::Test {}; + +// Test: test-kind=scenario, abc-kind=ArkTSStatic, category=positive +TEST_F(LibAbcKitTest, LibAbcKitTestStaticBranchElimination) +{ + std::cout << " LibAbcKitTestStaticBranchElimination source: " + << ABCKIT_TEST_DIR "scenarios/static_branch_elimination/static_branch_elimination.ets" << '\n'; + std::cout << " LibAbcKitTestStaticBranchElimination abc : " + << ABCKIT_ABC_DIR "scenarios/static_branch_elimination/static_branch_elimination.abc" << '\n'; + + auto output = helpers::ExecuteStaticAbc( + ABCKIT_ABC_DIR "scenarios/static_branch_elimination/static_branch_elimination.abc", "static_branch_elimination/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, + "\"MyFunc start...\"\n" + "\"MyFunc start...\"\n" + "\"Debug buisness logic...\"\n" + "\"Debug buisness logic...\"\n" + "\"MyFunc end...\"\n" + "\"MyFunc end...\"\n")); + + ASSERT_NE(impl, nullptr); + ASSERT_NE(implI, nullptr); + ASSERT_NE(implM, nullptr); + ASSERT_NE(implG, nullptr); + + abckit_File *ctxI = + impl->OpenAbc(ABCKIT_ABC_DIR "scenarios/static_branch_elimination/static_branch_elimination.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + // Transform method + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + helpers::TransformMethod(ctxI, "MyFunc", + [](abckit_ModifyContext *ctxM, abckit_Method *method, abckit_Graph *ctxG) { + auto ctxI = implI->MethodGetInspectContext(method); + abckit_Inst *ifInstr = nullptr; + + auto checkIfArg = [&ifInstr](abckit_File *ctxI, abckit_BasicBlock* bb) -> bool { + auto *curInst = implG->BBgetFirstInst(bb); + while(curInst != nullptr) { + abckit_IsaApiStaticOpcode op = statG->IgetOpcode(curInst); + if (op != abckit_IsaApiStaticOpcode_If) { + curInst = implG->IgetNext(curInst); + continue; + } + auto *cond = implG->IgetInput(curInst, 0); + if (implG->IcheckIsCall(cond)) { + abckit_Method *method = implG->IgetMethod(cond); + abckit_String *methodNameStr = implI->MethodGetName(method); + auto name = helpers::GetCropFuncName(helpers::abckit_StringToString(ctxI, methodNameStr)); + if (name == "IsDebug") { + LIBABCKIT_LOG(DEBUG) << "FOUND IF " << name << "\n"; + ifInstr = curInst; + return true; + } + } + curInst = implG->IgetNext(curInst); + } + return false; + }; + + std::vector bbs; + implG->GvisitBlocksRPO(ctxG, &bbs, [](abckit_BasicBlock *bb, void *data) { + ((std::vector *)data)->emplace_back(bb); + }); + + for (auto i = bbs.rbegin(), j = bbs.rend(); i != j; ++i) { + if (checkIfArg(ctxI, *i)) { + break; + } + } + + EXPECT_NE(ifInstr, nullptr); + auto *ifBB = implG->IgetBasicBlock(ifInstr); + EXPECT_NE(ifBB, nullptr); + auto *falseBB = implG->BBgetFalseBranch(ifBB); + EXPECT_NE(falseBB, nullptr); + implG->BBdisconnectBlocks(ifBB, falseBB); + implG->Iremove(ifInstr); + } + ); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + + // Write output file + impl->WriteAbc(ctxI, ABCKIT_ABC_DIR "scenarios/static_branch_elimination/static_branch_elimination_transformed.abc"); + ASSERT_EQ(impl->GetLastError(), abckit_Status_NO_ERROR); + output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR + "scenarios/static_branch_elimination/static_branch_elimination_transformed.abc", + "static_branch_elimination/ETSGLOBAL", "main"); + EXPECT_TRUE(helpers::Match(output, + "\"MyFunc start...\"\n" + "\"MyFunc start...\"\n" + "\"Release buisness logic...\"\n" + "\"Release buisness logic...\"\n" + "\"MyFunc end...\"\n" + "\"MyFunc end...\"\n")); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/scenarios/static_branch_elimination/static_branch_elimination.ets b/libabckit/tests/scenarios/static_branch_elimination/static_branch_elimination.ets new file mode 100644 index 0000000000000000000000000000000000000000..1cf7114891bd16325585ec70d6a7b3f222b69266 --- /dev/null +++ b/libabckit/tests/scenarios/static_branch_elimination/static_branch_elimination.ets @@ -0,0 +1,30 @@ +function ConsoleLogStr(a: string) { + console.log(a) +} + +function IsDebug(): boolean {return true} + +class MyClass { + MyFunc() { + for (let i = 0; i < 2; i++) { + ConsoleLogStr("MyFunc start...") + } + if(IsDebug()) { + for (let i = 0; i < 2; i++) { + ConsoleLogStr("Debug buisness logic...") + } + } else { + for (let i = 0; i < 2; i++) { + ConsoleLogStr("Release buisness logic...") + } + } + for (let i = 0; i < 2; i++) { + ConsoleLogStr("MyFunc end...") + } + } +} + +function main() { + let c = new MyClass(); + c.MyFunc(); +} diff --git a/libabckit/tests/stress/.gitignore b/libabckit/tests/stress/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c20c2ab73173da3e3b1163b01503cb8f8fa897fe --- /dev/null +++ b/libabckit/tests/stress/.gitignore @@ -0,0 +1,2 @@ +__pycache__ + diff --git a/libabckit/tests/stress/StressEts.py b/libabckit/tests/stress/StressEts.py new file mode 100755 index 0000000000000000000000000000000000000000..841f07dffc9f1a0a72148d9c97d0d773f79f6350 --- /dev/null +++ b/libabckit/tests/stress/StressEts.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# +import multiprocessing.pool +import os +import sys +from distutils.dir_util import copy_tree +import random +from typing import Tuple, Dict, Final, List + +import StressTest +import stress_common +from StressTest import StressTest, Test, Result + +from stress_common import SCRIPT_DIR, TMP_DIR, OUT_DIR, STRESS, get_build_arch, get_args, collect_from + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_ets.json') + +TEST_ETS_SOURCES_ROOT = os.path.join(SCRIPT_DIR, '..', '..', '..', 'static_core', 'plugins', "ets", "tests", + 'ets_func_tests') + +STDLIB_ETS_SOURCES_ROOT = os.path.join(SCRIPT_DIR, '..', '..', '..', 'static_core', 'plugins', "ets", "stdlib") + + +def get_stdlib_path() -> str: + return os.path.join(OUT_DIR, get_build_arch(), 'gen/arkcompiler/runtime_core/static_core/plugins/ets/etsstdlib.abc') + + +def get_verifier_path() -> str: + return os.path.abspath( + os.path.join(OUT_DIR, get_build_arch(), f'exe.unstripped/{get_build_arch()}/arkcompiler/runtime_core/verifier')) + + +def get_config_path() -> str: + return f'{OUT_DIR}/{get_build_arch()}/gen/tools/es2panda/generated/arktsconfig.json' + + +rc_lib_path: Final[str] = f'{OUT_DIR}/{get_build_arch()}/arkcompiler/runtime_core' + +cenv: Dict[str, str] = {'LD_LIBRARY_PATH': rc_lib_path} +venv: Dict[str, str] = { + 'LD_LIBRARY_PATH': f'{rc_lib_path}:{OUT_DIR}/{get_build_arch()}/lib.unstripped/{get_build_arch()}/thirdparty/icu/'} + + +def stress_single(test: Test) -> Result: + stress_abc = test.abc + '.stress.abc' + cmd = [STRESS, test.abc, stress_abc] + result: stress_common.ExecRes = stress_common.exec(cmd, allow_error=True, print_command=False, print_output=False) + if result.returncode == 0: + return Result(test.source, 0) + return Result(test.source, result.returncode, result.stdout, result.stderr) + + +class EtsStressTest(StressTest): + def __init__(self): + super().__init__() + self.ets_dir = os.path.join(TMP_DIR, 'abckit_test_ets') + self.stdlib_dir = os.path.join(TMP_DIR,'abckit_stdlib') + + self.cp = self.get_compiler_path() + self.vp = get_verifier_path() + self.sp = get_stdlib_path() + self.config = get_config_path() + + def run_single(self, test: Test) -> Result: + stress_result: Result = stress_single(test) + verify_result_one: Result = self.verify_single(test) + + r2p = Test(test.source, test.abc + ".stress.abc") + verify_result_two: Result = self.verify_single(r2p) + + if stress_result.result != 0: + error = stress_common.parse_stdout(stress_result.result, stress_result.stdout) + return Result(test.source, error) + # Stress test passed + + if verify_result_two.result == 0: + return Result(test.source, "0") + + if verify_result_one.result != verify_result_two.result: + return Result(test.source, f'Verifier result changed. Was {verify_result_one.result}, now {verify_result_two.result}') + + return Result(test.source, "0") + + def prepare(self) -> None: + self.download_ets() + self.download_stdlib() + + def download_ets(self) -> None: + abs_path = os.path.abspath(TEST_ETS_SOURCES_ROOT) + print(f'Ets test download from {abs_path}') + if not os.path.exists(abs_path): + print(f'Not exists {abs_path}') + return + copy_tree(abs_path, self.ets_dir) + + def download_stdlib(self) -> None: + + abs_path = os.path.abspath(STDLIB_ETS_SOURCES_ROOT) + print(f'Stdlib download from {abs_path}') + if not os.path.exists(abs_path): + print(f'Not exists {abs_path}') + return + copy_tree(abs_path, self.stdlib_dir) + + def get_compiler_path(self) -> str: + return os.path.abspath(os.path.join(OUT_DIR, get_build_arch(), 'arkcompiler/ets_frontend/es2panda')) + + def compile_single(self, src: str) -> Tuple[str, str, int]: + abc_path: src = src + '.abc' + cmd = [self.cp, '--ets-module', '--arktsconfig', self.config, f'--output={abc_path}', src] + result = stress_common.exec(cmd, allow_error=True, print_command=False, env=cenv) + if result.returncode == 0 and not os.path.exists(abc_path): + print(f'WARNING: for {src} es2abc has {result.returncode} return code, but has no output') + return src, abc_path, result.returncode + + def verify_single(self, test: Test) -> Result: + boot_panda_files = f'--boot-panda-files={self.sp}' + cmd = [self.vp, boot_panda_files, '--load-runtimes=ets', test.abc] + result = stress_common.exec(cmd, allow_error=True, print_command=False, env=venv) + return Result(test.source, result.returncode) + + def collect(self) -> List[str]: + tests: List[str] = [] + tests.extend(collect_from(self.ets_dir, lambda name: name.endswith('.ets') and not name.startswith('.'))) + tests.extend(collect_from(self.stdlib_dir, lambda name: name.endswith('.ets') and not name.startswith('.'))) + + random.shuffle(tests) + print(f'Total tests: {len(tests)}') + return tests + + +def main(): + return stress_common.StressRunner(EtsStressTest(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressEtsFull.py b/libabckit/tests/stress/StressEtsFull.py new file mode 100644 index 0000000000000000000000000000000000000000..c78e5e29516c3a902149d891f5e0d966e30a2da8 --- /dev/null +++ b/libabckit/tests/stress/StressEtsFull.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# + +import os +import random +import sys +from pathlib import Path +from typing import List + +import stress_common +from StressEts import EtsStressTest +from StressTest import Test, Result +from stress_common import SCRIPT_DIR, collect_from + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_ets_full.json') + + +class StressEtsFull(EtsStressTest): + def __init__(self) -> None: + super().__init__() + self.jvm = stress_common.get_args().ark_path + + def prepare(self) -> None: + self.download_ets() + + def collect(self) -> List[str]: + tests: List[str] = [] + tests.extend(collect_from(self.ets_dir, lambda name: name.endswith('.ets') and not name.startswith('.'))) + + random.shuffle(tests) + print(f'Total tests: {len(tests)}') + return tests + + def run_single(self, test: Test) -> Result: + result: Result = super().run_single(test) + if result.result != "0": + return result + test_result_one = self.run_ark(test) + if test_result_one.result != 0: + # no error as test failed before stress execution + return Result(test.source, "0", result.stdout, result.stderr) + + test2 = Test(test.source, test.abc + ".stress.abc") + test_result_two = self.run_ark(test2) + if test_result_two.result == 0: + return Result(test.source, "0") + + if test_result_one.result != test_result_two.result: + return Result(test.source, f'ETS Test result changed. Was {test_result_one.result}, now {test_result_two.result}') + return result + + def run_ark(self, test: Test) -> Result: + ep = f"{Path(test.source).stem}.ETSGLOBAL::main" + boot_panda_files = f'--boot-panda-files={self.sp}' + cmd = [self.jvm, boot_panda_files, "--load-runtimes=ets", test.abc, ep] + result = stress_common.exec(cmd, allow_error=True, print_command=False, print_output=False) + return Result(test.source, result.returncode) + + +def main(): + print('ABCKit stress test') + args = stress_common.get_args() + test = StressEtsFull(args.ark_path) + test.prepare() + + tests: List[Test] = test.build() + results = test.run(tests) + + fail_list = stress_common.get_fail_list(results) + + if not stress_common.check_regression_errors(FAIL_LIST_PATH, fail_list): + return 1 + + if args.update_fail_list: + stress_common.update_fail_list(FAIL_LIST_PATH, fail_list) + print(f'Failures/Total: {len(fail_list)}/{len(results)}') + return 0 + + if not stress_common.check_fail_list(FAIL_LIST_PATH, fail_list): + print(f'Failures/Total: {len(fail_list)}/{len(results)}') + return 1 + + print('ABCKit: no regressions') + print(f'Failures/Total: {len(fail_list)}/{len(results)}') + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressFuzzedJS.py b/libabckit/tests/stress/StressFuzzedJS.py new file mode 100644 index 0000000000000000000000000000000000000000..d8f308faa1bb00c58199e0c36ef4c05070c89d92 --- /dev/null +++ b/libabckit/tests/stress/StressFuzzedJS.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# + +import os +import sys + +import stress_common +from stress import StressJSTest +from stress_common import SCRIPT_DIR + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_fuzzedjs.json') +FUZZED_JS_PATH = os.path.join(SCRIPT_DIR, 'fuzzedjs.zip') + + +class StressFuzzedJSTest(StressJSTest): + + def __init__(self): + super().__init__() + self.js_dir = os.path.join(stress_common.TMP_DIR, 'abckit_fuzzedjs') + + def prepare(self) -> None: + if not os.path.exists(self.js_dir): + stress_common.exec(['unzip', FUZZED_JS_PATH, '-d', self.js_dir]) + + +def main(): + return stress_common.StressRunner(StressFuzzedJSTest(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressHermes.py b/libabckit/tests/stress/StressHermes.py new file mode 100755 index 0000000000000000000000000000000000000000..f2c5e90f242b62eb6f15b195187f2b43b004a481 --- /dev/null +++ b/libabckit/tests/stress/StressHermes.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# + +import os +import random +import sys +from typing import List + +import stress_common +from StressTest import Test +from stress import StressJSTest +from stress_common import SCRIPT_DIR, collect_from + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_hermes.json') + +HERMES_REVISION = "3feac7b2f9759d83879b04232479041baa805e7b" +HERMES_URL = "https://github.com/facebook/hermes.git" + + +class HermesStressTest(StressJSTest): + + def __init__(self): + super().__init__() + self.js_dir = os.path.join(stress_common.TMP_DIR, 'abckit_hermes') + + def prepare(self) -> None: + self.download_hermes() + + def download_hermes(self) -> None: + if not os.path.exists(self.js_dir): + stress_common.exec(['git', 'clone', HERMES_URL, self.js_dir]) + stress_common.exec(['git', '-C', self.js_dir, 'checkout', HERMES_REVISION]) + + def collect(self) -> List[str]: + tests: List[str] = [] + sp = os.path.join(self.js_dir, 'test') + tests.extend(collect_from(sp, lambda name: name.endswith('.js') and not name.startswith('.'))) + random.shuffle(tests) + + print(f'Total tests: {len(tests)}') + return tests + + +def main(): + return stress_common.StressRunner(HermesStressTest(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressHermesFull.py b/libabckit/tests/stress/StressHermesFull.py new file mode 100644 index 0000000000000000000000000000000000000000..0fa00204580c0b250a614c36931f7d3581088c48 --- /dev/null +++ b/libabckit/tests/stress/StressHermesFull.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# +import os +import sys +from typing import List + +import stress_common +from StressHermes import HermesStressTest +from StressTest import Test, Result +from stress_common import SCRIPT_DIR + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_hermes_full.json') + + +class HermesStressTestFull(HermesStressTest): + def run_single(self, test: Test) -> Result: + stress_abc = test.abc + '.stress.abc' + r1p = Test(test.source, test.abc) + r2p = Test(test.source, stress_abc) + + test_result_one = self.run_js_test_single(r1p) # Run test once + + cmd = [stress_common.STRESS, test.abc, stress_abc] + result: stress_common.ExecRes = stress_common.exec(cmd, allow_error=True, print_command=False) + if result.returncode != 0: + error = stress_common.parse_stdout(result.returncode, result.stdout) + return Result(test.source, error) + # Stress test passed + + if test_result_one.result == -1: # First attempt JS Test failed with timeout. This bypass next test + return Result(test.source, "0") + + test_result_two = self.run_js_test_single(r2p, self.repeats) # Run test with defined repeats + + if test_result_two.result == 0: + return Result(test.source, "0") + + if test_result_one.result != test_result_two.result: + return Result(test.source, f'JS Test result changed. Was {test_result_one.result}, now {test_result_two.result}') + + return Result(test.source, "0") + + +def main(): + return stress_common.StressRunner(HermesStressTestFull(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressJSFull.py b/libabckit/tests/stress/StressJSFull.py new file mode 100755 index 0000000000000000000000000000000000000000..edfe8432390b82b2882ae2a36eb9d8eccc48a34e --- /dev/null +++ b/libabckit/tests/stress/StressJSFull.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +import multiprocessing +import os +import sys +import re +from functools import lru_cache +import random +from typing import List, Dict, Any, Tuple, TextIO, Final + +import stress_common +from StressTest import Test, Result +from stress import StressJSTest, EXCLUDED_TESTS +from stress_common import SCRIPT_DIR, collect_from, get_build_arch, OUT_DIR + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_full.json') + + +class Descriptor: + def __init__(self, input_file: str) -> None: + self.input_file = input_file + self.header = re.compile( + r"/\*---(?P
.+)---\*/", re.DOTALL) + self.includes = re.compile(r"includes:\s+\[(?P.+)]") + self.content = self.get_content() + + def get_content(self) -> str: + with open(self.input_file, "r", encoding="utf-8") as file_pointer: + input_str = file_pointer.read() + return input_str + + def get_header(self) -> str: + header_comment = self.header.search(self.content) + return header_comment.group(0) if header_comment else "" + + def parse_descriptor(self) -> Dict[str, Any]: + header = self.get_header() + result: Dict[str, Any] = {} + + if len(header) == 0: + return result + + includes = [] + match = self.includes.search(header) + includes += [incl.strip() for incl in match.group("includes").split(",")] if match else [] + + result["includes"] = includes + return result + + +@lru_cache(maxsize=100000) +def get_harness_code(path: str = None) -> str: + return read_harness_code(path) + + +def read_harness_code(path: str = None) -> str: + ajs = os.path.abspath(os.path.join(path, 'harness', 'assert.js')) + sjs = os.path.abspath(os.path.join(path, 'harness', 'sta.js')) + + with open(ajs, 'r') as f: + assert_js = f.read() + with open(sjs, 'r') as f: + sta_js = f.read() + return assert_js + '\n' + sta_js + '\n' + + +@lru_cache(maxsize=10000) +def read_import(src: str) -> str: + with open(src, 'r') as f: + code = f.read() + return code + + +class StressJSFull(StressJSTest): + + def __init__(self) -> None: + super().__init__() + arr = stress_common.get_args().repeats + self.repeats = 3 if arr is None else arr + print(f'Repeats: {self.repeats} with timeout: {self.timeout}') + + def compile_single(self, src: str) -> Tuple[str, str, int]: + self.prepare_single(src) + cr = super().compile_single(src + '.mjs') + return src, cr[1], cr[2] + + def run_single(self, test: Test) -> Result: + stress_abc = test.abc + '.stress.abc' + r1p = Test(test.source + ".mjs", test.abc) + r2p = Test(test.source + ".mjs", stress_abc) + + test_result_one = self.run_js_test_single(r1p) # Run test once + + cmd = [stress_common.STRESS, test.abc, stress_abc] + result: stress_common.ExecRes = stress_common.exec(cmd, allow_error=True, print_command=False) + if result.returncode != 0: + error = stress_common.parse_stdout(result.returncode, result.stdout) + return Result(test.source, error) + # Stress test passed + + if test_result_one.result == -1: # First attempt JS Test failed with timeout. This bypass next test + return Result(test.source, "0") + + test_result_two = self.run_js_test_single(r2p, self.repeats) # Run test with defined repeats + + if test_result_two.result == 0: + return Result(test.source, "0") + + if test_result_one.result != test_result_two.result: + return Result(test.source, f'JS Test result changed. Was {test_result_one.result}, now {test_result_two.result}') + + return Result(test.source, "0") + + def prepare_single(self, src: str) -> None: + out: TextIO = open(src + ".mjs", 'w') + sf = open(src, 'r') + out.write(get_harness_code(self.js_dir)) + for include in Descriptor(src).parse_descriptor().get('includes', []): + imp = os.path.abspath(os.path.join(self.js_dir, 'harness', include)) + out.write(read_import(imp) + "\n") + out.write(sf.read()) + sf.close() + out.close() + + def collect(self) -> List[str]: + tests: List[str] = [] + sp = os.path.join(self.js_dir, 'test') + tests.extend(collect_from(sp, lambda name: name.endswith('.js') and not name.startswith('.'))) + sp = os.path.join(self.js_dir, 'implementation-contributed') + tests.extend(collect_from(sp, lambda name: name.endswith('.js') and not name.startswith('.'))) + random.shuffle(tests) + + print(f'Total tests: {len(tests)}') + for excluded in EXCLUDED_TESTS: + tests = list(filter(lambda name: excluded not in name, tests)) + print(f'Tests after exclude: {len(tests)}') + + return tests + + def build(self) -> List[Test]: + tests: List[str] = self.collect() + + print('Running compiler...') + compiled_tests: List[Test] = [] + counter = 0 + with multiprocessing.pool.ThreadPool(stress_common.NPROC) as pool: + for js_path, abc_path, retcode in pool.imap(self.compile_single, tests, chunksize=20): + if retcode == 0: + compiled_tests.append(Test(js_path, abc_path)) + counter += 1 + sys.stdout.write(f'{counter}/{len(tests)} \r') + + print(f'Tests successfully compiled: {len(compiled_tests)}') + return compiled_tests + + +def main(): + return stress_common.StressRunner(StressJSFull(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressNodeJS.py b/libabckit/tests/stress/StressNodeJS.py new file mode 100755 index 0000000000000000000000000000000000000000..623b1b9ceecefe4e5f55cb35e8c268cc8101d0e3 --- /dev/null +++ b/libabckit/tests/stress/StressNodeJS.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# + +import os +import sys +from typing import List + +import stress_common +from stress import StressJSTest +from stress_common import SCRIPT_DIR, TMP_DIR +from StressTest import StressTest, Test, Result + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list_node.json') + +NODE_GIT_URL = "https://github.com/nodejs/node.git" +NODE_GIT_HASH = "0095726bf3d0a2c01062d98e087526299e709515" + + +class NodeJSTest(StressJSTest): + def __init__(self): + super().__init__() + self.js_dir = os.path.join(TMP_DIR, 'abckit_nodejs') + + def prepare(self) -> None: + if not os.path.exists(self.js_dir): + stress_common.exec(['git', 'clone', NODE_GIT_URL, self.js_dir]) + stress_common.exec(['git', '-C', self.js_dir, 'checkout', NODE_GIT_HASH]) + + +def main(): + return stress_common.StressRunner(NodeJSTest(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/StressTest.py b/libabckit/tests/stress/StressTest.py new file mode 100644 index 0000000000000000000000000000000000000000..770bf25380a337b0ae2344194d3807cecbc00261 --- /dev/null +++ b/libabckit/tests/stress/StressTest.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# + +import multiprocessing.pool +import sys +from abc import abstractmethod +from typing import Tuple, List + +import stress_common + + +class Test: + def __init__(self, source: str, abc: str): + self.source = source + self.abc = abc + + +class Result: + def __init__(self, source, result, stdout=None, stderr=None): + self.source = source + self.result = result + self.stdout = stdout + self.stderr = stderr + + +class StressTest: + + def run(self, tests: List[Test]): + print('Running ABCKit...') + result_all = {} + counter = 0 + + with multiprocessing.pool.ThreadPool(stress_common.NPROC) as pool: + for result in pool.imap(self.run_single, tests): + result_all[result.source] = {} + result_all[result.source]['error'] = result.result + counter += 1 + sys.stdout.write(f'{counter}/{len(tests)} \r') + + return result_all + + @abstractmethod + def run_single(self, test: Test) -> Result: + pass + + @abstractmethod + def compile_single(self, src: str) -> Tuple[str, str, int]: + pass + + @abstractmethod + def prepare(self) -> None: + pass + + def build(self) -> List[Test]: + tests: List[str] = self.collect() + + print('Running compiler...') + compiled_tests: List[Test] = [] + counter = 0 + with multiprocessing.pool.ThreadPool(stress_common.NPROC) as pool: + for js_path, abc_path, retcode in pool.imap(self.compile_single, tests, chunksize=20): + if retcode == 0: + compiled_tests.append(Test(js_path, abc_path)) + counter += 1 + sys.stdout.write(f'{counter}/{len(tests)} \r') + + print(f'Tests successfully compiled: {len(compiled_tests)}') + return compiled_tests + + @abstractmethod + def collect(self) -> List[str]: + pass + + @abstractmethod + def get_compiler_path(self) -> str: + pass diff --git a/libabckit/tests/stress/fail_list.json b/libabckit/tests/stress/fail_list.json new file mode 100644 index 0000000000000000000000000000000000000000..1186834e855acb68de0527db75ae8847989b8388 --- /dev/null +++ b/libabckit/tests/stress/fail_list.json @@ -0,0 +1,17 @@ +{ + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.match].js": "134", + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.replace].js": "134", + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.search].js": "134", + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.split].js": "134", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/asm/embenchen/zlib.js": "139", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/asm/sqlite3/sqlite-change-heap.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/asm/sqlite3/sqlite-pointer-masking.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/asm/sqlite3/sqlite-safe-heap.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/asm/sqlite3/sqlite.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/compiler/regress-3786.js": "ASSERTION FAILED: sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/harmony/well-formed-json-stringify-checked.js": "139", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/harmony/well-formed-json-stringify-unchecked.js": "139", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/regress/regress-1177809.js": "ASSERTION FAILED: sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/regress/wasm/regress-810973b.js": "137", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/third_party/regexp-pcre/regexp-pcre.js": "139" +} \ No newline at end of file diff --git a/libabckit/tests/stress/fail_list_ets.json b/libabckit/tests/stress/fail_list_ets.json new file mode 100644 index 0000000000000000000000000000000000000000..0967ef424bce6791893e9a57bb952f80fd536e93 --- /dev/null +++ b/libabckit/tests/stress/fail_list_ets.json @@ -0,0 +1 @@ +{} diff --git a/libabckit/tests/stress/fail_list_ets_full.json b/libabckit/tests/stress/fail_list_ets_full.json new file mode 100644 index 0000000000000000000000000000000000000000..69e8baf54aeab5666ba67365a7a443de9409408c --- /dev/null +++ b/libabckit/tests/stress/fail_list_ets_full.json @@ -0,0 +1,174 @@ +{ + "/tmp/abckit_test_ets/algorithms/ChecksumsTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/algorithms/SortingTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/algorithms/TreeSanityTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/algorithms/division-by-zero-in-class.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/arkui/dollar_dollar_10.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/ArrayBufferTest1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/ArrayBufferTest2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/ArrayGet.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/ErrorStackTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/ErrorsTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/JsonReplacerTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/ReflectGetBadCases.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/escompat/RegExpCompileTest.ets": "ETS Test result changed. Was 0, now 2", + "/tmp/abckit_test_ets/regression/12961_loop_and_lambda_050.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/regression/SaveStateBridge.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/regression/default_interface_method.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Bigint/bigint-arithmetic-dec-2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Bigint/bigint-arithmetic-div-2-operands-by-zero.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Bigint/bigint-arithmetic-inc-2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_as_generic_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_as_generic_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_as_generic_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_as_generic_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_as_generic_5.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_as_generic_6.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_write_4.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Tuples_type/tuple_write_7.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_never/useWithLambdaAndUnion.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/assign/assign-undefined-to-undefined_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/assign/assign-undefined-to-untyped_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/define/define-class-member-as-question.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/define/define-class-member-as-undefined_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/define/define-class-member-as-undefined_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/define/define-class-member-as-undefined_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/Type_undefined/define/define-class-member-as-undefined_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/string/constructor_with_nullish_0010.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/string/constructor_with_nullish_0020.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/string/constructor_with_nullish_0030.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/string/constructor_with_nullish_0040.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/03.types/References_Types/string/constructor_with_nullish_0050.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_4.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_7.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/04.Names_Declarations_and_Scopes/Function_Declarations/issue14809_8.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_03.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_04.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_05.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_06.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_07_00.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_07_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_07_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_07_03.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/genericTypeArgumentWithDefaultParameterValue_07_05.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/issue15089_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/issue15089_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/issue15089_07.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/05.Generics/usingOutT.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/interfaces_overriding/interface_overriding_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/interfaces_overriding/interface_overriding_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/interfaces_overriding/interface_overriding_04.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/interfaces_overriding/interface_overriding_05.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/interfaces_overriding/interface_overriding_06.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/override_issue14812_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/10.Overriding_by_Instance_Methods/override_issue14812_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/Issue-14273_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/9.6.Method_Declarations/Issue-14273_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_4.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_5.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-13330_6.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-15142_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-15142_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-15142_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-15142_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Accessor_Declarations/issue-15142_4.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0001.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0002.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0003.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0004.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0005.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0007.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0008.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0009.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Constructor_Declaration/constructor_default_params_0010.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Inheritance/subtypingWithFunctionsRequiresExplicitType_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Inheritance/subtypingWithFunctionsRequiresExplicitType_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/Inheritance/subtypingWithFunctionsRequiresExplicitType_03.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/abstract-class-inheritance/abstract-class-inheritance-101.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/abstract-class-inheritance/abstract-class-inheritance-102.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/abstract-class-inheritance/abstract-class-inheritance-103.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/constructor-inheritance/issue14720_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/constructor-inheritance/issue14720_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/09.classes/constructor-inheritance/issue14720_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/11.Enumerations/enum_trailing_comma_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/11.Enumerations/enum_trailing_comma_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/11.Enumerations/issue14633_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/11.Enumerations/issue14633_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/11.Enumerations/issue14636_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/15.Semantic_Rules/Compatibility_Features/Extended_Conditional_Expressions/string/expr/string-expression-assert.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-short-with-param.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-short-with-param_1.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-short.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-with-param_0.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-with-param_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-with-param_3.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression-with-param_4.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-expression.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-instantiate_2.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-instantiate_6.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-instantiate_8.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/callable-classes/type-call-instantiate_9.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_fn_param_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_fn_param_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_fn_param_03.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_nested_07.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_nested_08.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_nested_09.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_only_fn_01_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_only_fn_02_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_only_fn_03_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_only_fn_04_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_return_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_stmt_01.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_stmt_02.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_stmt_03.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_stmt_04.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_stmt_05.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/16.Support_for_GUI_Programming/trailing_lambdas/trailing_stmt_06.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/17.Experimental_Features/Iterable_Types/for-of-s01-array-04.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/17.Experimental_Features/Iterable_Types/for_of_06.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0000.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0001.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0002.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0020.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0040.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0050.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0060.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s01-0070.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s02-0000.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s02-0001.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s02-0010.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s03-0010.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s03-0020.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/indexable/idx-s03-0030.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/lambda/capturingGlobalClassInLambda.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/lambda/compareBooleanWithTrue.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/lambda/resultFromAwait.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/spec/lambda/resultFromAwaitResolution.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/containers/ArrayAsListIntTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/containers/ArrayAsListStringTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/BadRadixTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/DoubleTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/EscapeUnescapeURITest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/TypeCreateClassTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/TypeCreateErasedBodyTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/TypeCreatePrimitiveNameTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/TypeMethodInvoke.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/TypeMethodInvokeConstructor.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/core/TypeMethodResolveConstructorFew.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/math/BoundariesTest.ets": "ETS Test result changed. Was 0, now 14", + "/tmp/abckit_test_ets/std/math/TestIntegerLog10.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/time/DateConstructorTest.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/time/DateCtorTypes.ets": "ETS Test result changed. Was 0, now 1", + "/tmp/abckit_test_ets/std/time/ValidDateTest.ets": "ETS Test result changed. Was 0, now 1" +} \ No newline at end of file diff --git a/libabckit/tests/stress/fail_list_full.json b/libabckit/tests/stress/fail_list_full.json new file mode 100644 index 0000000000000000000000000000000000000000..2b087cd5dd59837266e8a243f5078a7cb530b2c4 --- /dev/null +++ b/libabckit/tests/stress/fail_list_full.json @@ -0,0 +1,16 @@ +{ + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.match].js": 139, + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.replace].js": 139, + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.search].js": 139, + "/tmp/abckit_test262/implementation-contributed/javascriptcore/es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.split].js": 139, + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/es6/destructuring.js": 1, + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/harmony/well-formed-json-stringify-checked.js": 139, + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/harmony/well-formed-json-stringify-unchecked.js": 139, + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/regress/regress-1177809.js": "JS Test result changed. Was 0, now -6", + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/regress/regress-5454.js": 1, + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/regress/wasm/regress-810973b.js": 137, + "/tmp/abckit_test262/implementation-contributed/v8/mjsunit/third_party/regexp-pcre/regexp-pcre.js": 139, + "/tmp/abckit_test262/test/intl402/Intl/getCanonicalLocales/canonicalized-tags.js": "JS Test result changed. Was 255, now -11", + "/tmp/abckit_test262/test/intl402/language-tags-canonicalized.js": "JS Test result changed. Was 255, now -11", + "/tmp/abckit_test262/test/staging/ArrayBuffer/resizable/object-freeze.js": "JS Test result changed. Was 255, now -11" +} \ No newline at end of file diff --git a/libabckit/tests/stress/fail_list_fuzzedjs.json b/libabckit/tests/stress/fail_list_fuzzedjs.json new file mode 100644 index 0000000000000000000000000000000000000000..0db3279e44b0dc4fb7e694b6cb10210a96ba6ba5 --- /dev/null +++ b/libabckit/tests/stress/fail_list_fuzzedjs.json @@ -0,0 +1,3 @@ +{ + +} diff --git a/libabckit/tests/stress/fail_list_hermes.json b/libabckit/tests/stress/fail_list_hermes.json new file mode 100644 index 0000000000000000000000000000000000000000..bfc7d9e0ede99e4e33fb2fd4172e5ad5026b3792 --- /dev/null +++ b/libabckit/tests/stress/fail_list_hermes.json @@ -0,0 +1,9 @@ +{ + "/tmp/abckit_hermes/test/BCGen/HBC/es6/tagged-template-long.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_hermes/test/BCGen/HBC/many_args.js": "137", + "/tmp/abckit_hermes/test/BCGen/HBC/spill.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_hermes/test/BCGen/HBC/spill_for_in.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_hermes/test/hermes/generator.js": "RegEncoder failed!", + "/tmp/abckit_hermes/test/hermes/many_args.js": "137", + "/tmp/abckit_hermes/test/hermes/tagged-template-long.js": "RegAllocGraphColoring failed!" +} \ No newline at end of file diff --git a/libabckit/tests/stress/fail_list_hermes_full.json b/libabckit/tests/stress/fail_list_hermes_full.json new file mode 100644 index 0000000000000000000000000000000000000000..750866336187a68ab113270f25046ad0494143dc --- /dev/null +++ b/libabckit/tests/stress/fail_list_hermes_full.json @@ -0,0 +1,9 @@ +{ + "/tmp/abckit_hermes/test/BCGen/HBC/es6/tagged-template-long.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_hermes/test/BCGen/HBC/many_args.js": "137", + "/tmp/abckit_hermes/test/BCGen/HBC/spill.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_hermes/test/BCGen/HBC/spill_for_in.js": "RegAllocGraphColoring failed!", + "/tmp/abckit_hermes/test/hermes/generator.js": "RegEncoder failed!", + "/tmp/abckit_hermes/test/hermes/many_args.js": "137", + "/tmp/abckit_hermes/test/hermes/tagged-template-long.js": "RegAllocGraphColoring failed!" +} diff --git a/libabckit/tests/stress/fail_list_node.json b/libabckit/tests/stress/fail_list_node.json new file mode 100644 index 0000000000000000000000000000000000000000..c84b469f0604dd43cf5aa296d5c09625169086ec --- /dev/null +++ b/libabckit/tests/stress/fail_list_node.json @@ -0,0 +1,13 @@ +{ + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/asm/embenchen/zlib.js": "139", + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/compiler/regress-3786.js": "ASSERTION FAILED: sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG", + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/harmony/well-formed-json-stringify-checked.js": "139", + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/harmony/well-formed-json-stringify-unchecked.js": "139", + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/regress/regress-1177809.js": "ASSERTION FAILED: sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG", + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/regress/wasm/regress-810973b.js": "137", + "/tmp/abckit_nodejs/deps/v8/test/mjsunit/third_party/regexp-pcre/regexp-pcre.js": "139", + "/tmp/abckit_nodejs/test/fixtures/snapshot/typescript.js": "1", + "/tmp/abckit_nodejs/tools/eslint/node_modules/@babel/types/lib/asserts/generated/index.js": "1", + "/tmp/abckit_nodejs/tools/eslint/node_modules/@babel/types/lib/builders/generated/index.js": "1", + "/tmp/abckit_nodejs/tools/eslint/node_modules/@babel/types/lib/validators/generated/index.js": "1" +} \ No newline at end of file diff --git a/libabckit/tests/stress/fuzzedjs.zip b/libabckit/tests/stress/fuzzedjs.zip new file mode 100644 index 0000000000000000000000000000000000000000..63f7e014114989d66e6cb645df8a87780acb4aa5 Binary files /dev/null and b/libabckit/tests/stress/fuzzedjs.zip differ diff --git a/libabckit/tests/stress/stress.py b/libabckit/tests/stress/stress.py new file mode 100755 index 0000000000000000000000000000000000000000..f7eb76900d7ca76346cc0abbd844642f01fcbceb --- /dev/null +++ b/libabckit/tests/stress/stress.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# + +import os +import random +import sys +from typing import List, Tuple, Final, Dict + +import stress_common + +from StressTest import StressTest, Test, Result +from stress_common import SCRIPT_DIR, TMP_DIR, OUT_DIR, STRESS, get_build_arch, collect_from + +FAIL_LIST_PATH = os.path.join(SCRIPT_DIR, 'fail_list.json') + +TEST262_GIT_URL = "https://gitee.com/hufeng20/test262.git" +TEST262_GIT_HASH = "6f4601d095a3899d6102f2c320b671495cbe8757" + +rc_lib_path: Final[str] = f'{OUT_DIR}/{get_build_arch()}/arkcompiler/runtime_core' +ets_rc_lib_path: Final[str] = f'{OUT_DIR}/{get_build_arch()}/arkcompiler/ets_runtime' +icu_lib_path: Final[str] = f'{OUT_DIR}/{get_build_arch()}/lib.unstripped/{get_build_arch()}/thirdparty/icu/' +zlib_lib_path: Final[str] = f'{OUT_DIR}/{get_build_arch()}/lib.unstripped/{get_build_arch()}/thirdparty/zlib/' + +runtime_env: Dict[str, str] = {'LD_LIBRARY_PATH': f'{rc_lib_path}:{ets_rc_lib_path}:{icu_lib_path}:{zlib_lib_path}'} + +EXCLUDED_TESTS = [ + 'regress-4595.js', + 'module-jit-reachability.js', +] + + +class StressJSTest(StressTest): + def __init__(self): + self.js_dir = os.path.join(TMP_DIR, 'abckit_test262') + self.cp = self.get_compiler_path() + self.jvm = os.path.join(stress_common.OUT_DIR, get_build_arch(), 'arkcompiler/ets_runtime/ark_js_vm') + self.timeout = 10 + self.repeats = 1 + + def run_single(self, test: Test) -> Result: + cmd = [STRESS, test.abc] + result: stress_common.ExecRes = stress_common.exec(cmd, allow_error=True, print_command=False) + if result.returncode != 0: + error = stress_common.parse_stdout(str(result.returncode), result.stdout) + return Result(test.source, error) + return Result(test.source, "0") + + def compile_single(self, src: str) -> Tuple[str, str, int]: + abc_path: src = src + '.abc' + cmd = [self.cp, '--module', '--merge-abc', '--output', abc_path, src] + result = stress_common.exec(cmd, allow_error=True, print_command=False) + if result.returncode == 0 and not os.path.exists(abc_path): + print(f'WARNING: for {src} es2abc has {result.returncode} return code, but has no output') + return src, abc_path, result.returncode + + def prepare(self) -> None: + self.download_262() + + def get_compiler_path(self) -> str: + return os.path.join(OUT_DIR, get_build_arch(), 'arkcompiler/ets_frontend/es2abc') + + def download_262(self) -> None: + if not os.path.exists(self.js_dir): + stress_common.exec(['git', 'clone', TEST262_GIT_URL, self.js_dir]) + stress_common.exec(['git', '-C', self.js_dir, 'checkout', TEST262_GIT_HASH]) + + def collect(self) -> List[str]: + tests: List[str] = [] + tests.extend(collect_from(self.js_dir, lambda name: name.endswith('.js') and not name.startswith('.'))) + random.shuffle(tests) + + print(f'Total tests: {len(tests)}') + for excluded in EXCLUDED_TESTS: + tests = list(filter(lambda name: excluded not in name, tests)) + print(f'Tests after exclude: {len(tests)}') + + return tests + + def run_js_test_single(self, test: Test, repeats: int = 1) -> Result: + entry: str = f'--entry={os.path.basename(test.source)}' + cmd = [self.jvm, entry, test.abc] + result: stress_common.ExecRes = stress_common.exec(cmd, allow_error=True, print_command=False, + env=runtime_env, timeout=self.timeout, print_output=False, + repeats=repeats) + if result.returncode == 0: + return Result(test.source, 0) + + return Result(test.source, result.returncode, result.stdout, result.stderr) + + +def main(): + return stress_common.StressRunner(StressJSTest(), FAIL_LIST_PATH).run() + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/libabckit/tests/stress/stress_common.py b/libabckit/tests/stress/stress_common.py new file mode 100644 index 0000000000000000000000000000000000000000..70a8f3aa5949466b8a3a82dbf382fddaaafc8dbd --- /dev/null +++ b/libabckit/tests/stress/stress_common.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +# Copyright (c) 2024 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. +# +import argparse +import json +import multiprocessing +import os +import subprocess as spp +import tempfile +from collections import OrderedDict +from functools import lru_cache +from typing import List + + +import StressTest + +NPROC = multiprocessing.cpu_count() +TMP_DIR = tempfile.gettempdir() + +SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) + +OUT_DIR = os.path.join(SCRIPT_DIR, '..', '..', '..', '..', '..', 'out', 'rk3568') +STRESS = os.path.join(SCRIPT_DIR, '..', '..', 'scripts', 'stress.sh') + + +def get_build_arch() -> str: + return 'clang_x64' + + +@lru_cache(maxsize=100) +def get_args(): + parser = argparse.ArgumentParser(description="Abckit stress test") + parser.add_argument('--update-fail-list', action='store_true', default=False, help=f'Update fail list') + parser.add_argument("--ark-path", type=str, default=None, help=f'ARK runtime path') + parser.add_argument("--repeats", type=int, default=None, help=f'VM test retry attempts') + return parser.parse_args() + + +def collect_from(rd, func) -> List[str]: + tmp: List[str] = [] + for root, _, file_names in os.walk(rd): + for file_name in file_names: + tmp.append(os.path.join(root, file_name)) + return filter(func, tmp) + + +class ExecRes: + def __init__(self, returncode, stdout, stderr): + self.returncode = returncode + self.stdout = stdout + self.stderr = stderr + + +def exec(cmd, cwd=os.getcwd(), allow_error=False, timeout=600, print_output=False, print_command=True, env=None, + repeats: int = 1): + if print_command: + print(f'$ {cwd}> {" ".join(cmd)}') + + ct = timeout + for loop in range(repeats): + return_code, stdout, stderr = __exec_impl(cmd, cwd=cwd, timeout=ct, print_output=print_output, env=env) + if return_code != -1: + break + ct = ct + 60 + + if return_code != 0 and not allow_error: + raise Exception(f"Error: Non-zero return code\nstdout: {stdout}\nstderr: {stderr}") + return ExecRes(return_code, stdout, stderr) + + +def __exec_impl(cmd, cwd=os.getcwd(), timeout=600, print_output=False, env=None): + proc = spp.Popen(cmd, cwd=cwd, stdout=spp.PIPE, stderr=spp.STDOUT, encoding='ISO-8859-1', env=env) + while True and print_output: + line = proc.stdout.readline() + print(line.strip()) + if not line: + break + try: + stdout, stderr = proc.communicate(timeout=timeout) + return_code = proc.wait() + except spp.TimeoutExpired: + stdout, stderr = "timeout", "timeout" + return_code = -1 + + return return_code, stdout, stderr + + +def parse_stdout(error: str, stdout): + if stdout is not None and 'ASSERTION FAILED:' in stdout: + for line in stdout.split('\n'): + if 'ASSERTION FAILED:' in line: + error = line + if stdout is not None and 'ERROR: plugin returned non-zero' in stdout: + for line in stdout.split('\n'): + if 'failed!' in line: + error = line.split(' ')[-2] + " " + line.split(' ')[-1] + return error + + +def get_fail_list(result): + fail_list = OrderedDict() + for src_path in result: + if result[src_path]['error'] != '0': + fail_list[src_path] = result[src_path]['error'] + return fail_list + + +def check_regression_errors(kfl_path: str, fail_list): + with open(kfl_path, 'r') as f: + old_fail_list = json.load(f) + regression_errors = [] + for fail in fail_list: + if fail not in old_fail_list: + regression_errors.append(f'REGRESSION ERROR: new fail "{fail}"') + if regression_errors: + print('\n'.join(regression_errors)) + return False + return True + + +def update_fail_list(kfl_path: str, fail_list): + with open(kfl_path, 'w') as f: + json.dump(fail_list, f, indent=2, sort_keys=True) + + +def check_fail_list(kfl_path: str, fail_list): + with open(kfl_path, 'r') as f: + old_fail_list = json.load(f) + + errors = [] + for old_fail in old_fail_list: + if old_fail not in fail_list: + errors.append(f'ERROR: no file in new fail list "{old_fail}"') + if errors: + print('\n'.join(errors)) + print('Please update fail list, rerun this script with "--update-fail-list"') + return False + return True + + +class StressRunner: + def __init__(self, test: StressTest, fl:str): + self.args = get_args() + self.test = test; + self.failList = fl; + + def run(self) -> int: + print(f'ABCKit stress test {self.test.__class__.__name__}...') + self.test.prepare() + tests: List[StressTest.Test] = self.test.build() + results = self.test.run(tests) + fail_list = get_fail_list(results) + if not check_regression_errors(self.failList, fail_list): + return 1 + + if self.args.update_fail_list: + update_fail_list(self.failList, fail_list) + print(f'Failures/Total: {len(fail_list)}/{len(results)}') + return 0 + + if not check_fail_list(self.failList, fail_list): + print(f'Failures/Total: {len(fail_list)}/{len(results)}') + return 1 + + print('ABCKit: no regressions') + print(f'Failures/Total: {len(fail_list)}/{len(results)}') + return 0; diff --git a/libabckit/tests/test_args.gni b/libabckit/tests/test_args.gni new file mode 100644 index 0000000000000000000000000000000000000000..722d60330848d19fcdd05a987c272f3e3e24b4ac --- /dev/null +++ b/libabckit/tests/test_args.gni @@ -0,0 +1,17 @@ +# Copyright (c) 2024 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. + +declare_args() +{ + abckit_sanitizers=false +} diff --git a/libabckit/tests/test_helper.gni b/libabckit/tests/test_helper.gni new file mode 100644 index 0000000000000000000000000000000000000000..c59c0a345f51832d2e37b499d8db4544d9c8a305 --- /dev/null +++ b/libabckit/tests/test_helper.gni @@ -0,0 +1,58 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/runtime_core/ark_root.gni") +import("$build_root/test.gni") + +module_output_path = "arkcompiler/runtime_core/libabckit" + +template("host_unittest_action") { + _target_name_ = "${target_name}" + + # unittest for phone running + ohos_unittest(_target_name_) { + forward_variables_from(invoker, "*") + } + + _module_out_path_ = invoker.module_out_path + + # unittest for host running + action("${_target_name_}Action") { + testonly = true + + _host_test_target_ = ":${_target_name_}(${host_toolchain})" + _root_out_dir_ = get_label_info(_host_test_target_, "root_out_dir") + + deps = [ _host_test_target_ ] + + script = "//arkcompiler/ets_runtime/script/run_ark_executable.py" + + args = [ + "--script-file", + rebase_path(_root_out_dir_) + + "/tests/unittest/${_module_out_path_}/${_target_name_}", + "--expect-output", + "0", + "--env-path", + rebase_path(_root_out_dir_) + "/arkcompiler/runtime_core:" + + rebase_path(_root_out_dir_) + "/arkcompiler/ets_runtime:" + + rebase_path(_root_out_dir_) + "/arkcompiler/ets_frontend:" + + rebase_path(_root_out_dir_) + "/thirdparty/icu:" + + rebase_path(_root_out_dir_) + "/thirdparty/zlib:", + "--timeout-limit", + "1200", + ] + + outputs = [ "$target_out_dir/${_target_name_}/" ] + } +} diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests.cpp.erb b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..4b3d3114bf392dc9dfa75be7e06e1b5169abdc3b --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests.cpp.erb @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto <%= domain %> = abckit_Get<%= domain %>(1); + +class LibAbcKitWrongCtxTests<%=domain%><%=iteration%>: public ::testing::Test {}; + +% slice_start = index +% slice_end = index + slice_size +% api_funcs_arr[slice_start..slice_end].each do |api_func| +// Test: test-kind=api, api=<%= domain %>::<%= api_func %>, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTests<%=domain%><%=iteration%>, <%=domain%><%= api_func %>WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(<%= domain %>-><%= api_func %>); +} + +% end +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_ApiImpl_0.cpp b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_ApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aacc1d6b8c7d593f42e7ba2829e8cd4ffe67ba2a --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_ApiImpl_0.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto ApiImpl = abckit_GetApiImpl(1); + +class LibAbcKitWrongCtxTestsApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=ApiImpl::codeToGraph, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsApiImpl0, ApiImplcodeToGraphWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(ApiImpl->codeToGraph); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_GraphApiImpl_0.cpp b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_GraphApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2bb3c21fdaae2676730c039ee17156fb87271e00 --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_GraphApiImpl_0.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto GraphApiImpl = abckit_GetGraphApiImpl(1); + +class LibAbcKitWrongCtxTestsGraphApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstBack, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBaddInstBackWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBaddInstBack); +} + +// Test: test-kind=api, api=GraphApiImpl::BBaddInstFront, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBaddInstFrontWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBaddInstFront); +} + +// Test: test-kind=api, api=GraphApiImpl::BBcheckDominance, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBcheckDominanceWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBcheckDominance); +} + +// Test: test-kind=api, api=GraphApiImpl::BBconnectBlocks, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBconnectBlocksWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBconnectBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBdisconnectBlocks, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBdisconnectBlocksWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBdisconnectBlocks); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetPredBlock, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBsetPredBlockWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBsetPredBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::BBsetSuccBlock, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplBBsetSuccBlockWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->BBsetSuccBlock); +} + +// Test: test-kind=api, api=GraphApiImpl::IappendInput, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplIappendInputWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->IappendInput); +} + +// Test: test-kind=api, api=GraphApiImpl::IcheckDominance, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplIcheckDominanceWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->IcheckDominance); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertAfter, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplIinsertAfterWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->IinsertAfter); +} + +// Test: test-kind=api, api=GraphApiImpl::IinsertBefore, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplIinsertBeforeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->IinsertBefore); +} + +// Test: test-kind=api, api=GraphApiImpl::IsetMethod, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsGraphApiImpl0, GraphApiImplIsetMethodWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(GraphApiImpl->IsetMethod); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_0.cpp b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad8fb10104547a50857bea4de07104edd9253c13 --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_0.cpp @@ -0,0 +1,635 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiDynamicImpl = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitWrongCtxTestsIsaApiDynamicImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAdd2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAdd2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAdd2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAnd2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAnd2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAnd2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateApply, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateApplyWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateApply); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAshr2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAshr2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAshr2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionawaituncaught, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionawaituncaughtWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAsyncfunctionawaituncaught); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionreject, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionrejectWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAsyncfunctionreject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionresolve, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionresolveWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAsyncfunctionresolve); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncgeneratorreject, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncgeneratorrejectWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAsyncgeneratorreject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncgeneratorresolve, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncgeneratorresolveWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateAsyncgeneratorresolve); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg0, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallarg0WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallarg0); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg1, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallarg1WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallarg1); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallargs2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallargs2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs3, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallargs3WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallargs3); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallrange, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallrangeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeCallinit, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeCallinitWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeCallinit); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinefieldbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinefieldbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeDefinefieldbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinefieldbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinefieldbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeDefinefieldbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefineprivateproperty, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefineprivatepropertyWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeDefineprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinesendableclass, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinesendableclassWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeDefinesendableclass); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIsfalse, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeIsfalseWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeIsfalse); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIstrue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeIstrueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeIstrue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeNotifyconcurrentresult, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeNotifyconcurrentresultWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeNotifyconcurrentresult); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeStsendablevar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeStsendablevarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeStsendablevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeTopropertykey, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeTopropertykeyWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeTopropertykey); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWidestsendablevar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWidestsendablevarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallruntimeWidestsendablevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis0, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis0WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallthis0); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis1, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis1WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallthis1); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallthis2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis3, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis3WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallthis3); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthisrange, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthisrangeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCallthisrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCloseiterator, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCloseiteratorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCloseiterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCmp, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCmpWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCmp); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCopydataproperties, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCopydatapropertiesWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCopydataproperties); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateasyncgeneratorobj, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateasyncgeneratorobjWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCreateasyncgeneratorobj); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreategeneratorobj, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreategeneratorobjWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCreategeneratorobj); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateiterresultobj, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateiterresultobjWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCreateiterresultobj); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateobjectwithexcludedkeys, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateobjectwithexcludedkeysWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateCreateobjectwithexcludedkeys); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDec, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDecWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDec); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefineclasswithbuffer, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefineclasswithbufferWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDefineclasswithbuffer); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinefieldbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinefieldbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDefinefieldbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinefunc, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinefuncWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDefinefunc); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinegettersetterbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinegettersetterbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDefinegettersetterbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinemethod, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinemethodWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDefinemethod); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDelobjprop, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDelobjpropWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDelobjprop); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDiv2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDiv2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDiv2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDynamicimport, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDynamicimportWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateDynamicimport); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateEq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateEqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateEq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateExp, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateExpWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateExp); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetasynciterator, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetasynciteratorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGetasynciterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetiterator, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetiteratorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGetiterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetmodulenamespace, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetmodulenamespaceWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGetmodulenamespace); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetnextpropname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetnextpropnameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGetnextpropname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetpropiterator, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetpropiteratorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGetpropiterator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetresumemode, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetresumemodeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGetresumemode); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGettemplateobject, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGettemplateobjectWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGettemplateobject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreater, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGreaterWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGreater); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreatereq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGreatereqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateGreatereq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIf, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIfWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateIf); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInc, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIncWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateInc); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInstanceof, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateInstanceofWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateInstanceof); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsfalse, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIsfalseWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateIsfalse); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsin, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIsinWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateIsin); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIstrue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIstrueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateIstrue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdobjbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdobjbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdprivateproperty, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdprivatepropertyWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsuperbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsuperbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdsuperbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsuperbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsuperbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdsuperbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthisbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdthisbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLdthisbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLess, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLessWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLess); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLesseq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLesseqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateLesseq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMod2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateMod2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateMod2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMul2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateMul2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateMul2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNeg, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateNegWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateNeg); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewobjapply, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateNewobjapplyWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateNewobjapply); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNot, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateNotWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateNot); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNoteq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateNoteqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateNoteq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateOr2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateOr2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateOr2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateResumegenerator, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateResumegeneratorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateResumegenerator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturn, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateReturnWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateReturn); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSetgeneratorstate, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateSetgeneratorstateWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSetgeneratorstate); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSetobjectwithproto, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateSetobjectwithprotoWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSetobjectwithproto); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShl2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateShl2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateShl2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShr2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateShr2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateShr2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStarrayspread, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStarrayspreadWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStarrayspread); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStconsttoglobalrecord, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStconsttoglobalrecordWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStconsttoglobalrecord); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStglobalvar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStglobalvarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStglobalvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStlexvar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStlexvarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStlexvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStmodulevar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStmodulevarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStobjbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStobjbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStobjbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStobjbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStobjbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStownbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStownbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStownbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStownbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbynamewithnameset, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStownbynamewithnamesetWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStownbynamewithnameset); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStownbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStownbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvaluewithnameset, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStownbyvaluewithnamesetWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStownbyvaluewithnameset); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStprivateproperty, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStprivatepropertyWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStprivateproperty); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStricteq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateStricteqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStricteq); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_1.cpp b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a2d0b9ba351ffbcc1d056df002d1ea79ff94e12 --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiDynamicImpl_1.cpp @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiDynamicImpl = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitWrongCtxTestsIsaApiDynamicImpl1: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStricteq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStricteqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStricteq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStrictnoteq, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStrictnoteqWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStrictnoteq); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStsuperbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStsuperbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStsuperbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStsuperbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStsuperbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStsuperbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStthisbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStthisbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStthisbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStthisbyvalue, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStthisbyvalueWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateStthisbyvalue); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSttoglobalrecord, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSttoglobalrecordWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSttoglobalrecord); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSub2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSub2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSub2); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallarrowrange, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallarrowrangeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSupercallarrowrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallspread, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallspreadWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSupercallspread); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSuspendgenerator, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSuspendgeneratorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateSuspendgenerator); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTestin, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTestinWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateTestin); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrow, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateThrow); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowConstassignment, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowConstassignmentWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateThrowConstassignment); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfnotobject, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowIfnotobjectWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateThrowIfnotobject); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfsupernotcorrectcall, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowIfsupernotcorrectcallWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateThrowIfsupernotcorrectcall); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifhole, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowUndefinedifholeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateThrowUndefinedifhole); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifholewithname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowUndefinedifholewithnameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateThrowUndefinedifholewithname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumber, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTonumberWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateTonumber); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumeric, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTonumericWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateTonumeric); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTrystglobalbyname, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTrystglobalbynameWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateTrystglobalbyname); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTypeof, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTypeofWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateTypeof); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallrange, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCallrangeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideCallrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallthisrange, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCallthisrangeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideCallthisrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCreateobjectwithexcludedkeys, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCreateobjectwithexcludedkeysWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideCreateobjectwithexcludedkeys); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideGetmodulenamespace, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideGetmodulenamespaceWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideGetmodulenamespace); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdobjbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdobjbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideLdobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStlexvar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStlexvarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideStlexvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStmodulevar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStmodulevarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideStmodulevar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStobjbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStobjbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideStobjbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStownbyindex, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStownbyindexWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideStownbyindex); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStpatchvar, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStpatchvarWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideStpatchvar); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideSupercallarrowrange, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideSupercallarrowrangeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateWideSupercallarrowrange); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateXor2, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateXor2WrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiDynamicImpl->IcreateXor2); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiStaticImpl_0.cpp b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiStaticImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..effb2273d6efcf9de69d783cce7b7bd95cedeb9b --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_IsaApiStaticImpl_0.cpp @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiStaticImpl = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitWrongCtxTestsIsaApiStaticImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShr, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAShrWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateAShr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShrI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAShrIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateAShrI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAdd, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAddWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateAdd); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAddI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAddIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateAddI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAnd, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAndWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateAnd); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAndI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAndIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateAndI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallStatic, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCallStaticWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateCallStatic); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallVirtual, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCallVirtualWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateCallVirtual); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCast, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCastWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateCast); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCheckCast, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCheckCastWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateCheckCast); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCmp, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCmpWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateCmp); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDiv, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateDivWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateDiv); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDivI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateDivIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateDivI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateEquals, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateEqualsWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateEquals); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIf, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateIfWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateIf); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateInitObjectWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateInitObject); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIsInstance, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateIsInstanceWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateIsInstance); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLenArray, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLenArrayWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateLenArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadArray, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadArrayWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateLoadArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMod, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateModWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateMod); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateModI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateModIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateModI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMul, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateMulWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateMul); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMulI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateMulIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateMulI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNeg, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNegWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateNeg); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewArray, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNewArrayWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateNewArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewObject, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNewObjectWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateNewObject); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNot, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNotWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateNot); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOr, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateOrWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateOr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOrI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateOrIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateOrI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturn, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateReturnWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateReturn); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShl, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShlWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateShl); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShlI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShlIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateShlI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShr, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShrWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateShr); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShrI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShrIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateShrI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArray, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateStoreArrayWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateStoreArray); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArrayWide, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateStoreArrayWideWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateStoreArrayWide); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSub, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateSubWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateSub); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSubI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateSubIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateSubI); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateThrow, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateThrowWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateThrow); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXor, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateXorWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateXor); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXorI, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateXorIWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(IsaApiStaticImpl->IcreateXorI); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_ModifyApiImpl_0.cpp b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_ModifyApiImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..19b0614b364ea6a7668d2918dae69f7ef790b770 --- /dev/null +++ b/libabckit/tests/wrong_ctx_tests/wrong_ctx_tests_ModifyApiImpl_0.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by wrong_ctx_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "metadata.h" +#include "ir_core.h" + +#include "helpers/helpers.h" +#include "helpers/helpers_wrong_ctx.h" + +#include + +namespace libabckit { +namespace test { + +static auto ModifyApiImpl = abckit_GetModifyApiImpl(1); + +class LibAbcKitWrongCtxTestsModifyApiImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=ModifyApiImpl::MethodSetCode, abc-kind=NoABC, category=negative-ctx +TEST_F(LibAbcKitWrongCtxTestsModifyApiImpl0, ModifyApiImplMethodSetCodeWrongCtx) +{ + helpers_wrong_ctx::TestWrongCtx(ModifyApiImpl->MethodSetCode); +} + +} // namespace test +} // namespace libabckit diff --git a/libabckit/tests/wrong_mode_tests/mode_test_dynamic.js b/libabckit/tests/wrong_mode_tests/mode_test_dynamic.js new file mode 100644 index 0000000000000000000000000000000000000000..cfdafaa6155f876203097b40f07f38ff2496454a --- /dev/null +++ b/libabckit/tests/wrong_mode_tests/mode_test_dynamic.js @@ -0,0 +1,5 @@ +function foo(a, b, c, d, e, f) { + print("func") +} + +o = [1, 2, "str"] diff --git a/libabckit/tests/wrong_mode_tests/mode_test_static.ets b/libabckit/tests/wrong_mode_tests/mode_test_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..15b30934438ea6fbac74e8c9a3afc0f8250711fb --- /dev/null +++ b/libabckit/tests/wrong_mode_tests/mode_test_static.ets @@ -0,0 +1 @@ +function foo():void {} \ No newline at end of file diff --git a/libabckit/tests/wrong_mode_tests/wrong_mode_tests.cpp.erb b/libabckit/tests/wrong_mode_tests/wrong_mode_tests.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..212e318996cfe8e85207f835c8b7ca13e0eae768 --- /dev/null +++ b/libabckit/tests/wrong_mode_tests/wrong_mode_tests.cpp.erb @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers_mode.h" + +#include + +namespace libabckit { +namespace test { + +static auto <%= domain %> = abckit_Get<%= domain %>(1); + +class LibAbcKitWrongModeTests<%=domain%><%=iteration%>: public ::testing::Test {}; + +% slice_start = index +% slice_end = index + slice_size +% api_funcs_arr[slice_start..slice_end].each do |api_func| +// Test: test-kind=api, api=<%= domain %>::<%= api_func %>, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTests<%=domain%><%=iteration%>, <%= domain %><%= api_func %>Mod) +{ + helpers_mode::TestMode(<%= domain %>-><%= api_func %>, <%= domain.include? "IsaApiDynamicImpl" %>); +} + +% end +} // namespace test +} // namespace libabckit \ No newline at end of file diff --git a/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_0.cpp b/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25fbc52306b4e5f2cdceb60b4ff53ca34a020b7e --- /dev/null +++ b/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_0.cpp @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers_mode.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiDynamicImpl = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitWrongModeTestsIsaApiDynamicImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAdd2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAdd2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAdd2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAnd2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAnd2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAnd2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateApply, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateApplyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateApply, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAshr2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAshr2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAshr2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionawaituncaught, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionawaituncaughtMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAsyncfunctionawaituncaught, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionenter, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionenterMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAsyncfunctionenter, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionreject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionrejectMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAsyncfunctionreject, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncfunctionresolve, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncfunctionresolveMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAsyncfunctionresolve, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncgeneratorreject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncgeneratorrejectMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAsyncgeneratorreject, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateAsyncgeneratorresolve, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateAsyncgeneratorresolveMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateAsyncgeneratorresolve, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg0, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallarg0Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallarg0, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallarg1, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallarg1Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallarg1, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallargs2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallargs2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallargs3, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallargs3Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallargs3, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeCallinit, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeCallinitMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeCallinit, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeCreateprivateproperty, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeCreateprivatepropertyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeCreateprivateproperty, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinefieldbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinefieldbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeDefinefieldbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinefieldbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinefieldbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeDefinefieldbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefineprivateproperty, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefineprivatepropertyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeDefineprivateproperty, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeDefinesendableclass, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeDefinesendableclassMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeDefinesendableclass, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIsfalse, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeIsfalseMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeIsfalse, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeIstrue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeIstrueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeIstrue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeLdsendableclass, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeLdsendableclassMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeLdsendableclass, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeLdsendableexternalmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeLdsendableexternalmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeLdsendableexternalmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeLdsendablevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeLdsendablevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeLdsendablevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeNewsendableenv, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeNewsendableenvMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeNewsendableenv, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeNotifyconcurrentresult, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeNotifyconcurrentresultMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeNotifyconcurrentresult, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeStsendablevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeStsendablevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeStsendablevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeTopropertykey, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeTopropertykeyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeTopropertykey, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWideldsendableexternalmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWideldsendableexternalmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeWideldsendableexternalmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWideldsendablevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWideldsendablevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeWideldsendablevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWidenewsendableenv, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWidenewsendableenvMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeWidenewsendableenv, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallruntimeWidestsendablevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallruntimeWidestsendablevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallruntimeWidestsendablevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis0, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis0Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallthis0, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis1, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis1Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallthis1, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallthis2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthis3, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthis3Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallthis3, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCallthisrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCallthisrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCallthisrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCatchPhi, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCatchPhiMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCatchPhi, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCloseiterator, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCloseiteratorMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCloseiterator, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCmp, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCmpMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCmp, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCopydataproperties, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCopydatapropertiesMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCopydataproperties, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCopyrestargs, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCopyrestargsMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCopyrestargs, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreatearraywithbuffer, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreatearraywithbufferMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreatearraywithbuffer, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateasyncgeneratorobj, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateasyncgeneratorobjMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateasyncgeneratorobj, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateemptyarray, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateemptyarrayMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateemptyarray, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateemptyobject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateemptyobjectMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateemptyobject, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreategeneratorobj, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreategeneratorobjMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreategeneratorobj, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateiterresultobj, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateiterresultobjMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateiterresultobj, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateobjectwithbuffer, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateobjectwithbufferMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateobjectwithbuffer, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateobjectwithexcludedkeys, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateobjectwithexcludedkeysMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateobjectwithexcludedkeys, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateCreateregexpwithliteral, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateCreateregexpwithliteralMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateCreateregexpwithliteral, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDebugger, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDebuggerMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDebugger, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDec, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDecMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDec, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefineclasswithbuffer, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefineclasswithbufferMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDefineclasswithbuffer, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinefieldbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinefieldbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDefinefieldbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinefunc, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinefuncMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDefinefunc, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinegettersetterbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinegettersetterbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDefinegettersetterbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDefinemethod, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDefinemethodMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDefinemethod, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDelobjprop, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDelobjpropMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDelobjprop, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDiv2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDiv2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDiv2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateDynamicimport, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateDynamicimportMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateDynamicimport, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateEq, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateEqMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateEq, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateExp, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateExpMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateExp, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetasynciterator, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetasynciteratorMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetasynciterator, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetiterator, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetiteratorMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetiterator, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetmodulenamespace, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetmodulenamespaceMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetmodulenamespace, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetnextpropname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetnextpropnameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetnextpropname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetpropiterator, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetpropiteratorMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetpropiterator, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetresumemode, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetresumemodeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetresumemode, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGettemplateobject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGettemplateobjectMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGettemplateobject, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGetunmappedargs, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGetunmappedargsMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGetunmappedargs, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreater, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGreaterMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGreater, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateGreatereq, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateGreatereqMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateGreatereq, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIf, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIfMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateIf, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInc, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIncMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateInc, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateInstanceof, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateInstanceofMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateInstanceof, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsfalse, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIsfalseMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateIsfalse, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIsin, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIsinMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateIsin, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateIstrue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateIstrueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateIstrue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdbigint, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdbigintMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdbigint, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdexternalmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdexternalmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdexternalmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfalse, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdfalseMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdfalse, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdfunction, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdfunctionMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdfunction, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobal, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdglobalMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdglobal, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdglobalvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdglobalvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdglobalvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdhole, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdholeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdhole, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdinfinity, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdinfinityMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdinfinity, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdlexvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdlexvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdlexvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdlocalmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdlocalmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdlocalmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnan, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdnanMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdnan, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnewtarget, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdnewtargetMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdnewtarget, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdnull, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdnullMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdnull, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdobjbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdobjbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdobjbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdobjbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdobjbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdprivateproperty, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdprivatepropertyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdprivateproperty, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsuperbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsuperbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdsuperbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsuperbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsuperbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdsuperbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsymbol, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl0, IsaApiDynamicImplIcreateLdsymbolMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdsymbol, true); +} + +} // namespace test +} // namespace libabckit \ No newline at end of file diff --git a/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_1.cpp b/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3577915f9de3a376b8b6cb64285b0e6655732fdf --- /dev/null +++ b/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiDynamicImpl_1.cpp @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers_mode.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiDynamicImpl = abckit_GetIsaApiDynamicImpl(1); + +class LibAbcKitWrongModeTestsIsaApiDynamicImpl1: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdsymbol, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdsymbolMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdsymbol, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthis, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdthisMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdthis, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthisbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdthisbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdthisbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdthisbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdthisbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdthisbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdtrue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdtrueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdtrue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLdundefined, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLdundefinedMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLdundefined, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLess, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLessMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLess, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLesseq, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLesseqMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLesseq, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateLoadString, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateLoadStringMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateLoadString, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMod2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateMod2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateMod2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateMul2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateMul2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateMul2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNeg, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNegMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNeg, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewlexenv, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewlexenvMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNewlexenv, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewlexenvwithname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewlexenvwithnameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNewlexenvwithname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewobjapply, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewobjapplyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNewobjapply, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNewobjrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNewobjrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNewobjrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNot, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNotMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNot, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateNoteq, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateNoteqMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateNoteq, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateOr2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateOr2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateOr2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreatePoplexenv, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreatePoplexenvMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreatePoplexenv, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateResumegenerator, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateResumegeneratorMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateResumegenerator, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturn, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateReturnMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateReturn, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateReturnundefined, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateReturnundefinedMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateReturnundefined, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSetgeneratorstate, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSetgeneratorstateMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSetgeneratorstate, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSetobjectwithproto, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSetobjectwithprotoMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSetobjectwithproto, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShl2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateShl2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateShl2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateShr2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateShr2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateShr2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStarrayspread, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStarrayspreadMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStarrayspread, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStconsttoglobalrecord, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStconsttoglobalrecordMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStconsttoglobalrecord, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStglobalvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStglobalvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStglobalvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStlexvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStlexvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStlexvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStobjbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStobjbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStobjbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStobjbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStobjbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStobjbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStobjbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStownbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStownbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbynamewithnameset, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbynamewithnamesetMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStownbynamewithnameset, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStownbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStownbyvaluewithnameset, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStownbyvaluewithnamesetMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStownbyvaluewithnameset, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStprivateproperty, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStprivatepropertyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStprivateproperty, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStricteq, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStricteqMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStricteq, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStrictnoteq, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStrictnoteqMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStrictnoteq, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStsuperbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStsuperbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStsuperbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStsuperbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStsuperbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStsuperbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStthisbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStthisbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStthisbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateStthisbyvalue, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateStthisbyvalueMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateStthisbyvalue, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSttoglobalrecord, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSttoglobalrecordMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSttoglobalrecord, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSub2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSub2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSub2, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallarrowrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallarrowrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSupercallarrowrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallspread, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallspreadMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSupercallspread, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSupercallthisrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSupercallthisrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSupercallthisrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateSuspendgenerator, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateSuspendgeneratorMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateSuspendgenerator, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTestin, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTestinMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateTestin, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrow, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrow, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowConstassignment, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowConstassignmentMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowConstassignment, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowDeletesuperproperty, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowDeletesuperpropertyMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowDeletesuperproperty, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfnotobject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowIfnotobjectMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowIfnotobject, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowIfsupernotcorrectcall, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowIfsupernotcorrectcallMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowIfsupernotcorrectcall, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowNotexists, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowNotexistsMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowNotexists, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowPatternnoncoercible, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowPatternnoncoercibleMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowPatternnoncoercible, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifhole, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowUndefinedifholeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowUndefinedifhole, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateThrowUndefinedifholewithname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateThrowUndefinedifholewithnameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateThrowUndefinedifholewithname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumber, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTonumberMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateTonumber, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTonumeric, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTonumericMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateTonumeric, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTryldglobalbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTryldglobalbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateTryldglobalbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTrystglobalbyname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTrystglobalbynameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateTrystglobalbyname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateTypeof, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateTypeofMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateTypeof, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCallrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideCallrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCallthisrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCallthisrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideCallthisrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCopyrestargs, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCopyrestargsMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideCopyrestargs, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideCreateobjectwithexcludedkeys, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideCreateobjectwithexcludedkeysMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideCreateobjectwithexcludedkeys, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideGetmodulenamespace, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideGetmodulenamespaceMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideGetmodulenamespace, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdexternalmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdexternalmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideLdexternalmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdlexvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdlexvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideLdlexvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdlocalmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdlocalmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideLdlocalmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdobjbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdobjbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideLdobjbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideLdpatchvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideLdpatchvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideLdpatchvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideNewlexenv, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideNewlexenvMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideNewlexenv, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideNewlexenvwithname, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideNewlexenvwithnameMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideNewlexenvwithname, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideNewobjrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideNewobjrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideNewobjrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStlexvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStlexvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideStlexvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStmodulevar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStmodulevarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideStmodulevar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStobjbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStobjbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideStobjbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStownbyindex, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStownbyindexMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideStownbyindex, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideStpatchvar, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideStpatchvarMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideStpatchvar, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideSupercallarrowrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideSupercallarrowrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideSupercallarrowrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateWideSupercallthisrange, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateWideSupercallthisrangeMod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateWideSupercallthisrange, true); +} + +// Test: test-kind=api, api=IsaApiDynamicImpl::IcreateXor2, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiDynamicImpl1, IsaApiDynamicImplIcreateXor2Mod) +{ + helpers_mode::TestMode(IsaApiDynamicImpl->IcreateXor2, true); +} + +} // namespace test +} // namespace libabckit \ No newline at end of file diff --git a/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiStaticImpl_0.cpp b/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiStaticImpl_0.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b80dfbb4e255f08febae760e9e163d70babf34a --- /dev/null +++ b/libabckit/tests/wrong_mode_tests/wrong_mode_tests_IsaApiStaticImpl_0.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2024 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. + */ + +// Autogenerated file by gen_null_arg_tests.rb script -- DO NOT EDIT! + +#include "abckit.h" +#include "ir_core.h" +#include "isa/isa_dynamic.h" +#include "isa/isa_static.h" + +#include "helpers/helpers_mode.h" + +#include + +namespace libabckit { +namespace test { + +static auto IsaApiStaticImpl = abckit_GetIsaApiStaticImpl(1); + +class LibAbcKitWrongModeTestsIsaApiStaticImpl0: public ::testing::Test {}; + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShr, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAShrMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateAShr, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAShrI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAShrIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateAShrI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAdd, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAddMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateAdd, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAddI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAddIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateAddI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAnd, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAndMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateAnd, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateAndI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateAndIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateAndI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallStatic, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCallStaticMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateCallStatic, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCallVirtual, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCallVirtualMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateCallVirtual, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCast, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCastMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateCast, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCatchPhi, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCatchPhiMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateCatchPhi, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCheckCast, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCheckCastMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateCheckCast, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateCmp, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateCmpMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateCmp, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDiv, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateDivMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateDiv, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateDivI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateDivIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateDivI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateEquals, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateEqualsMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateEquals, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIf, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateIfMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateIf, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateInitObject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateInitObjectMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateInitObject, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateIsInstance, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateIsInstanceMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateIsInstance, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLenArray, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLenArrayMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateLenArray, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadArray, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadArrayMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateLoadArray, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadConstArray, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadConstArrayMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateLoadConstArray, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadString, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadStringMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateLoadString, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateLoadUndefined, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateLoadUndefinedMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateLoadUndefined, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMod, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateModMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateMod, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateModI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateModIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateModI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMul, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateMulMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateMul, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateMulI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateMulIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateMulI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNeg, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNegMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateNeg, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewArray, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNewArrayMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateNewArray, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNewObject, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNewObjectMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateNewObject, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateNot, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateNotMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateNot, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOr, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateOrMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateOr, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateOrI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateOrIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateOrI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturn, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateReturnMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateReturn, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateReturnVoid, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateReturnVoidMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateReturnVoid, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShl, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShlMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateShl, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShlI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShlIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateShlI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShr, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShrMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateShr, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateShrI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateShrIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateShrI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArray, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateStoreArrayMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateStoreArray, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateStoreArrayWide, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateStoreArrayWideMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateStoreArrayWide, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSub, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateSubMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateSub, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateSubI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateSubIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateSubI, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateThrow, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateThrowMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateThrow, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXor, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateXorMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateXor, false); +} + +// Test: test-kind=api, api=IsaApiStaticImpl::IcreateXorI, abc-kind=NoABC, category=negative-mode +TEST_F(LibAbcKitWrongModeTestsIsaApiStaticImpl0, IsaApiStaticImplIcreateXorIMod) +{ + helpers_mode::TestMode(IsaApiStaticImpl->IcreateXorI, false); +} + +} // namespace test +} // namespace libabckit \ No newline at end of file diff --git a/libpandabase/BUILD.gn b/libpandabase/BUILD.gn index e34d12a3bd74307901180e48a33f3a42575de4a9..ad144eb2ac7852f9b3b673bbc7c67131c65556d6 100644 --- a/libpandabase/BUILD.gn +++ b/libpandabase/BUILD.gn @@ -26,6 +26,8 @@ config("arkbase_public_config") { } include_dirs += platform_include_dirs + + configs = [ sdk_libc_secshared_config ] } config("arkbase_fuzz_config") { diff --git a/libpandafile/helpers.h b/libpandafile/helpers.h index f8dcbe388a1e63943f4725eda3c9abf07bba5586..05a5ac236b27a14ed41ad603b46c33d59a0972f2 100644 --- a/libpandafile/helpers.h +++ b/libpandafile/helpers.h @@ -16,7 +16,6 @@ #ifndef LIBPANDAFILE_HELPERS_H #define LIBPANDAFILE_HELPERS_H -#include "macros.h" #include "utils/bit_helpers.h" #include "utils/leb128.h" #include "utils/logger.h" diff --git a/static_core/BUILD.gn b/static_core/BUILD.gn index 30b32ffa1c7cc533e04a62333fe27bfccc65680f..d0eb10bb0da344ff8e3d9108ce8150848139697d 100644 --- a/static_core/BUILD.gn +++ b/static_core/BUILD.gn @@ -124,6 +124,12 @@ config("ark_config") { "$ark_third_party_root/asmjit:*", "$ark_third_party_root/vixl:*", "./*", + "//arkcompiler/runtime_core/libabckit:*", # FIXME + "//arkcompiler/runtime_core/libabckit/src/codegen:*", + "//arkcompiler/runtime_core/libabckit/src/mem_manager:*", + "//arkcompiler/runtime_core/libabckit/src/adapter_dynamic:*", + "//arkcompiler/runtime_core/libabckit/src/irbuilder_dynamic:*", + "//arkcompiler/runtime_core/libabckit/src/wrappers/graph_wrapper:*" ] } diff --git a/static_core/CMakeLists.txt b/static_core/CMakeLists.txt index 4d04d548e9929ec69d5575a6e46780945f6bd9da..fafcea99ffc5f95e38daeadb04968ac4911d9910 100644 --- a/static_core/CMakeLists.txt +++ b/static_core/CMakeLists.txt @@ -254,6 +254,7 @@ if(PANDA_WITH_TOOLCHAIN) add_subdirectory(libpandafile/external) endif() + add_subdirectory(abc2program) add_subdirectory(assembler) add_subdirectory(disassembler) diff --git a/static_core/abc2program/Abc2ProgramPostPlugins.cmake b/static_core/abc2program/Abc2ProgramPostPlugins.cmake new file mode 100644 index 0000000000000000000000000000000000000000..cd825c485372bbce1e31aba83b914dfe3196bc41 --- /dev/null +++ b/static_core/abc2program/Abc2ProgramPostPlugins.cmake @@ -0,0 +1,40 @@ +# Copyright (c) 2024 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. + +set(ABC2PROGRAM_PLUGINS_INC ${PANDA_BINARY_ROOT}/abc2program/abc2program_plugins.inc) +panda_gen_file( + DATA ${GEN_PLUGIN_OPTIONS_YAML} + TEMPLATE ${PANDA_ROOT}/abc2program/templates/abc2program_plugins.inc.erb + API ${PANDA_ROOT}/templates/plugin_options.rb + EXTRA_DEPENDENCIES plugin_options_merge + OUTPUTFILE ${ABC2PROGRAM_PLUGINS_INC} +) + +set(GET_LANGUAGE_SPECIFIC_METADATA_INC ${PANDA_BINARY_ROOT}/abc2program/get_language_specific_metadata.inc) +panda_gen_file( + DATA ${GEN_PLUGIN_OPTIONS_YAML} + TEMPLATE ${PANDA_ROOT}/abc2program/templates/get_language_specific_metadata.inc.erb + API ${PANDA_ROOT}/templates/plugin_options.rb + EXTRA_DEPENDENCIES plugin_options_merge + OUTPUTFILE ${GET_LANGUAGE_SPECIFIC_METADATA_INC} +) + + +add_custom_target(abc2program_plugin_gen DEPENDS + plugin_options_gen + ${ABC2PROGRAM_PLUGINS_INC} + ${GET_LANGUAGE_SPECIFIC_METADATA_INC} +) + +add_dependencies(abc2program abc2program_plugin_gen) +add_dependencies(panda_gen_files abc2program_plugin_gen) \ No newline at end of file diff --git a/static_core/abc2program/BUILD.gn b/static_core/abc2program/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..ae945189193c5722f588a42eb4e7440927fc88cb --- /dev/null +++ b/static_core/abc2program/BUILD.gn @@ -0,0 +1,159 @@ +# Copyright (c) 2024-2025 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. + +import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") +import("//build/ohos.gni") +import("$ark_root/plugins/plugins.gni") + +abc2program_sources = [ + "$target_gen_dir/abc_inst_convert.cpp", + "$target_gen_dir/abc_opcode_convert.cpp", + "$target_gen_dir/abc_type_convert.cpp", + "abc2program_compiler.cpp", + "abc2program_driver.cpp", + "abc2program_key_data.cpp", + "abc2program_log.cpp", + "abc2program_options.cpp", + "abc_class_processor.cpp", + "abc_code_processor.cpp", + "abc_debug_info_processor.cpp", + "abc_field_processor.cpp", + "abc_file_entity_processor.cpp", + "abc_file_processor.cpp", + "abc_file_utils.cpp", + "abc_literal_array_processor.cpp", + "abc_method_processor.cpp", + "abc_string_table.cpp", + "common/abc_code_converter.cpp", + "program_dump.cpp", +] +abc2program_sources += plugin_abc2program_sources + +abc2program_configs = [ + "$ark_root:ark_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandafile:arkfile_public_config", +] + +ohos_shared_library("arkts_abc2program") { + deps = [ ":abc2program_frontend_static" ] + + if (!is_standard_system) { + relative_install_dir = "ark" + } + output_extension = "so" + if (is_mingw) { + output_extension = "dll" + } + + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +ohos_static_library("abc2program_frontend_static") { + stack_protector_ret = false + sources = abc2program_sources + + include_dirs = [ + "$ark_root/abc2program", + "$target_gen_dir", + ] + + configs = abc2program_configs + + deps = [ + ":abc_type_convert_cpp", + ":abc2program_plugins_inc", + ":get_language_specific_metadata_inc", + ":isa_gen_abc2program_abc_inst_convert_cpp", + ":isa_gen_abc2program_abc_opcode_convert_cpp", + "$ark_root/assembler:libarktsassembler_frontend_static", + "$ark_root/libpandabase:libarktsbase_frontend_static", + "$ark_root/libpandafile:libarktsfile_frontend_static", + ] + + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +ohos_executable("arkts_abc2prog") { + sources = [ "abc2prog_main.cpp" ] + + include_dirs = [ + "$target_gen_dir", + "$root_gen_dir/libpandabase", + ] + + configs = [ + "$ark_root:ark_config", + "$ark_root/assembler:arkassembler_public_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", + ] + + deps = [ + ":abc2program_frontend_static", + "$ark_root/assembler:libarktsassembler_frontend_static", + "$ark_root/libpandabase:libarktsbase_frontend_static", + "$ark_root/libpandafile:libarktsfile_frontend_static", + ] + + libs = platform_libs + if (!is_mac && !is_mingw) { + ldflags = platform_ldflags + } + + install_enable = false + part_name = "runtime_core" + subsystem_name = "arkcompiler" +} + +ark_isa_gen("isa_gen_abc2program") { + template_files = [ + "abc_opcode_convert.cpp.erb", + "abc_inst_convert.cpp.erb", + ] + sources = "templates" + destination = "$target_gen_dir" + requires = [ + "$ark_root//assembler/asm_isapi.rb", + "$ark_root//libpandafile/pandafile_isapi.rb", + ] +} + +ark_gen_file("abc_type_convert_cpp") { + template_file = "$ark_root/abc2program/templates/abc_type_convert.cpp.erb" + data = [ "$ark_root/libpandafile/types.yaml" ] + api = [ "$ark_root/libpandafile/types.rb" ] + output_file = "$target_gen_dir/abc_type_convert.cpp" +} + +ark_gen_file("abc2program_plugins_inc") { + extra_dependencies = [ "$ark_root:concat_plugins_yamls" ] + template_file = + "templates/abc2program_plugins.inc.erb" + data = [ ark_plugin_options_yaml ] + api = [ "$ark_root/templates/plugin_options.rb" ] + output_file = "$target_gen_dir/abc2program_plugins.inc" +} + +ark_gen_file("get_language_specific_metadata_inc") { + extra_dependencies = [ "$ark_root:concat_plugins_yamls" ] + template_file = + "templates/get_language_specific_metadata.inc.erb" + data = [ ark_plugin_options_yaml ] + api = [ "$ark_root/templates/plugin_options.rb" ] + output_file = "$target_gen_dir/get_language_specific_metadata.inc" +} diff --git a/static_core/abc2program/CMakeLists.txt b/static_core/abc2program/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8ccf9c3094cb6af8312a63922e5882571fe8a145 --- /dev/null +++ b/static_core/abc2program/CMakeLists.txt @@ -0,0 +1,84 @@ +# Copyright (c) 2024 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. + +cmake_minimum_required(VERSION 3.3.2 FATAL_ERROR) +project(abc2program CXX) + +set(SOURCES + abc_type_convert.cpp + abc_opcode_convert.cpp + abc_inst_convert.cpp + abc2program_compiler.cpp + abc2program_driver.cpp + abc2program_key_data.cpp + abc2program_log.cpp + abc2program_options.cpp + abc_class_processor.cpp + abc_code_processor.cpp + abc_debug_info_processor.cpp + abc_field_processor.cpp + abc_file_entity_processor.cpp + abc_file_processor.cpp + abc_file_utils.cpp + abc_literal_array_processor.cpp + abc_method_processor.cpp + abc_string_table.cpp + common/abc_code_converter.cpp + program_dump.cpp +) + +panda_isa_gen( + TEMPLATES + "abc_opcode_convert.cpp.erb" + "abc_inst_convert.cpp.erb" + REQUIRES + "${PANDA_ROOT}/assembler/asm_isapi.rb" + "${PANDA_ROOT}/libpandafile/pandafile_isapi.rb" +) + +set(ABC_TYPE_CONVERT_CPP ${CMAKE_CURRENT_BINARY_DIR}/abc_type_convert.cpp) +panda_gen_file( + DATA ${PANDA_ROOT}/libpandafile/types.yaml + TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/templates/abc_type_convert.cpp.erb + OUTPUTFILE ${ABC_TYPE_CONVERT_CPP} + API ${PANDA_ROOT}/libpandafile/types.rb +) +add_custom_target(abc_type_convert_cpp DEPENDS ${ABC_TYPE_CONVERT_CPP}) +add_dependencies(panda_gen_files abc_type_convert_cpp) + +panda_add_library(abc2program SHARED ${SOURCES}) +panda_target_include_directories(abc2program + PUBLIC ${CMAKE_CURRENT_BINARY_DIR} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} +) +add_dependencies(abc2program + abc_type_convert_cpp + isa_gen_abc2program +) +panda_target_link_libraries(abc2program + arkbase + arkfile + arkassembler +) +add_dependencies(abc2program merge_plugins) + +panda_add_executable(abc2prog abc2prog_main.cpp) +panda_target_link_libraries(abc2prog abc2program) + +target_include_directories(abc2program PUBLIC + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR}/libpandabase +) + +add_subdirectory(tests) diff --git a/static_core/abc2program/abc2prog_main.cpp b/static_core/abc2program/abc2prog_main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d9651a385d8125321af4cca8fb244521b8e0f6b --- /dev/null +++ b/static_core/abc2program/abc2prog_main.cpp @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2024-2025 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 "abc2program_driver.h" + +int main(int argc, const char **argv) +{ + ark::abc2program::Abc2ProgramDriver driver; + return driver.Run(argc, argv); +} diff --git a/static_core/abc2program/abc2program_compiler.cpp b/static_core/abc2program/abc2program_compiler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0269f82c26c243f5142ce7cfdab77f7cc10c731c --- /dev/null +++ b/static_core/abc2program/abc2program_compiler.cpp @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2024-2025 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 "abc2program_compiler.h" +#include +#include "abc_file_processor.h" + +namespace ark::abc2program { + +bool Abc2ProgramCompiler::OpenAbcFile(const std::string &filePath) +{ + file_ = panda_file::File::Open(filePath); + if (file_ == nullptr) { + std::cerr << "Unable to open specified abc file " << filePath << std::endl; + return false; + } + stringTable_ = std::make_unique(*file_); + return true; +} + +const panda_file::File &Abc2ProgramCompiler::GetAbcFile() const +{ + return *file_; +} + +AbcStringTable &Abc2ProgramCompiler::GetAbcStringTable() const +{ + return *stringTable_; +} + +bool Abc2ProgramCompiler::FillProgramData(pandasm::Program &program) +{ + keyData_ = std::make_unique(*file_, *stringTable_, program); + AbcFileProcessor fileProcessor(*keyData_); + bool success = fileProcessor.ProcessFile(); + return success; +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc2program_compiler.h b/static_core/abc2program/abc2program_compiler.h new file mode 100644 index 0000000000000000000000000000000000000000..d1e58e6a5385cd0d1d11452bfd11779f318bdf12 --- /dev/null +++ b/static_core/abc2program/abc2program_compiler.h @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC2PROGRAM_COMPILER_H +#define ABC2PROGRAM_ABC2PROGRAM_COMPILER_H + +#include +#include +#include "abc_string_table.h" +#include "abc2program_key_data.h" + +namespace ark::abc2program { + +class Abc2ProgramCompiler { +public: + bool OpenAbcFile(const std::string &filePath); + const panda_file::File &GetAbcFile() const; + AbcStringTable &GetAbcStringTable() const; + bool FillProgramData(pandasm::Program &program); + +private: + std::unique_ptr file_; + std::unique_ptr stringTable_; + std::unique_ptr keyData_; +}; // class Abc2ProgramCompiler + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC2PROGRAM_COMPILER_H diff --git a/static_core/abc2program/abc2program_driver.cpp b/static_core/abc2program/abc2program_driver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7567b31e07e8716d52110ca0f08aff2fad25d43f --- /dev/null +++ b/static_core/abc2program/abc2program_driver.cpp @@ -0,0 +1,74 @@ +/** + * Copyright (c) 2024-2025 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 "abc2program_driver.h" +#include "program_dump.h" +#include "abc2program_options.h" + +namespace ark::abc2program { + +int Abc2ProgramDriver::Run(int argc, const char **argv) +{ + Abc2ProgramOptions options; + if (!options.Parse(argc, argv)) { + return 1; + } + if (Run(options.GetInputFilePath(), options.GetOutputFilePath())) { + return 0; + } + return 1; +} + +bool Abc2ProgramDriver::Run(const std::string &inputFilePath, const std::string &outputFilePath) +{ + return (Compile(inputFilePath) && Dump(outputFilePath)); +} + +bool Abc2ProgramDriver::Compile(const std::string &inputFilePath) +{ + return Compile(inputFilePath, program_); +} + +bool Abc2ProgramDriver::Compile(const std::string &inputFilePath, pandasm::Program &program) +{ + // abc file compile logic + if (!compiler_.OpenAbcFile(inputFilePath)) { + return false; + } + return compiler_.FillProgramData(program); +} + +bool Abc2ProgramDriver::Dump(const std::string &outputFilePath) +{ + // program dump logic + std::ofstream ofs; + ofs.open(outputFilePath, std::ios::trunc | std::ios::out); + PandasmProgramDumper dumper(compiler_.GetAbcFile(), compiler_.GetAbcStringTable()); + dumper.Dump(ofs, program_); + ofs.close(); + return true; +} + +const pandasm::Program &Abc2ProgramDriver::GetProgram() const +{ + return program_; +} + +pandasm::Program &Abc2ProgramDriver::GetProgram() +{ + return program_; +} + +} // namespace ark::abc2program \ No newline at end of file diff --git a/static_core/abc2program/abc2program_driver.h b/static_core/abc2program/abc2program_driver.h new file mode 100644 index 0000000000000000000000000000000000000000..9f816195ae6fff1f7bf47b645565b2d09636019d --- /dev/null +++ b/static_core/abc2program/abc2program_driver.h @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC2PROGRAM_DRIVER_H +#define ABC2PROGRAM_ABC2PROGRAM_DRIVER_H + +#include +#include +#include "abc2program_compiler.h" + +namespace ark::abc2program { + +class Abc2ProgramDriver { +public: + int Run(int argc, const char **argv); + bool Run(const std::string &inputFilePath, const std::string &outputFilePath); + bool Compile(const std::string &inputFilePath); + const pandasm::Program &GetProgram() const; + pandasm::Program &GetProgram(); + +private: + bool Dump(const std::string &outputFilePath); + bool Compile(const std::string &inputFilePath, pandasm::Program &program); + Abc2ProgramCompiler compiler_; + pandasm::Program program_; +}; // class Abc2ProgramDriver + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC2PROGRAM_DRIVER_H diff --git a/static_core/abc2program/abc2program_key_data.cpp b/static_core/abc2program/abc2program_key_data.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f002215fd23d55c0b5950b609b1c144574d6ac78 --- /dev/null +++ b/static_core/abc2program/abc2program_key_data.cpp @@ -0,0 +1,77 @@ +/** + * Copyright (c) 2024-2025 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 "abc2program_key_data.h" +#include "method_data_accessor.h" + +namespace ark::abc2program { + +const panda_file::File &Abc2ProgramKeyData::GetAbcFile() const +{ + return file_; +} + +AbcStringTable &Abc2ProgramKeyData::GetAbcStringTable() const +{ + return stringTable_; +} + +pandasm::Program &Abc2ProgramKeyData::GetProgram() const +{ + return program_; +} + +std::string Abc2ProgramKeyData::GetFullRecordNameById(const panda_file::File::EntityId &classId) const +{ + std::string name = stringTable_.GetStringById(classId); + pandasm::Type type = pandasm::Type::FromDescriptor(name); + return type.GetPandasmName(); +} + +std::string Abc2ProgramKeyData::GetFullFunctionNameById(const panda_file::File::EntityId &methodId) const +{ + ark::panda_file::MethodDataAccessor methodAccessor(file_, methodId); + + const auto methodNameRaw = stringTable_.GetStringById(methodAccessor.GetNameId()); + + std::string className = GetFullRecordNameById(methodAccessor.GetClassId()); + if (IsSystemType(className)) { + className = ""; + } else { + className += "."; + } + + return className + methodNameRaw; +} + +inline bool Abc2ProgramKeyData::IsSystemType(const std::string &typeName) const +{ + bool isArrayType = typeName.back() == ']'; + bool isGlobal = typeName == "_GLOBAL"; + + return isArrayType || isGlobal; +} + +ark::panda_file::SourceLang Abc2ProgramKeyData::GetFileLanguage() const +{ + return fileLanguage_; +} + +void Abc2ProgramKeyData::SetFileLanguage(ark::panda_file::SourceLang language) +{ + fileLanguage_ = language; +} + +} // namespace ark::abc2program \ No newline at end of file diff --git a/static_core/abc2program/abc2program_key_data.h b/static_core/abc2program/abc2program_key_data.h new file mode 100644 index 0000000000000000000000000000000000000000..ebc20295cbc7ee450c4443d5891cea55ea12e5fa --- /dev/null +++ b/static_core/abc2program/abc2program_key_data.h @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC2PROGRAM_KEY_DATA_H +#define ABC2PROGRAM_ABC2PROGRAM_KEY_DATA_H + +#include +#include +#include +#include "file.h" +#include "abc_string_table.h" + +namespace ark::abc2program { + +class Abc2ProgramKeyData { +public: + Abc2ProgramKeyData(const panda_file::File &file, AbcStringTable &stringTable, pandasm::Program &program) + : file_(file), stringTable_(stringTable), program_(program) + { + } + const panda_file::File &GetAbcFile() const; + std::map GetFunctionTable(); + AbcStringTable &GetAbcStringTable() const; + pandasm::Program &GetProgram() const; + std::string GetFullRecordNameById(const panda_file::File::EntityId &classId) const; + std::string GetFullFunctionNameById(const panda_file::File::EntityId &methodId) const; + ark::panda_file::SourceLang GetFileLanguage() const; + void SetFileLanguage(ark::panda_file::SourceLang language); + + std::map> externalFieldTable_ {}; + std::map recordNameToId_ {}; + std::map methodNameToId_ {}; + +private: + inline bool IsSystemType(const std::string &typeName) const; + + const panda_file::File &file_; + AbcStringTable &stringTable_; + pandasm::Program &program_; + ark::panda_file::SourceLang fileLanguage_ = panda_file::SourceLang::PANDA_ASSEMBLY; +}; // class Abc2ProgramKeyData + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC2PROGRAM_KEY_DATA_H diff --git a/static_core/abc2program/abc2program_log.cpp b/static_core/abc2program/abc2program_log.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9d5c7fefbb88a8c8171272e74191e8a8c673d72 --- /dev/null +++ b/static_core/abc2program/abc2program_log.cpp @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2024-2025 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 "abc2program_log.h" +#include "utils/logger.h" + +namespace ark::abc2program { + +namespace log { + +void Unimplemented(const std::string &funcName) +{ + LOG(ERROR, ABC2PROGRAM) << "Function : " << funcName << " unimplemented now!"; +} + +} // namespace log + +} // namespace ark::abc2program \ No newline at end of file diff --git a/static_core/abc2program/abc2program_log.h b/static_core/abc2program/abc2program_log.h new file mode 100644 index 0000000000000000000000000000000000000000..fc26e03ac2367866b813ea732c075a2eceadf9f0 --- /dev/null +++ b/static_core/abc2program/abc2program_log.h @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC2PROGRAM_LOG_H +#define ABC2PROGRAM_ABC2PROGRAM_LOG_H + +#include + +namespace ark::abc2program { + +namespace log { + +void Unimplemented(const std::string &funcName); + +} // namespace log + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC2PROGRAM_LOG_H diff --git a/static_core/abc2program/abc2program_options.cpp b/static_core/abc2program/abc2program_options.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd92b505b45d913b6b72c927481b280c72cfb9dd --- /dev/null +++ b/static_core/abc2program/abc2program_options.cpp @@ -0,0 +1,102 @@ +/** + * Copyright (c) 2024-2025 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 "abc2program_options.h" +#include + +namespace ark::abc2program { + +bool Abc2ProgramOptions::Parse(int argc, const char **argv) +{ + ark::PandArg help("help", false, "Print this message and exit"); + ark::PandArg debug( + "debug", false, "enable debug messages (will be printed to standard output if no --debug-file was specified) "); + ark::PandArg debugFile("debug-file", "", + "(--debug-file FILENAME) set debug file name. default is std::cout"); + ark::PandArg inputFile("inputFile", "", "Path to the source binary code"); + ark::PandArg outputFile("outputFile", "", "Path to the generated assembly code"); + helpArg_ = &help; + debugArg_ = &debug; + debugFileArg_ = &debugFile; + inputFileArg_ = &inputFile; + outputFileArg_ = &outputFile; + paParser_.Add(&help); + paParser_.Add(&debug); + paParser_.Add(&debugFile); + paParser_.PushBackTail(&inputFile); + paParser_.PushBackTail(&outputFile); + paParser_.EnableTail(); + if (!ProcessArgs(argc, argv)) { + PrintErrorMsg(); + paParser_.DisableTail(); + return false; + } + paParser_.DisableTail(); + return true; +} + +bool Abc2ProgramOptions::ProcessArgs(int argc, const char **argv) +{ + if (!paParser_.Parse(argc, argv)) { + ConstructErrorMsg(); + return false; + } + if (debugArg_->GetValue()) { + if (debugFileArg_->GetValue().empty()) { + ark::Logger::InitializeStdLogging(ark::Logger::Level::DEBUG, + ark::Logger::ComponentMask().set(ark::Logger::Component::ABC2PROGRAM)); + } else { + ark::Logger::InitializeFileLogging(debugFileArg_->GetValue(), ark::Logger::Level::DEBUG, + ark::Logger::ComponentMask().set(ark::Logger::Component::ABC2PROGRAM)); + } + } else { + ark::Logger::InitializeStdLogging(ark::Logger::Level::ERROR, + ark::Logger::ComponentMask().set(ark::Logger::Component::ABC2PROGRAM)); + } + inputFilePath_ = inputFileArg_->GetValue(); + outputFilePath_ = outputFileArg_->GetValue(); + if (inputFilePath_.empty() || outputFilePath_.empty()) { + ConstructErrorMsg(); + return false; + } + return true; +} + +void Abc2ProgramOptions::ConstructErrorMsg() +{ + std::stringstream ss; + ss << "Usage:" << std::endl; + ss << "abc2prog [options] inputFile outputFile" << std::endl; + ss << "Supported options:" << std::endl; + ss << paParser_.GetHelpString() << std::endl; + errorMsg_ = ss.str(); +} + +const std::string &Abc2ProgramOptions::GetInputFilePath() const +{ + return inputFilePath_; +} + +const std::string &Abc2ProgramOptions::GetOutputFilePath() const +{ + return outputFilePath_; +} + +void Abc2ProgramOptions::PrintErrorMsg() const +{ + std::cerr << errorMsg_; +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc2program_options.h b/static_core/abc2program/abc2program_options.h new file mode 100644 index 0000000000000000000000000000000000000000..4012acf8af00f8e53c8f097426b2934213d4486c --- /dev/null +++ b/static_core/abc2program/abc2program_options.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC2PROGRAM_OPTIONS_H +#define ABC2PROGRAM_ABC2PROGRAM_OPTIONS_H + +#include +#include "utils/pandargs.h" +#include "utils/logger.h" + +namespace ark::abc2program { + +class Abc2ProgramOptions { +public: + bool Parse(int argc, const char **argv); + const std::string &GetInputFilePath() const; + const std::string &GetOutputFilePath() const; + +private: + bool ProcessArgs(int argc, const char **argv); + void ConstructErrorMsg(); + void PrintErrorMsg() const; + ark::PandArgParser paParser_; + std::string inputFilePath_; + std::string outputFilePath_; + std::string errorMsg_; + ark::PandArg *helpArg_ = nullptr; + ark::PandArg *debugArg_ = nullptr; + ark::PandArg *debugFileArg_ = nullptr; + ark::PandArg *inputFileArg_ = nullptr; + ark::PandArg *outputFileArg_ = nullptr; +}; // class Abc2ProgramOptions + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC2PROGRAM_OPTIONS_H \ No newline at end of file diff --git a/static_core/abc2program/abc_class_processor.cpp b/static_core/abc2program/abc_class_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..900c0070b5e127b881f76e068274e010cb87da1b --- /dev/null +++ b/static_core/abc2program/abc_class_processor.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024-2025 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 "abc_class_processor.h" +#include +#include "abc_method_processor.h" +#include "abc_field_processor.h" +#include "mangling.h" + +namespace ark::abc2program { + +AbcClassProcessor::AbcClassProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData) + : AbcFileEntityProcessor(entityId, keyData) +{ + FillProgramData(); +} + +void AbcClassProcessor::FillProgramData() +{ + FillRecord(); +} + +void AbcClassProcessor::FillRecord() +{ + pandasm::Record record("", keyData_.GetFileLanguage()); + record.name = keyData_.GetFullRecordNameById(entityId_); + FillRecordMetaData(record); + if (!file_->IsExternal(entityId_)) { + FillRecordData(record); + } + std::string name = record.name; + keyData_.recordNameToId_.emplace(name, entityId_); + program_->recordTable.emplace(name, std::move(record)); +} + +void AbcClassProcessor::FillRecordData(pandasm::Record &record) +{ + classDataAccessor_ = std::make_unique(*file_, entityId_); + FillFields(record); + FillFunctions(); + FillRecordSourceFile(record); +} + +void AbcClassProcessor::FillRecordMetaData(pandasm::Record &record) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting metadata]\nrecord id: " << entityId_ << " (0x" << std::hex << entityId_ << ")"; + + auto external = file_->IsExternal(entityId_); + + SetEntityAttribute( + record, [external]() { return external; }, "external"); + + if (!external) { + auto cda = panda_file::ClassDataAccessor {*file_, entityId_}; + SetEntityAttributeValue( + record, [&cda]() { return cda.IsPublic(); }, "access.record", "public"); + + SetEntityAttributeValue( + record, [&cda]() { return cda.IsProtected(); }, "access.record", "protected"); + + SetEntityAttributeValue( + record, [&cda]() { return cda.IsPrivate(); }, "access.record", "private"); + + SetEntityAttribute( + record, [&cda]() { return cda.IsFinal(); }, "final"); + } +} + +void AbcClassProcessor::FillFields(pandasm::Record &record) +{ + classDataAccessor_->EnumerateFields([&](panda_file::FieldDataAccessor &fda) -> void { + panda_file::File::EntityId fieldId = fda.GetFieldId(); + AbcFieldProcessor fieldProcessor(fieldId, keyData_, record); + }); +} + +void AbcClassProcessor::FillRecordSourceFile(pandasm::Record &record) +{ + std::optional sourceFileId = classDataAccessor_->GetSourceFileId(); + if (sourceFileId.has_value()) { + record.sourceFile = stringTable_->GetStringById(sourceFileId.value()); + } else { + record.sourceFile = ""; + } +} + +void AbcClassProcessor::FillFunctions() +{ + classDataAccessor_->EnumerateMethods([&](panda_file::MethodDataAccessor &mda) -> void { + panda_file::File::EntityId methodId = mda.GetMethodId(); + AbcMethodProcessor methodProcessor(methodId, keyData_); + }); +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_class_processor.h b/static_core/abc2program/abc_class_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..fbb90bfdcbfc4ab4cbbbffa44e7fc9060f551d13 --- /dev/null +++ b/static_core/abc2program/abc_class_processor.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_CLASS_PROCESSOR_H +#define ABC2PROGRAM_ABC_CLASS_PROCESSOR_H + +#include +#include "abc_file_entity_processor.h" +#include "class_data_accessor-inl.h" + +namespace ark::abc2program { + +class AbcClassProcessor : public AbcFileEntityProcessor { +public: + AbcClassProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData); + void FillProgramData() override; + +private: + void FillRecord(); + void FillRecordData(pandasm::Record &record); + void FillRecordSourceFile(pandasm::Record &record); + void FillRecordMetaData(pandasm::Record &record); + void FillFields(pandasm::Record &record); + void FillFunctions(); + std::unique_ptr classDataAccessor_; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_CLASS_PROCESSOR_H diff --git a/static_core/abc2program/abc_code_processor.cpp b/static_core/abc2program/abc_code_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cc520edc55a8dd377d17ac477ef85bd0ba86900d --- /dev/null +++ b/static_core/abc2program/abc_code_processor.cpp @@ -0,0 +1,299 @@ +/** + * Copyright (c) 2024-2025 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 "abc_code_processor.h" +#include +#include "abc_field_processor.h" +#include "abc_method_processor.h" +#include "assembly-record.h" +#include "source_lang_enum.h" + +namespace ark::abc2program { + +AbcCodeProcessor::AbcCodeProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData, + panda_file::File::EntityId methodId) + : AbcFileEntityProcessor(entityId, keyData), methodId_(methodId) +{ + codeDataAccessor_ = std::make_unique(*file_, entityId_); + codeConverter_ = std::make_unique(keyData); + FillProgramData(); +} + +std::vector AbcCodeProcessor::GetIns() const +{ + return ins; +} + +std::vector AbcCodeProcessor::GetCatchBlocks() const +{ + return catchBlocks; +} + +uint32_t AbcCodeProcessor::GetNumVregs() const +{ + return codeDataAccessor_->GetNumVregs(); +} + +static size_t GetBytecodeInstructionNumber(BytecodeInstruction bcInsFirst, BytecodeInstruction bcInsCur) +{ + size_t count = 0; + + while (bcInsFirst.GetAddress() != bcInsCur.GetAddress()) { + count++; + bcInsFirst = bcInsFirst.GetNext(); + if (bcInsFirst.GetAddress() > bcInsCur.GetAddress()) { + return std::numeric_limits::max(); + } + } + + return count; +} + +static void TranslateImmToLabel(pandasm::Ins *paIns, LabelTable *labelTable, const uint8_t *insArr, + BytecodeInstruction bcIns, BytecodeInstruction bcInsLast, + panda_file::File::EntityId codeId) +{ + const int32_t jmpOffset = std::get(paIns->imms.at(0)); + const auto bcInsDest = bcIns.JumpTo(jmpOffset); + if (bcInsLast.GetAddress() > bcInsDest.GetAddress()) { + size_t idx = GetBytecodeInstructionNumber(BytecodeInstruction(insArr), bcInsDest); + if (idx != std::numeric_limits::max()) { + if (labelTable->find(idx) == labelTable->end()) { + std::stringstream ss {}; + ss << "jump_label_" << labelTable->size(); + (*labelTable)[idx] = ss.str(); + } + + paIns->imms.clear(); + paIns->ids.push_back(labelTable->at(idx)); + } else { + LOG(ERROR, ABC2PROGRAM) << "> error encountered at " << codeId << " (0x" << std::hex << codeId + << "). incorrect instruction at offset: 0x" << (bcIns.GetAddress() - insArr) + << ": invalid jump offset 0x" << jmpOffset + << " - jumping in the middle of another instruction!"; + } + } else { + LOG(ERROR, ABC2PROGRAM) << "> error encountered at " << codeId << " (0x" << std::hex << codeId + << "). incorrect instruction at offset: 0x" << (bcIns.GetAddress() - insArr) + << ": invalid jump offset 0x" << jmpOffset << " - jumping out of bounds!"; + } +} + +void AbcCodeProcessor::FillProgramData() +{ + const auto insSize = codeDataAccessor_->GetCodeSize(); + const auto insArr = codeDataAccessor_->GetInstructions(); + auto bcIns = BytecodeInstruction(insArr); + const auto bcInsLast = bcIns.JumpTo(insSize); + + LabelTable labelTable = GetExceptions(methodId_, entityId_); + + while (bcIns.GetAddress() != bcInsLast.GetAddress()) { + if (bcIns.HasFlag(BytecodeInstruction::Flags::FIELD_ID)) { + auto idx = bcIns.GetId().AsIndex(); + auto id = file_->ResolveFieldIndex(methodId_, idx); + CollectExternalFields(id); + } + + pandasm::Ins paIns = codeConverter_->BytecodeInstructionToPandasmInstruction(bcIns, methodId_); + + if (paIns.IsJump()) { + TranslateImmToLabel(&paIns, &labelTable, insArr, bcIns, bcInsLast, entityId_); + } + // check if method id is unknown external method. if so, emplace it in table + if (bcIns.HasFlag(BytecodeInstruction::Flags::METHOD_ID)) { + const auto argMethodIdx = bcIns.GetId().AsIndex(); + const auto argMethodId = file_->ResolveMethodIndex(methodId_, argMethodIdx); + + AbcMethodProcessor methodProcessor(argMethodId, keyData_); + } + + if (bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID)) { + const auto offset = bcIns.GetId().AsFileId(); + stringTable_->AddStringId(offset); + } + + ins.emplace_back(paIns); + bcIns = bcIns.GetNext(); + } + + for (const auto &pair : labelTable) { + ins[pair.first].label = pair.second; + ins[pair.first].setLabel = true; + } +} + +bool AbcCodeProcessor::LocateCatchBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast, + const panda_file::CodeDataAccessor::CatchBlock &catchBlock, + pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, + size_t tryIdx, size_t catchIdx) +{ + const auto handlerBeginOffset = catchBlock.GetHandlerPc(); + const auto handlerEndOffset = handlerBeginOffset + catchBlock.GetCodeSize(); + + const auto handlerBeginBcIns = bcIns.JumpTo(handlerBeginOffset); + const auto handlerEndBcIns = bcIns.JumpTo(handlerEndOffset); + + const size_t handlerBeginIdx = GetBytecodeInstructionNumber(bcIns, handlerBeginBcIns); + const size_t handlerEndIdx = GetBytecodeInstructionNumber(bcIns, handlerEndBcIns); + + const bool handlerBeginOffsetInRange = bcInsLast.GetAddress() > handlerBeginBcIns.GetAddress(); + const bool handlerEndOffsetInRange = bcInsLast.GetAddress() > handlerEndBcIns.GetAddress(); + const bool handlerBeginOffsetValid = handlerBeginIdx != std::numeric_limits::max(); + const bool handlerEndOffsetValid = handlerEndIdx != std::numeric_limits::max(); + + if (!handlerBeginOffsetInRange || !handlerBeginOffsetValid) { + LOG(ERROR, ABC2PROGRAM) << "> invalid catch block begin offset! address is: 0x" << std::hex + << handlerBeginBcIns.GetAddress(); + return false; + } + + auto itBegin = labelTable->find(handlerBeginIdx); + if (itBegin == labelTable->end()) { + std::stringstream ss {}; + ss << "handler_begin_label_" << tryIdx << "_" << catchIdx; + catchBlockPa->catchBeginLabel = ss.str(); + labelTable->insert(std::pair(handlerBeginIdx, ss.str())); + } else { + catchBlockPa->catchBeginLabel = itBegin->second; + } + + if (!handlerEndOffsetInRange || !handlerEndOffsetValid) { + LOG(ERROR, ABC2PROGRAM) << "> invalid catch block end offset! address is: 0x" << std::hex + << handlerEndBcIns.GetAddress(); + return false; + } + + auto itEnd = labelTable->find(handlerEndIdx); + if (itEnd == labelTable->end()) { + std::stringstream ss {}; + ss << "handler_end_label_" << tryIdx << "_" << catchIdx; + catchBlockPa->catchEndLabel = ss.str(); + labelTable->insert(std::pair(handlerEndIdx, ss.str())); + } else { + catchBlockPa->catchEndLabel = itEnd->second; + } + + return true; +} + +bool AbcCodeProcessor::LocateTryBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast, + const panda_file::CodeDataAccessor::TryBlock &tryBlock, + pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, + size_t tryIdx) +{ + const auto tryBeginBcIns = bcIns.JumpTo(tryBlock.GetStartPc()); + const auto tryEndBcIns = bcIns.JumpTo(tryBlock.GetStartPc() + tryBlock.GetLength()); + + const size_t tryBeginIdx = GetBytecodeInstructionNumber(bcIns, tryBeginBcIns); + const size_t tryEndIdx = GetBytecodeInstructionNumber(bcIns, tryEndBcIns); + + const bool tryBeginOffsetInRange = bcInsLast.GetAddress() > tryBeginBcIns.GetAddress(); + const bool tryEndOffsetInRange = bcInsLast.GetAddress() >= tryEndBcIns.GetAddress(); + const bool tryBeginOffsetValid = tryBeginIdx != std::numeric_limits::max(); + const bool tryEndOffsetValid = tryEndIdx != std::numeric_limits::max(); + + if (!tryBeginOffsetInRange || !tryBeginOffsetValid) { + LOG(ERROR, ABC2PROGRAM) << "> invalid try block begin offset! address is: 0x" << std::hex + << tryBeginBcIns.GetAddress(); + return false; + } + + auto itBegin = labelTable->find(tryBeginIdx); + if (itBegin == labelTable->end()) { + std::stringstream ss {}; + ss << "try_begin_label_" << tryIdx; + catchBlockPa->tryBeginLabel = ss.str(); + labelTable->insert(std::pair(tryBeginIdx, ss.str())); + } else { + catchBlockPa->tryBeginLabel = itBegin->second; + } + + if (!tryEndOffsetInRange || !tryEndOffsetValid) { + LOG(ERROR, ABC2PROGRAM) << "> invalid try block end offset! address is: 0x" << std::hex + << tryEndBcIns.GetAddress(); + return false; + } + + auto itEnd = labelTable->find(tryEndIdx); + if (itEnd == labelTable->end()) { + std::stringstream ss {}; + ss << "try_end_label_" << tryIdx; + catchBlockPa->tryEndLabel = ss.str(); + labelTable->insert(std::pair(tryEndIdx, ss.str())); + } else { + catchBlockPa->tryEndLabel = itEnd->second; + } + + return true; +} + +LabelTable AbcCodeProcessor::GetExceptions(panda_file::File::EntityId methodId, panda_file::File::EntityId codeId) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting exceptions]\ncode id: " << codeId << " (0x" << std::hex << codeId << ")"; + panda_file::CodeDataAccessor codeAccessor(*file_, codeId); + + const auto bcIns = BytecodeInstruction(codeAccessor.GetInstructions()); + const auto bcInsLast = bcIns.JumpTo(codeAccessor.GetCodeSize()); + + size_t tryIdx = 0; + LabelTable labelTable {}; + codeAccessor.EnumerateTryBlocks([&](panda_file::CodeDataAccessor::TryBlock &tryBlock) { + pandasm::Function::CatchBlock catchBlockPa {}; + if (!LocateTryBlock(bcIns, bcInsLast, tryBlock, &catchBlockPa, &labelTable, tryIdx)) { + return false; + } + size_t catchIdx = 0; + tryBlock.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catchBlock) { + auto classIdx = catchBlock.GetTypeIdx(); + if (classIdx == panda_file::INVALID_INDEX) { + catchBlockPa.exceptionRecord = ""; + } else { + const auto classId = file_->ResolveClassIndex(methodId, classIdx); + + catchBlockPa.exceptionRecord = keyData_.GetFullRecordNameById(classId); + } + if (!LocateCatchBlock(bcIns, bcInsLast, catchBlock, &catchBlockPa, &labelTable, tryIdx, catchIdx)) { + return false; + } + + catchBlocks.push_back(catchBlockPa); + catchBlockPa.catchBeginLabel = ""; + catchBlockPa.catchEndLabel = ""; + catchIdx++; + + return true; + }); + tryIdx++; + + return true; + }); + + return labelTable; +} + +void AbcCodeProcessor::CollectExternalFields(const panda_file::File::EntityId &fieldId) +{ + panda_file::FieldDataAccessor fieldAccessor(*file_, fieldId); + if (!fieldAccessor.IsExternal()) { + return; + } + auto recordName = keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()); + pandasm::Record record {"", keyData_.GetFileLanguage()}; + + AbcFieldProcessor fieldProcessor(fieldId, keyData_, record, true); +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_code_processor.h b/static_core/abc2program/abc_code_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..f3dc21ca7afc393cc4751d0ce157ceac3729e187 --- /dev/null +++ b/static_core/abc2program/abc_code_processor.h @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_CODE_PROCESSOR_H +#define ABC2PROGRAM_ABC_CODE_PROCESSOR_H + +#include +#include "abc_file_entity_processor.h" +#include "assembly-function.h" +#include "common/abc_code_converter.h" +#include "code_data_accessor-inl.h" + +namespace ark::abc2program { + +using LabelTable = std::map; +class AbcCodeProcessor : public AbcFileEntityProcessor { +public: + AbcCodeProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData, + panda_file::File::EntityId methodId); + void FillProgramData() override; + std::vector GetIns() const; + std::vector GetCatchBlocks() const; + uint32_t GetNumVregs() const; + +private: + LabelTable GetExceptions(panda_file::File::EntityId methodId, panda_file::File::EntityId codeId); + bool LocateTryBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast, + const panda_file::CodeDataAccessor::TryBlock &tryBlock, + pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx); + bool LocateCatchBlock(const BytecodeInstruction &bcIns, const BytecodeInstruction &bcInsLast, + const panda_file::CodeDataAccessor::CatchBlock &catchBlock, + pandasm::Function::CatchBlock *catchBlockPa, LabelTable *labelTable, size_t tryIdx, + size_t catchIdx); + void CollectExternalFields(const panda_file::File::EntityId &fieldId); + panda_file::File::EntityId methodId_; + std::unique_ptr codeDataAccessor_; + std::unique_ptr codeConverter_; + std::vector ins; + std::vector catchBlocks; +}; // AbcCodeProcessor + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_CODE_PROCESSOR_H diff --git a/static_core/abc2program/abc_debug_info_processor.cpp b/static_core/abc2program/abc_debug_info_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6528bf9d3485c26019a98f8d8b7f909c6d6f4a2 --- /dev/null +++ b/static_core/abc2program/abc_debug_info_processor.cpp @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2024-2025 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 "abc_debug_info_processor.h" +#include "abc2program_log.h" + +namespace ark::abc2program { + +AbcDebugInfoProcessor::AbcDebugInfoProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData) + : AbcFileEntityProcessor(entityId, keyData) +{ + debugInfoDataAccessor_ = std::make_unique(*file_, entityId_); + FillProgramData(); +} + +void AbcDebugInfoProcessor::FillProgramData() +{ + log::Unimplemented(__PRETTY_FUNCTION__); +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_debug_info_processor.h b/static_core/abc2program/abc_debug_info_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..523614154ccf148a379c542dca4cf8d096db8a3b --- /dev/null +++ b/static_core/abc2program/abc_debug_info_processor.h @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_DEBUG_INFO_PROCESSOR_H +#define ABC2PROGRAM_ABC_DEBUG_INFO_PROCESSOR_H + +#include "abc_file_entity_processor.h" +#include "debug_data_accessor-inl.h" +#include "debug_data_accessor.h" + +namespace ark::abc2program { + +class AbcDebugInfoProcessor : public AbcFileEntityProcessor { +public: + AbcDebugInfoProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData); + void FillProgramData() override; + +private: + std::unique_ptr debugInfoDataAccessor_; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_DEBUG_INFO_PROCESSOR_H diff --git a/static_core/abc2program/abc_field_processor.cpp b/static_core/abc2program/abc_field_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1eb44c35645fa2923aa0ccee1d4b3325227b1563 --- /dev/null +++ b/static_core/abc2program/abc_field_processor.cpp @@ -0,0 +1,92 @@ +/** + * Copyright (c) 2024-2025 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 "abc_field_processor.h" +#include "abc2program_log.h" + +namespace ark::abc2program { + +AbcFieldProcessor::AbcFieldProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData, + pandasm::Record &record, bool isExternal) + : AbcFileEntityProcessor(entityId, keyData), record_(record), isExternal_(isExternal) +{ + fieldDataAccessor_ = std::make_unique(*file_, entityId_); + typeConverter_ = std::make_unique(*stringTable_); + FillProgramData(); +} + +void AbcFieldProcessor::FillProgramData() +{ + pandasm::Field field(keyData_.GetFileLanguage()); + FillFieldData(field); + if (isExternal_) { + auto &fieldList = + keyData_.externalFieldTable_[keyData_.GetFullRecordNameById(fieldDataAccessor_->GetClassId())]; + auto retField = std::find_if(fieldList.begin(), fieldList.end(), [&field](pandasm::Field &fieldFromList) { + return field.name == fieldFromList.name; + }); + if (retField == fieldList.end()) { + fieldList.push_back(std::move(field)); + } + return; + } + record_.fieldList.emplace_back(std::move(field)); +} + +void AbcFieldProcessor::FillFieldData(pandasm::Field &field) +{ + FillFieldName(field); + FillFieldType(field); + FillFieldMetaData(field); +} + +void AbcFieldProcessor::FillFieldName(pandasm::Field &field) +{ + panda_file::File::EntityId fieldNameId = fieldDataAccessor_->GetNameId(); + field.name = stringTable_->GetStringById(fieldNameId); +} + +void AbcFieldProcessor::FillFieldType(pandasm::Field &field) +{ + uint32_t fieldType = fieldDataAccessor_->GetType(); + field.type = typeConverter_->FieldTypeToPandasmType(fieldType); +} + +void AbcFieldProcessor::FillFieldMetaData(pandasm::Field &field) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting metadata]\nfield id: " << entityId_ << " (0x" << std::hex << entityId_ << ")"; + + panda_file::FieldDataAccessor fieldAccessor(*file_, entityId_); + + SetEntityAttribute( + field, [&fieldAccessor]() { return fieldAccessor.IsExternal(); }, "external"); + + SetEntityAttribute( + field, [&fieldAccessor]() { return fieldAccessor.IsStatic(); }, "static"); + + SetEntityAttributeValue( + field, [&fieldAccessor]() { return fieldAccessor.IsPublic(); }, "access.field", "public"); + + SetEntityAttributeValue( + field, [&fieldAccessor]() { return fieldAccessor.IsProtected(); }, "access.field", "protected"); + + SetEntityAttributeValue( + field, [&fieldAccessor]() { return fieldAccessor.IsPrivate(); }, "access.field", "private"); + + SetEntityAttribute( + field, [&fieldAccessor]() { return fieldAccessor.IsFinal(); }, "final"); +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_field_processor.h b/static_core/abc2program/abc_field_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..b9158c06a80180e069e73df773724327b3582741 --- /dev/null +++ b/static_core/abc2program/abc_field_processor.h @@ -0,0 +1,44 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_FIELD_PROCESSOR_H +#define ABC2PROGRAM_ABC_FIELD_PROCESSOR_H + +#include "abc_file_entity_processor.h" +#include "field_data_accessor-inl.h" +#include "common/abc_type_converter.h" + +namespace ark::abc2program { + +class AbcFieldProcessor : public AbcFileEntityProcessor { +public: + AbcFieldProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData, pandasm::Record &record, + bool isExternal = false); + void FillProgramData() override; + +private: + void FillFieldData(pandasm::Field &field); + void FillFieldName(pandasm::Field &field); + void FillFieldType(pandasm::Field &field); + void FillFieldMetaData(pandasm::Field &field); + pandasm::Record &record_; + std::unique_ptr fieldDataAccessor_; + std::unique_ptr typeConverter_; + bool isExternal_; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_FIELD_PROCESSOR_H diff --git a/static_core/abc2program/abc_file_entity_processor.cpp b/static_core/abc2program/abc_file_entity_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..72f37173b84e7b04f97364f1ecd0c65ffffbe5a4 --- /dev/null +++ b/static_core/abc2program/abc_file_entity_processor.cpp @@ -0,0 +1,28 @@ +/** + * Copyright (c) 2024-2025 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 "abc_file_entity_processor.h" + +namespace ark::abc2program { + +AbcFileEntityProcessor::AbcFileEntityProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData) + : entityId_(entityId), keyData_(keyData) +{ + file_ = &(keyData_.GetAbcFile()); + stringTable_ = &(keyData_.GetAbcStringTable()); + program_ = &(keyData_.GetProgram()); +} + +} // namespace ark::abc2program \ No newline at end of file diff --git a/static_core/abc2program/abc_file_entity_processor.h b/static_core/abc2program/abc_file_entity_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..7cd5d784e36feadd12d528c01892a43faaeb1ae0 --- /dev/null +++ b/static_core/abc2program/abc_file_entity_processor.h @@ -0,0 +1,64 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_FILE_ENTITY_PROCESSOR_H +#define ABC2PROGRAM_ABC_FILE_ENTITY_PROCESSOR_H + +#include "abc2program_key_data.h" +#include "abc2program_log.h" +#include "abc_file_utils.h" + +namespace ark::abc2program { + +class AbcFileEntityProcessor { +public: + AbcFileEntityProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData); + +protected: + template + static void SetEntityAttribute(T &entity, const std::function &shouldSet, std::string_view attribute) + { + LOG(DEBUG, ABC2PROGRAM) << attribute; + if (shouldSet()) { + auto err = entity.metadata->SetAttribute(attribute); + if (err.has_value()) { + LOG(DEBUG, ABC2PROGRAM) << err.value().GetMessage(); + } + } + } + + template + static void SetEntityAttributeValue(T &entity, const std::function &shouldSet, std::string_view attribute, + const char *value) + { + LOG(DEBUG, ABC2PROGRAM) << attribute; + if (shouldSet()) { + auto err = entity.metadata->SetAttributeValue(attribute, value); + if (err.has_value()) { + LOG(DEBUG, ABC2PROGRAM) << err.value().GetMessage(); + } + } + } + virtual void FillProgramData() = 0; + panda_file::File::EntityId entityId_; + Abc2ProgramKeyData &keyData_; + const panda_file::File *file_ = nullptr; + AbcStringTable *stringTable_ = nullptr; + pandasm::Program *program_ = nullptr; +}; // class AbcFileEntityProcessor + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_FILE_ENTITY_PROCESSOR_H diff --git a/static_core/abc2program/abc_file_processor.cpp b/static_core/abc2program/abc_file_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dbb8b933b50d2bec8a528ab3b9901e825a39a129 --- /dev/null +++ b/static_core/abc2program/abc_file_processor.cpp @@ -0,0 +1,264 @@ +/** + * Copyright (c) 2024-2025 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 "abc_file_processor.h" +#include +#include "abc_class_processor.h" +#include "abc2program_log.h" +#include "abc_file_utils.h" + +#include "abc_literal_array_processor.h" +#include "abc_method_processor.h" +#include "get_language_specific_metadata.inc" +#include "mangling.h" + +namespace ark::abc2program { + +AbcFileProcessor::AbcFileProcessor(Abc2ProgramKeyData &keyData) : keyData_(keyData) +{ + file_ = &(keyData_.GetAbcFile()); + stringTable_ = &(keyData_.GetAbcStringTable()); + program_ = &(keyData_.GetProgram()); +} + +bool AbcFileProcessor::ProcessFile() +{ + ProcessClasses(); + FillLiteralArrays(); + FillProgramStrings(); + FillExternalFieldsToRecords(); + GetLanguageSpecificMetadata(); + program_->lang = keyData_.GetFileLanguage(); + return true; +} + +void AbcFileProcessor::FillLiteralArrays() +{ + AbcLiteralArrayProcessor litArrayProcessor(file_->GetLiteralArraysId(), keyData_); +} + +void AbcFileProcessor::ProcessClasses() +{ + const auto classes = file_->GetClasses(); + for (size_t i = 0; i < classes.size(); i++) { + uint32_t classIdx = classes[i]; + auto classOff = file_->GetHeader()->classIdxOff + sizeof(uint32_t) * i; + if (classIdx > file_->GetHeader()->fileSize) { + LOG(FATAL, ABC2PROGRAM) << "> error encountered in record at " << classOff << " (0x" << std::hex << classOff + << "). binary file corrupted. record offset (0x" << classIdx + << ") out of bounds (0x" << file_->GetHeader()->fileSize << ")!"; + break; + } + panda_file::File::EntityId recordId(classIdx); + auto language = GetRecordLanguage(recordId); + if (language != keyData_.GetFileLanguage()) { + if (keyData_.GetFileLanguage() == panda_file::SourceLang::PANDA_ASSEMBLY) { + keyData_.SetFileLanguage(language); + } else if (language != panda_file::SourceLang::PANDA_ASSEMBLY) { + LOG(ERROR, ABC2PROGRAM) << "> possible error encountered in record at" << classOff << " (0x" << std::hex + << classOff << "). record's language (" + << panda_file::LanguageToString(language) << ") differs from file's language (" + << panda_file::LanguageToString(keyData_.GetFileLanguage()) << ")!"; + } + } + AbcClassProcessor classProcessor(recordId, keyData_); + } +} + +void AbcFileProcessor::FillProgramStrings() +{ + program_->strings = stringTable_->GetStringSet(); +} + +void AbcFileProcessor::FillExternalFieldsToRecords() +{ + for (auto &[recordName, record] : program_->recordTable) { + auto it = keyData_.externalFieldTable_.find(recordName); + if (it == keyData_.externalFieldTable_.end()) { + continue; + } + auto &[unused, fieldList] = *it; + (void)unused; + if (fieldList.empty()) { + continue; + } + for (auto &fieldIter : fieldList) { + if (!fieldIter.name.empty()) { + record.fieldList.push_back(std::move(fieldIter)); + } + } + keyData_.externalFieldTable_.erase(recordName); + } +} + +std::string AbcFileProcessor::AnnotationTagToString(const char tag) const +{ + static const std::unordered_map TAG_TO_STRING = {{'1', "u1"}, + {'2', "i8"}, + {'3', "u8"}, + {'4', "i16"}, + {'5', "u16"}, + {'6', "i32"}, + {'7', "u32"}, + {'8', "i64"}, + {'9', "u64"}, + {'A', "f32"}, + {'B', "f64"}, + {'C', "string"}, + {'D', "record"}, + {'E', "method"}, + {'F', "enum"}, + {'G', "annotation"}, + {'J', "method_handle"}, + {'H', "array"}, + {'K', "u1[]"}, + {'L', "i8[]"}, + {'M', "u8[]"}, + {'N', "i16[]"}, + {'O', "u16[]"}, + {'P', "i32[]"}, + {'Q', "u32[]"}, + {'R', "i64[]"}, + {'S', "u64[]"}, + {'T', "f32[]"}, + {'U', "f64[]"}, + {'V', "string[]"}, + {'W', "record[]"}, + {'X', "method[]"}, + {'Y', "enum[]"}, + {'Z', "annotation[]"}, + {'@', "method_handle[]"}, + {'*', "nullptr_string"}}; + + return TAG_TO_STRING.at(tag); +} + +std::string AbcFileProcessor::ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type) +{ + std::stringstream ss; + + if (type == "i8") { + auto res = value.Get(); + ss << static_cast(res); + } else if (type == "u1" || type == "u8") { + auto res = value.Get(); + ss << static_cast(res); + } else if (type == "i16") { + ss << value.Get(); + } else if (type == "u16") { + ss << value.Get(); + } else if (type == "i32") { + ss << value.Get(); + } else if (type == "u32") { + ss << value.Get(); + } else if (type == "i64") { + ss << value.Get(); + } else if (type == "u64") { + ss << value.Get(); + } else if (type == "f32") { + ss << value.Get(); + } else if (type == "f64") { + ss << value.Get(); + } else if (type == "string") { + const auto id = value.Get(); + ss << "\"" << stringTable_->GetStringById(id) << "\""; + } else if (type == "record") { + const auto id = value.Get(); + ss << keyData_.GetFullRecordNameById(id); + } else if (type == "method") { + const auto id = value.Get(); + AbcMethodProcessor methodProcessor(id, keyData_); + ss << methodProcessor.GetMethodSignature(); + } else if (type == "enum") { + const auto id = value.Get(); + panda_file::FieldDataAccessor fieldAccessor(*file_, id); + ss << keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()) << "." + << stringTable_->GetStringById(fieldAccessor.GetNameId()); + } else if (type == "annotation") { + const auto id = value.Get(); + ss << "id_" << id; + } else if (type == "void") { + return std::string(); + } else if (type == "method_handle") { + } else if (type == "nullptr_string") { + ss << static_cast(0); + } + + return ss.str(); +} + +std::string AbcFileProcessor::ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, + const size_t idx) +{ + std::stringstream ss; + + if (type == "i8") { + auto res = value.Get(idx); + ss << static_cast(res); + } else if (type == "u1" || type == "u8") { + auto res = value.Get(idx); + ss << static_cast(res); + } else if (type == "i16") { + ss << value.Get(idx); + } else if (type == "u16") { + ss << value.Get(idx); + } else if (type == "i32") { + ss << value.Get(idx); + } else if (type == "u32") { + ss << value.Get(idx); + } else if (type == "i64") { + ss << value.Get(idx); + } else if (type == "u64") { + ss << value.Get(idx); + } else if (type == "f32") { + ss << value.Get(idx); + } else if (type == "f64") { + ss << value.Get(idx); + } else if (type == "string") { + const auto id = value.Get(idx); + ss << '\"' << stringTable_->GetStringById(id) << '\"'; + } else if (type == "record") { + const auto id = value.Get(idx); + ss << keyData_.GetFullRecordNameById(id); + } else if (type == "method") { + const auto id = value.Get(idx); + AbcMethodProcessor methodProcessor(id, keyData_); + ss << methodProcessor.GetMethodSignature(); + } else if (type == "enum") { + const auto id = value.Get(idx); + panda_file::FieldDataAccessor fieldAccessor(*file_, id); + ss << keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()) << "." + << stringTable_->GetStringById(fieldAccessor.GetNameId()); + } else if (type == "annotation") { + const auto id = value.Get(idx); + ss << "id_" << id; + } else if (type == "method_handle") { + } else if (type == "nullptr_string") { + } + + return ss.str(); +} + +ark::panda_file::SourceLang AbcFileProcessor::GetRecordLanguage(panda_file::File::EntityId classId) const +{ + if (file_->IsExternal(classId)) { + return ark::panda_file::SourceLang::PANDA_ASSEMBLY; + } + + panda_file::ClassDataAccessor cda(*file_, classId); + return cda.GetSourceLang().value_or(panda_file::SourceLang::PANDA_ASSEMBLY); +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_file_processor.h b/static_core/abc2program/abc_file_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..f94f1d4e4b761469b5947a1dbc0b6af2a77e486c --- /dev/null +++ b/static_core/abc2program/abc_file_processor.h @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_FILE_PROCESSOR_H +#define ABC2PROGRAM_ABC_FILE_PROCESSOR_H + +#include "source_lang_enum.h" +#include "value.h" +#include "abc2program_key_data.h" + +namespace ark::abc2program { + +using AnnotationList = std::vector>; + +struct RecordAnnotations { + AnnotationList annList; + std::map fieldAnnotations; +}; + +struct ProgAnnotations { + std::map methodAnnotations; + std::map recordAnnotations; +}; + +class AbcFileProcessor { +public: + explicit AbcFileProcessor(Abc2ProgramKeyData &keyData); + bool ProcessFile(); + +private: +#include "abc2program_plugins.inc" + ark::panda_file::SourceLang GetRecordLanguage(panda_file::File::EntityId classId) const; + std::string ScalarValueToString(const panda_file::ScalarValue &value, const std::string &type); + std::string ArrayValueToString(const panda_file::ArrayValue &value, const std::string &type, const size_t idx); + std::string AnnotationTagToString(const char tag) const; + void FillExternalFieldsToRecords(); + void FillLiteralArrays(); + void ProcessClasses(); + void FillProgramStrings(); + void GetLanguageSpecificMetadata(); + Abc2ProgramKeyData &keyData_; + const panda_file::File *file_ = nullptr; + AbcStringTable *stringTable_ = nullptr; + pandasm::Program *program_ = nullptr; + ProgAnnotations progAnn_ {}; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_FILE_PROCESSOR_H diff --git a/static_core/abc2program/abc_file_utils.cpp b/static_core/abc2program/abc_file_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ecae0469d551193982cf36d7d53b07d9e4ee46d4 --- /dev/null +++ b/static_core/abc2program/abc_file_utils.cpp @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2024-2025 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 "abc_file_utils.h" +#include "os/file.h" + +namespace ark::abc2program { + +static std::string_view GLOBAL_TYPE_NAME = "_GLOBAL"; + +static const char ARRAY_TYPE_POSTFIX = ']'; + +bool AbcFileUtils::IsSystemTypeName(const std::string &typeName) +{ + bool isArrayType = typeName.back() == ARRAY_TYPE_POSTFIX; + bool isGlobal = typeName == GLOBAL_TYPE_NAME; + + return isArrayType || isGlobal; +} + +std::string AbcFileUtils::GetFileNameByAbsolutePath(const std::string &absolutePath) +{ + LOG(DEBUG, ABC2PROGRAM) << "Absolute path is : " << absolutePath; + size_t pos = absolutePath.find_last_of(ark::os::file::File::GetPathDelim()); + ASSERT(pos != std::string::npos); + std::string fileName = absolutePath.substr(pos + 1); + return fileName; +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_file_utils.h b/static_core/abc2program/abc_file_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..37406ab8ef47c4251ae4f84c992d9a62a9ced059 --- /dev/null +++ b/static_core/abc2program/abc_file_utils.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_FILE_UTILS_H +#define ABC2PROGRAM_ABC_FILE_UTILS_H + +#include +#include "libpandafile/file.h" +#include "value.h" + +namespace ark::abc2program { + +// attribute constant +constexpr std::string_view ABC_ATTR_EXTERNAL = "external"; +constexpr std::string_view ABC_ATTR_STATIC = "static"; + +// dump constant +constexpr std::string_view DUMP_TITLE_SOURCE_BINARY = "# source binary: "; +constexpr std::string_view DUMP_TITLE_LANGUAGE = ".language "; +constexpr std::string_view DUMP_TITLE_LITERALS = "# LITERALS"; +constexpr std::string_view DUMP_TITLE_RECORDS = "# RECORDS"; +constexpr std::string_view DUMP_TITLE_RECORD = ".record "; +constexpr std::string_view DUMP_TITLE_RECORD_SOURCE_FILE = "# .record.source_file "; +constexpr std::string_view DUMP_TITLE_METHODS = "# METHODS"; +constexpr std::string_view DUMP_TITLE_FUNCTION = ".function "; +constexpr std::string_view DUMP_TITLE_LITERAL_ARRAY = ".array "; +constexpr std::string_view DUMP_LITERAL_ARRAY_PREFIX = "array_"; +constexpr std::string_view DUMP_TITLE_STRING = "# STRING\n\n"; +constexpr std::string_view DUMP_TITLE_SEPARATOR = "# ====================\n"; +constexpr std::string_view DUMP_CONTENT_ETS = "eTS"; +constexpr std::string_view DUMP_CONTENT_PANDA_ASSEMBLY = "PandaAssembly"; +constexpr std::string_view DUMP_CONTENT_SINGLE_ENDL = "\n"; +constexpr std::string_view DUMP_CONTENT_DOUBLE_ENDL = "\n\n"; + +class AbcFileUtils { +public: + static bool IsSystemTypeName(const std::string &typeName); + static std::string GetFileNameByAbsolutePath(const std::string &absolutePath); +}; // class AbcFileUtils + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_FILE_UTILS_H diff --git a/static_core/abc2program/abc_literal_array_processor.cpp b/static_core/abc2program/abc_literal_array_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1f70554f3b4a431aac2ae71d77ee67c3af7d75e5 --- /dev/null +++ b/static_core/abc2program/abc_literal_array_processor.cpp @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2024-2025 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 "abc_literal_array_processor.h" +#include "abc2program_log.h" + +namespace ark::abc2program { + +AbcLiteralArrayProcessor::AbcLiteralArrayProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData) + : AbcFileEntityProcessor(entityId, keyData) +{ + literalDataAccessor_ = std::make_unique(*file_, entityId_); + FillProgramData(); +} + +template +void AbcLiteralArrayProcessor::FillLiteralArrayData(pandasm::LiteralArray *litArray, const panda_file::LiteralTag &tag, + const panda_file::LiteralDataAccessor::LiteralValue &value) const +{ + panda_file::File::EntityId id(std::get(value)); + auto sp = file_->GetSpanFromId(id); + auto len = panda_file::helpers::Read(&sp); + if (tag != panda_file::LiteralTag::ARRAY_STRING) { + for (size_t i = 0; i < len; i++) { + pandasm::LiteralArray::Literal lit; + lit.tag = tag; + lit.value = bit_cast(panda_file::helpers::Read(&sp)); + litArray->literals.push_back(lit); + } + } else { + for (size_t i = 0; i < len; i++) { + auto strId = panda_file::helpers::Read(&sp); + pandasm::LiteralArray::Literal lit; + lit.tag = tag; + lit.value = stringTable_->GetStringById(panda_file::File::EntityId(strId)); + litArray->literals.push_back(lit); + } + } +} + +void AbcLiteralArrayProcessor::FillLiteralData(pandasm::LiteralArray *litArray, + const panda_file::LiteralDataAccessor::LiteralValue &value, + const panda_file::LiteralTag &tag) const +{ + pandasm::LiteralArray::Literal lit; + lit.tag = tag; + switch (tag) { + case panda_file::LiteralTag::BOOL: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::ACCESSOR: + case panda_file::LiteralTag::NULLVALUE: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::METHODAFFILIATE: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::INTEGER: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::BIGINT: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::FLOAT: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::DOUBLE: { + lit.value = std::get(value); + break; + } + case panda_file::LiteralTag::STRING: + case panda_file::LiteralTag::METHOD: + case panda_file::LiteralTag::GENERATORMETHOD: { + lit.value = stringTable_->GetStringById(panda_file::File::EntityId(std::get(value))); + break; + } + case panda_file::LiteralTag::TAGVALUE: { + return; + } + default: { + LOG(ERROR, ABC2PROGRAM) << "Unsupported literal with tag 0x" << std::hex << static_cast(tag); + UNREACHABLE(); + } + } + litArray->literals.push_back(lit); +} + +void AbcLiteralArrayProcessor::GetLiteralArray(pandasm::LiteralArray *litArray, const size_t index) +{ + LOG(DEBUG, ABC2PROGRAM) << "\n[getting literal array]\nindex: " << index; + + literalDataAccessor_->EnumerateLiteralVals( + index, [this, litArray](const panda_file::LiteralDataAccessor::LiteralValue &value, + const panda_file::LiteralTag &tag) { + switch (tag) { + case panda_file::LiteralTag::ARRAY_U1: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_I8: + case panda_file::LiteralTag::ARRAY_U8: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_I16: + case panda_file::LiteralTag::ARRAY_U16: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_I32: + case panda_file::LiteralTag::ARRAY_U32: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_I64: + case panda_file::LiteralTag::ARRAY_U64: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_F32: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_F64: { + FillLiteralArrayData(litArray, tag, value); + break; + } + case panda_file::LiteralTag::ARRAY_STRING: { + FillLiteralArrayData(litArray, tag, value); + break; + } + default: { + FillLiteralData(litArray, value, tag); + } + } + }); +} + +void AbcLiteralArrayProcessor::FillProgramData() +{ + LOG(DEBUG, ABC2PROGRAM) << "\n[getting literal arrays]\nid: " << entityId_ << " (0x" << std::hex << entityId_ + << ")"; + + size_t numLitarrays = literalDataAccessor_->GetLiteralNum(); + for (size_t index = 0; index < numLitarrays; index++) { + ark::pandasm::LiteralArray litAr; + GetLiteralArray(&litAr, index); + program_->literalarrayTable.emplace(std::to_string(index), litAr); + } +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_literal_array_processor.h b/static_core/abc2program/abc_literal_array_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..525818abad62ced894f0a98122899dbe041efca7 --- /dev/null +++ b/static_core/abc2program/abc_literal_array_processor.h @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_LITERAL_ARRAY_PROCESSOR_H +#define ABC2PROGRAM_ABC_LITERAL_ARRAY_PROCESSOR_H + +#include "abc_file_entity_processor.h" + +namespace ark::abc2program { + +class AbcLiteralArrayProcessor : public AbcFileEntityProcessor { +public: + AbcLiteralArrayProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData); + void FillProgramData() override; + +private: + template + void FillLiteralArrayData(pandasm::LiteralArray *litArray, const panda_file::LiteralTag &tag, + const panda_file::LiteralDataAccessor::LiteralValue &value) const; + std::unique_ptr literalDataAccessor_; + void FillLiteralData(pandasm::LiteralArray *litArray, const panda_file::LiteralDataAccessor::LiteralValue &value, + const panda_file::LiteralTag &tag) const; + void GetLiteralArray(pandasm::LiteralArray *litArray, const size_t index); +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_LITERAL_ARRAY_PROCESSOR_H diff --git a/static_core/abc2program/abc_method_processor.cpp b/static_core/abc2program/abc_method_processor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8eb081ba8239a01bf30adf16377ce1374587a98e --- /dev/null +++ b/static_core/abc2program/abc_method_processor.cpp @@ -0,0 +1,229 @@ +/** + * Copyright (c) 2024-2025 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 "abc_method_processor.h" +#include "abc_code_processor.h" +#include "assembly-function.h" +#include "mangling.h" +#include "source_lang_enum.h" +#include "proto_data_accessor-inl.h" + +namespace ark::abc2program { + +AbcMethodProcessor::AbcMethodProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData) + : AbcFileEntityProcessor(entityId, keyData), + function_(pandasm::Function("", keyData.GetFileLanguage())) +{ + methodDataAccessor_ = std::make_unique(*file_, entityId_); + FillProgramData(); +} + +void AbcMethodProcessor::FillProgramData() +{ + FillFunction(); +} + +void AbcMethodProcessor::FillFunction() +{ + GetMethodName(); + + methodSignature_ = pandasm::MangleFunctionName(function_.name, function_.params, function_.returnType); + if (keyData_.methodNameToId_.find(methodSignature_) != keyData_.methodNameToId_.end()) { + return; + } + + keyData_.methodNameToId_.emplace(methodSignature_, entityId_); + + GetMethodCode(); + + program_->functionTable.emplace(methodSignature_, std::move(function_)); +} + +void AbcMethodProcessor::GetMethodName() +{ + function_.name = keyData_.GetFullFunctionNameById(entityId_); + + LOG(DEBUG, ABC2PROGRAM) << "name: " << function_.name; + + GetParams(methodDataAccessor_->GetProtoId()); + GetMetaData(); +} + +void AbcMethodProcessor::GetMethodCode() +{ + if (!function_.HasImplementation()) { + return; + } + + std::optional codeId = methodDataAccessor_->GetCodeId(); + if (codeId.has_value()) { + AbcCodeProcessor codeProcessor(codeId.value(), keyData_, entityId_); + function_.ins = codeProcessor.GetIns(); + function_.regsNum = codeProcessor.GetNumVregs(); + function_.catchBlocks = codeProcessor.GetCatchBlocks(); + } else { + LOG(ERROR, ABC2PROGRAM) << "> error encountered at " << entityId_ << " (0x" << std::hex << entityId_ + << "). implementation of method expected, but no \'CODE\' tag was found!"; + + return; + } +} + +void AbcMethodProcessor::GetMetaData() +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting metadata]\nmethod id: " << entityId_ << " (0x" << std::hex << entityId_ << ")"; + + const auto methodNameRaw = stringTable_->GetStringById((methodDataAccessor_->GetNameId())); + + if (!methodDataAccessor_->IsStatic()) { + auto className = stringTable_->GetStringById((methodDataAccessor_->GetClassId())); + std::replace(className.begin(), className.end(), '/', '.'); + auto thisType = pandasm::Type::FromDescriptor(className); + + LOG(DEBUG, ABC2PROGRAM) << "method (raw: \'" << methodNameRaw + << "\') is not static. emplacing self-argument of type " << thisType.GetName(); + + function_.params.insert(function_.params.begin(), + pandasm::Function::Parameter(thisType, keyData_.GetFileLanguage())); + } + SetEntityAttribute( + function_, [this]() { return methodDataAccessor_->IsStatic(); }, "static"); + + SetEntityAttribute( + function_, [this]() { return file_->IsExternal(methodDataAccessor_->GetMethodId()); }, "external"); + + SetEntityAttribute( + function_, [this]() { return methodDataAccessor_->IsNative(); }, "native"); + + SetEntityAttribute( + function_, [this]() { return methodDataAccessor_->IsAbstract(); }, "noimpl"); + + SetEntityAttributeValue( + function_, [this]() { return methodDataAccessor_->IsPublic(); }, "access.function", "public"); + + SetEntityAttributeValue( + function_, [this]() { return methodDataAccessor_->IsProtected(); }, "access.function", "protected"); + + SetEntityAttributeValue( + function_, [this]() { return methodDataAccessor_->IsPrivate(); }, "access.function", "private"); + + SetEntityAttribute( + function_, [this]() { return methodDataAccessor_->IsFinal(); }, "final"); + + std::string ctorName = ark::panda_file::GetCtorName(keyData_.GetFileLanguage()); + std::string cctorName = ark::panda_file::GetCctorName(keyData_.GetFileLanguage()); + + const bool isCtor = (methodNameRaw == ctorName); + const bool isCctor = (methodNameRaw == cctorName); + + if (isCtor) { + function_.metadata->SetAttribute("ctor"); + function_.name.replace(function_.name.find(ctorName), ctorName.length(), "_ctor_"); + } else if (isCctor) { + function_.metadata->SetAttribute("cctor"); + function_.name.replace(function_.name.find(cctorName), cctorName.length(), "_cctor_"); + } +} + +void AbcMethodProcessor::GetParams(const panda_file::File::EntityId &protoId) +{ + /// frame size - 2^16 - 1 + static const uint32_t MAX_ARG_NUM = 0xFFFF; + + LOG(DEBUG, ABC2PROGRAM) << "[getting params]\nproto id: " << protoId << " (0x" << std::hex << protoId << ")"; + + panda_file::ProtoDataAccessor protoAccessor(*file_, protoId); + + if (protoAccessor.GetNumArgs() > MAX_ARG_NUM) { + LOG(ERROR, ABC2PROGRAM) << "> error encountered at " << protoId << " (0x" << std::hex << protoId + << "). number of function's arguments (" << std::dec << protoAccessor.GetNumArgs() + << ") exceeds MAX_ARG_NUM (" << MAX_ARG_NUM << ") !"; + + return; + } + + size_t refIdx = 0; + function_.returnType = PFTypeToPandasmType(protoAccessor.GetReturnType(), protoAccessor, refIdx); + + for (size_t i = 0; i < protoAccessor.GetNumArgs(); i++) { + auto argType = PFTypeToPandasmType(protoAccessor.GetArgType(i), protoAccessor, refIdx); + function_.params.emplace_back(argType, keyData_.GetFileLanguage()); + } +} + +pandasm::Type AbcMethodProcessor::PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda, + size_t &refIdx) const +{ + pandasm::Type pandasmType; + + switch (type.GetId()) { + case panda_file::Type::TypeId::INVALID: + pandasmType = pandasm::Type("invalid", 0); + break; + case panda_file::Type::TypeId::VOID: + pandasmType = pandasm::Type("void", 0); + break; + case panda_file::Type::TypeId::U1: + pandasmType = pandasm::Type("u1", 0); + break; + case panda_file::Type::TypeId::I8: + pandasmType = pandasm::Type("i8", 0); + break; + case panda_file::Type::TypeId::U8: + pandasmType = pandasm::Type("u8", 0); + break; + case panda_file::Type::TypeId::I16: + pandasmType = pandasm::Type("i16", 0); + break; + case panda_file::Type::TypeId::U16: + pandasmType = pandasm::Type("u16", 0); + break; + case panda_file::Type::TypeId::I32: + pandasmType = pandasm::Type("i32", 0); + break; + case panda_file::Type::TypeId::U32: + pandasmType = pandasm::Type("u32", 0); + break; + case panda_file::Type::TypeId::F32: + pandasmType = pandasm::Type("f32", 0); + break; + case panda_file::Type::TypeId::F64: + pandasmType = pandasm::Type("f64", 0); + break; + case panda_file::Type::TypeId::I64: + pandasmType = pandasm::Type("i64", 0); + break; + case panda_file::Type::TypeId::U64: + pandasmType = pandasm::Type("u64", 0); + break; + case panda_file::Type::TypeId::TAGGED: + pandasmType = pandasm::Type("any", 0); + break; + case panda_file::Type::TypeId::REFERENCE: + std::string typeName = stringTable_->GetStringById(pda.GetReferenceType(refIdx++)); + std::replace(typeName.begin(), typeName.end(), '/', '.'); + pandasmType = pandasm::Type::FromDescriptor(typeName); + break; + } + + return pandasmType; +} + +std::string AbcMethodProcessor::GetMethodSignature() +{ + return methodSignature_; +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_method_processor.h b/static_core/abc2program/abc_method_processor.h new file mode 100644 index 0000000000000000000000000000000000000000..6eb1a03b8382abae5a5cf1f83607dfc892c5b7c4 --- /dev/null +++ b/static_core/abc2program/abc_method_processor.h @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_METHOD_PROCESSOR_H +#define ABC2PROGRAM_ABC_METHOD_PROCESSOR_H + +#include "abc_file_entity_processor.h" +#include "method_data_accessor-inl.h" + +namespace ark::abc2program { + +class AbcMethodProcessor : public AbcFileEntityProcessor { +public: + AbcMethodProcessor(panda_file::File::EntityId entityId, Abc2ProgramKeyData &keyData); + void GetMethodName(); + void GetMethodCode(); + void FillProgramData() override; + std::string GetMethodSignature(); + +private: + pandasm::Function function_; + void GetParams(const panda_file::File::EntityId &protoId); + void GetMetaData(); + pandasm::Type PFTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda, + size_t &refIdx) const; + void FillFunction(); + std::unique_ptr methodDataAccessor_; + std::string methodSignature_; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_METHOD_PROCESSOR_H diff --git a/static_core/abc2program/abc_string_table.cpp b/static_core/abc2program/abc_string_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c0638d7d91d4541871a085843be73a2a72385299 --- /dev/null +++ b/static_core/abc2program/abc_string_table.cpp @@ -0,0 +1,116 @@ +/** + * Copyright (c) 2024-2025 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 "abc_string_table.h" +#include "abc_file_utils.h" + +namespace ark::abc2program { + +std::string AbcStringTable::GetStringById(uint32_t stringId) const +{ + panda_file::File::EntityId entity_id(stringId); + return GetStringById(entity_id); +} + +std::string AbcStringTable::GetStringById(panda_file::File::EntityId entityId) const +{ + std::string str = StringDataToString(file_.GetStringData(entityId)); + return str; +} + +void AbcStringTable::AddStringId(uint32_t stringId) +{ + auto it = stingIdSet_.find(stringId); + if (it != stingIdSet_.end()) { + return; + } + stingIdSet_.insert(stringId); +} + +void AbcStringTable::AddStringId(panda_file::File::EntityId entityId) +{ + AddStringId(entityId.GetOffset()); +} + +std::set AbcStringTable::GetStringSet() const +{ + std::set stringSet; + for (uint32_t stringId : stingIdSet_) { + stringSet.insert(GetStringById(stringId)); + } + return stringSet; +} + +void AbcStringTable::Dump(std::ostream &os) const +{ + for (uint32_t stringId : stingIdSet_) { + DumpStringById(os, stringId); + } +} + +void AbcStringTable::DumpStringById(std::ostream &os, uint32_t stringId) const +{ + os << "[offset:0x" << std::hex << stringId << ", name_value:" << GetStringById(stringId) << "]" << std::endl; +} + +std::string AbcStringTable::StringDataToString(panda_file::File::StringData sd) const +{ + std::string str = std::string(utf::Mutf8AsCString(sd.data)); + std::replace(str.begin(), str.end(), '#', '_'); + size_t symPos = 0; + while (symPos = str.find_first_of("\a\b\f\n\r\t\v\'\\\"", symPos), symPos != std::string::npos) { + std::string sym; + switch (str[symPos]) { + case '\a': + sym = R"(\a)"; + break; + case '\b': + sym = R"(\b)"; + break; + case '\f': + sym = R"(\f)"; + break; + case '\n': + sym = R"(\n)"; + break; + case '\r': + sym = R"(\r)"; + break; + case '\t': + sym = R"(\t)"; + break; + case '\v': + sym = R"(\v)"; + break; + case '\"': + sym = R"(\")"; + break; + case '\'': + sym = R"(\')"; + break; + case '\\': + sym = R"(\\)"; + break; + default: + UNREACHABLE(); + } + str = str.replace(symPos, 1, sym); + ASSERT(sym.size() == 2U); + symPos += 2U; + } + return str; +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/abc_string_table.h b/static_core/abc2program/abc_string_table.h new file mode 100644 index 0000000000000000000000000000000000000000..79d1be26a5b1f655deef22d7133106555ae4e9c5 --- /dev/null +++ b/static_core/abc2program/abc_string_table.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_ABC_STRING_TABLE_H +#define ABC2PROGRAM_ABC_STRING_TABLE_H + +#include +#include +#include +#include +#include +#include "file-inl.h" +#include "file.h" + +namespace ark::abc2program { + +class AbcStringTable { +public: + explicit AbcStringTable(const panda_file::File &file) : file_(file) {} + std::string GetStringById(uint32_t stringId) const; + std::string GetStringById(panda_file::File::EntityId entityId) const; + void AddStringId(uint32_t stringId); + void AddStringId(panda_file::File::EntityId entityId); + std::set GetStringSet() const; + std::string StringDataToString(panda_file::File::StringData sd) const; + void Dump(std::ostream &os) const; + +private: + void DumpStringById(std::ostream &os, uint32_t stringId) const; + const panda_file::File &file_; + std::set stingIdSet_; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_ABC_STRING_TABLE_H diff --git a/static_core/abc2program/common/abc_code_converter.cpp b/static_core/abc2program/common/abc_code_converter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4c4fdfd7f28eb2fdec58ec37b77520957856560d --- /dev/null +++ b/static_core/abc2program/common/abc_code_converter.cpp @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2024-2025 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 "abc_code_converter.h" +#include "abc_method_processor.h" +#include "os/file.h" +#include "type_helper.h" + +namespace ark::abc2program { + +AbcCodeConverter::AbcCodeConverter(Abc2ProgramKeyData &keyData) : keyData_(keyData) +{ + file_ = &(keyData_.GetAbcFile()); + stringTable_ = &(keyData_.GetAbcStringTable()); +} + +std::string AbcCodeConverter::IDToString(BytecodeInstruction bcIns, panda_file::File::EntityId methodId) const +{ + std::stringstream name; + + if (bcIns.HasFlag(BytecodeInstruction::Flags::TYPE_ID)) { + auto type = pandasm::Type::FromDescriptor( + stringTable_->GetStringById(file_->ResolveClassIndex(methodId, bcIns.GetId().AsIndex()))); + name.str(""); + name << type.GetPandasmName(); + } else if (bcIns.HasFlag(BytecodeInstruction::Flags::METHOD_ID)) { + auto id = file_->ResolveMethodIndex(methodId, bcIns.GetId().AsIndex()); + AbcMethodProcessor methodProcessor(id, keyData_); + name << methodProcessor.GetMethodSignature(); + } else if (bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID)) { + const auto offset = bcIns.GetId().AsFileId(); + stringTable_->AddStringId(offset); + std::string strData = stringTable_->GetStringById(offset); + // name << '\"'; + name << stringTable_->GetStringById(bcIns.GetId().AsFileId()); + // name << '\"'; + } else if (bcIns.HasFlag(BytecodeInstruction::Flags::FIELD_ID)) { + auto id = file_->ResolveFieldIndex(methodId, bcIns.GetId().AsIndex()); + panda_file::FieldDataAccessor fieldAccessor(*file_, id); + + auto recordName = keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()); + if (!panda_file::IsDummyClassName(recordName)) { + name << recordName; + name << '.'; + } + name << stringTable_->GetStringById(fieldAccessor.GetNameId()); + } else if (bcIns.HasFlag(BytecodeInstruction::Flags::LITERALARRAY_ID)) { + auto index = bcIns.GetId().AsIndex(); + name << "array_" << index; + } + + return name.str(); +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/common/abc_code_converter.h b/static_core/abc2program/common/abc_code_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..00d33fccc4202cbc39c9951092e83fd2084341c0 --- /dev/null +++ b/static_core/abc2program/common/abc_code_converter.h @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_COMMON_ABC_CODE_CONVERTER_H +#define ABC2PROGRAM_COMMON_ABC_CODE_CONVERTER_H + +#include +#include "bytecode_instruction-inl.h" +#include "bytecode_instruction.h" +#include "abc_string_table.h" +#include "abc2program_key_data.h" + +namespace ark::abc2program { + +class AbcCodeConverter { +public: + explicit AbcCodeConverter(Abc2ProgramKeyData &keyData); + pandasm::Ins BytecodeInstructionToPandasmInstruction(BytecodeInstruction bcIns, + panda_file::File::EntityId methodId) const; + pandasm::Opcode BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode opcode) const; + std::string IDToString(BytecodeInstruction bcIns, panda_file::File::EntityId methodId) const; + +private: + Abc2ProgramKeyData &keyData_; + const panda_file::File *file_ = nullptr; + AbcStringTable *stringTable_ = nullptr; +}; // class AbcCodeConverter + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_COMMON_ABC_CODE_CONVERTER_H \ No newline at end of file diff --git a/static_core/abc2program/common/abc_type_converter.h b/static_core/abc2program/common/abc_type_converter.h new file mode 100644 index 0000000000000000000000000000000000000000..97e653a68980ec2e3f3bab30905bab43c79e194a --- /dev/null +++ b/static_core/abc2program/common/abc_type_converter.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_COMMON_ABC_TYPE_CONVERTER_H +#define ABC2PROGRAM_COMMON_ABC_TYPE_CONVERTER_H + +#include +#include "proto_data_accessor-inl.h" +#include "abc_string_table.h" + +namespace ark::abc2program { + +class AbcTypeConverter { +public: + explicit AbcTypeConverter(AbcStringTable &stringTable) : stringTable_(stringTable) {} + pandasm::Type PandaFileTypeToPandasmType(const panda_file::Type &type, panda_file::ProtoDataAccessor &pda, + size_t &refIdx) const; + pandasm::Type FieldTypeToPandasmType(const uint32_t &type) const; + +private: + AbcStringTable &stringTable_; +}; // class AbcTypeConverter + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_COMMON_ABC_TYPE_CONVERTER_H \ No newline at end of file diff --git a/static_core/abc2program/program_dump.cpp b/static_core/abc2program/program_dump.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29143a9194ac181f0e14888b9664fd348dbdb257 --- /dev/null +++ b/static_core/abc2program/program_dump.cpp @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2024-2025 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 "program_dump.h" +#include "mangling.h" +#include "method_data_accessor-inl.h" +#include "abc2program_log.h" +#include "abc_file_utils.h" +#include "source_language.h" + +namespace ark::abc2program { + +void PandasmProgramDumper::Dump(std::ostream &os, const pandasm::Program &program) const +{ + os << std::flush; + DumpAbcFilePath(os); + DumpProgramLanguage(os, program); + DumpLiteralArrayTable(os, program); + DumpRecordTable(os, program); + DumpFunctionTable(os, program); +} + +bool PandasmProgramDumper::HasNoAbcInput() const +{ + return ((file_ == nullptr) || (stringTable_ == nullptr)); +} + +void PandasmProgramDumper::DumpAbcFilePath(std::ostream &os) const +{ + if (HasNoAbcInput()) { + return; + } + os << DUMP_TITLE_SOURCE_BINARY << file_->GetFilename() << DUMP_CONTENT_DOUBLE_ENDL; +} + +void PandasmProgramDumper::DumpProgramLanguage(std::ostream &os, const pandasm::Program &program) const +{ + os << DUMP_TITLE_LANGUAGE; + os << ark::panda_file::LanguageToString(program.lang); + os << DUMP_CONTENT_DOUBLE_ENDL; +} + +void PandasmProgramDumper::DumpLiteralArrayTable(std::ostream &os, const pandasm::Program &program) const +{ + if (HasNoAbcInput()) { + DumpLiteralArrayTableWithoutKey(os, program); + } else { + DumpLiteralArrayTableWithKey(os, program); + } +} + +void PandasmProgramDumper::DumpLiteralArrayTableWithKey(std::ostream &os, const pandasm::Program &program) const +{ + os << DUMP_TITLE_SEPARATOR; + os << DUMP_TITLE_LITERALS << DUMP_CONTENT_SINGLE_ENDL; + for (auto &[key, litArray] : program.literalarrayTable) { + DumpLiteralArrayWithKey(os, key, litArray, program); + } + os << DUMP_CONTENT_DOUBLE_ENDL; +} + +void PandasmProgramDumper::DumpLiteralArrayWithKey(std::ostream &os, const std::string &key, + const pandasm::LiteralArray &litArray, + const pandasm::Program &program) const +{ + os << DUMP_TITLE_LITERAL_ARRAY; + os << DUMP_LITERAL_ARRAY_PREFIX; + os << key << " "; + DumpLiteralArray(os, litArray, program); + os << DUMP_CONTENT_SINGLE_ENDL; +} + +void PandasmProgramDumper::DumpLiteralArrayTableWithoutKey(std::ostream &os, const pandasm::Program &program) const +{ + for (auto &[unused, litArray] : program.literalarrayTable) { + (void)unused; + DumpLiteralArray(os, litArray, program); + os << DUMP_CONTENT_SINGLE_ENDL; + } + os << DUMP_CONTENT_DOUBLE_ENDL; +} + +void PandasmProgramDumper::DumpRecordTable(std::ostream &os, const pandasm::Program &program) const +{ + os << DUMP_TITLE_SEPARATOR; + os << DUMP_TITLE_RECORDS; + os << DUMP_CONTENT_DOUBLE_ENDL; + for (const auto &it : program.recordTable) { + DumpRecord(os, it.second); + } + os << DUMP_CONTENT_SINGLE_ENDL; +} + +void PandasmProgramDumper::DumpRecord(std::ostream &os, const pandasm::Record &record) const +{ + if (AbcFileUtils::IsSystemTypeName(record.name)) { + return; + } + os << DUMP_TITLE_RECORD << record.name; + if (DumpMetaData(os, *record.metadata)) { + DumpFieldList(os, record); + } + DumpRecordSourceFile(os, record); +} + +void PandasmProgramDumper::DumpFieldList(std::ostream &os, const pandasm::Record &record) const +{ + if (record.metadata->IsForeign() && record.fieldList.empty()) { + os << DUMP_CONTENT_DOUBLE_ENDL; + return; + } + os << " {" << DUMP_CONTENT_SINGLE_ENDL; + for (const auto &it : record.fieldList) { + DumpField(os, it); + os << DUMP_CONTENT_SINGLE_ENDL; + } + os << DUMP_CONTENT_SINGLE_ENDL << "}" << DUMP_CONTENT_SINGLE_ENDL; +} + +void PandasmProgramDumper::DumpField(std::ostream &os, const pandasm::Field &field) const +{ + os << "\t" << field.type.GetPandasmName() << " " << field.name; + DumpMetaData(os, *field.metadata); +} + +bool PandasmProgramDumper::DumpMetaData(std::ostream &os, const pandasm::ItemMetadata &meta) const +{ + auto boolAttributes = meta.GetBoolAttributes(); + auto attributes = meta.GetAttributes(); + if (boolAttributes.empty() && attributes.empty()) { + return true; + } + + os << " <"; + + size_t size = boolAttributes.size(); + size_t idx = 0; + for (const auto &attr : boolAttributes) { + os << attr; + ++idx; + + if (!attributes.empty() || idx < size) { + os << ", "; + } + } + + size = attributes.size(); + idx = 0; + for (const auto &[key, values] : attributes) { + for (size_t i = 0; i < values.size(); i++) { + os << key << "=" << values[i]; + + if (i < values.size() - 1) { + os << ", "; + } + } + + ++idx; + + if (idx < size) { + os << ", "; + } + } + + os << ">"; + return true; +} + +void PandasmProgramDumper::DumpRecordSourceFile(std::ostream &os, const pandasm::Record &record) const +{ + os << DUMP_TITLE_RECORD_SOURCE_FILE << record.sourceFile << DUMP_CONTENT_DOUBLE_ENDL; +} + +void PandasmProgramDumper::DumpFunctionTable(std::ostream &os, const pandasm::Program &program) const +{ + os << DUMP_TITLE_SEPARATOR; + os << DUMP_TITLE_METHODS; + os << DUMP_CONTENT_DOUBLE_ENDL; + for (const auto &it : program.functionTable) { + DumpFunction(os, it.second); + } +} + +void PandasmProgramDumper::DumpFunction(std::ostream &os, const pandasm::Function &function) const +{ + os << DUMP_TITLE_FUNCTION; + os << function.returnType.GetPandasmName() << " " << function.name << "("; + if (!function.params.empty()) { + os << function.params[0].type.GetPandasmName() << " a0"; + + for (size_t i = 1; i < function.params.size(); i++) { + os << ", " << function.params[i].type.GetPandasmName() << " a" << (size_t)i; + } + } + os << ")"; + + const std::string signature = pandasm::GetFunctionSignatureFromName(function.name, function.params); + + DumpMetaData(os, *function.metadata); + + if (!function.HasImplementation()) { + os << DUMP_CONTENT_DOUBLE_ENDL; + return; + } + + os << " {"; + + os << DUMP_CONTENT_SINGLE_ENDL; + + DumpInstructions(os, function); + + os << "}" << DUMP_CONTENT_DOUBLE_ENDL; +} + +void PandasmProgramDumper::DumpInstructions(std::ostream &os, const pandasm::Function &function) const +{ + for (auto instr : function.ins) { + std::string ins = instr.ToString("", function.GetParamsNum() != 0, function.regsNum); + if (instr.setLabel) { + std::string delim = ": "; + size_t pos = ins.find(delim); + std::string label = ins.substr(0, pos); + ins.erase(0, pos + delim.length()); + + os << label << ":"; + os << DUMP_CONTENT_SINGLE_ENDL; + } + + os << "\t"; + os << ins; + os << DUMP_CONTENT_SINGLE_ENDL; + } +} + +void PandasmProgramDumper::DumpStrings(std::ostream &os, const pandasm::Program &program) const +{ + if (HasNoAbcInput()) { + DumpStringsByProgram(os, program); + } else { + DumpStringsByStringTable(os, *stringTable_); + } +} + +void PandasmProgramDumper::DumpStringsByStringTable(std::ostream &os, const AbcStringTable &stringTable) const +{ + os << DUMP_TITLE_SEPARATOR; + os << DUMP_TITLE_STRING; + stringTable.Dump(os); + os << DUMP_CONTENT_SINGLE_ENDL; +} + +void PandasmProgramDumper::DumpStringsByProgram(std::ostream &os, const pandasm::Program &program) const +{ + os << DUMP_TITLE_SEPARATOR; + os << DUMP_TITLE_STRING; + os << DUMP_CONTENT_SINGLE_ENDL; + for (const std::string &str : program.strings) { + os << str << DUMP_CONTENT_SINGLE_ENDL; + } + os << DUMP_CONTENT_SINGLE_ENDL; +} + +void PandasmProgramDumper::DumpLiteralArray(std::ostream &os, const pandasm::LiteralArray &litArray, + const pandasm::Program &program) const +{ + if (litArray.literals.empty()) { + return; + } + + bool isConst = litArray.literals[0].IsArray(); + + std::stringstream specifiers {}; + if (isConst) { + specifiers << LiteralTagToString(litArray.literals[0].tag, program) << " " << litArray.literals.size() << " "; + } + os << specifiers.str() << "{"; + + DumpValues(litArray, isConst, os, program); + + os << "}" << DUMP_CONTENT_SINGLE_ENDL; +} + +template +std::string LiteralIntegralValueToString(const pandasm::LiteralArray::Literal &lit) +{ + std::stringstream res {}; + T value = std::get(lit.value); + if (lit.IsSigned()) { + res << +static_cast::type>(value); + } else { + res << +value; + } + return res.str(); +} + +std::string PandasmProgramDumper::LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const +{ + if (lit.IsBoolValue()) { + std::stringstream res {}; + res << (std::get(lit.value)); + return res.str(); + } + + if (lit.IsByteValue()) { + return LiteralIntegralValueToString(lit); + } + + if (lit.IsShortValue()) { + return LiteralIntegralValueToString(lit); + } + + if (lit.IsIntegerValue()) { + return LiteralIntegralValueToString(lit); + } + + if (lit.IsLongValue()) { + return LiteralIntegralValueToString(lit); + } + + if (lit.IsDoubleValue()) { + std::stringstream res {}; + res << std::get(lit.value); + return res.str(); + } + + if (lit.IsFloatValue()) { + std::stringstream res {}; + res << std::get(lit.value); + return res.str(); + } + + if (lit.IsStringValue()) { + std::stringstream res {}; + res << "\"" << std::get(lit.value) << "\""; + return res.str(); + } + + UNREACHABLE(); +} + +void PandasmProgramDumper::DumpValues(const pandasm::LiteralArray &litArray, const bool isConst, std::ostream &os, + const pandasm::Program &program) const +{ + std::string separator = (isConst) ? (" ") : ("\n"); + + os << separator; + + if (isConst) { + for (const auto &l : litArray.literals) { + os << LiteralValueToString(l) << separator; + } + } else { + for (const auto &l : litArray.literals) { + os << "\t" << LiteralTagToString(l.tag, program) << " " << LiteralValueToString(l) << separator; + } + } +} + +std::string PandasmProgramDumper::LiteralTagToString(const panda_file::LiteralTag &tag, + const pandasm::Program &program) const +{ + switch (tag) { + case panda_file::LiteralTag::BOOL: + case panda_file::LiteralTag::ARRAY_U1: + return "u1"; + case panda_file::LiteralTag::ARRAY_U8: + return "u8"; + case panda_file::LiteralTag::ARRAY_I8: + return "i8"; + case panda_file::LiteralTag::ARRAY_U16: + return "u16"; + case panda_file::LiteralTag::ARRAY_I16: + return "i16"; + case panda_file::LiteralTag::ARRAY_U32: + return "u32"; + case panda_file::LiteralTag::INTEGER: + case panda_file::LiteralTag::ARRAY_I32: + return "i32"; + case panda_file::LiteralTag::ARRAY_U64: + return "u64"; + case panda_file::LiteralTag::BIGINT: + case panda_file::LiteralTag::ARRAY_I64: + return "i64"; + case panda_file::LiteralTag::FLOAT: + case panda_file::LiteralTag::ARRAY_F32: + return "f32"; + case panda_file::LiteralTag::DOUBLE: + case panda_file::LiteralTag::ARRAY_F64: + return "f64"; + case panda_file::LiteralTag::STRING: + case panda_file::LiteralTag::ARRAY_STRING: + return pandasm::Type::FromDescriptor(panda_file::GetStringClassDescriptor(program.lang)).GetPandasmName(); + case panda_file::LiteralTag::ACCESSOR: + return "accessor"; + case panda_file::LiteralTag::NULLVALUE: + return "nullvalue"; + case panda_file::LiteralTag::METHODAFFILIATE: + return "method_affiliate"; + case panda_file::LiteralTag::METHOD: + return "method"; + case panda_file::LiteralTag::GENERATORMETHOD: + return "generator_method"; + default: + LOG(ERROR, ABC2PROGRAM) << "Unsupported literal with tag 0x" << std::hex << static_cast(tag); + UNREACHABLE(); + } +} + +} // namespace ark::abc2program diff --git a/static_core/abc2program/program_dump.h b/static_core/abc2program/program_dump.h new file mode 100644 index 0000000000000000000000000000000000000000..73e7b9ca14ba3106e312ed7bcaafab625c7f8ffb --- /dev/null +++ b/static_core/abc2program/program_dump.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024-2025 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. + */ + +#ifndef ABC2PROGRAM_PROGRANM_DUMPER_PROGRAM_DUMP_H +#define ABC2PROGRAM_PROGRANM_DUMPER_PROGRAM_DUMP_H + +#include +#include +#include "abc_string_table.h" + +namespace ark::abc2program { + +class PandasmProgramDumper { +public: + PandasmProgramDumper(const panda_file::File &file, const AbcStringTable &stringTable) + : file_(&file), stringTable_(&stringTable) + { + } + PandasmProgramDumper() {} + void Dump(std::ostream &os, const pandasm::Program &program) const; + +private: + bool HasNoAbcInput() const; + void DumpAbcFilePath(std::ostream &os) const; + void DumpProgramLanguage(std::ostream &os, const pandasm::Program &program) const; + void DumpLiteralArrayTable(std::ostream &os, const pandasm::Program &program) const; + void DumpLiteralArrayTableWithKey(std::ostream &os, const pandasm::Program &program) const; + void DumpLiteralArrayTableWithoutKey(std::ostream &os, const pandasm::Program &program) const; + void DumpLiteralArrayWithKey(std::ostream &os, const std::string &key, const pandasm::LiteralArray &litArray, + const pandasm::Program &program) const; + void DumpRecordTable(std::ostream &os, const pandasm::Program &program) const; + void DumpRecord(std::ostream &os, const pandasm::Record &record) const; + void DumpFieldList(std::ostream &os, const pandasm::Record &record) const; + void DumpField(std::ostream &os, const pandasm::Field &field) const; + bool DumpMetaData(std::ostream &os, const pandasm::ItemMetadata &meta) const; + void DumpRecordSourceFile(std::ostream &os, const pandasm::Record &record) const; + void DumpFunctionTable(std::ostream &os, const pandasm::Program &program) const; + void DumpFunction(std::ostream &os, const pandasm::Function &function) const; + void DumpInstructions(std::ostream &os, const pandasm::Function &function) const; + void DumpStrings(std::ostream &os, const pandasm::Program &program) const; + void DumpStringsByStringTable(std::ostream &os, const AbcStringTable &stringTable) const; + void DumpStringsByProgram(std::ostream &os, const pandasm::Program &program) const; + void DumpLiteralArray(std::ostream &os, const pandasm::LiteralArray &litArray, + const pandasm::Program &program) const; + std::string LiteralTagToString(const panda_file::LiteralTag &tag, const pandasm::Program &program) const; + std::string LiteralValueToString(const pandasm::LiteralArray::Literal &lit) const; + void DumpValues(const pandasm::LiteralArray &litArray, const bool isConst, std::ostream &os, + const pandasm::Program &program) const; + const panda_file::File *file_ = nullptr; + const AbcStringTable *stringTable_ = nullptr; +}; + +} // namespace ark::abc2program + +#endif // ABC2PROGRAM_PROGRANM_DUMPER_PROGRAM_DUMP_H diff --git a/static_core/abc2program/templates/abc2program_plugins.inc.erb b/static_core/abc2program/templates/abc2program_plugins.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..fd8d80e30f488bf1fb4fb3fffb387f91353e59b6 --- /dev/null +++ b/static_core/abc2program/templates/abc2program_plugins.inc.erb @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef ABC2PROGRAM_TEMPLATES_ABC2PROGRAM_PLUGINS_INC_INCLUDED +#define ABC2PROGRAM_TEMPLATES_ABC2PROGRAM_PLUGINS_INC_INCLUDED + +<%= Common::include_plugin_files "Abc2Prog", "language_interface_path" %> + +#endif \ No newline at end of file diff --git a/static_core/abc2program/templates/abc_inst_convert.cpp.erb b/static_core/abc2program/templates/abc_inst_convert.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..eb12fa5c5c6f89b2a372095eb924f2d63a9f0442 --- /dev/null +++ b/static_core/abc2program/templates/abc_inst_convert.cpp.erb @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024-2025 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 "common/abc_code_converter.h" +#include "proto_data_accessor-inl.h" +#include "method_data_accessor-inl.h" + +namespace ark::abc2program { + +pandasm::Ins AbcCodeConverter::BytecodeInstructionToPandasmInstruction(BytecodeInstruction bcIns, + panda_file::File::EntityId methodId) const +{ + pandasm::Ins ins{}; + + ins.opcode = BytecodeOpcodeToPandasmOpcode(bcIns.GetOpcode()); + + const BytecodeInstruction::Format format = bcIns.GetFormat(); + + switch (format) { +% insns_uniq_sort_fmts.each do |i| # Panda::formats.each do |fmt| +% imm_count = 0 +% reg_count = 0 + case BytecodeInstruction::Format::<%=i.format.pretty.upcase%>: +% +% i.operands.each do |operand| +% if (operand.name == :imm) + if(bcIns.HasFlag(BytecodeInstruction::Flags::FLOAT)) { +% if (operand.is_64bit_imm?) + ins.imms.push_back(bit_cast(bcIns.GetImm, <%=imm_count%>>())); +% else + ins.imms.push_back(bit_cast(bcIns.GetImm, <%=imm_count%>>())); +% end + } +% if (!operand.is_64bit_imm?) + ins.imms.push_back(static_cast(bcIns.GetImm, <%=imm_count%>>())); +% else + ins.imms.push_back(bcIns.GetImm, <%=imm_count%>>()); +% end +% imm_count += 1 +% +% elsif (operand.name == :v) + ins.regs.push_back(bcIns.GetVReg(<%=reg_count%>)); +% reg_count += 1 +% elsif (i.operands.count(&:id?) != 0) + ins.ids.push_back(IDToString(bcIns, methodId)); +% end +% end + break; +% end + default: + break; + } + + if (ins.IsCall()) { + // clearing excessive arguments if there are any + // if format has ID in it - recieve it. else instruction is indirect call and id = methodId + panda_file::File::EntityId id; + + if (bcIns.HasId(format, 0)) { + auto idx = bcIns.GetId().AsIndex(); + id = file_->ResolveMethodIndex(methodId, idx); + } else { + id = methodId; + } + + panda_file::MethodDataAccessor mda(*file_, id); + panda_file::ProtoDataAccessor pda(*file_, mda.GetProtoId()); + + int overhead; + + const bool isInitobj = ins.opcode == pandasm::Opcode::INITOBJ_SHORT || + ins.opcode == pandasm::Opcode::INITOBJ_RANGE || ins.opcode == pandasm::Opcode::INITOBJ; + + const bool isAcc = ins.opcode == pandasm::Opcode::CALL_ACC_SHORT || ins.opcode == pandasm::Opcode::CALL_ACC || + ins.opcode == pandasm::Opcode::CALL_VIRT_ACC_SHORT || + ins.opcode == pandasm::Opcode::CALL_VIRT_ACC; + + if (mda.IsStatic() || isInitobj) { + overhead = ins.regs.size() - pda.GetNumArgs(); + } else { + overhead = ins.regs.size() - pda.GetNumArgs() - 1; + } + // call.acc recieves fixed amount of registers + if (isAcc) { + return ins; + } + if (overhead < 0 || overhead > static_cast(ins.regs.size())) { + LOG(ERROR, ABC2PROGRAM) + << "> error encountered in code of " << std::dec << methodId.GetOffset() << " (" + << "0x" << std::hex << methodId.GetOffset() << ") while disassembling call <" << ins.ToString("") + << ">. Invalid method id given or corrupted: calculated overhead (difference " + "between amount of registers specified by instruction format and amount of function's arguments) " + "exceeds number of registers specified in ISA or is lesser than 0!"; + return ins; + } + + for (int i = 0; i < overhead; i++) { + ins.regs.pop_back(); + } + } + + return ins; +} + +} // namespace panda::abc2program diff --git a/static_core/abc2program/templates/abc_opcode_convert.cpp.erb b/static_core/abc2program/templates/abc_opcode_convert.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..c8d6c3d258f0949eab8e803d89df05bbcaa8d227 --- /dev/null +++ b/static_core/abc2program/templates/abc_opcode_convert.cpp.erb @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024-2025 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 "common/abc_code_converter.h" + +namespace ark::abc2program { + +pandasm::Opcode AbcCodeConverter::BytecodeOpcodeToPandasmOpcode(BytecodeInstruction::Opcode opcode) const +{ + switch (opcode) { +% Panda::instructions.each do |i| + case BytecodeInstruction::Opcode::<%= i.opcode.upcase %>: + return pandasm::Opcode::<%= i.mnemonic.tr('.', '_').upcase %>; +% end + default: + return pandasm::Opcode::INVALID; + } +} + +} // namespace panda::abc2program diff --git a/static_core/abc2program/templates/abc_type_convert.cpp.erb b/static_core/abc2program/templates/abc_type_convert.cpp.erb new file mode 100644 index 0000000000000000000000000000000000000000..2014f036bd3a44393d1c487c7f8f49df4dd70a3d --- /dev/null +++ b/static_core/abc2program/templates/abc_type_convert.cpp.erb @@ -0,0 +1,71 @@ +/** + * Copyright (c) 2024-2025 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 "common/abc_type_converter.h" +#include "proto_data_accessor-inl.h" + +namespace ark::abc2program { + +pandasm::Type AbcTypeConverter::PandaFileTypeToPandasmType(const panda_file::Type& type, + panda_file::ProtoDataAccessor& pda, + size_t& refIdx) const { + pandasm::Type pandasmType; + + switch (type.GetId()) { +% PandaFile::types.each do |type| + case panda_file::Type::TypeId::<%= type.name.upcase %>: +% if (type.name == "reference") + pandasmType = pandasm::Type::FromDescriptor(stringTable_.GetStringById(pda.GetReferenceType(refIdx++))); +% elsif (type.name == "tagged") + pandasmType = pandasm::Type("any", 0); +% else + pandasmType = pandasm::Type("<%= type.name %>", 0); +% end + break; +% end + } + + return pandasmType; +} + +pandasm::Type AbcTypeConverter::FieldTypeToPandasmType(const uint32_t& type) const { + pandasm::Type fieldType; + + auto pfType = panda_file::Type::GetTypeFromFieldEncoding(type); + + switch (pfType.GetId()) { +% PandaFile::types.each do |type| +% if (type.name != "reference" && type.name != "tagged") + case panda_file::Type::TypeId::<%= type.name.upcase %>: + fieldType = pandasm::Type("<%= type.name %>", 0); + break; +% end +% end + case panda_file::Type::TypeId::TAGGED: + fieldType = pandasm::Type("any", 0); + break; + default: + panda_file::File::EntityId fieldId(type); + std::string typeName = stringTable_.GetStringById(fieldId); + std::replace(typeName.begin(), typeName.end(), '/', '.'); + + fieldType = pandasm::Type::FromDescriptor(typeName); + break; + } + + return fieldType; +} + +} // namespace panda::abc2program \ No newline at end of file diff --git a/static_core/abc2program/templates/get_language_specific_metadata.inc.erb b/static_core/abc2program/templates/get_language_specific_metadata.inc.erb new file mode 100644 index 0000000000000000000000000000000000000000..0c82b3e2b7a5cfb2909200d575b11ebaf8e831c0 --- /dev/null +++ b/static_core/abc2program/templates/get_language_specific_metadata.inc.erb @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 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 "abc_file_processor.h" + +namespace ark::abc2program { + +void AbcFileProcessor::GetLanguageSpecificMetadata() { + LOG(DEBUG, ABC2PROGRAM) << "\n[getting language-specific annotations]\n"; + +% Common::each_plugin_suboption("Abc2Prog", "language_interface_path") do |_, _, plugin_opts| + Get<%= plugin_opts["directive_name"] %>Metadata(); +% end +} +} // namespace ark::abc2program diff --git a/static_core/abc2program/tests/BUILD.gn b/static_core/abc2program/tests/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..68fb9556f1948882a316ce9f6776d60662f5fabb --- /dev/null +++ b/static_core/abc2program/tests/BUILD.gn @@ -0,0 +1,75 @@ +# Copyright (c) 2024 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. + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//arkcompiler/runtime_core/ark_config.gni") +import("$ark_root/tests/test_helper.gni") + +abc2prog_test_configs = [ + "$ark_root:ark_config", + "$ark_root/libpandabase:arkbase_public_config", + "$ark_root/libpandafile:arkfile_public_config", + sdk_libc_secshared_config, +] + +abc2prog_test_deps = [ + "$ark_root/abc2program:arkts_abc2program", + "$ark_root/libpandabase:libarkbase_static", + "$ark_root/libpandafile:libarkfile_static", +] + +test_ets_path = "//arkcompiler/runtime_core/abc2program/tests/ets/" + +abc2prog_test_ets_files = [ "HelloWorld", "Functions" ] + +foreach(file, abc2prog_test_ets_files) { + es2abc_gen_abc("gen_${file}_abc") { + test_ets = "${test_ets_path}${file}.ets" + test_abc = "$target_out_dir/${file}.abc" + + src_ets = rebase_path(test_ets) + dst_file = rebase_path(test_abc) + + in_puts = [ test_ets ] + out_puts = [ test_abc ] + } +} + +abc2prog_include_dirs = [ + "$ark_root/abc2program", + "$ark_root/assembler", + "$target_gen_dir", + "$target_gen_dir/../", + "$target_gen_dir/../../assembler", +] + +script_sources = [ "cpp_sources/hello_world_test.cpp" ] + +host_unittest_action("Abc2ProgScriptTest") { + module_out_path = module_output_path + sources = script_sources + include_dirs = abc2prog_include_dirs + configs = abc2prog_test_configs + deps = abc2prog_test_deps + test_abc_dir = rebase_path(target_out_dir) + defines = [ "GRAPH_TEST_ABC_DIR=\"${test_abc_dir}/\"" ] + + foreach(file, abc2prog_test_ets_files) { + deps += [ ":gen_${file}_abc" ] + } +} + +group("host_unittest") { + testonly = true + deps = [ ":Abc2ProgScriptTestAction" ] +} diff --git a/static_core/abc2program/tests/CMakeLists.txt b/static_core/abc2program/tests/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d0c939874ddf933a3f8bf83792d4a4bf4bc8f237 --- /dev/null +++ b/static_core/abc2program/tests/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2024 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. + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ets) + +set(abc2progTestFiles + "HelloWorld" + "Functions" +) + +add_custom_target(abc2program_gen) + +foreach(NAME ${abc2progTestFiles}) + add_custom_target(abc2program_gen_${NAME} COMMENT "Generating ${NAME} for abc2program" + COMMAND ${PANDA_BINARY_ROOT}/bin/es2panda ${CMAKE_CURRENT_SOURCE_DIR}/ets/${NAME}.ets + --output=${CMAKE_CURRENT_BINARY_DIR}/ets/${NAME}.abc + DEPENDS es2panda) + add_dependencies(abc2program_gen abc2program_gen_${NAME}) +endforeach() + +panda_add_gtest( + NAME abc2program_tests + SOURCES + abc2program_test.cpp + LIBRARIES + abc2program + SANITIZERS + ${PANDA_SANITIZERS_LIST} + DEPS_TARGETS + abc2program_gen +) diff --git a/static_core/abc2program/tests/abc2program_test.cpp b/static_core/abc2program/tests/abc2program_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23a1cb10c87e92487dc7485346f8bb7ab01a3eb3 --- /dev/null +++ b/static_core/abc2program/tests/abc2program_test.cpp @@ -0,0 +1,225 @@ +/** + * Copyright (c) 2024-2025 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 +#include +#include +#include +#include +#include "abc2program_driver.h" + +namespace ark::abc2program { + +static const std::string HELLO_WORLD_ABC_TEST_FILE_NAME = "ets/HelloWorld.abc"; +static const std::string FUNCTIONS_ABC_TEST_FILE_NAME = "ets/Functions.abc"; + +class Abc2ProgramTest : public testing::Test { +public: + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + + void TearDown() {} + + template + bool ValidateString(const T &strings, const T &expectedStrings) + { + if (strings.size() != expectedStrings.size()) { + return false; + } + for (const std::string &expectedString : expectedStrings) { + const auto stringIter = std::find(strings.begin(), strings.end(), expectedString); + if (stringIter == strings.end()) { + return false; + } + } + return true; + } + + Abc2ProgramDriver driver_; + const pandasm::Program *prog_ = nullptr; +}; + +class Abc2ProgramHelloWorldTest : public Abc2ProgramTest { +public: + void SetUp() + { + (void)driver_.Compile(HELLO_WORLD_ABC_TEST_FILE_NAME); + prog_ = &(driver_.GetProgram()); + } +}; + +class Abc2ProgramFunctionsTest : public Abc2ProgramTest { +public: + void SetUp() + { + (void)driver_.Compile(FUNCTIONS_ABC_TEST_FILE_NAME); + prog_ = &(driver_.GetProgram()); + } +}; + +/** + * @tc.name: Lang + * @tc.desc: get program language. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramHelloWorldTest, Lang) +{ + panda_file::SourceLang expectedLang = panda_file::SourceLang::ETS; + bool langMatched = (prog_->lang == expectedLang); + EXPECT_TRUE(langMatched); +} + +/** + * @tc.name: RecordTable + * @tc.desc: get program recordTable. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramHelloWorldTest, RecordTable) +{ + std::vector expectedRecordNames = {"HelloWorld", "ETSGLOBAL"}; + panda_file::SourceLang expectedLang = panda_file::SourceLang::ETS; + std::vector recordNames; + for (const auto &it : prog_->recordTable) { + EXPECT_TRUE(it.second.language == expectedLang); + EXPECT_TRUE(it.first == it.second.name); + recordNames.emplace_back(it.first); + } + ValidateString(recordNames, expectedRecordNames); +} + +/** + * @tc.name: Functions + * @tc.desc: get program functionTable. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramHelloWorldTest, Functions) +{ + std::set expectedFunctions = {"ETSGLOBAL._$init$_:()", + "ETSGLOBAL._cctor_:()", + "ETSGLOBAL.main:()", + "HelloWorld._ctor_:(HelloWorld)", + "HelloWorld.bar:(HelloWorld,std.core.Object)", + "HelloWorld.foo:(HelloWorld,i32)", + "std.core.Console.log:(std.core.Console,i32)", + "std.core.Object._ctor_:(std.core.Object)"}; + std::set existingFunctions {}; + for (auto &it : prog_->functionTable) { + existingFunctions.insert(it.first); + } + bool result = ValidateString(existingFunctions, expectedFunctions); + EXPECT_TRUE(result); +} + +/** + * @tc.name: Fields + * @tc.desc: get program fields. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramHelloWorldTest, Fields) +{ + for (const auto &it : prog_->recordTable) { + if (it.first == "HelloWorld") { + EXPECT_TRUE(it.second.fieldList.size() == 2); + } + } +} + +/** + * @tc.name: StringTable + * @tc.desc: get existed string. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramHelloWorldTest, StringTable) +{ + std::set expectedStrings = {R"(HelloWorld)", R"(NewLine\n)"}; + bool stringMatched = ValidateString(prog_->strings, expectedStrings); + EXPECT_TRUE(stringMatched); +} + +/** + * @tc.name: Lang + * @tc.desc: get program language. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramFunctionsTest, Lang) +{ + panda_file::SourceLang expectedLang = panda_file::SourceLang::ETS; + bool langMatched = (prog_->lang == expectedLang); + EXPECT_TRUE(langMatched); +} + +/** + * @tc.name: RecordTable + * @tc.desc: get program record_table. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramFunctionsTest, RecordTable) +{ + std::vector expectedRecordNames = {"ETSGLOBAL"}; + panda_file::SourceLang expectedLang = panda_file::SourceLang::ETS; + std::vector recordNames; + for (const auto &it : prog_->recordTable) { + EXPECT_TRUE(it.second.language == expectedLang); + EXPECT_TRUE(it.first == it.second.name); + recordNames.emplace_back(it.first); + } + ValidateString(recordNames, expectedRecordNames); +} + +/** + * @tc.name: Functions + * @tc.desc: get program functionTable. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramFunctionsTest, Functions) +{ + std::set expectedFunctions = {"ETSGLOBAL._$init$_:()", + "ETSGLOBAL._cctor_:()", + "ETSGLOBAL.bar:(f64)", + "ETSGLOBAL.foo:(std.core.String)", + "std.core.StringBuilder._ctor_:(std.core.StringBuilder)", + "std.core.StringBuilder.append:(std.core.StringBuilder,f64)", + "std.core.StringBuilder.append:(std.core.StringBuilder,std.core.String)", + "std.core.StringBuilder.toString:(std.core.StringBuilder)"}; + std::set existingFunctions {}; + for (auto &it : prog_->functionTable) { + existingFunctions.insert(it.first); + } + bool result = ValidateString(existingFunctions, expectedFunctions); + EXPECT_TRUE(result); +} + +/** + * @tc.name: StringTable + * @tc.desc: get existed string. + * @tc.type: FUNC + * @tc.require: file path and name + */ +TEST_F(Abc2ProgramFunctionsTest, StringTable) +{ + std::set expectedStrings = {"Function foo was called", "Function bar was called"}; + bool result = ValidateString(prog_->strings, expectedStrings); + EXPECT_TRUE(result); +} + +}; // namespace ark::abc2program \ No newline at end of file diff --git a/static_core/abc2program/tests/ets/Functions.ets b/static_core/abc2program/tests/ets/Functions.ets new file mode 100644 index 0000000000000000000000000000000000000000..ba26081b9bb0611dbd07c5cb538180b0b39f1cd8 --- /dev/null +++ b/static_core/abc2program/tests/ets/Functions.ets @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 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. + */ + +function foo(x:string) : string { + let b: string = "Function foo was called" + return b + x; +} + +function bar(y:number) : string { + let b: string = "Function bar was called" + return b + y; +} \ No newline at end of file diff --git a/static_core/abc2program/tests/ets/HelloWorld.ets b/static_core/abc2program/tests/ets/HelloWorld.ets new file mode 100644 index 0000000000000000000000000000000000000000..59a39de78790aebab66cccab1d6b6fd62cdfb1ed --- /dev/null +++ b/static_core/abc2program/tests/ets/HelloWorld.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024 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. + */ + +class HelloWorld { + str = "HelloWorld" + line = "NewLine\n" + foo(x:int):int {return x} + bar(x:Object):Object {return x} +} + +function main() { + let world = new HelloWorld(); + + console.log(world.foo(5)); +} diff --git a/static_core/ark_config.gni b/static_core/ark_config.gni index b14aaec6314c49f0701a8618541e1d641f54dc45..4f8fd4fbc5602b78e1be9fb079c4d7eebf93d8c7 100644 --- a/static_core/ark_config.gni +++ b/static_core/ark_config.gni @@ -73,6 +73,8 @@ vixl_with_panda = true sdk_libc_secshared_dep = "" sdk_libc_secshared_ext_dep = "" +sdk_libc_secshared_config = + "$ark_third_party_root/bounds_checking_function:libsec_public_config" if (ark_standalone_build) { sdk_libc_secshared_dep = "securec:libc_secshared" @@ -335,12 +337,29 @@ template("es2panda_gen") { es2panda_root_out = get_label_info("$ark_es2panda_root/aot:es2panda(${host_toolchain})", "root_out_dir") - script = es2panda_root_out + "/arkcompiler/ets_frontend/es2panda" + + script = "//arkcompiler/ets_runtime/script/run_ark_executable.py" + deps = [ "$ark_es2panda_root/aot:es2panda(${host_toolchain})" ] + external_deps = [ "ets_frontend:es2panda(${host_toolchain})" ] inputs = invoker.inputs outputs = invoker.outputs sources = invoker.sources - args = invoker.args + + args = [ + "--script-file", + rebase_path("${es2panda_root_out}/arkcompiler/ets_frontend/es2panda"), + "--script-args", + string_join(" " , invoker.args), + "--env-path", + rebase_path("${es2panda_root_out}/lib.unstripped/clang_x64/arkcompiler/runtime_core/") + ":" + + rebase_path("${es2panda_root_out}/lib.unstripped/clang_x64/arkcompiler/ets_frontend/") + ":" + + rebase_path("${es2panda_root_out}/lib.unstripped/clang_x64/arkcompiler/ets_runtime/") + ":" + + rebase_path("${es2panda_root_out}/lib.unstripped/clang_x64/thirdparty/zlib/") + ":" + + rebase_path("${es2panda_root_out}/lib.unstripped/clang_x64/thirdparty/icu/"), + "--expect-output", + "0" + ] } } diff --git a/static_core/assembler/BUILD.gn b/static_core/assembler/BUILD.gn index 5ba186992006be7a15f9d95581b0eaa6261578b9..8f0bcd1f9327b039550c62b5f7f8a8d4df45846b 100644 --- a/static_core/assembler/BUILD.gn +++ b/static_core/assembler/BUILD.gn @@ -17,7 +17,8 @@ import("$ark_root/plugins/plugins.gni") ohos_static_library("libarktsassembler_package") { deps = [] if (enable_static_vm) { - deps += [ ":libarktsassembler_frontend_static" ] + # deps += [ ":libarktsassembler_frontend_static" ] + deps += [ ":libarktsassembler" ] } part_name = ark_part_name diff --git a/static_core/bytecode_optimizer/BUILD.gn b/static_core/bytecode_optimizer/BUILD.gn index 8adc20bfceda58b85bf39b974acc5814dc42f554..b4a754c7bfb3cac05b0a9497a64df6e21af4dc6a 100644 --- a/static_core/bytecode_optimizer/BUILD.gn +++ b/static_core/bytecode_optimizer/BUILD.gn @@ -19,7 +19,8 @@ import("$ark_root/plugins/plugins.gni") ohos_static_library("libarktsbytecodeopt_package") { deps = [] if (enable_static_vm) { - deps += [ ":libarktsbytecodeopt_frontend_static" ] + # deps += [ ":libarktsbytecodeopt_frontend_static" ] + deps += [ ":libarktsbytecodeopt" ] } part_name = ark_part_name @@ -62,6 +63,11 @@ libarkbytecodeopt_configs = [ libarkbytecodeopt_configs += plugin_bytecodeopt_configs +if (enable_libabckit && (current_toolchain == host_toolchain)) { + libabckit_deps = ["$ark_root/../libabckit/src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_inl", + "$ark_root/../libabckit/src/templates/bct_intrinsics:ark_gen_libabckit_bct_intrinsics_vreg_width_h"] +} + ohos_shared_library("libarktsbytecodeopt") { sources = libarkbytecodeopt_sources @@ -85,6 +91,9 @@ ohos_shared_library("libarktsbytecodeopt") { ] deps += plugin_bytecodeopt_deps + if (enable_libabckit && (current_toolchain == host_toolchain)) { + deps += libabckit_deps + } external_deps = [ sdk_libc_secshared_dep ] @@ -117,10 +126,14 @@ ohos_static_library("libarktsbytecodeopt_frontend_static") { deps += plugin_bytecodeopt_deps + if (enable_libabckit && (current_toolchain == host_toolchain)) { + deps += libabckit_deps + } + external_deps = [ sdk_libc_secshared_dep ] part_name = ark_part_name - subsystem_name = ark_subsystem_name + subsystem_name = "$ark_subsystem_name" } ark_isa_gen("isa_gen_arkbytecodeopt") { diff --git a/static_core/bytecode_optimizer/common.cpp b/static_core/bytecode_optimizer/common.cpp index ce27ef56f73e7b3001ed74595369932ee6fdd5bc..a314f49cd1915a72ef53fd5ba8cbaee9dfbe7204 100644 --- a/static_core/bytecode_optimizer/common.cpp +++ b/static_core/bytecode_optimizer/common.cpp @@ -23,7 +23,7 @@ uint8_t AccReadIndex(const compiler::Inst *inst) { // For calls we cannot tell static index for acc position, thus // ensure that we don't invoke this for calls - ASSERT(!inst->IsCallOrIntrinsic()); + ASSERT(!inst->IsCallOrIntrinsic() || (inst->GetBasicBlock()->GetGraph()->IsBCT() && !inst->IsCall())); switch (inst->GetOpcode()) { case compiler::Opcode::LoadArray: @@ -35,6 +35,12 @@ uint8_t AccReadIndex(const compiler::Inst *inst) return 2U; default: { if (inst->IsIntrinsic() && inst->IsAccRead()) { +#if defined(ENABLE_LIBABCKIT) + if (inst->GetBasicBlock()->GetGraph()->IsBCT()) { + ASSERT(inst->GetInputsCount() >= 1U); + return inst->GetInputsCount() - 1L; + } +#endif ASSERT(inst->GetBasicBlock()->GetGraph()->IsDynamicMethod()); ASSERT(inst->GetInputsCount() >= 2U); return inst->GetInputsCount() - 2L; @@ -44,6 +50,10 @@ uint8_t AccReadIndex(const compiler::Inst *inst) } } +#if defined (ENABLE_LIBABCKIT) +#include +#endif + // This method is used by bytecode optimizer's codegen. bool CanConvertToIncI(const compiler::BinaryImmOperation *binop) { diff --git a/static_core/bytecode_optimizer/common.h b/static_core/bytecode_optimizer/common.h index 8b059b9bc43a3911521e937b439ea1c1dfe549c0..f669c1f0bcf674b9cbca8085a094d74c2a748a81 100644 --- a/static_core/bytecode_optimizer/common.h +++ b/static_core/bytecode_optimizer/common.h @@ -33,6 +33,11 @@ constexpr ark::compiler::Register NUM_COMPACTLY_ENCODED_REGS = 16; // Get the position where accumulator read happens. uint8_t AccReadIndex(const compiler::Inst *inst); +#if defined (ENABLE_LIBABCKIT) +bool IsBCTIntrinsic(compiler::RuntimeInterface::IntrinsicId intrinsicId); +bool IsBCTIntrinsicRange(compiler::RuntimeInterface::IntrinsicId intrinsicId); +bool IsBCTInitObject(compiler::RuntimeInterface::IntrinsicId intrinsicId); +#endif bool CanConvertToIncI(const compiler::BinaryImmOperation *binop); } // namespace ark::bytecodeopt diff --git a/static_core/bytecode_optimizer/ir_interface.h b/static_core/bytecode_optimizer/ir_interface.h index bfb0349302e82a19ea3e16bc8c3b7eda5076f161..a2d83227b3f05dc841f0cfa8ad3e1ee96d023a2d 100644 --- a/static_core/bytecode_optimizer/ir_interface.h +++ b/static_core/bytecode_optimizer/ir_interface.h @@ -142,7 +142,7 @@ public: return prog_ != nullptr ? prog_->lang : panda_file::SourceLang::PANDA_ASSEMBLY; } -private: +public: pandasm::Program *prog_ {nullptr}; const pandasm::AsmEmitter::PandaFileToPandaAsmMaps *maps_ {nullptr}; std::unordered_map pcInsMap_; diff --git a/static_core/bytecode_optimizer/reg_acc_alloc.cpp b/static_core/bytecode_optimizer/reg_acc_alloc.cpp index bcc1c01ddaef8ef51789c309ee19bff767bc0ecd..01a93d6380c38d848a24c187ca91ab04887dbc5a 100644 --- a/static_core/bytecode_optimizer/reg_acc_alloc.cpp +++ b/static_core/bytecode_optimizer/reg_acc_alloc.cpp @@ -50,12 +50,16 @@ bool IsAccWriteBetween(compiler::Inst *srcInst, compiler::Inst *dstInst) inst = *(block->AllInsts()); } else { if (inst->IsAccWrite()) { +#ifdef ENABLE_LIBABCKIT + return true; +#else if (!inst->IsConst()) { return true; } if (inst->GetDstReg() == compiler::ACC_REG_ID) { return true; } +#endif } if (inst->IsAccRead()) { @@ -108,6 +112,16 @@ bool RegAccAlloc::IsAccWrite(compiler::Inst *inst) const return UNLIKELY(inst->IsPhi()) ? IsPhiOptimizable(inst) : inst->IsAccWrite(); } +#if defined(ENABLE_LIBABCKIT) +bool RegAccAlloc::CanIntrinsicReadAcc(compiler::IntrinsicInst *inst) const +{ + if (GetGraph()->GetMode().IsBCT()) { + return inst->IsAccRead(); + } + return inst->GetInputsCount() <= (MAX_NUM_NON_RANGE_ARGS + 1U); +} +#endif + /** * Decide if user can use accumulator as source. * Do modifications on the order of inputs if necessary. @@ -157,6 +171,17 @@ bool RegAccAlloc::CanUserReadAcc(compiler::Inst *inst, compiler::Inst *user) con return false; } +#if defined(ENABLE_LIBABCKIT) + if (GetGraph()->IsBCT()) { + if (user->IsIntrinsic()) { + return CanIntrinsicReadAcc(user->CastToIntrinsic()) && user->GetInput(AccReadIndex(user)).GetInst() == inst; + } + if (user->IsCall()) { + return user->GetInputsCount() <= (MAX_NUM_NON_RANGE_ARGS); + } + } +#endif + if (user->IsCallOrIntrinsic()) { return user->GetInputsCount() <= (MAX_NUM_NON_RANGE_ARGS + 1U); // +1 for SaveState } @@ -213,9 +238,18 @@ void RegAccAlloc::SetNeedLda(compiler::Inst *inst, bool need) if (!IsAccRead(inst)) { return; } +#if defined(ENABLE_LIBABCKIT) + if (inst->IsCall()) { + return; + } + if (inst->IsIntrinsic() && !GetGraph()->IsBCT()) { + return; + } +#else if (inst->IsCallOrIntrinsic()) { // we never need lda for calls return; } +#endif compiler::Register reg = need ? compiler::INVALID_REG : compiler::ACC_REG_ID; inst->SetSrcReg(AccReadIndex(inst), reg); } @@ -223,6 +257,14 @@ void RegAccAlloc::SetNeedLda(compiler::Inst *inst, bool need) static inline bool MaybeRegDst(compiler::Inst *inst) { compiler::Opcode opcode = inst->GetOpcode(); +#if defined(ENABLE_LIBABCKIT) + if (inst->GetBasicBlock()->GetGraph()->IsBCT() && inst->IsIntrinsic()) { + auto id = inst->CastToIntrinsic()->GetIntrinsicId(); + return id == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT || + id == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT_WIDE || + id == ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_OBJECT_OBJECT; + } +#endif return inst->IsConst() || inst->IsBinaryInst() || inst->IsBinaryImmInst() || opcode == compiler::Opcode::LoadObject; } @@ -322,11 +364,18 @@ bool RegAccAlloc::RunImpl() if (inst->GetInputsCount() == 0U) { continue; } - +#if defined(ENABLE_LIBABCKIT) + if (inst->IsCall()) { + continue; + } + if (inst->IsIntrinsic() && !GetGraph()->IsBCT()) { + continue; + } +#else if (inst->IsCallOrIntrinsic()) { continue; } - +#endif compiler::Inst *input = inst->GetInput(AccReadIndex(inst)).GetInst(); if (IsAccWriteBetween(input, inst)) { diff --git a/static_core/bytecode_optimizer/reg_acc_alloc.h b/static_core/bytecode_optimizer/reg_acc_alloc.h index 2e3c2b57ad56b13848f380b3c55aa5ac6973d077..4e3a5f5c3bcae2df12b8b874d1ae01d5f8c28159 100644 --- a/static_core/bytecode_optimizer/reg_acc_alloc.h +++ b/static_core/bytecode_optimizer/reg_acc_alloc.h @@ -50,6 +50,9 @@ private: bool IsAccWrite(compiler::Inst *inst) const; bool CanUserReadAcc(compiler::Inst *inst, compiler::Inst *user) const; +#if defined(ENABLE_LIBABCKIT) + bool CanIntrinsicReadAcc(compiler::IntrinsicInst *inst) const; +#endif bool IsPhiAccReady(compiler::Inst *phi) const; void SetNeedLda(compiler::Inst *inst, bool need); diff --git a/static_core/bytecode_optimizer/reg_encoder.cpp b/static_core/bytecode_optimizer/reg_encoder.cpp index 10577a42115210dc7daecbdf0c232e31b721eeae..074a40a32f6538139d5c24d4dfa29b94cd062065 100644 --- a/static_core/bytecode_optimizer/reg_encoder.cpp +++ b/static_core/bytecode_optimizer/reg_encoder.cpp @@ -16,6 +16,9 @@ #include "reg_encoder.h" #include "common.h" #include "compiler/optimizer/ir/basicblock.h" +#if defined(ENABLE_LIBABCKIT) +#include "generated/bct_intrinsics_vreg_width.h" +#endif namespace ark::bytecodeopt { @@ -24,6 +27,11 @@ static bool IsIntrinsicRange(Inst *inst) if (inst->GetOpcode() != compiler::Opcode::Intrinsic) { return false; } +#if defined(ENABLE_LIBABCKIT) + if (inst->GetBasicBlock()->GetGraph()->IsBCT()) { + return IsBCTIntrinsicRange(inst->CastToIntrinsic()->GetIntrinsicId()); + } +#endif #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT) switch (inst->CastToIntrinsic()->GetIntrinsicId()) { #ifdef ARK_INTRINSIC_SET @@ -351,9 +359,24 @@ static void AddMoveBefore(Inst *inst, const T &spContainer) static bool IsAccReadPosition(compiler::Inst *inst, size_t pos) { // Calls can have accumulator at any position, return false for them +#if defined(ENABLE_LIBABCKIT) + auto mode = inst->GetBasicBlock()->GetGraph()->GetMode(); + if (mode.IsBCT() && inst->IsIntrinsic()) { + return inst->IsAccRead() && pos == AccReadIndex(inst); + } +#endif return !inst->IsCallOrIntrinsic() && inst->IsAccRead() && pos == AccReadIndex(inst); } +static void AddMoveAfter(Inst *inst, compiler::Register src, RegContent dst) +{ + auto sfInst = inst->GetBasicBlock()->GetGraph()->CreateInstSpillFill(); + sfInst->AddMove(src, dst.reg, dst.type); + LOG(DEBUG, BYTECODE_OPTIMIZER) << "RegEncoder: Move v" << static_cast(dst.reg) << " <- v" + << static_cast(src) << " was added"; + inst->GetBasicBlock()->InsertAfter(sfInst, inst); +} + void RegEncoder::InsertSpillsForDynInputsInst(compiler::Inst *inst) { ASSERT(state_ == RegEncoderState::INSERT_SPILLS); @@ -400,6 +423,16 @@ void RegEncoder::InsertSpillsForDynInputsInst(compiler::Inst *inst) AddMoveBefore(inst, spillMap); AddMoveBefore(inst, spillVec); + +#if defined(ENABLE_LIBABCKIT) + if (inst->GetBasicBlock()->GetGraph()->IsBCT() && IsDstRegNeedRenumbering(inst)) { + auto reg = inst->GetDstReg(); + if (RegNeedsRenumbering(reg) && reg >= NUM_COMPACTLY_ENCODED_REGS) { + inst->SetDstReg(temp); + AddMoveAfter(inst, temp, RegContent(reg, GetRegType(inst->GetType()))); + } + } +#endif } size_t RegEncoder::GetStartInputIndex(compiler::Inst *inst) @@ -411,15 +444,6 @@ size_t RegEncoder::GetStartInputIndex(compiler::Inst *inst) : 0U; // exclude LoadAndInitClass and NewObject } -static void AddMoveAfter(Inst *inst, compiler::Register src, RegContent dst) -{ - auto sfInst = inst->GetBasicBlock()->GetGraph()->CreateInstSpillFill(); - sfInst->AddMove(src, dst.reg, dst.type); - LOG(DEBUG, BYTECODE_OPTIMIZER) << "RegEncoder: Move v" << static_cast(dst.reg) << " <- v" - << static_cast(src) << " was added"; - inst->GetBasicBlock()->InsertAfter(sfInst, inst); -} - static bool IsBoundDstSrc(const compiler::Inst *inst) { if (!inst->IsBinaryInst()) { @@ -596,17 +620,31 @@ void RegEncoder::VisitInitObject(GraphVisitor *visitor, Inst *inst) void RegEncoder::VisitIntrinsic(GraphVisitor *visitor, Inst *inst) { +#if defined(ENABLE_LIBABCKIT) + if (inst->GetBasicBlock()->GetGraph()->IsBCT() && inst->IsIntrinsic()) { + auto re = static_cast(visitor); + if (IsIntrinsicRange(inst)) { + re->Check4Width(inst); + return; + } + if (IsBCTIntrinsic(inst->CastToIntrinsic()->GetIntrinsicId())) { + CheckWidthBCTIntrinsic(re, inst); + } + CallHelper(visitor, inst); + return; + } +#endif if (inst->IsCallOrIntrinsic()) { CallHelper(visitor, inst); return; } auto re = static_cast(visitor); if (IsIntrinsicRange(inst)) { - re->Check4Width(inst->CastToIntrinsic()); + re->Check4Width(inst); return; } - re->Check8Width(inst->CastToIntrinsic()); + re->Check8Width(inst); } void RegEncoder::VisitLoadObject(GraphVisitor *v, Inst *instBase) diff --git a/static_core/cmake/PostPlugins.cmake b/static_core/cmake/PostPlugins.cmake index cbf2551c7720e5b59316b3eda55a56a22fac150c..190c395c37d0433c11ba720e36a6f43e257de65d 100644 --- a/static_core/cmake/PostPlugins.cmake +++ b/static_core/cmake/PostPlugins.cmake @@ -64,6 +64,7 @@ include(compiler/CompilerIntrinsicsPostPlugins.cmake) include(compiler/CompilerOptionsPostPlugins.cmake) include(compiler/CompilerInstTestPostPlugins.cmake) include(disassembler/DisassemblerPostPlugins.cmake) +include(abc2program/Abc2ProgramPostPlugins.cmake) include(isa/IsaPostPlugins.cmake) include(irtoc/templates/IrtocPostPlugins.cmake) include(verification/VerifierPostPlugins.cmake) diff --git a/static_core/compiler/BUILD.gn b/static_core/compiler/BUILD.gn index 4433b2e59012b02184fc2618b3c9e6a647cbf381..f48f247c38f65a4d741f9ea14dc50e1343926e58 100644 --- a/static_core/compiler/BUILD.gn +++ b/static_core/compiler/BUILD.gn @@ -20,7 +20,8 @@ import("$ark_root/plugins/plugins.gni") ohos_static_library("libarktscompiler_package") { deps = [] if (enable_static_vm) { - deps += [ ":libarktscompiler_frontend_static" ] + # deps += [ ":libarktscompiler_frontend_static" ] + deps += [ ":libarktscompiler" ] } part_name = ark_part_name @@ -49,6 +50,9 @@ config("arkcompiler_public_config") { if (enable_bytecode_optimizer && plugin_enable_bytecode_optimizer) { defines += [ "ENABLE_BYTECODE_OPT" ] } + if (enable_libabckit && (current_toolchain == host_toolchain)) { + defines += [ "ENABLE_LIBABCKIT" ] + } cflags_cc = [] if (target_cpu == "x64" || target_cpu == "x86_64") { @@ -83,7 +87,7 @@ libarkcompiler_sources = [ "optimizer/analysis/reg_alloc_verifier.cpp", "optimizer/analysis/rpo.cpp", "optimizer/analysis/types_analysis.cpp", - "optimizer/code_generator/encode.cpp", + # "optimizer/code_generator/encode.cpp", "optimizer/ir/analysis.cpp", "optimizer/ir/aot_data.cpp", "optimizer/ir/basicblock.cpp", @@ -172,6 +176,13 @@ if (!is_win && !is_mac && !is_mingw) { libarkcompiler_sources += [ "$target_gen_dir/generated/inst_builder_gen.cpp" ] +if (enable_libabckit && (current_toolchain == host_toolchain)) { + libabckit_deps = ["$ark_root/../libabckit/src/templates/bct_intrinsics:ark_gen_libabckit_inst_builder_bct_intrinsics_inc"] + libabckit_includes = [ "$ark_root/../libabckit", + "$ark_root/bytecode_optimizer", + "$target_gen_dir/../bytecode_optimizer/generated" ] +} + libarkcompiler_configs = [ ":arkcompiler_public_config", "$ark_root:ark_config", @@ -267,6 +278,11 @@ ohos_shared_library("libarktscompiler") { "$ark_root/compiler/optimizer/code_generator", ] + if (enable_libabckit && (current_toolchain == host_toolchain)) { + include_dirs += libabckit_includes + deps += libabckit_deps + } + output_extension = "so" part_name = ark_part_name subsystem_name = "$ark_subsystem_name" @@ -357,6 +373,12 @@ ohos_source_set("libarktscompiler_frontend_static") { "$ark_root/compiler/optimizer", "$ark_root/compiler/optimizer/code_generator", ] + + if (enable_libabckit && (current_toolchain == host_toolchain)) { + include_dirs += libabckit_includes + deps += libabckit_deps + } + part_name = ark_part_name subsystem_name = ark_subsystem_name } @@ -377,7 +399,11 @@ ark_isa_gen("isa_gen_libarkcompiler") { } ark_gen("libarkcompiler_intrinsics_gen_inl") { - data = [ "$target_gen_dir/../runtime/intrinsics.yaml" ] + if (enable_libabckit && (current_toolchain == host_toolchain)) { + data = [ "$target_gen_dir/../runtime/bct_intrinsics.yaml" ] + } else { + data = [ "$target_gen_dir/../runtime/intrinsics.yaml" ] + } template_files = [ "intrinsics_enum.inl.erb", "get_intrinsics.inl.erb", @@ -402,6 +428,12 @@ ark_gen("libarkcompiler_intrinsics_gen_inl") { ] requires = [ "$ark_root/libpandabase/utils.rb" ] extra_dependencies = [ "$ark_root/runtime:arkruntime_gen_intrinsics_yaml" ] + if (enable_libabckit && (current_toolchain == host_toolchain)) { + extra_dependencies += [ "$ark_root/../libabckit/src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_enum_inc", + "$ark_root/../libabckit/src/templates/dyn_intrinsics:isa_gen_libabckit_get_dyn_intrinsics_names_inc", + "$ark_root/../libabckit/src/templates/dyn_intrinsics:isa_gen_libabckit_dyn_intrinsics_flags_inc", + "$ark_root/../libabckit:concat_bct_intrinsics_yaml"] + } } ark_gen("libarkcompiler_opcodes_h") { diff --git a/static_core/compiler/optimizer/analysis/rpo.cpp b/static_core/compiler/optimizer/analysis/rpo.cpp index b0b12438452058812444c6bd4df241116e26c8aa..8dbf120229cd48fc83c393ed92a63cd8e68649f8 100644 --- a/static_core/compiler/optimizer/analysis/rpo.cpp +++ b/static_core/compiler/optimizer/analysis/rpo.cpp @@ -50,6 +50,7 @@ bool Rpo::RunImpl() ASSERT_PRINT(marker_ != UNDEF_MARKER, "There are no free markers. Please erase unused markers"); DFS(GetGraph()->GetStartBlock(), &blocksCount); #ifndef NDEBUG +#ifndef ENABLE_LIBABCKIT if (blocksCount != 0) { std::cerr << "There are unreachable blocks:\n"; for (auto bb : *GetGraph()) { @@ -59,6 +60,7 @@ bool Rpo::RunImpl() } UNREACHABLE(); } +#endif #endif // NDEBUG GetGraph()->EraseMarker(marker_); return true; diff --git a/static_core/compiler/optimizer/ir/graph.cpp b/static_core/compiler/optimizer/ir/graph.cpp index a3adc6eb9ec369f2e89988179a63802bda06ec11..735c483102d428950cb69c63e7414080e79c35aa 100644 --- a/static_core/compiler/optimizer/ir/graph.cpp +++ b/static_core/compiler/optimizer/ir/graph.cpp @@ -849,6 +849,7 @@ void GraphMode::Dump(std::ostream &stm) DUMP_MODE(Boundary); DUMP_MODE(Interpreter); DUMP_MODE(InterpreterEntry); + DUMP_MODE(BCT); } size_t GetObjectOffset(const Graph *graph, ObjectType objType, RuntimeInterface::FieldPtr field, uint32_t typeId) diff --git a/static_core/compiler/optimizer/ir/graph.h b/static_core/compiler/optimizer/ir/graph.h index 7b638dfe78f76440b27c8570eac8eb17142980de..18af8f15d2bc2d833e5f6a28aa0db31c8030c1b7 100644 --- a/static_core/compiler/optimizer/ir/graph.h +++ b/static_core/compiler/optimizer/ir/graph.h @@ -91,6 +91,8 @@ public: DECLARE_GRAPH_MODE(Interpreter); // Graph will be compiled for interpreter main loop DECLARE_GRAPH_MODE(InterpreterEntry); + // Graph will be compiled for abckit + DECLARE_GRAPH_MODE(BCT); #undef DECLARE_GRAPH_MODE #undef DECLARE_GRAPH_MODE_MODIFIERS @@ -112,6 +114,7 @@ private: using FlagBoundary = FlagFastPath::NextFlag; using FlagInterpreter = FlagBoundary::NextFlag; using FlagInterpreterEntry = FlagInterpreter::NextFlag; + using FlagBCT = FlagInterpreterEntry::NextFlag; uint32_t value_ {0}; @@ -1070,6 +1073,11 @@ public: return mode_.IsDynamicMethod(); } + bool IsBCT() const + { + return mode_.IsBCT(); + } + bool SupportManagedCode() const { return mode_.SupportManagedCode(); @@ -1108,6 +1116,11 @@ public: mode_.SetDynamicMethod(true); } + void SetBCT() + { + mode_.SetBCT(true); + } + void SetDynamicStub() { mode_.SetDynamicStub(true); diff --git a/static_core/compiler/optimizer/ir/graph_checker.cpp b/static_core/compiler/optimizer/ir/graph_checker.cpp index 6c47392b1b449d2da7c60b534ec93bc492067ecb..38101c147e665700df0940a9eeaf7bf33ba7789c 100644 --- a/static_core/compiler/optimizer/ir/graph_checker.cpp +++ b/static_core/compiler/optimizer/ir/graph_checker.cpp @@ -261,6 +261,13 @@ void GraphChecker::CheckInputType(Inst *inst) const } [[maybe_unused]] auto inputType = GetCommonType(inst->GetInputType(i)); [[maybe_unused]] auto realInputType = GetCommonType(input->GetType()); +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + if (inputType == DataType::ANY && input->IsConst() && (inst->IsIntrinsic() || inst->IsPhi())) { + continue; + } + } +#endif ASSERT_DO_EXT( inputType == realInputType || (realInputType == DataType::ANY && diff --git a/static_core/compiler/optimizer/ir/inst.h b/static_core/compiler/optimizer/ir/inst.h index 56737ed1bc418c49dbdf0e083e874d480f6bdf43..6dac3d7de9753f079f4a9b18a2820ac5d83d0e66 100644 --- a/static_core/compiler/optimizer/ir/inst.h +++ b/static_core/compiler/optimizer/ir/inst.h @@ -5039,6 +5039,7 @@ public: void DumpImms(std::ostream *out) const; + std::string GetIntrinsicOpcodeName() const; protected: using ArgumentsOnStack = LastField::NextFlag; using Relocate = ArgumentsOnStack::NextFlag; @@ -5048,6 +5049,7 @@ protected: using LastField = MethodFirstInput; private: + IntrinsicId intrinsicId_ {RuntimeInterface::IntrinsicId::COUNT}; ArenaVector *imms_ {nullptr}; // record imms appeared in intrinsics }; diff --git a/static_core/compiler/optimizer/ir/runtime_interface.h b/static_core/compiler/optimizer/ir/runtime_interface.h index 3d259aabb34fcb0cfe03d617b7c31a6662bcf0a6..ccfcfd7652213ced3428df9151d4ed33ad1bd73c 100644 --- a/static_core/compiler/optimizer/ir/runtime_interface.h +++ b/static_core/compiler/optimizer/ir/runtime_interface.h @@ -1274,6 +1274,7 @@ public: uintptr_t GetEntrypointTlsOffset(Arch arch, EntrypointId id) const { return cross_values::GetManagedThreadEntrypointOffset(arch, ark::EntrypointId(static_cast(id))); + // return 0x1234; } virtual EntrypointId GetGlobalVarEntrypointId() diff --git a/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h b/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h index a757e04bc5eea986d8940222b556647814d9b1dd..90565e185cdbeaa8752c4d466390438fb7c6b76a 100644 --- a/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h +++ b/static_core/compiler/optimizer/ir_builder/inst_builder-inl.h @@ -25,13 +25,28 @@ template void InstBuilder::BuildCall(const BytecodeInstruction *bcInst, bool isRange, bool accRead, Inst *additionalInput) { auto methodId = GetRuntime()->ResolveMethodIndex(GetMethod(), bcInst->GetId(0).AsIndex()); +#ifdef ENABLE_LIBABCKIT + if (!GetGraph()->IsBCT()) { +#endif if (GetRuntime()->IsMethodIntrinsic(GetMethod(), methodId)) { BuildIntrinsic(bcInst, isRange, accRead); return; } +#ifdef ENABLE_LIBABCKIT + } +#endif auto pc = GetPc(bcInst->GetAddress()); - auto saveState = CreateSaveState(Opcode::SaveState, pc); auto hasImplicitArg = !GetRuntime()->IsMethodStatic(GetMethod(), methodId); + SaveStateInst *saveState = nullptr; +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + saveState = hasImplicitArg ? CreateSaveState(Opcode::SaveState, pc) : nullptr; + } else { +#endif + saveState = CreateSaveState(Opcode::SaveState, pc); +#ifdef ENABLE_LIBABCKIT + } +#endif auto method = GetRuntime()->GetMethodById(GetMethod(), methodId); NullCheckInst *nullCheck = nullptr; @@ -50,16 +65,28 @@ void InstBuilder::BuildCall(const BytecodeInstruction *bcInst, bool isRange, boo Inst *resolver = nullptr; // NOLINTNEXTLINE(readability-magic-numbers) CallInst *call = BuildCallInst(method, methodId, pc, &resolver, classId); +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + call->ClearFlag(inst_flags::REQUIRE_STATE); + } +#endif SetCallArgs(bcInst, isRange, accRead, resolver, call, nullCheck, saveState, hasImplicitArg, methodId, additionalInput); // Add SaveState - AddInstruction(saveState); + if (saveState != nullptr) { + AddInstruction(saveState); + } + // Add NullCheck if (hasImplicitArg) { ASSERT(nullCheck != nullptr); AddInstruction(nullCheck); +#ifdef ENABLE_LIBABCKIT + } else if (!call->IsUnresolved() && call->GetCallMethod() != nullptr && !GetGraph()->IsBCT()) { +#else } else if (!call->IsUnresolved() && call->GetCallMethod() != nullptr) { +#endif // Initialize class as call is resolved BuildInitClassInstForCallStatic(method, classId, pc, saveState); } @@ -129,10 +156,16 @@ void InstBuilder::SetCallArgs(const BytecodeInstruction *bcInst, bool isRange, b call->AddInputType(GetMethodArgumentType(methodId, i)); } } +#ifdef ENABLE_LIBABCKIT + if (!GetGraph()->IsBCT()) { +#endif if (saveState != nullptr) { call->AppendInput(saveState); call->AddInputType(DataType::NO_TYPE); } +#ifdef ENABLE_LIBABCKIT + } +#endif } // NOLINTNEXTLINE(misc-definitions-in-headers) @@ -267,6 +300,11 @@ void InstBuilder::BuildDefaultStaticIntrinsic(const BytecodeInstruction *bcInst, auto retType = GetMethodReturnType(methodId); auto pc = GetPc(bcInst->GetAddress()); IntrinsicInst *call = GetGraph()->CreateInstIntrinsic(retType, pc, intrinsicId); +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + call->ClearFlag(inst_flags::REQUIRE_STATE); + } +#endif // If an intrinsic may call runtime then we need a SaveState SaveStateInst *saveState = call->RequireState() ? CreateSaveState(Opcode::SaveState, pc) : nullptr; SetCallArgs(bcInst, isRange, accRead, nullptr, call, nullptr, saveState, false, methodId); @@ -651,6 +689,12 @@ void InstBuilder::BuildDefaultVirtualCallIntrinsic(const BytecodeInstruction *bc graph_->CreateInstNullCheck(DataType::REFERENCE, bcAddr, GetArgDefinition(bcInst, 0, accRead), saveState); auto call = GetGraph()->CreateInstIntrinsic(GetMethodReturnType(methodId), bcAddr, intrinsicId); +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + call->ClearFlag(inst_flags::REQUIRE_STATE); + return; + } +#endif SetCallArgs(bcInst, isRange, accRead, nullptr, call, nullCheck, call->RequireState() ? saveState : nullptr, true, methodId); @@ -675,6 +719,12 @@ void InstBuilder::BuildDefaultVirtualCallIntrinsic(const BytecodeInstruction *bc template void InstBuilder::BuildLoadObject(const BytecodeInstruction *bcInst, DataType::Type type) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTLoadObjectIntrinsic(bcInst, type); + return; + } +#endif auto pc = GetPc(bcInst->GetAddress()); // Create SaveState instruction auto saveState = CreateSaveState(Opcode::SaveState, pc); @@ -758,6 +808,12 @@ Inst *InstBuilder::BuildStoreObjectInst(const BytecodeInstruction *bcInst, DataT template void InstBuilder::BuildStoreObject(const BytecodeInstruction *bcInst, DataType::Type type) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTStoreObjectIntrinsic(bcInst, type); + return; + } +#endif // Create SaveState instruction auto saveState = CreateSaveState(Opcode::SaveState, GetPc(bcInst->GetAddress())); @@ -851,6 +907,12 @@ Inst *InstBuilder::BuildAnyTypeCheckInst(size_t bcAddr, Inst *input, Inst *saveS // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildLoadStatic(const BytecodeInstruction *bcInst, DataType::Type type) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTLoadStaticIntrinsic(bcInst, type); + return; + } +#endif auto fieldIndex = bcInst->GetId(0).AsIndex(); auto fieldId = GetRuntime()->ResolveFieldIndex(GetMethod(), fieldIndex); if (type != DataType::REFERENCE) { @@ -912,6 +974,12 @@ Inst *InstBuilder::BuildStoreStaticInst(const BytecodeInstruction *bcInst, DataT // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildStoreStatic(const BytecodeInstruction *bcInst, DataType::Type type) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTStoreStaticIntrinsic(bcInst, type); + return; + } +#endif auto fieldIndex = bcInst->GetId(0).AsIndex(); auto fieldId = GetRuntime()->ResolveFieldIndex(GetMethod(), fieldIndex); if (type != DataType::REFERENCE) { @@ -953,6 +1021,12 @@ void InstBuilder::BuildChecksBeforeArray(size_t pc, Inst *arrayRef, Inst **ss, I // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildLoadArray(const BytecodeInstruction *bcInst, DataType::Type type) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTLoadArrayIntrinsic(bcInst, type); + return; + } +#endif ASSERT(type != DataType::NO_TYPE); Inst *saveState = nullptr; Inst *nullCheck = nullptr; @@ -1072,6 +1146,12 @@ void InstBuilder::BuildLoadConstStringArray(const BytecodeInstruction *bcInst) // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildLoadConstArray(const BytecodeInstruction *bcInst) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_CONST_ARRAY); + return; + } +#endif auto literalArrayIdx = bcInst->GetId(0).AsIndex(); auto litArray = GetRuntime()->GetLiteralArray(GetMethod(), literalArrayIdx); // Unfold LoadConstArray instruction @@ -1123,6 +1203,12 @@ void InstBuilder::BuildLoadConstArray(const BytecodeInstruction *bcInst) // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildStoreArray(const BytecodeInstruction *bcInst, DataType::Type type) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTStoreArrayIntrinsic(bcInst, type); + return; + } +#endif BuildStoreArrayInst(bcInst, type, GetDefinition(bcInst->GetVReg(0)), GetDefinition(bcInst->GetVReg(1)), GetDefinitionAcc()); } @@ -1181,6 +1267,12 @@ void InstBuilder::BuildLenArray(const BytecodeInstruction *bcInst) // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildNewArray(const BytecodeInstruction *bcInst) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_NEW_ARRAY); + return; + } +#endif auto saveState = CreateSaveState(Opcode::SaveState, GetPc(bcInst->GetAddress())); auto negCheck = graph_->CreateInstNegativeCheck(DataType::INT32, GetPc(bcInst->GetAddress()), GetDefinition(bcInst->GetVReg(1)), saveState); @@ -1200,6 +1292,12 @@ void InstBuilder::BuildNewArray(const BytecodeInstruction *bcInst) // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildNewObject(const BytecodeInstruction *bcInst) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_NEW_OBJECT); + return; + } +#endif auto classId = GetRuntime()->ResolveTypeIndex(GetMethod(), bcInst->GetId(0).AsIndex()); auto pc = GetPc(bcInst->GetAddress()); auto saveState = CreateSaveState(Opcode::SaveState, pc); @@ -1350,6 +1448,12 @@ void InstBuilder::BuildInitString(const BytecodeInstruction *bcInst) // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildInitObject(const BytecodeInstruction *bcInst, bool isRange) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildBCTInitObjectIntrinsic(bcInst, isRange); + return; + } +#endif auto methodId = GetRuntime()->ResolveMethodIndex(GetMethod(), bcInst->GetId(0).AsIndex()); auto typeId = GetRuntime()->GetClassIdForMethod(GetMethod(), methodId); if (GetRuntime()->IsArrayClass(GetMethod(), typeId)) { @@ -1408,6 +1512,12 @@ void InstBuilder::BuildInitObject(const BytecodeInstruction *bcInst, bool isRang // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildCheckCast(const BytecodeInstruction *bcInst) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_CHECK_CAST); + return; + } +#endif auto typeIndex = bcInst->GetId(0).AsIndex(); auto typeId = GetRuntime()->ResolveTypeIndex(GetMethod(), typeIndex); auto klassType = GetRuntime()->GetClassType(GetGraph()->GetMethod(), typeId); @@ -1422,6 +1532,12 @@ void InstBuilder::BuildCheckCast(const BytecodeInstruction *bcInst) // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildIsInstance(const BytecodeInstruction *bcInst) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_IS_INSTANCE); + return; + } +#endif auto typeIndex = bcInst->GetId(0).AsIndex(); auto typeId = GetRuntime()->ResolveTypeIndex(GetMethod(), typeIndex); auto klassType = GetRuntime()->GetClassType(GetGraph()->GetMethod(), typeId); @@ -1452,6 +1568,12 @@ Inst *InstBuilder::BuildLoadClass(RuntimeInterface::IdType typeId, size_t pc, In // NOLINTNEXTLINE(misc-definitions-in-headers) void InstBuilder::BuildThrow(const BytecodeInstruction *bcInst) { +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_THROW); + return; + } +#endif auto saveState = CreateSaveState(Opcode::SaveState, GetPc(bcInst->GetAddress())); auto inst = graph_->CreateInstThrow(DataType::NO_TYPE, GetPc(bcInst->GetAddress()), GetDefinition(bcInst->GetVReg(0)), saveState); @@ -1484,6 +1606,12 @@ void InstBuilder::BuildLoadFromPool(const BytecodeInstruction *bcInst) } else { // NOLINTNEXTLINE(readability-magic-numbers) static_assert(OPCODE == Opcode::LoadString); +#ifdef ENABLE_LIBABCKIT + if (GetGraph()->IsBCT()) { + BuildDefaultBCTIntrinsic(bcInst, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_LOAD_STRING); + return; + } +#endif typeId = bcInst->GetId(0).AsFileId().GetOffset(); if (!GetGraph()->IsDynamicMethod() || GetGraph()->IsBytecodeOptimizer()) { inst = GetGraph()->CreateInstLoadString(DataType::REFERENCE, GetPc(bcInst->GetAddress())); @@ -1598,6 +1726,10 @@ bool InstBuilder::TryBuildStringCharAtIntrinsic(const BytecodeInstruction *bcIns return true; } +#ifdef ENABLE_LIBABCKIT +#include +#endif + } // namespace ark::compiler #endif // PANDA_INST_BUILDER_INL_H diff --git a/static_core/compiler/optimizer/ir_builder/inst_builder.h b/static_core/compiler/optimizer/ir_builder/inst_builder.h index 7264513e5ab54f11c295511d3e768ff079ac2064..fd23bf0e12f791e2abc7d83d26b9b8ae66f82d64 100644 --- a/static_core/compiler/optimizer/ir_builder/inst_builder.h +++ b/static_core/compiler/optimizer/ir_builder/inst_builder.h @@ -386,6 +386,18 @@ private: void BuildDefaultStaticIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead); void BuildDefaultVirtualCallIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead); void BuildVirtualCallIntrinsic(const BytecodeInstruction *bcInst, bool isRange, bool accRead); +#if defined(ENABLE_LIBABCKIT) + void BuildDefaultBCTIntrinsic(const BytecodeInstruction *bcInst, RuntimeInterface::IntrinsicId intrinsicId); + void BuildBCTInitObjectIntrinsic(const BytecodeInstruction *bcInst, bool isRange = false); + template + void BuildBCTLoadObjectIntrinsic(const BytecodeInstruction *bcInst, DataType::Type rawType); + template + void BuildBCTStoreObjectIntrinsic(const BytecodeInstruction *bcInst, DataType::Type rawType); + void BuildBCTLoadStaticIntrinsic(const BytecodeInstruction *bcInst, DataType::Type rawType); + void BuildBCTStoreStaticIntrinsic(const BytecodeInstruction *bcInst, DataType::Type rawType); + void BuildBCTLoadArrayIntrinsic(const BytecodeInstruction *bcInst, DataType::Type type); + void BuildBCTStoreArrayIntrinsic(const BytecodeInstruction *bcInst, DataType::Type type); +#endif void BuildThrow(const BytecodeInstruction *bcInst); void BuildLenArray(const BytecodeInstruction *bcInst); void BuildNewArray(const BytecodeInstruction *bcInst); diff --git a/static_core/compiler/optimizer/ir_builder/inst_templates.yaml b/static_core/compiler/optimizer/ir_builder/inst_templates.yaml index 22eaca275d7121fed09ffd991c0586f4f73db262..0f28e20f160fe13c9540ed91d95ec20c46e80c4a 100644 --- a/static_core/compiler/optimizer/ir_builder/inst_templates.yaml +++ b/static_core/compiler/optimizer/ir_builder/inst_templates.yaml @@ -106,22 +106,46 @@ templates: AddInstruction(inst); UpdateDefinitionAcc(inst); if: |- - auto inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); - inst->SetOperandsType(<%= get_type(inst.type(0)) %>); + #ifdef ENABLE_LIBABCKIT + if (graph_->GetMode().IsBCT()) { + auto inst = graph_->CreateInstIf(DataType::NO_TYPE, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); + inst->SetOperandsType(<%= get_type(inst.type(0)) %>); % if inst.acc_and_operands.size > 2 - inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); % else % if inst.mnemonic.include? "obj" - inst->SetInput(1, graph_->GetOrCreateNullPtr()); + inst->SetInput(1, graph_->GetOrCreateNullPtr()); % else - inst->SetInput(1, FindOrCreateConstant(0)); + % if ['i64' 'f64' 'b64' 'u64'].include?(inst.type(0)) + inst->SetInput(1, FindOrCreateConstant(0)); + % else + inst->SetInput(1, FindOrCreate32BitConstant(0)); + % end % end % end - inst->SetInput(0, GetDefinitionAcc()); - auto inst_jump = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), inst, 0, - DataType::BOOL, ConditionCode::CC_NE, graph_->GetMethod()); - AddInstruction(inst); - AddInstruction(inst_jump); + inst->SetInput(0, GetDefinitionAcc()); + AddInstruction(inst); + } else { + #endif + auto inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); + inst->SetOperandsType(<%= get_type(inst.type(0)) %>); + % if inst.acc_and_operands.size > 2 + inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); + % else + % if inst.mnemonic.include? "obj" + inst->SetInput(1, graph_->GetOrCreateNullPtr()); + % else + inst->SetInput(1, FindOrCreateConstant(0)); + % end + % end + inst->SetInput(0, GetDefinitionAcc()); + auto inst_jump = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), inst, 0, + DataType::BOOL, ConditionCode::CC_NE, graph_->GetMethod()); + AddInstruction(inst); + AddInstruction(inst_jump); + #ifdef ENABLE_LIBABCKIT + } + #endif jump: |- mov: |- % if inst.mnemonic.include? "null" diff --git a/static_core/compiler/optimizer/optimizations/move_constants.cpp b/static_core/compiler/optimizer/optimizations/move_constants.cpp index 901957711cbdb56849db749d2b9902f3b819bf7c..23c23fa892bb80abd01254735b5529526f08bbf5 100644 --- a/static_core/compiler/optimizer/optimizations/move_constants.cpp +++ b/static_core/compiler/optimizer/optimizations/move_constants.cpp @@ -88,7 +88,19 @@ void MoveConstants::MoveFromStartBlock(Inst *inst) if (targetBb != graph->GetStartBlock()) { graph->GetStartBlock()->EraseInst(inst); - targetBb->PrependInst(inst); + auto firstInst = targetBb->GetFirstInst(); + if (firstInst != nullptr && (firstInst->IsCatchPhi() || firstInst->IsPhi())) { + while (firstInst != nullptr && (firstInst->IsCatchPhi() || firstInst->IsPhi())) { + firstInst = firstInst->GetNext(); + } + if (firstInst != nullptr) { + targetBb->InsertBefore(inst, firstInst); + } else { + targetBb->AppendInst(inst); + } + } else { + targetBb->PrependInst(inst); + } movedConstantsCounter_++; } } diff --git a/static_core/compiler/optimizer/templates/intrinsics/get_intrinsics_names.inl.erb b/static_core/compiler/optimizer/templates/intrinsics/get_intrinsics_names.inl.erb index 797bf9c7a87bfcd59a37926ecdaf3312dccf1c3d..5b51fb6e3a0663b3df6effb654cd7fc097caf457 100644 --- a/static_core/compiler/optimizer/templates/intrinsics/get_intrinsics_names.inl.erb +++ b/static_core/compiler/optimizer/templates/intrinsics/get_intrinsics_names.inl.erb @@ -35,6 +35,9 @@ inline std::string GetIntrinsicName(RuntimeInterface::IntrinsicId intrinsic) { return "LIB_CALL_MEMSET_F32"; case RuntimeInterface::IntrinsicId::LIB_CALL_MEMSET_F64: return "LIB_CALL_MEMSET_F64"; +#if defined(ENABLE_LIBABCKIT) +#include +#endif default: return ""; } diff --git a/static_core/compiler/optimizer/templates/intrinsics/intrinsics_enum.inl.erb b/static_core/compiler/optimizer/templates/intrinsics/intrinsics_enum.inl.erb index b8d4a12c0c00db9d3c6dd1ea5dfa644d8bebef0b..2a43087c646dbd48a3b1a040b274e95f0a88d1c8 100644 --- a/static_core/compiler/optimizer/templates/intrinsics/intrinsics_enum.inl.erb +++ b/static_core/compiler/optimizer/templates/intrinsics/intrinsics_enum.inl.erb @@ -21,6 +21,9 @@ % end enum class IntrinsicId { +#if defined(ENABLE_LIBABCKIT) +#include +#endif % Compiler::intrinsics.select{ |x| !x.is_irtoc? }.each do |intrinsic| <%= intrinsic.entrypoint_name %>, % end diff --git a/static_core/compiler/optimizer/templates/intrinsics/intrinsics_flags.inl.erb b/static_core/compiler/optimizer/templates/intrinsics/intrinsics_flags.inl.erb index 7f5fb3a2ecfb6d7e3e0b2e7c88155316be5efbff..4a7c7b2907a8f341f41db4ea1a1334e6217cd313 100644 --- a/static_core/compiler/optimizer/templates/intrinsics/intrinsics_flags.inl.erb +++ b/static_core/compiler/optimizer/templates/intrinsics/intrinsics_flags.inl.erb @@ -36,6 +36,9 @@ inline void AdjustFlags([[maybe_unused]] RuntimeInterface::IntrinsicId intrinsic break; } % end +#if defined(ENABLE_LIBABCKIT) +#include +#endif default: return; } diff --git a/static_core/compiler/optimizer/templates/ir-dyn-base-types.h.erb b/static_core/compiler/optimizer/templates/ir-dyn-base-types.h.erb index c1b97ef4048662c22721e6f7bfa2a52ab63d81d0..a615d946175eccd2af5b10443ad464663b11213d 100644 --- a/static_core/compiler/optimizer/templates/ir-dyn-base-types.h.erb +++ b/static_core/compiler/optimizer/templates/ir-dyn-base-types.h.erb @@ -17,7 +17,7 @@ #define COMPILER_OPTIMIZER_TEMPLATES_IR_DYN_BASE_TYPES_H #include "compiler/optimizer/ir/datatype.h" -#include "compiler/optimizer/code_generator/encode.h" +#include "optimizer/code_generator/encode.h" #include "profiling/profiling.h" #include "source_languages.h" diff --git a/static_core/cross_values/BUILD.gn b/static_core/cross_values/BUILD.gn index 37819c4994428b1e1974a1fd69f0e64d9c2eaaef..d32fbd418da9c55e2ba5b1ef722a7d3f02a7f52c 100644 --- a/static_core/cross_values/BUILD.gn +++ b/static_core/cross_values/BUILD.gn @@ -87,5 +87,7 @@ action("cross_values_getters_generate") { deps = [ ":asm_defines_def_cpp_gen", ":cross_values_generate", + ":asm_defines_def_cpp_gen(${default_toolchain})", + ":cross_values_generate(${default_toolchain})", ] } diff --git a/static_core/isa/isapi.rb b/static_core/isa/isapi.rb index 3b3f0c903211906f7575375183ad6a27572a47c2..a5000827cda27af872c25a02bf998ab597b0f886 100755 --- a/static_core/isa/isapi.rb +++ b/static_core/isa/isapi.rb @@ -345,6 +345,10 @@ class Operand @name == :v end + def is_64bit_imm? + %i[i64 f64 b64 u64].include?(@type.to_sym) + end + def acc? @name == :acc end diff --git a/static_core/libpandabase/BUILD.gn b/static_core/libpandabase/BUILD.gn index 534ceb5ba775cf4fd84dd7b8d855bb29ea2d2de9..5755caceb83c8803adee31bea146bd715afda153 100644 --- a/static_core/libpandabase/BUILD.gn +++ b/static_core/libpandabase/BUILD.gn @@ -18,7 +18,8 @@ import("//build/ohos.gni") ohos_static_library("libarktsbase_package") { deps = [] if (enable_static_vm) { - deps += [ ":libarktsbase_frontend_static" ] + # deps += [ ":libarktsbase_frontend_static" ] + deps += [ ":libarktsbase" ] } part_name = ark_part_name @@ -40,6 +41,8 @@ config("arkbase_public_config") { if (ark_standalone_build) { ldflags = [ "-ldl" ] } + + configs = [ sdk_libc_secshared_config ] } ark_gen_file("events_gen") { @@ -244,7 +247,7 @@ ohos_shared_library("libarktsbase") { if (!is_mingw && !is_mac) { output_extension = "so" } - part_name = ark_part_name + part_name = "$ark_part_name" subsystem_name = "$ark_subsystem_name" } @@ -260,8 +263,8 @@ source_set("libarkbase_frontend_set_static") { ohos_source_set("libarktsbase_frontend_static") { deps = [ ":libarkbase_frontend_set_static" ] - part_name = ark_part_name - subsystem_name = ark_subsystem_name + part_name = "$ark_part_name" + subsystem_name = "$ark_subsystem_name" } action("logger_yaml_gen") { diff --git a/static_core/libpandabase/templates/logger.yaml b/static_core/libpandabase/templates/logger.yaml index fe91caa44b63a8a98c83233e1bd79aaf3e7d7c18..954b0ff70a133acee084f8375efec1d338bf4d19 100644 --- a/static_core/libpandabase/templates/logger.yaml +++ b/static_core/libpandabase/templates/logger.yaml @@ -51,6 +51,7 @@ components: - name: verifier - name: compilation_queue - name: disassembler + - name: abc2program - name: ziparchive - name: bytecode_optimizer - name: AOT diff --git a/static_core/libpandafile/bytecode_instruction.h b/static_core/libpandafile/bytecode_instruction.h index 55f262700a9e87a34d9963e4910d863412f76366..0be1f7da3dfcbfe5bccbfcfa074bd389156bc96f 100644 --- a/static_core/libpandafile/bytecode_instruction.h +++ b/static_core/libpandafile/bytecode_instruction.h @@ -385,6 +385,8 @@ public: template ::Opcode> bool HasFlag(Flags flag) const; + bool IsIdMatchFlag(size_t idx, Flags flag) const; + bool IsThrow(Exceptions exception) const; bool IsJump() const diff --git a/static_core/libpandafile/file.h b/static_core/libpandafile/file.h index bad5404915cdc83e765edc26e34bd87595cc1483..b7e0d4c88697e1d0ca113d65d91d0945d224f99c 100644 --- a/static_core/libpandafile/file.h +++ b/static_core/libpandafile/file.h @@ -301,6 +301,12 @@ public: return index[idx]; } + EntityId ResolveOffsetByIndex(EntityId id, Index idx) const + { + auto index = GetMethodIndex(id); + return index[idx]; + } + EntityId ResolveFieldIndex(EntityId id, Index idx) const { auto index = GetFieldIndex(id); diff --git a/static_core/libpandafile/templates/bytecode_instruction-inl_gen.h.erb b/static_core/libpandafile/templates/bytecode_instruction-inl_gen.h.erb index b9cbe437fde5fdbfc5c272038ea7a4421d30deb3..7f959f91ec933e36dc3d7048237592d39b388e6a 100644 --- a/static_core/libpandafile/templates/bytecode_instruction-inl_gen.h.erb +++ b/static_core/libpandafile/templates/bytecode_instruction-inl_gen.h.erb @@ -479,6 +479,33 @@ inline bool BytecodeInst::HasFlag inline bool BytecodeInst::IsIdMatchFlag(size_t idx, Flags flag) const { + switch(GetOpcode()) { +% Panda::instructions.each do |i| +% flag_array = i.properties.map {|prop| prop.upcase} +% flag_array = [] if flag_array.empty? +% ids = [] +% flag_array.each do |f| +% if f == "STRING_ID" || f == "METHOD_ID" || f == "LITERALARRAY_ID" +% ids << "Flags::" + f +% end +% end + case BytecodeInst::Opcode::<%= i.opcode.upcase %>: { +% if ids.empty? + return false; + } +% else + constexpr std::array> ids_array { <%= ids.join(', ') %> }; + return ids_array[idx] == flag; + } +% end +% end + default: + return false; + } +} + // NOLINTNEXTLINE(readability-function-size) template inline bool BytecodeInst::IsThrow(Exceptions exception) const { switch(GetOpcode()) { diff --git a/static_core/plugins/ets/CMakeLists.txt b/static_core/plugins/ets/CMakeLists.txt index b92ca9fb805270570ef5528006eea7d874bd1e41..4bd6a88c9bb8bcad5f4271d9a49f812d48fcba0b 100644 --- a/static_core/plugins/ets/CMakeLists.txt +++ b/static_core/plugins/ets/CMakeLists.txt @@ -94,6 +94,7 @@ endif() if(PANDA_WITH_TOOLCHAIN) add_subdirectory(assembler) add_subdirectory(disassembler) + add_subdirectory(abc2program) add_subdirectory(isa) endif() diff --git a/static_core/plugins/ets/abc2program/CMakeLists.txt b/static_core/plugins/ets/abc2program/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3a47d490b2134ad7e25c29d5a0a31a62443e1131 --- /dev/null +++ b/static_core/plugins/ets/abc2program/CMakeLists.txt @@ -0,0 +1,17 @@ +# Copyright (c) 2024 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. + +set(PLUGIN_DIR ${PANDA_ETS_PLUGIN_SOURCE}/abc2program) + +panda_target_sources(abc2program PRIVATE ${PLUGIN_DIR}/abc2program_ets_plugin.cpp) +panda_target_include_directories(abc2program PUBLIC ${PLUGIN_DIR}) diff --git a/static_core/plugins/ets/abc2program/abc2program_ets_plugin.cpp b/static_core/plugins/ets/abc2program/abc2program_ets_plugin.cpp new file mode 100644 index 0000000000000000000000000000000000000000..568f6f076c6a93bf16672e4866b3e04b124ef168 --- /dev/null +++ b/static_core/plugins/ets/abc2program/abc2program_ets_plugin.cpp @@ -0,0 +1,290 @@ +/** + * Copyright (c) 2024 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 "abc_file_processor.h" +#include "abc_file_utils.h" +#include "abc_method_processor.h" +#include "annotation_data_accessor.h" +#include "class_data_accessor.h" + +namespace ark::abc2program { +void AbcFileProcessor::GeteTSMetadata() +{ + LOG(DEBUG, ABC2PROGRAM) << "\n[getting ETS-specific metadata]\n"; + + for (auto &pair : program_->recordTable) { + if (pair.second.language == ark::panda_file::SourceLang::ETS) { + const auto recordId = keyData_.recordNameToId_[pair.first]; + + if (file_->IsExternal(recordId)) { + continue; + } + + GetETSMetadata(&pair.second, recordId); + + panda_file::ClassDataAccessor classAccessor(*file_, recordId); + + size_t fieldIdx = 0; + classAccessor.EnumerateFields([&](panda_file::FieldDataAccessor &fieldAccessor) { + GetETSMetadata(&pair.second.fieldList[fieldIdx++], fieldAccessor.GetFieldId()); + }); + } + } + + for (auto &pair : program_->functionTable) { + if (pair.second.language == ark::panda_file::SourceLang::ETS) { + const auto methodId = keyData_.methodNameToId_[pair.first]; + + GetETSMetadata(&pair.second, methodId); + } + } +} + +void AbcFileProcessor::GetETSMetadata(pandasm::Record *record, const panda_file::File::EntityId &recordId) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting ETS metadata]\nrecord id: " << recordId; + if (record == nullptr) { + LOG(ERROR, ABC2PROGRAM) << "> nullptr recieved!"; + return; + } + + panda_file::ClassDataAccessor classAccessor(*file_, recordId); + const auto recordName = keyData_.GetFullRecordNameById(classAccessor.GetClassId()); + SetETSAttributes(record, recordId); + AnnotationList annList {}; + LOG(DEBUG, ABC2PROGRAM) << "[getting ets annotations]\nrecord id: " << recordId; + + classAccessor.EnumerateAnnotations([&](panda_file::File::EntityId id) { + const auto annListPart = GetETSAnnotation(id, "class"); + annList.reserve(annList.size() + annListPart.size()); + annList.insert(annList.end(), annListPart.begin(), annListPart.end()); + }); + + classAccessor.EnumerateRuntimeAnnotations([&](panda_file::File::EntityId id) { + const auto annListPart = GetETSAnnotation(id, "runtime"); + annList.reserve(annList.size() + annListPart.size()); + annList.insert(annList.end(), annListPart.begin(), annListPart.end()); + }); + + if (!annList.empty()) { + RecordAnnotations recordEtsAnn {}; + recordEtsAnn.annList = std::move(annList); + progAnn_.recordAnnotations.emplace(recordName, std::move(recordEtsAnn)); + } +} + +void AbcFileProcessor::SetETSAttributes(pandasm::Record *record, const panda_file::File::EntityId &recordId) const +{ + // id of std.core.Object + [[maybe_unused]] static const size_t OBJ_ENTITY_ID = 0; + + panda_file::ClassDataAccessor classAccessor(*file_, recordId); + uint32_t accFlags = classAccessor.GetAccessFlags(); + + if ((accFlags & ACC_INTERFACE) != 0) { + record->metadata->SetAttribute("ets.interface"); + } + if ((accFlags & ACC_ABSTRACT) != 0) { + record->metadata->SetAttribute("ets.abstract"); + } + if ((accFlags & ACC_ANNOTATION) != 0) { + record->metadata->SetAttribute("ets.annotation"); + } + if ((accFlags & ACC_ENUM) != 0) { + record->metadata->SetAttribute("ets.enum"); + } + if ((accFlags & ACC_SYNTHETIC) != 0) { + record->metadata->SetAttribute("ets.synthetic"); + } + + if (classAccessor.GetSuperClassId().GetOffset() != OBJ_ENTITY_ID) { + const auto superClassName = keyData_.GetFullRecordNameById(classAccessor.GetSuperClassId()); + record->metadata->SetAttributeValue("ets.extends", superClassName); + } + + classAccessor.EnumerateInterfaces([&](panda_file::File::EntityId id) { + const auto ifaceName = keyData_.GetFullRecordNameById(id); + record->metadata->SetAttributeValue("ets.implements", ifaceName); + }); +} + +void AbcFileProcessor::GetETSMetadata(pandasm::Function *method, const panda_file::File::EntityId &methodId) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting ETS metadata]\nmethod id: " << methodId; + if (method == nullptr) { + LOG(ERROR, ABC2PROGRAM) << "> nullptr recieved!"; + return; + } + + panda_file::MethodDataAccessor methodAccessor(*file_, methodId); + SetETSAttributes(method, methodId); + AnnotationList annList {}; + LOG(DEBUG, ABC2PROGRAM) << "[getting ETS annotations]\nmethod id: " << methodId; + + methodAccessor.EnumerateAnnotations([&](panda_file::File::EntityId id) { + const auto annListPart = GetETSAnnotation(id, "class"); + annList.reserve(annList.size() + annListPart.size()); + annList.insert(annList.end(), annListPart.begin(), annListPart.end()); + }); + + methodAccessor.EnumerateRuntimeAnnotations([&](panda_file::File::EntityId id) { + const auto annListPart = GetETSAnnotation(id, "runtime"); + annList.reserve(annList.size() + annListPart.size()); + annList.insert(annList.end(), annListPart.begin(), annListPart.end()); + }); + + if (!annList.empty()) { + AbcMethodProcessor methodProcessor(methodId, keyData_); + const auto methodName = methodProcessor.GetMethodSignature(); + progAnn_.methodAnnotations.emplace(methodName, std::move(annList)); + } +} + +void AbcFileProcessor::SetETSAttributes(pandasm::Function *method, const panda_file::File::EntityId &methodId) const +{ + panda_file::MethodDataAccessor methodAccessor(*file_, methodId); + uint32_t accFlags = methodAccessor.GetAccessFlags(); + if ((accFlags & ACC_ABSTRACT) != 0) { + method->metadata->SetAttribute("ets.abstract"); + } +} + +void AbcFileProcessor::GetETSMetadata(pandasm::Field *field, const panda_file::File::EntityId &fieldId) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting ETS metadata]\nfield id: " << fieldId; + if (field == nullptr) { + LOG(ERROR, ABC2PROGRAM) << "> nullptr recieved!"; + return; + } + + panda_file::FieldDataAccessor fieldAccessor(*file_, fieldId); + SetETSAttributes(field, fieldId); + AnnotationList annList {}; + + LOG(DEBUG, ABC2PROGRAM) << "[getting ETS annotations]\nfield id: " << fieldId; + + fieldAccessor.EnumerateAnnotations([&](panda_file::File::EntityId id) { + const auto annListPart = GetETSAnnotation(id, "class"); + annList.reserve(annList.size() + annListPart.size()); + annList.insert(annList.end(), annListPart.begin(), annListPart.end()); + }); + + fieldAccessor.EnumerateRuntimeAnnotations([&](panda_file::File::EntityId id) { + const auto annListPart = GetETSAnnotation(id, "runtime"); + annList.reserve(annList.size() + annListPart.size()); + annList.insert(annList.end(), annListPart.begin(), annListPart.end()); + }); + + if (!annList.empty()) { + const auto recordName = keyData_.GetFullRecordNameById(fieldAccessor.GetClassId()); + const auto fieldName = stringTable_->StringDataToString(file_->GetStringData(fieldAccessor.GetNameId())); + progAnn_.recordAnnotations[recordName].fieldAnnotations.emplace(fieldName, std::move(annList)); + } +} + +void AbcFileProcessor::SetETSAttributes(pandasm::Field *field, const panda_file::File::EntityId &fieldId) const +{ + panda_file::FieldDataAccessor fieldAccessor(*file_, fieldId); + uint32_t accFlags = fieldAccessor.GetAccessFlags(); + if ((accFlags & ACC_VOLATILE) != 0) { + field->metadata->SetAttribute("ets.volatile"); + } + if ((accFlags & ACC_ENUM) != 0) { + field->metadata->SetAttribute("ets.enum"); + } + if ((accFlags & ACC_TRANSIENT) != 0) { + field->metadata->SetAttribute("ets.transient"); + } + if ((accFlags & ACC_SYNTHETIC) != 0) { + field->metadata->SetAttribute("ets.synthetic"); + } +} + +// CODECHECK-NOLINTNEXTLINE(C_RULE_ID_FUNCTION_SIZE) +AnnotationList AbcFileProcessor::GetETSAnnotation(const panda_file::File::EntityId &annotationId, + const std::string &type) +{ + LOG(DEBUG, ABC2PROGRAM) << "[getting ets annotation]\nid: " << annotationId; + panda_file::AnnotationDataAccessor annotationAccessor(*file_, annotationId); + AnnotationList annList {}; + // annotation + + const auto className = keyData_.GetFullRecordNameById(annotationAccessor.GetClassId()); + + if (annotationAccessor.GetCount() == 0) { + if (!type.empty()) { + annList.push_back({"ets.annotation.type", type}); + } + annList.push_back({"ets.annotation.class", className}); + annList.push_back({"ets.annotation.id", "id_" + std::to_string(annotationId.GetOffset())}); + } + + for (size_t i = 0; i < annotationAccessor.GetCount(); ++i) { + // element + const auto elemNameId = annotationAccessor.GetElement(i).GetNameId(); + auto elemType = AnnotationTagToString(annotationAccessor.GetTag(i).GetItem()); + const bool isArray = elemType.back() == ']'; + const auto elemCompType = + elemType.substr(0, elemType.length() - 2); // 2 last characters are '[' & ']' if annotation is an array + // adding necessary annotations + if (elemType == "annotations") { + const auto val = annotationAccessor.GetElement(i).GetScalarValue().Get(); + const auto annDefinition = GetETSAnnotation(val, ""); + for (const auto &elem : annDefinition) { + annList.push_back(elem); + } + } + if (isArray && elemCompType == "annotation") { + const auto values = annotationAccessor.GetElement(i).GetArrayValue(); + for (size_t idx = 0; idx < values.GetCount(); ++idx) { + const auto val = values.Get(idx); + const auto annDefinition = GetETSAnnotation(val, ""); + for (const auto &elem : annDefinition) { + annList.push_back(elem); + } + } + } + if (!type.empty()) { + annList.push_back({"ets.annotation.type", type}); + } + + annList.push_back({"ets.annotation.class", className}); + + annList.push_back({"ets.annotation.id", "id_" + std::to_string(annotationId.GetOffset())}); + annList.push_back( + {"ets.annotation.element.name", stringTable_->StringDataToString(file_->GetStringData(elemNameId))}); + // type + if (isArray) { + elemType = "array"; + annList.push_back({"ets.annotation.element.type", elemType}); + annList.push_back({"ets.annotation.element.array.component.type", elemCompType}); + // values + const auto values = annotationAccessor.GetElement(i).GetArrayValue(); + for (size_t idx = 0; idx < values.GetCount(); ++idx) { + annList.push_back({"ets.annotation.element.value", ArrayValueToString(values, elemCompType, idx)}); + } + } else { + annList.push_back({"ets.annotation.element.type", elemType}); + // value + if (elemType != "void") { + const auto value = annotationAccessor.GetElement(i).GetScalarValue(); + annList.push_back({"ets.annotation.element.value", ScalarValueToString(value, elemType)}); + } + } + } + return annList; +} + +} // namespace ark::abc2program \ No newline at end of file diff --git a/static_core/plugins/ets/abc2program/abc2program_ets_plugin.inc b/static_core/plugins/ets/abc2program/abc2program_ets_plugin.inc new file mode 100644 index 0000000000000000000000000000000000000000..40da6e3bbcd07bf384bc58c9f82d9860634da589 --- /dev/null +++ b/static_core/plugins/ets/abc2program/abc2program_ets_plugin.inc @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 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. + */ + +#ifndef ABC2PROGRAM_ETS_PLUGIN_INCLUDED +#define ABC2PROGRAM_ETS_PLUGIN_INCLUDED + +void GeteTSMetadata(); +void GetETSMetadata(pandasm::Record *record, const panda_file::File::EntityId &recordId); +void SetETSAttributes(pandasm::Record *record, const panda_file::File::EntityId &recordId) const; +void GetETSMetadata(pandasm::Function *method, const panda_file::File::EntityId &methodId); +void SetETSAttributes(pandasm::Function *method, const panda_file::File::EntityId &methodId) const; +void GetETSMetadata(pandasm::Field *field, const panda_file::File::EntityId &fieldId); +void SetETSAttributes(pandasm::Field *field, const panda_file::File::EntityId &fieldId) const; +AnnotationList GetETSAnnotation(const panda_file::File::EntityId &id, const std::string &type = ""); + +#endif diff --git a/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_builder.cpp b/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_builder.cpp index 8e15adcfaa9d5c3441fc7dbe28ac9de4dbb34b09..1d68bb0ee6970bf340824c025de5d3caa98caba5 100644 --- a/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_builder.cpp +++ b/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_builder.cpp @@ -28,6 +28,11 @@ namespace ark::compiler { template void InstBuilder::BuildLaunch(const BytecodeInstruction *bcInst, bool isRange, bool accRead) { +// #if defined(ENABLE_LIBABCKIT) +// if (GetGraph()->IsBCT()) { +// BuildBCTLaunchIntrinsic(bcInst, isRange, accRead); +// } +// #endif if (graph_->GetArch() == Arch::AARCH32) { failed_ = true; return; @@ -50,11 +55,6 @@ template void InstBuilder::BuildLaunch(const Bytecode void InstBuilder::BuildLdObjByName(const BytecodeInstruction *bcInst, DataType::Type type) { auto pc = GetPc(bcInst->GetAddress()); - // Create SaveState instruction - auto saveState = CreateSaveState(Opcode::SaveState, pc); - - // Create NullCheck instruction - auto nullCheck = graph_->CreateInstNullCheck(DataType::REFERENCE, pc, GetDefinition(bcInst->GetVReg(0)), saveState); auto runtime = GetRuntime(); auto fieldIndex = bcInst->GetId(0).AsIndex(); @@ -91,13 +91,31 @@ void InstBuilder::BuildLdObjByName(const BytecodeInstruction *bcInst, DataType:: break; } auto intrinsic = GetGraph()->CreateInstIntrinsic(type, pc, id); + + // Create SaveState instruction + auto saveState = CreateSaveState(Opcode::SaveState, pc); + + // Create NullCheck instruction + auto nullCheck = graph_->CreateInstNullCheck(DataType::REFERENCE, pc, GetDefinition(bcInst->GetVReg(0)), saveState); + intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 2_I); intrinsic->AppendInput(nullCheck); intrinsic->AddInputType(DataType::REFERENCE); +#if defined(ENABLE_LIBABCKIT) + if (GetGraph()->IsBCT()) { + intrinsic->ClearFlag(inst_flags::REQUIRE_STATE); + } else { +#endif intrinsic->AppendInput(saveState); intrinsic->AddInputType(DataType::NO_TYPE); +#if defined(ENABLE_LIBABCKIT) + } +#endif + AddInstruction(saveState); + AddInstruction(nullCheck); + intrinsic->AddImm(GetGraph()->GetAllocator(), fieldId); intrinsic->AddImm(GetGraph()->GetAllocator(), pc); @@ -105,8 +123,6 @@ void InstBuilder::BuildLdObjByName(const BytecodeInstruction *bcInst, DataType:: intrinsic->SetMethodFirstInput(); intrinsic->SetMethod(GetMethod()); - AddInstruction(saveState); - AddInstruction(nullCheck); AddInstruction(intrinsic); UpdateDefinitionAcc(intrinsic); @@ -115,11 +131,6 @@ void InstBuilder::BuildLdObjByName(const BytecodeInstruction *bcInst, DataType:: void InstBuilder::BuildStObjByName(const BytecodeInstruction *bcInst, DataType::Type type) { auto pc = GetPc(bcInst->GetAddress()); - // Create SaveState instruction - auto saveState = CreateSaveState(Opcode::SaveState, pc); - - // Create NullCheck instruction - auto nullCheck = graph_->CreateInstNullCheck(DataType::REFERENCE, pc, GetDefinition(bcInst->GetVReg(0)), saveState); auto runtime = GetRuntime(); auto fieldIndex = bcInst->GetId(0).AsIndex(); @@ -168,7 +179,23 @@ void InstBuilder::BuildStObjByName(const BytecodeInstruction *bcInst, DataType:: break; } auto intrinsic = GetGraph()->CreateInstIntrinsic(DataType::VOID, pc, id); + + // Create SaveState instruction + auto saveState = CreateSaveState(Opcode::SaveState, pc); + + // Create NullCheck instruction + auto nullCheck = graph_->CreateInstNullCheck(DataType::REFERENCE, pc, GetDefinition(bcInst->GetVReg(0)), saveState); + +#if defined(ENABLE_LIBABCKIT) + if (GetGraph()->IsBCT()) { + intrinsic->ClearFlag(compiler::inst_flags::REQUIRE_STATE); + intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 2_I); + } else { +#endif intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 3_I); +#if defined(ENABLE_LIBABCKIT) + } +#endif intrinsic->AppendInput(nullCheck); intrinsic->AddInputType(DataType::REFERENCE); @@ -176,16 +203,24 @@ void InstBuilder::BuildStObjByName(const BytecodeInstruction *bcInst, DataType:: intrinsic->AppendInput(storeVal); intrinsic->AddInputType(type); +#if defined(ENABLE_LIBABCKIT) + if (!GetGraph()->IsBCT()) { +#endif intrinsic->AppendInput(saveState); intrinsic->AddInputType(DataType::NO_TYPE); +#if defined(ENABLE_LIBABCKIT) + } +#endif + + AddInstruction(saveState); + AddInstruction(nullCheck); + intrinsic->AddImm(GetGraph()->GetAllocator(), fieldId); intrinsic->AddImm(GetGraph()->GetAllocator(), pc); intrinsic->SetMethodFirstInput(); intrinsic->SetMethod(GetMethod()); - AddInstruction(saveState); - AddInstruction(nullCheck); AddInstruction(intrinsic); } @@ -196,8 +231,13 @@ void InstBuilder::BuildEquals(const BytecodeInstruction *bcInst) Inst *obj1 = GetDefinition(bcInst->GetVReg(0)); Inst *obj2 = GetDefinition(bcInst->GetVReg(1)); - auto intrinsic = GetGraph()->CreateInstIntrinsic(DataType::BOOL, pc, - RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_EQUALS); + RuntimeInterface::IntrinsicId intrinsicId = RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_EQUALS; +#if defined(ENABLE_LIBABCKIT) + if (GetGraph()->IsBCT()) { + intrinsicId = RuntimeInterface::IntrinsicId::INTRINSIC_BCT_EQUALS; + } +#endif + auto intrinsic = GetGraph()->CreateInstIntrinsic(DataType::BOOL, pc, intrinsicId); intrinsic->AllocateInputTypes(GetGraph()->GetAllocator(), 2_I); intrinsic->AppendInput(obj1); diff --git a/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_templates.yaml b/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_templates.yaml index 83c6a5a217a9295d64908f8babfdd3db21df6215..f8c91fc608dcdeb641007726a9962fd2c8e14f30 100644 --- a/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_templates.yaml +++ b/static_core/plugins/ets/compiler/optimizer/ir_builder/ets_inst_templates.yaml @@ -28,11 +28,19 @@ % when "MOVUNDEFINED" UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), graph_->GetOrCreateUndefinedInst()); % when "ISUNDEFINED" - auto undef_inst = graph_->GetOrCreateUndefinedInst(); - auto cmp_inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), GetDefinitionAcc(), - undef_inst, DataType::REFERENCE, ConditionCode::CC_EQ); - AddInstruction(cmp_inst); - UpdateDefinitionAcc(cmp_inst); + #ifdef ENABLE_LIBABCKIT + if (graph_->GetMode().IsBCT()) { + BuildDefaultBCTIntrinsic(instruction, compiler::RuntimeInterface::IntrinsicId::INTRINSIC_BCT_IS_UNDEFINED); + } else { + #endif + auto undef_inst = graph_->GetOrCreateUndefinedInst(); + auto cmp_inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), GetDefinitionAcc(), + undef_inst, DataType::REFERENCE, ConditionCode::CC_EQ); + AddInstruction(cmp_inst); + UpdateDefinitionAcc(cmp_inst); + #ifdef ENABLE_LIBABCKIT + } + #endif % when "EQUALS" BuildEquals(instruction); % else diff --git a/static_core/plugins/ets/ets_plugin_options.yaml b/static_core/plugins/ets/ets_plugin_options.yaml index f75597cfb01a1102e10535335dadebf3396c4b88..bc2f5509d48bff48e6d185700636dd08db413ae4 100644 --- a/static_core/plugins/ets/ets_plugin_options.yaml +++ b/static_core/plugins/ets/ets_plugin_options.yaml @@ -43,6 +43,9 @@ Disasm: language_interface_path: plugins/ets/disassembler/disasm_ets_plugin.inc + Abc2Prog: + language_interface_path: plugins/ets/abc2program/abc2program_ets_plugin.inc + logger: components: - name: ets diff --git a/static_core/plugins/ets/subproject_sources.gn b/static_core/plugins/ets/subproject_sources.gn index b153b929a025d3b1567fba3e2d9e51d37f4a696b..dac4170415c42670cd3f65ed0ac3feed0405b672 100644 --- a/static_core/plugins/ets/subproject_sources.gn +++ b/static_core/plugins/ets/subproject_sources.gn @@ -30,11 +30,14 @@ srcs_compiler = [ "compiler/optimizer/optimizations/interop_js/interop_intrinsic_optimization.cpp", ] +arkcompiler_deps = [] if (is_ohos && is_standard_system) { - arkcompiler_deps = + arkcompiler_deps += [ "$ark_root/plugins/ets/runtime/interop_js:interop_intrinsic_kinds_h" ] } +srcs_abc2program = [ "abc2program/abc2program_ets_plugin.cpp" ] + srcs_disassembler = [ "disassembler/disasm_ets_plugin.cpp" ] srcs_isa = [ "isa/isa.yaml" ] @@ -70,6 +73,8 @@ arkruntime_deps = [ "$ark_root/libpandafile:libarktsfile_frontend_static", ] +arkcompiler_deps += [ "$_plugin_dir/runtime/interop_js:interop_intrinsic_kinds_h(${default_toolchain})"] + srcs_runtime = [ "runtime/ets_annotation.cpp", "runtime/ets_class_linker.cpp", diff --git a/static_core/plugins/plugins.gni b/static_core/plugins/plugins.gni index ae1ac527fab9a4d6aad2d8dd65c72d76dc981624..250ae8d588004695456a61749038483849255fa6 100644 --- a/static_core/plugins/plugins.gni +++ b/static_core/plugins/plugins.gni @@ -37,6 +37,7 @@ plugin_libarkbytecodeopt_sources = [] plugin_libarkcompiler_sources = [] plugin_runtime_sources = [] plugin_verifier_sources = [] +plugin_abc2program_sources = [] plugin_entrypoints_yamls = [] plugin_inst_templates_yamls = [] @@ -126,6 +127,11 @@ foreach(plugin, ark_enabled_plugins) { } } + if (defined(_plugin_vars.srcs_abc2program)) { + foreach(src, _plugin_vars.srcs_abc2program) { + plugin_abc2program_sources += [ "$_plugin_dir/$src" ] + } + } if (defined(_plugin_vars.srcs_disassembler)) { foreach(src, _plugin_vars.srcs_disassembler) { plugin_arkdisassembler_sources += [ "$_plugin_dir/$src" ] diff --git a/static_core/runtime/BUILD.gn b/static_core/runtime/BUILD.gn index 33ea5a3800f49ee5aeb761cf032dae86dcd0034a..a7c10e2c9cbe28f8e34936d95185aed7c02ab070 100644 --- a/static_core/runtime/BUILD.gn +++ b/static_core/runtime/BUILD.gn @@ -12,6 +12,7 @@ # limitations under the License. import("//arkcompiler/runtime_core/static_core/ark_config.gni") +import("//arkcompiler/runtime_core/static_vm_config.gni") import("//build/ohos.gni") import("$ark_root/plugins/plugins.gni") import("$ark_root/verification/verification.gni") @@ -67,6 +68,10 @@ config("arkruntime_config") { } group("arkruntime_header_deps") { + if (current_toolchain == host_toolchain) { + enable_irtoc = false + } + deps = [ ":arkruntime_gen_entrypoints_entrypoints_gen_S", ":arkruntime_gen_entrypoints_entrypoints_gen_h", @@ -113,6 +118,10 @@ group("arkruntime_header_deps") { } ohos_source_set("libarkruntime_set_static") { + if (current_toolchain == host_toolchain) { + enable_irtoc = false + } + sources = [ "arch/asm_support.cpp", "assert_gc_scope.cpp", @@ -459,6 +468,12 @@ config("arkruntime_interpreter_impl_config") { ] defines = [] + if (current_toolchain == host_toolchain) { + cflags_cc += [ + "-UPANDA_WITH_IRTOC", + ] + } + if (ark_enable_global_register_variables) { if (current_cpu == "arm64") { cflags_cc += [ @@ -561,6 +576,9 @@ config("profiling_gen_public_config") { } ark_isa_gen("isa_gen_libarkruntime") { + if (current_toolchain == host_toolchain) { + enable_irtoc = false + } template_files = [ "interpreter-inl_gen.h.erb", "isa_constants_gen.h.erb", @@ -652,7 +670,11 @@ ark_gen("arkruntime_gen_entrypoints_compiler_checksum") { } ark_gen("arkruntime_gen_intrinsics") { - data = [ "$target_gen_dir/intrinsics.yaml" ] + if (enable_libabckit && (current_toolchain == host_toolchain)) { + data = [ "$target_gen_dir/bct_intrinsics.yaml" ] + } else { + data = [ "$target_gen_dir/intrinsics.yaml" ] + } template_files = [ "intrinsics_gen.h.erb", "intrinsics.h.erb", @@ -664,6 +686,9 @@ ark_gen("arkruntime_gen_intrinsics") { sources = "templates" destination = "$target_gen_dir" extra_dependencies = [ ":arkruntime_gen_intrinsics_yaml" ] + if (enable_libabckit && (current_toolchain == host_toolchain)) { + extra_dependencies += [ "$ark_root/../libabckit:concat_bct_intrinsics_yaml" ] + } } ark_gen_file("libarkruntime_options_gen_h") { diff --git a/static_vm_config.gni b/static_vm_config.gni index 40573e5028ada61ab7ee8a1701b4559ac697bf8c..c6a39c7062481a966156e2f8d55d0ea99eda903e 100644 --- a/static_vm_config.gni +++ b/static_vm_config.gni @@ -15,6 +15,7 @@ import("//build/config/sanitizers/sanitizers.gni") import("//build/ohos_var.gni") enable_arkplatform = true +enable_libabckit = true enable_static_vm = true if (is_asan && use_hwasan) { enable_arkplatform = false