diff --git a/.gitignore b/.gitignore index f71bf2703f6ebf9a684037b3df228a6082d56a73..dcf0dec08f06bb5391c8935caae1a02ce71b0c3c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ third_party/aosp_10.0.0_r35* third_party/aosp_modified* third_party/ctorture* third_party/llvm_modified* +third_party/llvm-* +tools/lib tools/bin* tools/android* tools/aosp* diff --git a/BUILD.gn b/BUILD.gn index 6801cf5b4813146f60163e5bf837271829983af0..40e691379fdb548eb9a6292775b15262bfa1c51d 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -13,52 +13,56 @@ # See the Mulan PSL v2 for more details. # group("maple") { - deps = [ - "${MAPLEALL_ROOT}:maple", - ] + deps = [ "${MAPLEALL_ROOT}:maple" ] } group("irbuild") { - deps = [ - "${MAPLEALL_ROOT}:irbuild", - ] + deps = [ "${MAPLEALL_ROOT}:irbuild" ] } group("hir2mpl") { - deps = [ - "${HIR2MPL_ROOT}:hir2mpl", - ] + deps = [ "${HIR2MPL_ROOT}:hir2mpl" ] } group("hir2mplUT") { - deps = [ - "${HIR2MPL_ROOT}/test:hir2mplUT", - ] + deps = [ "${HIR2MPL_ROOT}/test:hir2mplUT" ] } group("maple-rt") { - deps = [ - "${MAPLE_MRT_ROOT}:maple-rt", - ] + deps = [ "${MAPLE_MRT_ROOT}:maple-rt" ] } group("ast2mpl") { deps = [] if (IS_AST2MPL_EXISTS == "1") { - deps = [ - "${AST2MPL_ROOT}/src:ast2mpl", - ] + deps = [ "${AST2MPL_ROOT}/src:ast2mpl" ] } } +group("mapleallUT") { + deps = [ + "${MAPLEALL_ROOT}/test:mapleallUT", + ] +} + group("maplegendef") { - exec_script("${MAPLEALL_ROOT}/maple_be/mdgen/gendef.py", - [ - rebase_path("${GN_BINARY_OUTPUT_DIRECTORY}/maplegen", - root_build_dir), - rebase_path("${MAPLEALL_ROOT}/maple_be/include/ad/cortex_a55", - root_build_dir), - rebase_path("${MAPLE_BUILD_OUTPUT}/common/target", - root_build_dir), - ]) + exeTool = "-e" + rebase_path("${GN_BINARY_OUTPUT_DIRECTORY}/maplegen", root_build_dir) + mdDir = "-m" + rebase_path("${MAPLEALL_ROOT}/maple_be/include/ad/cortex_a55", root_build_dir) + outDir = "-o" + rebase_path("${MAPLE_BUILD_OUTPUT}/common/target", root_build_dir) + if (ASAN == 1) { + exec_script("${MAPLEALL_ROOT}/maple_be/mdgen/gendef.py", + [ + "-aLD_PRELOAD=${LLVMLIBDIR}/libclang_rt.asan-x86_64.so", + exeTool, + mdDir, + outDir, + ]) + } else { + exec_script("${MAPLEALL_ROOT}/maple_be/mdgen/gendef.py", + [ + exeTool, + mdDir, + outDir + ]) + } } diff --git a/Makefile b/Makefile index 250f27b5c0b3e6adb5888bb50a361d67a321f1e7..9e1db783ba597e773f0729926dd388415c20b919 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,9 @@ RELEASE_VERSION := $(MAPLE_RELEASE_VERSION) BUILD_VERSION := $(MAPLE_BUILD_VERSION) GIT_REVISION := $(shell git log --pretty=format:"%H" -1) MAST := 0 - +ASAN := 0 +ONLY_C := 0 +COV := 0 ifeq ($(DEBUG),0) BUILD_TYPE := RELEASE else @@ -55,7 +57,10 @@ GN_OPTIONS := \ RELEASE_VERSION="$(RELEASE_VERSION)" \ BUILD_VERSION="$(BUILD_VERSION)" \ GIT_REVISION="$(GIT_REVISION)" \ - MAST=$(MAST) + MAST=$(MAST) \ + ASAN=$(ASAN) \ + ONLY_C=$(ONLY_C) \ + COV=$(COV) .PHONY: default default: install @@ -117,13 +122,17 @@ libcore: maple-rt maple-rt: java-core-def $(call build_gn, $(GN_OPTIONS), maple-rt) +.PHONY: mapleallUT +mapleallUT: install_patch + $(call build_gn, $(GN_OPTIONS), mapleallUT) + .PHONY: java-core-def java-core-def: install mkdir -p $(LIB_CORE_PATH); \ cp -rp $(MAPLE_ROOT)/libjava-core/* $(LIB_CORE_PATH)/; \ cd $(LIB_CORE_PATH); \ ln -f -s $(MAPLE_ROOT)/build/core/libcore.mk ./makefile; \ - $(MAKE) gen-def OPT=$(OPT) DEBUG=$(DEBUG) OPS_ANDROID=$(OPS_ANDROID) + $(MAKE) gen-def OPT=$(OPT) DEBUG=$(DEBUG) .PHONY: install install: maple dex2mpl_install irbuild hir2mpl @@ -158,6 +167,10 @@ ctorture-ci: ctorture: (cd third_party/ctorture; git checkout .; git pull; ./run.sh work.list) +.PHONY: ctorture2 +ctorture2: + (cd third_party/ctorture; git checkout .; git pull; ./run.sh work.list hir2mpl) + THREADS := 50 ifneq ($(findstring test,$(MAKECMDGOALS)),) TESTTARGET := $(MAKECMDGOALS) diff --git a/Readme.md b/Readme.md index 36f87f02582b5b8c3612d3080da5f0a8c59c0062..870f27a720326ec28ca5afd48ac9a87b4d16265f 100644 --- a/Readme.md +++ b/Readme.md @@ -38,7 +38,7 @@ Open the front end, back end, and compilation optimization of compilers. Support - source build/envsetup.sh arm release or - source build/envsetup.sh arm debug -- make setup +- make setup (In this step, you may need to configure the proxy or VPN to download all dependencies.) - make - make libcore - make testall @@ -79,4 +79,4 @@ C example: - 9:00 am - 10:30 am everyday, developers can discuss community issues in the voice channel "panel discussion" - [Discord-MapleFE](https://discord.gg/sBj3cc4GhM) -- we have weekly meeting about projects related to MapleFE \ No newline at end of file +- we have weekly meeting about projects related to MapleFE diff --git a/Readme_zh.md b/Readme_zh.md index e1eb04f06f47761671c74246c7cc94ff275111bb..a2aab5783752ad526e2a212a7374fd72ca03abbd 100644 --- a/Readme_zh.md +++ b/Readme_zh.md @@ -38,7 +38,7 @@ OpenArkCompiler是来自华为方舟编译器的开源项目。 - source build/envsetup.sh arm release 或 - source build/envsetup.sh arm debug -- make setup +- make setup (这一步可能需要配置代理或者vpn,才能将所有依赖下载下来) - make - make libcore - make testall @@ -73,4 +73,4 @@ OpenArkCompiler是来自华为方舟编译器的开源项目。 - 每天上午9:00~10:30不定时在语音频道“panel disscussion”交流社区议题。 ## 如何提交代码 -- [wiki](https://gitee.com/openarkcompiler/OpenArkCompiler/wikis/%E4%BB%A3%E7%A0%81%E6%8F%90%E4%BA%A4%E6%B5%81%E7%A8%8B?sort_id=2447213) \ No newline at end of file +- [wiki](https://gitee.com/openarkcompiler/OpenArkCompiler/wikis/%E4%BB%A3%E7%A0%81%E6%8F%90%E4%BA%A4%E6%B5%81%E7%A8%8B?sort_id=2447213) diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 81fc233d64b05293fc648a8cf990823947250c91..58f11e6829075e805ff374ef95f547f8925b25f4 100755 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -31,6 +31,9 @@ declare_args() { BUILD_VERSION = "" GIT_REVISION = "" MAST = 0 + ASAN = 0 + ONLY_C = 0 + COV = 0 } # Define global args diff --git a/build/tools/common/maplec b/build/tools/common/maplec index 673500285d33bc9876a82d75892952c0f00f6028..6d0ff340990039bb46fce6644349ed53a70d9b58 100755 --- a/build/tools/common/maplec +++ b/build/tools/common/maplec @@ -180,7 +180,7 @@ function hir2mpl() { excecute $TOOLS_BIN/clang $CLANG_FLAGS $option $src_file_path -o $file_name.ast # generate .mpl color_print "Starting hir2mpl for $src_file_path:" - excecute $MAPLE_BIN/hir2mpl $file_name.ast + excecute $MAPLE_BIN/hir2mpl $file_name.ast --enable-variable-array } function clangfe() { diff --git a/doc/cn/DeveloperGuide.md b/doc/cn/DeveloperGuide.md index c99545f42b7b02dbf8f7f1fc527d5294395d8fd6..969f52b08816f29a9a796d8852ce78f9b60395ee 100644 --- a/doc/cn/DeveloperGuide.md +++ b/doc/cn/DeveloperGuide.md @@ -27,17 +27,17 @@ make - `make` 编译OpenArkCompiler的Release版本; - `make BUILD_TYPE=DEBUG` 编译OpenArkCompiler的Debug版本。 -在openarkcompiler目录下执行以下命令,编译出OpenArkCompiler及maple runtime部分,默认输出路径 openarkcompiler/output/TYPE。 +在openarkcompiler目录下执行以下命令,编译出OpenArkCompiler及maple runtime部分,默认输出路径 openarkcompiler/output/TYPE, TYPE: aarch64-clang-release。 ``` source build/envsetup.sh arm release +make setup make libcore ``` 命令说明: - `make libcore` 编译OpenArkCompiler及maple runtime部分的Release版本; -- `make libcore OPS_ANDROID=1` 编译Android版本的OpenArkCompiler及maple runtime部分的Release版本; - `make libcore BUILD_TYPE=DEBUG` 编译OpenArkCompiler及maple runtime部分的Debug版本; 此外,方舟编译器还提供了源码编译脚本,开发者也可以通过在openarkcompiler目录下执行该脚本,默认编译出OpenArkCompiler及maple runtime部分的Release版本。执行命令如下: diff --git a/doc/en/DeveloperGuide.md b/doc/en/DeveloperGuide.md index d5ecfa04d30547db1fbea61a12d32a8a1c0a8dd2..7b604e2540d76f5c04f236e94ee23ebed3a2717e 100644 --- a/doc/en/DeveloperGuide.md +++ b/doc/en/DeveloperGuide.md @@ -17,10 +17,11 @@ You can download the OpenArkCompiler source code in `Clone` or `Download` mode. ## Compiling Source Code -Run the following command in the openarkcompiler directory to compile OpenArkCompiler. The output path is openarkcompiler/output/bin by default. +Run the following command in the openarkcompiler directory to compile OpenArkCompiler. The output path is openarkcompiler/output/TYPE/bin, TYPE: aarch64-clang-release by default. ``` source build/envsetup.sh +make setup make ``` Command description: @@ -29,6 +30,19 @@ Command description: - `make`: Compile the release version of OpenArkCompiler. - `make BUILD_TYPE=DEBUG`: Compile the debug version of OpenArkCompiler. +Run the following command in the openarkcompiler directory to compile OpenArkCompiler and maple runtime. The output path is openarkcompiler/output/TYPE, TYPE: aarch64-clang-release by default. + +``` +source build/envsetup.sh arm release +make setup +make libcore +``` + +命令说明: + +- `make libcore` Compile the release version of OpenArkCompiler; +- `make libcore BUILD_TYPE=DEBUG` Compile the debug version of OpenArkCompiler; + In addition, the OpenArkCompiler also provides a shell script which contains the command to compile OpenArkCompiler. The developer can run the script in the openarkcompiler directory to compile OpenArkCompiler. The command to run the script: ``` diff --git a/doc/en/TargetConstants.md b/doc/en/TargetConstants.md new file mode 100644 index 0000000000000000000000000000000000000000..4be1770113c4d96ab7d45d7cfd760b8b9abe2c07 --- /dev/null +++ b/doc/en/TargetConstants.md @@ -0,0 +1,136 @@ +### Introduction +This document describes the way to work with target constants in maple IR. +It's very important to distinguish `host` constants from the `target` ones. +`Host` constants represent values on the machine where the compiler runs. +`Target` constants represent values that will be present in the target code generated by the compiler. +So, in the common case there is no one-to-one mapping between `host` constants and `target` ones. +For example, a host machine has `one's complement` representation for integers, but the `target` machine +has `two's complement` integers representation. Or more realistic case when the target machine supports `int128_t` and can +hold 128-bit constants directly, but the `host` machine does not. +So, we need to find a safe and convenient way how to represent and operate on the `target` constants in maple IR +while compiling a user program. + +### Working with constants in maple IR +Let's show how to work with constants on `Constant Folding` optimization as an example. +Consider the following Maple IR: +``` +func &foo static used () i8 { + return (add i8 (constval i8 1, constval i8 2)) +} +``` +we want to fold this `add` to perform calculation at compile time. +We could do something like this: +```c++ +MIRConst *ConstantFold::FoldIntConstBinaryMIRConst(Opcode opcode, PrimType resultType, + const MIRIntConst *intConst0, + const MIRIntConst *intConst1) const { + int64 intValueOfConst0 = intConst0->GetValue(); + int64 intValueOfConst1 = intConst1->GetValue(); + + uint64 result64 = 0; + uint32 result32 = 0; + uint16 result16 = 0; + uint8 result8 = 0; + + bool useResult64 = (GetPrimTypeSize(resultType) == 8); + bool useResult32 = (GetPrimTypeSize(resultType) == 4); + bool useResult16 = (GetPrimTypeSize(resultType) == 2); + bool useResult8 = (GetPrimTypeSize(resultType) == 1); + + switch (opcode) { + case OP_add: { + if (useResult64) { + result64 = static_cast(intValueOfConst0) + static_cast(intValueOfConst1); + } else if (useResult32) { + result32 = static_cast(intValueOfConst0) + static_cast(intValueOfConst1); + } else if (useResult16) { + result16 = static_cast(intValueOfConst0) + static_cast(intValueOfConst1); + } else if (useResult8) { + result8 = static_cast(intValueOfConst0) + static_cast(intValueOfConst1); + } + break; + } + ... +``` +As can be seen, there is a lot of boilerplate code depending on the type size of the result of operation. +In a more general case, the sign of the result type is also has to be taken into account, doubling the code size (e.g. div) +Also, if we manipulate with 128-bit types it's possible that there is no `int128_t` type on the host machine and in this +case we need to perform such calculation manually. For example, we need to hold the value in two `int64_t` variables. +So, we need to be able to work with target constants in a safe and convenient way. To achieve this goal we can use +a special class that's called `IntVal`. It provides a convenient interface for manipulation with target constants. +For example, the above case can be managed as follows: +```c++ +MIRConst *ConstantFold::FoldIntConstBinaryMIRConst(Opcode opcode, PrimType resultType, + const MIRIntConst *intConst0, + const MIRIntConst *intConst1) const { + IntVal intVal0 = intConst0->GetValue(); + IntVal intVal1 = intConst1->GetValue(); + + IntVal result(0, resultType); + + switch (opcode) { + case OP_add: { + result = intVal0.Add(intVal1, resultType); + // or + // result = intVal0 + intVal1; + // if resultType is equal to type of operands + break; + } + ... +``` +Let's take a look at `IntVal` class in more detail. + +##### The IntVal class +This class represents a target integer constant in `two's complement` representation. +It's able to hold signed and unsigned integers with arbitrary bit-width (currently, no more than 64 bits. 128-bit support is in progress) +that can be created using the following constructors: +```c++ +/// Creates IntVal object from uint64 value with bit-width defined by bitWidth parameter +/// and interpreted as signed value if isSigned parameter is true +IntVal(uint64 val, uint8 bitWidth, bool isSigned); + +/// The same as above, but bit-width and signedness are obtained from the given PrimType +IntVal(uint64 val, PrimType type); +``` +Also, this class provides an interface to perform arithmetic, bitwise, comparison and other operations on the target constants. +For example: +```c++ +/// perform an addition: *this + val. Bit-width and signedness of values must be the same +IntVal operator+(const IntVal &val) const; + +/// the same as above, but performs '+' in terms of the given integer PrimType +IntVal Add(const IntVal &val, PrimType pType) const; + +/// perform a binary 'and': *this & val. Bit-width and signedness of values must be the same +IntVal operator&(const IntVal &val) const; + +/// the same as above, but performs '&' in terms of the given integer PrimType +IntVal And(const IntVal &val, PrimType pType) const; + +/// perform a comparison: *this < val. Bit-width and signedness of values must be the same +bool operator<(const IntVal &rhs) const; + +/// the same as above, but performs '<' in terms of the given integer PrimType +bool Less(const IntVal &rhs, PrimType pType) const; +``` + +There are `Extend`, `Trunc` and `TruncOrExtend` functions that allow truncating or extending (zero or sign extension) +depending on the given integer PrimType. These functions return new `IntVal` object that has bit-width and sign obtained +from the given PrimType and has a value obtained from the original value by truncation or extension (zero of sign). +```c++ +IntVal TruncOrExtend(PrimType newType) cosnt; +IntVal Extend(PrimType newType) cosnt; +IntVal Trunc(PrimType newType) cosnt; +``` +It's possible to get a host constant from the target one (in case the value can fit into the host constant) using the following +interfaces: +```c++ +/// perform zero extension of the value +uint64 GetZXTValue(uint8 size = 0) const; + +/// perform sign extension of the value +int64 GetSXTValue(uint8 size = 0) const; + +/// perform sign or zero extension of the value depending on its sign +int64 GetExtValue(uint8 size = 0) const; +``` diff --git a/src/MapleFE/.gitignore b/src/MapleFE/.gitignore index 46890e54e45d66060ba85adb278ca197da8524d8..533695ff01a419af9567d36b8d2cf41970296906 100644 --- a/src/MapleFE/.gitignore +++ b/src/MapleFE/.gitignore @@ -10,6 +10,7 @@ output/ *.png *.out.ts *.ts.ast +*.java.ast gdbfile test/typescript/**/*.cpp test/typescript/**/*.h diff --git a/src/MapleFE/Makefile b/src/MapleFE/Makefile index a0d1730fdc576a8dff4cb459cd068a3ad16241a1..f1dbcac61dd5bed54e947fda4a6c6be58a2144c1 100644 --- a/src/MapleFE/Makefile +++ b/src/MapleFE/Makefile @@ -14,7 +14,7 @@ include Makefile.in -TARGS = autogen shared recdetect ladetect astopt java2mpl ast2mpl ts2ast ast2cpp c2ast +TARGS = autogen shared recdetect ladetect astopt java2mpl ast2mpl ts2ast ast2cpp c2ast obfuscate # create BUILDDIR first $(shell $(MKDIR_P) $(BUILDDIR)) @@ -22,7 +22,7 @@ $(shell $(MKDIR_P) $(BUILDDIR)) ifeq ($(SRCLANG),java) TARGET := java2ast ast2mpl else ifeq ($(SRCLANG),typescript) - TARGET := ts2ast ast2cpp + TARGET := ts2ast ast2cpp obfuscate else ifeq ($(SRCLANG),c) TARGET := c2ast endif @@ -53,6 +53,9 @@ astopt: shared recdetect ladetect ast2cpp: astopt ts2ast $(MAKE) -C ast2cpp +obfuscate: astopt ts2ast ast2cpp + $(MAKE) -C tools/obfuscate + shared: autogen $(MAKE) -C shared diff --git a/src/MapleFE/ast2cpp/include/cpp_declaration.h b/src/MapleFE/ast2cpp/include/cpp_declaration.h index fcf6b61c323171b9e610b6907c739231132cc512..352a0006bc51c858d06c97b5bd1a24562cb4e327 100644 --- a/src/MapleFE/ast2cpp/include/cpp_declaration.h +++ b/src/MapleFE/ast2cpp/include/cpp_declaration.h @@ -36,8 +36,6 @@ public: return EmitTreeNode(GetASTModule()); } - std::string GenFunctionClass(FunctionNode* node); - void AddImportedModule(const std::string& module); bool IsImportedModule(const std::string& module); @@ -60,7 +58,6 @@ public: std::string EmitCallNode(CallNode *node) override; std::string EmitFunctionNode(FunctionNode *node) override; std::string EmitPrimTypeNode(PrimTypeNode *node) override; - std::string EmitPrimArrayTypeNode(PrimArrayTypeNode *node) override; std::string EmitModuleNode(ModuleNode *node) override; std::string EmitClassNode(ClassNode *node) override; @@ -71,13 +68,15 @@ public: std::string EmitStructNode(StructNode *node) override; std::string EmitTypeAliasNode(TypeAliasNode* node) override; std::string EmitLiteralNode(LiteralNode* node) override; + std::string EmitArrayTypeNode(ArrayTypeNode *node) override; std::string GetTypeString(TreeNode *node, TreeNode *child = nullptr); - std::string EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::string type); std::string EmitTSEnum(StructNode *node); std::string EmitInterface(StructNode *node); void CollectFuncArgInfo(TreeNode* node); + std::string ConstructArray(ArrayLiteralNode* node, int dim, std::string type); + std::string ConstructArrayAny(ArrayLiteralNode* node); }; inline bool IsVarInitStructLiteral(DeclNode* node) { @@ -92,8 +91,6 @@ inline bool IsVarInitClass(DeclNode* node) { node->GetInit()->IsIdentifier(); } -bool IsBuiltinObj(std::string name); - template bool HasAttrStatic(T* node) { for (unsigned i = 0; i < node->GetAttrsNum(); ++i) { diff --git a/src/MapleFE/ast2cpp/include/cpp_definition.h b/src/MapleFE/ast2cpp/include/cpp_definition.h index 07dfec249ed6cc74b436aac3a7d428f40a6bcd12..ab4c1b077356d1a8b6d1ac7f80797a6e58a25583 100644 --- a/src/MapleFE/ast2cpp/include/cpp_definition.h +++ b/src/MapleFE/ast2cpp/include/cpp_definition.h @@ -26,8 +26,9 @@ class CppDef : public CppEmitter { public: CppDecl &mCppDecl; bool mIsInit; + bool mIsGenerator; - CppDef(Module_Handler *h, CppDecl &d) : CppEmitter(h), mCppDecl(d), mIsInit(false) {} + CppDef(Module_Handler *h, CppDecl &d) : CppEmitter(h), mCppDecl(d), mIsInit(false), mIsGenerator(false) {} std::string Emit() { return EmitTreeNode(GetASTModule()); @@ -64,24 +65,26 @@ public: std::string EmitAsTypeNode(AsTypeNode *node) override; std::string EmitNamespaceNode(NamespaceNode *node) override; std::string EmitRegExprNode(RegExprNode *node); + std::string EmitStructNode(StructNode *node) override; + std::string EmitStructLiteralNode(StructLiteralNode* node) override; + std::string EmitWhileLoopNode(WhileLoopNode *node) override; + std::string EmitYieldNode(YieldNode *node) override; std::string& HandleTreeNode(std::string &str, TreeNode *node) override; std::string EmitClassProps(TreeNode *node); std::string EmitFuncScopeVarDecls(FunctionNode *node); - std::string EmitStructNode(StructNode *node); - std::string EmitStructLiteralNode(StructLiteralNode* node); std::string EmitCppCtor(ClassNode* node); std::string EmitCtorInstance(ClassNode *c); std::string EmitDefaultCtor(ClassNode *c); std::string EmitBracketNotationProp(ArrayElementNode* ae, OprId binOpId, bool isLhs, bool& isDynProp); - std::string EmitArrayLiteral(TreeNode* arrType, TreeNode* arrLiteral); - std::string EmitArrayLiterals(TreeNode* arrLiteral, int dim, std::string type); TypeId GetTypeIdFromDecl(TreeNode* id); bool IsClassField(ArrayElementNode* node, std::string propKey); std::string GetTypeForTemplateArg(TreeNode* node); TreeNode* FindDeclType(TreeNode* node); std::string GetThisParamObjType(TreeNode *node); - std::string GenArrayOfAny(TreeNode* node); + + std::string ConstructArray(ArrayLiteralNode* node, int dim, std::string type); + std::string ConstructArrayAny(ArrayLiteralNode* node); std::string GenObjectLiteral(TreeNode* var, std::string varName, TreeNode* idType, StructLiteralNode* n); std::string GenDirectFieldInit(std::string varName, StructLiteralNode* node); }; diff --git a/src/MapleFE/ast2cpp/include/cpp_emitter.h b/src/MapleFE/ast2cpp/include/cpp_emitter.h index 74d81734fdf2746d8b6853074ccabc0cf39d7ef1..ec2f269dba259ae718c2db3d18ca98b74b05c500 100644 --- a/src/MapleFE/ast2cpp/include/cpp_emitter.h +++ b/src/MapleFE/ast2cpp/include/cpp_emitter.h @@ -34,6 +34,11 @@ public: bool IsClassId(TreeNode *node); bool IsVarTypeClass(TreeNode* var); void InsertEscapes(std::string& str); + bool IsGenerator(TreeNode *node); + FunctionNode* GetGeneratorFunc(TreeNode *node); + void GetArrayTypeInfo(ArrayLiteralNode* node, int& numDim, std::string& type); + std::string FunctionHeader(FunctionNode* node, std::string retType); + std::string GetClassName(TreeNode* node); }; } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/include/emitter.h b/src/MapleFE/ast2cpp/include/emitter.h index 7ad2b1e895eccb8911887cf04aa5a5431ea06007..f8447db75616fe3886cdee9d83e863082a074955 100644 --- a/src/MapleFE/ast2cpp/include/emitter.h +++ b/src/MapleFE/ast2cpp/include/emitter.h @@ -120,11 +120,13 @@ public: virtual std::string EmitAwaitNode(AwaitNode *node); virtual std::string EmitNameTypePairNode(NameTypePairNode *node); virtual std::string EmitTupleTypeNode(TupleTypeNode *node); + virtual std::string EmitTripleSlashNode(TripleSlashNode *node); virtual std::string EmitModuleNode(ModuleNode *node); virtual std::string EmitAttrNode(AttrNode *node); + virtual std::string EmitArrayTypeNode(ArrayTypeNode *node); + virtual std::string EmitFunctionTypeNode(FunctionTypeNode *node); virtual std::string EmitPrimTypeNode(PrimTypeNode *node); virtual std::string EmitPrimArrayTypeNode(PrimArrayTypeNode *node); - virtual std::string EmitArrayTypeNode(ArrayTypeNode *node); virtual std::string EmitTreeNode(TreeNode *node); virtual std::string& HandleTreeNode(std::string &str, TreeNode *node); @@ -141,6 +143,7 @@ public: //static const char *GetEnumStructProp(StructProp k); //static const char *GetEnumForLoopProp(ForLoopProp k); //static const char *GetEnumLambdaProperty(LambdaProperty k); + const char *GetEnumTripleSlashProp(TripleSlashProp k); std::string &AddParentheses(std::string &str, TreeNode *node); }; diff --git a/src/MapleFE/ast2cpp/include/helper.h b/src/MapleFE/ast2cpp/include/helper.h index 297d57f4070a956300db59c14899edab68cef580..0eb8e89843ecb23e65507e68955a116bbc319deb 100644 --- a/src/MapleFE/ast2cpp/include/helper.h +++ b/src/MapleFE/ast2cpp/include/helper.h @@ -29,13 +29,16 @@ using namespace std::string_literals; namespace maplefe { +extern std::string GeneratorFn_start; +extern std::string GeneratorFn_return; extern std::unordered_mapTypeIdToJSType; extern std::unordered_mapTypeIdToJSTypeCXX; extern TypeId hlpGetTypeId(TreeNode* node); extern std::string GenClassFldAddProp(std::string, std::string, std::string, std::string, std::string); -extern std::string FunctionTemplate(std::string retType, std::string funcName, std::string params, std::string args); -extern std::string GenGeneratorClass(std::string funcName, std::vector>args); +extern std::string FunctionClassDecl(std::string retType, std::string funcName, unsigned nodeId); +extern std::string GeneratorClassDecl(std::string funcName, unsigned nodeId); +extern std::string GeneratorClassDef(std::string ns, std::string funcName, unsigned nodeId); extern std::string tab(int n); extern bool IsClassMethod(TreeNode* node); extern std::string GetClassOfAssignedFunc(TreeNode* node); @@ -43,9 +46,31 @@ extern std::string GenAnonFuncName(TreeNode* node); inline std::string ClsName(std::string func) { return "Cls_"s + func; } inline std::string GeneratorName(std::string func) { return "Generator_"s + func; } inline std::string GeneratorFuncName(std::string func) { return "GeneratorFunc_"s + func; } -extern void HandleThisParam(unsigned nParams, TreeNode* node, std::string& params, std::string&args); extern std::string hlpGetJSValTypeStr(TypeId typeId); extern std::string ArrayCtorName(int dim, std::string type); +extern bool IsBuiltinObj(std::string name); +extern std::string ObjectTypeStr(std::string name); +extern std::string GeneratorFuncHeader(std::string cls, unsigned nodeId); +extern std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly = false, bool byRef = false, bool fdInit = false, bool capture = false); + +class GeneratorLabels { +private: + unsigned GenLoopId = 0; + unsigned GenYieldId= 0; +public: + std::string NextLoopLabel(void) { + std::string label = "_loop_" + std::to_string(++GenLoopId); + return label; + } + std::string NextYieldLabel(void) { + std::string label = "_yield_" + std::to_string(++GenYieldId); + return label; + } + void ResetLabels(void) { + GenLoopId = 0; + GenYieldId = 0; + } +}; class FuncTable { private: @@ -111,6 +136,7 @@ public: }; extern FuncTable hFuncTable; +extern GeneratorLabels GenFnLabels; } #endif // __HELPER_H__ diff --git a/src/MapleFE/ast2cpp/runtime/include/builtins.h b/src/MapleFE/ast2cpp/runtime/include/builtins.h index 8acac0e030cdd30ce4605930dec3629cac8ddc83..af0fe8f50dd34f39cf5912d7ed54593be4ce5748 100644 --- a/src/MapleFE/ast2cpp/runtime/include/builtins.h +++ b/src/MapleFE/ast2cpp/runtime/include/builtins.h @@ -133,12 +133,15 @@ class Error : public Object { // ecma-262 section references are based on ecma-262 edition 12.0 // ecma262 27.1.1.5 IteratorResult interface: -struct IteratorResult { - bool _done; // status of iterator next() call - JS_Val _value; // done=false: current iteration element value - // done=true: return value of the iterator, undefined if none returned - IteratorResult() : _done(true), _value(undefined) { } - IteratorResult(bool done, JS_Val val) : _done(done), _value(val) { } +struct IteratorResult : public Object { + bool done; // status of iterator next() call + JS_Val value; // done=false: current iteration element value + // done=true: return value of the iterator, undefined if none returned + IteratorResult() : done(true), value(undefined) { + this->AddProp("done", t2crt::ClassFld(&IteratorResult::done).NewProp(this, t2crt::TY_CXX_Bool)); + this->AddProp("value", t2crt::ClassFld(&IteratorResult::value).NewProp(this, t2crt::TY_CXX_Any)); + } + IteratorResult(bool done, JS_Val val) : done(done), value(val) { } ~IteratorResult() { } }; @@ -159,12 +162,13 @@ struct IteratorResult { // 3) %IteratorPrototype%[Symbol.iterator]() = this (current iterator instance) - used in for loops class IteratorProto : public Object { public: + IteratorResult _res; IteratorProto(Function* ctor, Object* proto) : Object(ctor, proto) { } ~IteratorProto() { } // note: the arg on an iterator's 1st next() call is ignored per spec 27.5.1.2 - virtual IteratorResult _next (JS_Val* arg = nullptr) { return IteratorResult(); } - virtual IteratorResult _return(JS_Val* val = nullptr) { return IteratorResult(); } - virtual IteratorResult _throw(Error exception) { return IteratorResult(); } + virtual IteratorResult* next (JS_Val* arg = nullptr) { return &_res; } + virtual IteratorResult* _return(JS_Val* val = nullptr) { return &_res; } + virtual IteratorResult* _throw(Error exception) { return &_res; } // TODO: %IteratorPrototype%[Symbol.iterator]() = this (current iterator instance) }; @@ -182,13 +186,12 @@ public: bool _finished = false; // flag if generator is in finished state bool _firstNext = true; // flag if first next has been called on iterator (27.5.1.2) - IteratorResult _return(JS_Val* arg = nullptr) override { - IteratorResult res; + IteratorResult* _return(JS_Val* arg = nullptr) override { _finished = true; if (arg != nullptr) { - res._value = *arg; + _res.value = *arg; } - return res; + return &_res; } }; diff --git a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h index c94ea6fd2d282526fd2e10f8fea0dde29a300334..cdf48d2d55cc3ac65f17f6585192b2efbcd8fb25 100644 --- a/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h +++ b/src/MapleFE/ast2cpp/runtime/include/ts2cpp.h @@ -52,6 +52,7 @@ typedef enum JS_Type : uint8_t { TY_Function, // "function" TY_Object, // "object" TY_Array, + TY_Any, // JS_Val::x.field points to a JS_Val TY_LAST, TY_CXX_Undef = TY_Undef | TY_CXX, TY_CXX_Null, @@ -64,7 +65,7 @@ typedef enum JS_Type : uint8_t { TY_CXX_Function, TY_CXX_Object, TY_CXX_Array, - TY_CXX_Any, //indicate JS_Val::x.field pointing to a JS_Val + TY_CXX_Any, // JS_Val::x.field points to a JS_Val TY_CXX_LAST, } JS_Type; diff --git a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp index dc0177419dadae333d0bdc07177ff59f42d093d4..50fecb38bc70c6b4c71e517d5bf98f7392e4178e 100644 --- a/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp +++ b/src/MapleFE/ast2cpp/runtime/src/ts2cpp.cpp @@ -16,6 +16,7 @@ std::ostream& operator<< (std::ostream& out, const t2crt::JS_Val& v) { case t2crt::TY_Symbol: out << "symbol"; break; case t2crt::TY_Function: out << "function"; break; case t2crt::TY_Object: out << v.x.val_obj; break; + case t2crt::TY_Any: out << *(t2crt::JS_Val*)v.x.field; break; case t2crt::TY_CXX_Undef: out << "undefined"; break; case t2crt::TY_CXX_Null: out << "null"; break; @@ -27,11 +28,14 @@ std::ostream& operator<< (std::ostream& out, const t2crt::JS_Val& v) { case t2crt::TY_CXX_Symbol: out << "symbol"; break; case t2crt::TY_CXX_Function: out << "function"; break; case t2crt::TY_CXX_Object: out << *(Object**)v.x.field; break; + case t2crt::TY_CXX_Any: out << *(t2crt::JS_Val*)v.x.field; break; } return out; } std::ostream& operator<< (std::ostream& out, t2crt::Object *obj) { + if (obj == nullptr) + return out; out << obj->Dump(); return out; } diff --git a/src/MapleFE/ast2cpp/src/Makefile b/src/MapleFE/ast2cpp/src/Makefile index 32bb62fbc396ac746d0bc80f8b53c2182d27d328..084bcad114a3f5728966433d2aaf28c3569731ba 100644 --- a/src/MapleFE/ast2cpp/src/Makefile +++ b/src/MapleFE/ast2cpp/src/Makefile @@ -27,10 +27,12 @@ SRCG := $(wildcard $(BUILDGEN)/gen*.cpp) OBJG := $(patsubst %.cpp, %.o, $(SRCG)) DEPG := $(patsubst %.cpp, %.d, $(SRCG)) -OBJS :=$(foreach obj,$(OBJ), $(BUILD)/$(obj)) $(OBJG) -DEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) $(DEPG) +LOCALOBJS :=$(foreach obj,$(OBJ), $(BUILD)/$(obj)) +LOCALDEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) +OBJS :=$(LOCALOBJS) $(OBJG) +DEPS :=$(LOCALDEPS) $(DEPG) -LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(OBJS)) +LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(LOCALOBJS)) GENDIR:=${BUILDDIR}/ast_gen/shared @@ -45,6 +47,8 @@ INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ INCLUDEGEN := -I $(MAPLEFE_ROOT)/shared/include -I $(BUILDDIR)/gen -I $(BUILDASTGEN) TARGET=ast2cpp +TARGET_A=ast2cpp.a + SHAREDLIB = $(BUILDDIR)/astopt/astopt.a $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a LANGSPEC=$(BUILDDIR)/typescript/lang_spec.o @@ -78,9 +82,12 @@ $(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) +$(BUILD)/$(TARGET_A): $(LIBOBJS) + /usr/bin/ar rcs $(BUILD)/$(TARGET_A) $(LIBOBJS) + +$(BUILDBIN)/$(TARGET): $(BUILD)/$(TARGET_A) $(OBJS) $(SHAREDLIB) @mkdir -p $(BUILDBIN) - $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(LANGSPEC) $(SHAREDLIB) + $(LD) -o $(BUILDBIN)/$(TARGET) $(BUILD)/main.o $(BUILD)/$(TARGET_A) $(OBJG) $(LANGSPEC) $(SHAREDLIB) clean: rm -rf $(BUILD) diff --git a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp index 96a1e654b0ad4ce3770cbe39f3821cb78f2548cd..315c8624b6a528f0959b5770b4a3d2642a03470b 100644 --- a/src/MapleFE/ast2cpp/src/cpp_declaration.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_declaration.cpp @@ -327,28 +327,6 @@ bool CppDecl::IsImportedModule(const std::string& module) { return res != mImportedModules.end(); } -// Generate class to encap TS/JS required func interfaces -// note: for top level and nested functions only. Not for class methods. -std::string CppDecl::GenFunctionClass(FunctionNode* node) { - std::string params, args, retType; - for (unsigned i = 0; i < node->GetParamsNum(); ++i) { - if (i) { - params += ", "s; - args += ", "s; - } - if (auto n = node->GetParam(i)) { - params += EmitTreeNode(n); - args += GetIdentifierName(n); - if (i==0) - HandleThisParam(node->GetParamsNum(), n, params, args); - } - } - if (node->GetParamsNum() == 0) - HandleThisParam(0, nullptr, params, args); - - return FunctionTemplate(GetTypeString(node->GetType(), nullptr), GetIdentifierName(node), params, args); -} - void CppDecl::CollectFuncArgInfo(TreeNode* node) { if (!node->IsFunction()) return; @@ -403,26 +381,34 @@ namespace )""" + module + R"""( { for(unsigned i = 0; i < num; ++i) { CfgFunc *func = mod->GetNestedFuncAtIndex(i); TreeNode *node = func->GetFuncNode(); + std::string funcName = GetIdentifierName(node); + + CollectFuncArgInfo(node); if (!IsClassMethod(node)) { - bool isGenerator = static_cast(node)->IsGenerator(); - CollectFuncArgInfo(node); std::string ns = GetNamespace(node); if (!ns.empty()) str += "namespace "s + ns + " {\n"s; - if (isGenerator) - str += GenGeneratorClass(GetIdentifierName(node), hFuncTable.GetArgInfo(node->GetNodeId())); - else - str += GenFunctionClass(static_cast(node)); // gen func cls for each top level func + bool isGenerator = static_cast(node)->IsGenerator(); + std::string generatorClassDef; + if (isGenerator) { + str += GeneratorClassDecl(funcName, node->GetNodeId()); + generatorClassDef = GeneratorClassDef(ns, funcName, node->GetNodeId()); + AddDefinition(generatorClassDef); + } + else { + // gen function class for each top level function + str += FunctionClassDecl(GetTypeString(static_cast(node)->GetRetType(), nullptr), GetIdentifierName(node), node->GetNodeId()); + } if (!mHandler->IsFromLambda(node)) { // top level funcs instantiated here as function objects from their func class // top level lamda funcs instantiated later in assignment stmts - std::string typeName = isGenerator? GeneratorFuncName(node->GetName()): ClsName(node->GetName()); - std::string funcinit = typeName + "* "s + node->GetName() + " = new "s + typeName + "();\n"s; + std::string typeName = isGenerator? GeneratorFuncName(funcName): ClsName(funcName); + std::string funcinit = typeName + "* "s + funcName + " = new "s + typeName + "();\n"s; if (ns.empty()) AddDefinition(funcinit); else AddDefinition("namespace "s + ns + " {\n"s + funcinit + "\n}\n"s); - str += "extern "s + typeName + "* "s + node->GetName() + ";\n"s; + str += "extern "s + typeName + "* "s + funcName + ";\n"s; } if (!ns.empty()) str += "\n} // namespace " + ns + '\n'; @@ -455,7 +441,7 @@ namespace )""" + module + R"""( { std::string CppDecl::EmitFunctionNode(FunctionNode *node) { if (node == nullptr) return std::string(); - std::string str(GetTypeString(node->GetType(), node->GetType())); + std::string str(GetTypeString(node->GetRetType(), node->GetRetType())); if(node->GetStrIdx()) str += " "s + node->GetName(); str += "("s; @@ -527,6 +513,11 @@ std::string CppDecl::EmitIdentifierNode(IdentifierNode *node) { if (HasAttrStatic(node)) str = "static "s + str; + else if (auto n = node->GetInit()) { + // emit init for non static class field + if (node->GetParent() && node->GetParent()->IsClass()) + str += " = "s + EmitTreeNode(n); + } return str; } @@ -571,25 +562,36 @@ std::string CppDecl::EmitAssertNode(AssertNode *node) { return std::string(); } -std::string CppDecl::EmitArrayLiteralNode(ArrayLiteralNode *node) { - if (node == nullptr) +// Generate code to construct an array of type any from an ArrayLiteral. TODO: merge with similar in cppdef +std::string CppDecl::ConstructArrayAny(ArrayLiteralNode *node) { + if (node == nullptr || !node->IsArrayLiteral()) return std::string(); - std::string str("{"s); + + // Generate array ctor call to instantiate array + std::string literals; for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) - str += ", "s; + literals += ", "s; if (auto n = node->GetLiteral(i)) { - str += EmitTreeNode(n); + if (n->IsArrayLiteral()) + // Recurse to handle array elements that are arrays + literals += ConstructArrayAny(static_cast(n)); + else { + // Wrap element in JS_Val. C++ class constructor of JS_Val + // will set tupe tag in JS_Val according to element type. + literals += "t2crt::JS_Val("s + EmitTreeNode(n) + ")"s; + } } } - str += "}"s; + std::string str = ArrayCtorName(1, "t2crt::JS_Val") + "._new({"s + literals + "})"s; return str; } -std::string CppDecl::EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::string type) { - if (node == nullptr) - return std::string(); - +// Generate code to construct an array object with brace-enclosed initializer list TODO: merge with similar in cppdef +std::string CppDecl::ConstructArray(ArrayLiteralNode *node, int dim, std::string type) { + if (type.empty()) { + return ConstructArrayAny(node); // proceed as array of type any if no type info + } // Generate array ctor call to instantiate array std::string str = ArrayCtorName(dim, type) + "._new({"s; for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { @@ -597,7 +599,7 @@ std::string CppDecl::EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::stri str += ", "s; if (auto n = node->GetLiteral(i)) { if (n->IsArrayLiteral()) - str += EmitArrayLiteral(static_cast(n), dim-1, type); + str += ConstructArray(static_cast(n), dim-1, type); else str += EmitTreeNode(n); } @@ -606,7 +608,35 @@ std::string CppDecl::EmitArrayLiteral(ArrayLiteralNode *node, int dim, std::stri return str; } -std::string GetArrayTypeString(int dim, std::string typeStr) { +std::string CppDecl::EmitArrayLiteralNode(ArrayLiteralNode *node) { // TODO: merge with similar in cppdef + if (node == nullptr) + return std::string(); + if (node->GetParent() && + node->GetParent()->IsDecl() || // for var decl init + node->GetParent()->IsIdentifier() || // for default val init in class field decl + node->GetParent()->IsFieldLiteral()) { // for obj decl with struct literal init + // emit code to construct array object with brace-enclosed initializer list + int dim; + std::string str, type; + GetArrayTypeInfo(node, dim, type); + str = ConstructArray(node, dim, type); + return str; + } + + // emit code to build a brace-enclosed intializer list (for rhs of array var assignment op) + std::string str("{"s); + for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { + if (i) + str += ", "s; + if (auto n = node->GetLiteral(i)) { + str += EmitTreeNode(n); + } + } + str += "}"s; + return str; +} + +std::string BuildArrayType(int dim, std::string typeStr) { std::string str; str = "t2crt::Array<"s + typeStr + ">*"s;; for (unsigned i = 1; i < dim; ++i) { @@ -615,20 +645,16 @@ std::string GetArrayTypeString(int dim, std::string typeStr) { return str; } -std::string CppDecl::EmitPrimArrayTypeNode(PrimArrayTypeNode *node) { +std::string CppDecl::EmitArrayTypeNode(ArrayTypeNode *node) { if (node == nullptr) return std::string(); std::string str; - if (node->GetPrim() && node->GetDims()) { - str = GetArrayTypeString( - static_cast(node->GetDims())->GetDimensionsNum(), - EmitPrimTypeNode(node->GetPrim())); - } - /* - if (auto n = node->GetDims()) { - str += EmitDimensionNode(n); + + if (node->GetElemType() && node->GetDims()) { + str = BuildArrayType( + node->GetDims()->GetDimensionsNum(), + EmitTreeNode(node->GetElemType())); } - */ return str; } @@ -636,27 +662,13 @@ std::string CppDecl::EmitFieldNode(FieldNode *node) { return std::string(); } -// note: entries below are to match values from ast nodes. Do not prepend with "t2crt::" -std::vectorbuiltins = {"Object", "Function", "Number", "Array", "Record"}; - -bool IsBuiltinObj(std::string name) { - return std::find(builtins.begin(), builtins.end(), name) != builtins.end(); -} - -std::string GetUserTypeString(UserTypeNode* n) { - std::string str=""; - if (n->GetId()->IsTypeIdClass()) - str = n->GetId()->GetName() + "*"s; - else if (IsBuiltinObj(n->GetId()->GetName())) - str = "t2crt::"s + n->GetId()->GetName() + "*"s; - else // TypeAlias Id - str = n->GetId()->GetName(); - return str; -} - std::string CppDecl::GetTypeString(TreeNode *node, TreeNode *child) { std::string str; if (node) { + if (IsGenerator(node)) { // check generator type + if (auto func = GetGeneratorFunc(node)) + return GeneratorName(GetIdentifierName(func)) + "*"s; + } TypeId k = node->GetTypeId(); if (k == TY_None || k == TY_Class) { switch(node->GetKind()) { @@ -706,11 +718,6 @@ std::string CppDecl::GetTypeString(TreeNode *node, TreeNode *child) { if (str != "none"s) return str + " "s; } - if (mHandler->IsGeneratorUsed(node->GetNodeId())) { - // check if generator type - if (auto func = mHandler->GetGeneratorUsed(node->GetNodeId())) - return GeneratorName(GetIdentifierName(func)) + "*"s; - } } return "t2crt::JS_Val "s; } @@ -727,18 +734,20 @@ std::string CppDecl::EmitUserTypeNode(UserTypeNode *node) { std::string str, usrType; if (auto n = node->GetId()) { - if (n->IsTypeIdClass()) - usrType = n->GetName() + "*"s; + if (n->IsTypeIdClass()) { + if (mHandler->IsGeneratorUsed(n->GetNodeId())) { + // Check if a generator type : TODO: this needs TI + auto func = mHandler->GetGeneratorUsed(n->GetNodeId()); + usrType = GetIdentifierName(func) + "*"s; + } else + usrType = n->GetName() + "*"s; + } else if (IsBuiltinObj(n->GetName())) usrType = "t2crt::"s + n->GetName() + "*"s; else // TypeAlias Id gets returned here usrType = n->GetName(); - if (node->GetDims()) { - return GetArrayTypeString(node->GetDims()->GetDimensionsNum(), usrType); - } else { - str = usrType; - } + str = usrType; // note: array dimension now come from ArrayTypeNode auto num = node->GetTypeGenericsNum(); if(num) { std::string lastChar = ""; @@ -796,26 +805,13 @@ std::string CppDecl::EmitClassNode(ClassNode *node) { // class field decl and init. TODO: handle private, protected attrs. for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { auto n = node->GetField(i); - if (n->IsIdentifier() && GetIdentifierName(n).compare("private")==0) - continue; str += " "s + EmitTreeNode(n); if (n->IsIdentifier()) { - IdentifierNode* id = static_cast(n); - if (HasAttrStatic(id)) { + if (HasAttrStatic(static_cast(n))) { // static field - add field to ctor prop and init later at field def in cpp staticProps += tab(3) + "this->AddProp(\""s + clsName + "\", t2crt::JS_Val("s + - TypeIdToJSTypeCXX[n->GetTypeId()] + ", &"s + clsName + "::"s + id->GetName() + "));\n"s; - } else if (auto init = id->GetInit()) { - if (init->IsArrayLiteral() && id->GetType() && id->GetType()->IsPrimArrayType()) { - // Generate initializer for t2crt::Array member field decl in header file - PrimArrayTypeNode* mtype = static_cast(id->GetType()); - str += " = "s + EmitArrayLiteral(static_cast(init), - mtype->GetDims()->GetDimensionsNum(), - EmitPrimTypeNode(mtype->GetPrim())); - } else { - str += " = "s + EmitTreeNode(init); - } + TypeIdToJSTypeCXX[n->GetTypeId()] + ", &"s + clsName + "::"s + GetIdentifierName(n) + "));\n"s; } } str += ";\n"; @@ -906,11 +902,8 @@ std::string CppDecl::EmitInterface(StructNode *node) { if (superClass.back() == '*') superClass.pop_back(); } - - if (auto n = node->GetStructId()) { - ifName = GetIdentifierName(n); - str = "class "s + ifName + " : public "s + superClass + " {\n"s; - } + ifName = GetIdentifierName(node); + str = "class "s + ifName + " : public "s + superClass + " {\n"s; str += " public:\n"s; // Generate code to add prop in class constructor @@ -1124,17 +1117,7 @@ std::string CppDecl::EmitLiteralNode(LiteralNode *node) { mPrecedence = '\030'; str = HandleTreeNode(str, node); if (auto n = node->GetType()) { - if (str.compare("this") == 0) { - // handle special literal "this" - std::string type = EmitTreeNode(n); - if (type.compare("t2crt::JS_Val ") == 0) - // map type ANY for "this" to generic object type - str = "t2crt::Object* "s + "_this"s; - else - str = type + " _this"; - } - else - str += ": "s + EmitTreeNode(n); + str += ": "s + EmitTreeNode(n); } if (auto n = node->GetInit()) { str += " = "s + EmitTreeNode(n); diff --git a/src/MapleFE/ast2cpp/src/cpp_definition.cpp b/src/MapleFE/ast2cpp/src/cpp_definition.cpp index 6ac4cfd41551455954c094d2a829b45992f6f6e9..d6b1935446c577ae09fecea01366394615c1d2df 100644 --- a/src/MapleFE/ast2cpp/src/cpp_definition.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_definition.cpp @@ -188,14 +188,6 @@ std::string CppDef::EmitXXportAsPairNode(XXportAsPairNode *node) { return std::string(); } -// Return class name from class method or class field -inline std::string GetClassName(TreeNode* node) { - TreeNode* n = node->GetParent(); - if (n && n->IsClass()) - return n->GetName(); - return ""s; -} - inline bool IsClassMethod(FunctionNode* f) { return (f && f->GetParent() && f->GetParent()->IsClass()); } @@ -236,7 +228,7 @@ std::string CppDef::EmitClassProps(TreeNode* node) { // a decl list with unique names for insert into function definition. // // The var may be initialized to different values in different -// blocks which will done in the individual DeclNodes (re: var-dup.ts) +// blocks which will be done in the individual DeclNodes (re: var-dup.ts) std::string CppDef::EmitFuncScopeVarDecls(FunctionNode *node) { std::unordered_mapvarDeclsInScope; ASTScope* s = node->GetScope(); @@ -258,57 +250,89 @@ std::string CppDef::EmitFuncScopeVarDecls(FunctionNode *node) { } std::string str; for (auto const&[key, val] : varDeclsInScope) { - // Emit decl for the var (just type, name - init part emitted - // when corresponding DeclNode processed + // Emit decl for the var (just type and name). The init part + // to be emitted when corresponding DeclNode is processed str += tab(1) + mCppDecl.EmitTreeNode(val->GetVar()) + ";\n"s; } return str; } -std::string CppDef::EmitFunctionNode(FunctionNode *node) { - bool isTopLevel = hFuncTable.IsTopLevelFunc(node); - if (mIsInit || node == nullptr) +std::string CppDef::EmitYieldNode(YieldNode *node) { + if (node == nullptr) return std::string(); + //std::string str(node->IsTransfer() ? "yield* " : "yield "); + std::string str, res; + if (auto n = node->GetResult()) + res = EmitTreeNode(n); + else + res = "undefined"; - std::string str, className, ns = GetNamespace(node); - if (!ns.empty()) - ns += "::"s; - if (node->IsConstructor()) { - className = ns + GetClassName(node); - str = "\n"s; - str += className + "* "s + className + "::Ctor::operator()("s + className + "* obj"s; - } else { - str = mCppDecl.GetTypeString(node->GetType(), node->GetType()); - std::string funcName = GetIdentifierName(node); - str += " "s; - - if (IsClassMethod(node)) - str += ns + GetClassName(node) + "::"s + funcName; - else if (isTopLevel) - str += ns + "Cls_"s + funcName + "::_body"s; // emit body of top level function - else - str += ns + funcName; - str += "("s; - } - - std::string params, unused; - for (unsigned i = 0; i < node->GetParamsNum(); ++i) { - if (i || node->IsConstructor()) - params += ", "s; - if (auto n = node->GetParam(i)) { - params += mCppDecl.EmitTreeNode(n); - if (isTopLevel && i == 0) { - HandleThisParam(node->GetParamsNum(), n, params, unused); - } + std::string yieldLabel = GenFnLabels.NextYieldLabel(); + str += " yield = &&" + yieldLabel + ";\n"; // save yp + str += " res.value = t2crt::JS_Val(" +res+ ");\n"; // init value and return + str += " res.done = false;\n"; + str += " return;\n"; + str += yieldLabel + ":\n"; // label for this yp + + mPrecedence = '\024'; + return str; +} + +std::string CppDef::EmitWhileLoopNode(WhileLoopNode *node) { +// return(Emitter::EmitWhileLoopNode(node)); + + if (node == nullptr) + return std::string(); + std::string str; + std::string loopLabel; + + if(auto n = node->GetLabel()) { + str = EmitTreeNode(n) + ":\n"s; + } + + if (mIsGenerator) { // insert label and loop cond check + loopLabel = GenFnLabels.NextLoopLabel(); + str += loopLabel + ":\n"; + if (auto n = node->GetCond()) { + std::string cond = EmitTreeNode(n); + str += " if (!(" +cond+ "))\n"; + str += " goto " +loopLabel+ "_exit;\n"; + } + } else { // normal while loop + str += "while("s; + if (auto n = node->GetCond()) { + str += EmitTreeNode(n); } + str += ')'; } - if (isTopLevel && !IsClassMethod(node)) { - if (node->GetParamsNum() == 0) { - HandleThisParam(0, nullptr, params, unused); + if (auto n = node->GetBody()) { + str += EmitTreeNode(n) + GetEnding(n); + if (mIsGenerator) { + str.insert(str.find_first_of("{"), " "); + str.insert(str.find_last_of("}"), " "); } } - str += params + ") "s; + + if (mIsGenerator) { // insert loop back and label at loop exit + str += " goto " +loopLabel+ ";\n"; + str += loopLabel + "_exit:"; + } + + return HandleTreeNode(str, node); +} + + +std::string CppDef::EmitFunctionNode(FunctionNode *node) { + if (mIsInit || node == nullptr) + return std::string(); + + bool isTopLevel = hFuncTable.IsTopLevelFunc(node); + std::string str; + str += "\n"; + str += FunctionHeader(node, mCppDecl.GetTypeString(node->GetRetType(), node->GetRetType())); + mIsGenerator = node->IsGenerator(); + int bodyPos = str.size(); if (auto n = node->GetBody()) { auto varDecls = EmitFuncScopeVarDecls(node); @@ -323,6 +347,11 @@ std::string CppDef::EmitFunctionNode(FunctionNode *node) { } else str += "{}\n"s; + if (mIsGenerator) { + str.insert(str.find_first_of("{")+1, GeneratorFn_start); + str.insert(str.find_last_of("}"), GeneratorFn_return); + } + if (node->IsConstructor()) { Emitter::Replace(str, "this->", "obj->", 0); std::string ctorBody; @@ -331,6 +360,10 @@ std::string CppDef::EmitFunctionNode(FunctionNode *node) { str += EmitCtorInstance(static_cast(node->GetParent())); } + if (mIsGenerator) { + mIsGenerator = false; + GenFnLabels.ResetLabels(); + } return str; } @@ -370,7 +403,7 @@ std::string CppDef::EmitStructLiteralNode(StructLiteralNode* node) { case TY_Function: break; case TY_Array: - fieldVal = EmitArrayLiteral(nullptr, lit); + fieldVal = EmitTreeNode(lit); // ArrayLiteralNode str += "std::make_pair(\""s + fieldName + "\", t2crt::JS_Val("s + fieldVal + "))"s; break; case TY_Boolean: @@ -456,19 +489,19 @@ std::string CppDef::GenObjectLiteral(TreeNode* var, std::string varName, TreeNod } // Generate code to construct an array of type any from an ArrayLiteral. -std::string CppDef::GenArrayOfAny(TreeNode *node) { +std::string CppDef::ConstructArrayAny(ArrayLiteralNode *node) { if (node == nullptr || !node->IsArrayLiteral()) return std::string(); // Generate array ctor call to instantiate array std::string literals; - for (unsigned i = 0; i < static_cast(node)->GetLiteralsNum(); ++i) { + for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) literals += ", "s; - if (auto n = static_cast(node)->GetLiteral(i)) { + if (auto n = node->GetLiteral(i)) { if (n->IsArrayLiteral()) // Recurse to handle array elements that are arrays - literals += GenArrayOfAny(n); + literals += ConstructArrayAny(static_cast(n)); else { // Wrap element in JS_Val. C++ class constructor of JS_Val // will set tupe tag in JS_Val according to element type. @@ -480,21 +513,19 @@ std::string CppDef::GenArrayOfAny(TreeNode *node) { return str; } -std::string CppDef::EmitArrayLiterals(TreeNode *node, int dim, std::string type) { - if (node == nullptr || !node->IsArrayLiteral()) - return std::string(); - - if (type.back() == ' ') - type.pop_back(); - +// Generate code to construct an array object with brace-enclosed initializer list +std::string CppDef::ConstructArray(ArrayLiteralNode *node, int dim, std::string type) { + if (type.empty()) { + return ConstructArrayAny(node); // proceed as array of type any if no type info + } // Generate array ctor call to instantiate array std::string str = ArrayCtorName(dim, type) + "._new({"s; - for (unsigned i = 0; i < static_cast(node)->GetLiteralsNum(); ++i) { + for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) str += ", "s; - if (auto n = static_cast(node)->GetLiteral(i)) { + if (auto n = node->GetLiteral(i)) { if (n->IsArrayLiteral()) - str += EmitArrayLiterals(static_cast(n), dim-1, type); + str += ConstructArray(static_cast(n), dim-1, type); else str += EmitTreeNode(n); } @@ -503,36 +534,19 @@ std::string CppDef::EmitArrayLiterals(TreeNode *node, int dim, std::string type) return str; } -std::string CppDef::EmitArrayLiteral(TreeNode* arrType, TreeNode* arrLiteral) { - std::string str, type; - int dims = 1; // default to 1 dim array if no Dims info - if (arrLiteral == nullptr) - return "nullptr"s; - - if (arrType == nullptr) { - // if no arrary type info proceed as array of type any (JS_Val) - str = GenArrayOfAny(arrLiteral); - } else if (arrType->IsUserType()) { // array of usertyp - if (static_cast(arrType)->GetDims()) - dims = static_cast(arrType)->GetDimsNum(); - if (auto id = static_cast(arrType)->GetId()) { - type = id->GetName(); - if (type.compare("t2crt::Object") == 0 || type.compare("Object") == 0) - type = "t2crt::Object*"; - } - str = EmitArrayLiterals(arrLiteral, dims, type); - } else if (arrType->IsPrimArrayType()) { // array of prim type - if (static_cast(arrType)->GetDims()) - dims = static_cast(arrType)->GetDims()->GetDimensionsNum(); - type= EmitPrimTypeNode(static_cast(arrType)->GetPrim()); - str = EmitArrayLiterals(arrLiteral, dims, type); - } - return str; -} - // decl of global var is handled by EmitDeclNode in cpp_declaration // decl of function vars of type JS_Var is handled in EmitFuncSCopeVarDecls // This function handles init of global/func var, and decl/init of func let/const. +// +// Declaration of Javascript "var", "let" an "const" variables: +// - "var" decls are function/global scoped +// - "let" and "const" are block scoped +// TS/JS allows duplicate "var" declarations in global scope as well as +// function scope. Duplicate global scope var decls are resolved +// by the front end which make only 1 decl for the dup and changes any inits +// in the dup decls to assigments. Duplicate function scope var decls are +// handled in CppDef::EmitFuncScopeVarDecls. +// std::string CppDef::EmitDeclNode(DeclNode *node) { if (node == nullptr) return std::string(); @@ -560,9 +574,7 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { } } if (auto n = node->GetInit()) { - if (n->IsArrayLiteral()) - str += varStr + " = " + EmitArrayLiteral(idType, n); - else if (n->IsStructLiteral()) + if (n->IsStructLiteral()) str += GenObjectLiteral(node->GetVar(), varStr, idType, static_cast(n)); else if (node->GetVar()->IsIdentifier() && n->IsIdentifier() && n->IsTypeIdClass()) str += varStr + "= &"s + n->GetName() + "::ctor"s; // init with ctor address @@ -572,9 +584,8 @@ std::string CppDef::EmitDeclNode(DeclNode *node) { hFuncTable.AddNameIsTopLevelFunc(varStr); } } else { - // if no type info, assume type is any and wrap initializer in JS_Val. str += varStr + " = "; - if (varType == TY_None) + if (varType == TY_None) // no type info. assume TY_Any and wrap val in JS_Val str += "t2crt::JS_Val("s + EmitTreeNode(n) + ")"s; else str += EmitTreeNode(n); @@ -713,9 +724,23 @@ std::string CppDef::EmitArrayElementNode(ArrayElementNode *node) { return HandleTreeNode(str, node); } + std::string CppDef::EmitArrayLiteralNode(ArrayLiteralNode *node) { if (node == nullptr) return std::string(); + if (node->GetParent() && + node->GetParent()->IsDecl() || // for var decl init + node->GetParent()->IsIdentifier() || // for default val init in class field decl + node->GetParent()->IsFieldLiteral()) { // for obj decl with struct literal init + // emit code to construct array object with brace-enclosed initializer list + int dim; + std::string str, type; + GetArrayTypeInfo(node, dim, type); + str = ConstructArray(node, dim, type); + return str; + } + + // emit code to build a brace-enclosed intializer list (for rhs of array var assignment op) std::string str("{"s); for (unsigned i = 0; i < node->GetLiteralsNum(); ++i) { if (i) @@ -734,9 +759,11 @@ std::string CppDef::EmitFieldNode(FieldNode *node) { std::string upper, field, propType; bool isRhs = false; // indicate if field is rhs (val) or lhs (ref) auto upnode = node->GetUpper(); + bool upperIsGenerator = false; if (upnode) { upper = EmitTreeNode(upnode); isRhs = !mHandler->IsDef(upnode); + upperIsGenerator = IsGenerator(upnode); // TODO: await TI fix for generator3.ts } if (auto n = node->GetField()) { if (isRhs) { @@ -796,6 +823,10 @@ std::string CppDef::EmitBlockNode(BlockNode *node) { for (unsigned i = 0; i < node->GetChildrenNum(); ++i) { if (auto n = node->GetChildAtIndex(i)) { std::string s = EmitTreeNode(n); + if (n->IsYield()) { + str += s; + continue; + } if (!s.empty()) str += " "s + s + GetEnding(n); } @@ -1013,6 +1044,9 @@ std::string CppDef::EmitBracketNotationProp(ArrayElementNode* ae, OprId binOpId, case TY_Object: str = objName + "->GetPropObj("s + propKey + ")"s; break; + case TY_Any: + str = objName + "->GetProp("s + propKey + ")"s; + break; default: str = "(*"s + objName + ")["s + propKey + ']'; } @@ -1243,7 +1277,7 @@ std::string CppDef::GetThisParamObjType(TreeNode *node) { std::string str = "t2crt::Object"; if (static_cast(node)->GetParamsNum()) { auto n = static_cast(node)->GetParam(0); - if (n->IsIdentifier() && n->IsThis()) { + if (n->IsThis()) { TreeNode* tn = static_cast(n)->GetType(); str = mCppDecl.GetTypeString(tn, nullptr); if (str.back() == '*') @@ -1287,6 +1321,7 @@ std::string CppDef::EmitNewNode(NewNode *node) { str = fnName + "->ctor("s + newObj + ", "s; // call ctor function with new obj as this arg } } else { + // for builtins str = "new "s + EmitTreeNode(node->GetId()); str += "("s; } diff --git a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp index ab730ccb84fc15d9f1f607c160f8bddd81f275db..c5c92c0b0409646a598f2cc081f2b3d50197f638 100644 --- a/src/MapleFE/ast2cpp/src/cpp_emitter.cpp +++ b/src/MapleFE/ast2cpp/src/cpp_emitter.cpp @@ -26,7 +26,13 @@ std::string CppEmitter::GetIdentifierName(TreeNode *node) { case NK_Decl: return GetIdentifierName(static_cast(node)->GetVar()); case NK_Struct: - return GetIdentifierName(static_cast(node)->GetStructId()); + // Named StructNode has name in StructId. Unamed StructNode is assigned + // anonymous name by frontend and can be accessed using node mStrIdx + // through node GetName() interface. + if (auto n = static_cast(node)->GetStructId()) + return GetIdentifierName(n); + else + return node->GetName(); // for anonomyous name case NK_Function: if (static_cast(node)->GetFuncName()) return GetIdentifierName(static_cast(node)->GetFuncName()); @@ -126,4 +132,114 @@ void CppEmitter::InsertEscapes(std::string& str) { Emitter::Replace(str, "\"", "\\\"", 0); } +bool CppEmitter::IsGenerator(TreeNode* node) { + return mHandler->IsGeneratorUsed(node->GetNodeId()); +} + +FunctionNode* CppEmitter::GetGeneratorFunc(TreeNode* node) { + return mHandler->GetGeneratorUsed(node->GetNodeId()); +} + +// +// Interface to get array type and dimension interface for an ArrayLiteral +// (should be just a wrapper to call TI interfaces GetArrayElemTypeId() +// and GetArrayDim(), but until the usage of those 2 interface can cover all +// use caes, this interface encaps any additional work to get array type info. +// +void CppEmitter::GetArrayTypeInfo(ArrayLiteralNode* node, int& numDim, std::string& type) { + TypeId typeId = mHandler->GetArrayElemTypeId(node->GetNodeId()); + DimensionNode* dim = mHandler->GetArrayDim(node->GetNodeId()); + if (dim) + numDim = dim->GetDimensionsNum(); + switch(typeId) { + case TY_Class: { + unsigned tIdx = mHandler->GetArrayElemTypeIdx(node->GetNodeId()); + TreeNode* tp = gTypeTable.GetTypeFromTypeIdx(tIdx); + type = ObjectTypeStr(tp->GetName()); + break; + } + case TY_Int: + type = "long"; + break; + case TY_String: + type = "std::string"; + break; + case TY_Double: + type = "double"; + break; + case TY_None: + type = "t2crt::JS_Val"; + break; +#if 0 + case TY_Array: + type = "t2crt::Array*"; + break; +#endif + case TY_Function: + default: + // TODO + dim = 0; + type = "TBD"; + break; + } + return; + +#if 0 + if (!node->GetParent()) + return; + + switch(node->GetParent()->GetKind()) { + case NK_Decl: + // e.g. var arr: number[]=[1,2,3]; + //GetArrInfoByVarId(node, dim, type); + break; + case NK_Identifier: + // e.g. class Foo { arr: number[]=[1,2,3]; } + //GetArrInfoByClassFieldId(node, dim, type); + break; + case NK_FieldLiteral: + // e.g. var: {arr:number[]} = { n:[1,2,3] }; + //GetArrInfoByObjLiteralClassField(node, dim, type); + break; + } +#endif +} + +// C++ function header for different TS function types: +// Generator: t2crt::IteratorResult [::]GeneratorFunc_::_body(t2crt::Object* _this, void*& yield[, &]...) +// Class ctor: [::]* ::Ctor::operator()(* obj[, ]...) +// Class method: [::]::([params]...) +// Function: [::]Cls_::_body(t2crt::Object|* _this[, params]...) +std::string CppEmitter::FunctionHeader(FunctionNode* node, std::string retType) { + std::string str; + std::string ns = GetNamespace(node).empty() ? ""s : GetNamespace(node)+"::"; + std::string funcName = GetIdentifierName(node); + std::string className= ns + GetClassName(node); + bool isTopLevel = hFuncTable.IsTopLevelFunc(node); + retType = retType + " "s + ns; + + if (node->IsGenerator()) // generator + str += GeneratorFuncHeader(ns+GeneratorFuncName(funcName)+"::", node->GetNodeId()); + else if (node->IsConstructor()) { // class constructor + std::string param = FunctionParams(node->GetNodeId(), false); + param = param.empty() ? ""s : (", "s+param); + str += className + "* "s + className + "::Ctor::operator()" + "(" +className+ "* obj" +param+ ") "; + } + else if (IsClassMethod(node)) // class method + str += retType + GetClassName(node) + "::" + funcName + "(" + FunctionParams(node->GetNodeId(), false) + ") "; + else if (isTopLevel) // top level function + str += retType + "Cls_" + funcName + "::_body" + "(" + FunctionParams(node->GetNodeId(), true) + ") "; + else + str += retType + funcName + "(" + FunctionParams(node->GetNodeId(), false) + ") "; + return str; +} + +// Return class name from class method or class field +std::string CppEmitter::GetClassName(TreeNode* node) { + TreeNode* n = node->GetParent(); + if (n && n->IsClass()) + return n->GetName(); + return ""s; +} + } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/src/emitter.cpp b/src/MapleFE/ast2cpp/src/emitter.cpp index e4926858fae238e405496ce4a490d8e76b6d6703..fbf695857eaf577226ec8854914a7f84f48dba2c 100644 --- a/src/MapleFE/ast2cpp/src/emitter.cpp +++ b/src/MapleFE/ast2cpp/src/emitter.cpp @@ -45,7 +45,8 @@ std::string Emitter::GetEnding(TreeNode *n) { std::string str; switch(n->GetKind()) { case NK_Function: - str = "\n"s; + case NK_TripleSlash: + str += '\n'; break; default: str += ';'; @@ -60,7 +61,7 @@ std::string Emitter::GetEnding(TreeNode *n) { case NK_Namespace: case NK_Declare: case NK_Module: - str += "\n"s; + str += '\n'; } return str; } @@ -284,7 +285,7 @@ std::string Emitter::EmitFunctionNode(FunctionNode *node) { str += " : asserts "s + EmitTreeNode(n); auto body = node->GetBody(); - if (auto n = node->GetType()) { + if (auto n = node->GetRetType()) { std::string s = EmitTreeNode(n); if(!s.empty()) { str += (body || has_name || inside ? " : "s : " => "s) + s; @@ -703,6 +704,7 @@ std::string Emitter::EmitConditionalTypeNode(ConditionalTypeNode *node) { precd = mPrecedence; } if (auto n = node->GetTypeB()) { + str = Clean(str); if (precd < '\024') str = '(' + str + ')'; str += " extends "s + EmitTreeNode(n); @@ -1536,7 +1538,7 @@ std::string Emitter::EmitCallNode(CallNode *node) { bool optional = n->IsOptional(); if (optional && !s.empty() && s.back() == '?') s.pop_back(); - if(n->IsFunction() || n->IsLambda()) + if(n->IsFunction() || n->IsLambda() || n->IsTerOperator()) str += '(' + s + ')'; else str += s; @@ -1764,7 +1766,7 @@ std::string Emitter::EmitLambdaNode(LambdaNode *node) { str += ')'; if (auto n = node->GetBody()) { - if (auto t = node->GetType()) { + if (auto t = node->GetRetType()) { str += ": "s + EmitTreeNode(t); } std::string s = EmitTreeNode(n); @@ -1774,7 +1776,7 @@ std::string Emitter::EmitLambdaNode(LambdaNode *node) { str += " => "s + s; } else { - if (auto t = node->GetType()) { + if (auto t = node->GetRetType()) { str += " => "s + EmitTreeNode(t); } } @@ -1925,6 +1927,19 @@ std::string Emitter::EmitTupleTypeNode(TupleTypeNode *node) { mPrecedence = '\030'; return str; } + +std::string Emitter::EmitTripleSlashNode(TripleSlashNode *node) { + if (node == nullptr) + return std::string(); + std::string str; + str += "/// GetProp()); + if (auto n = node->GetValue()) { + str += '=' + EmitTreeNode(n); + } + str += " />"s; + return str; +} + std::string Emitter::EmitModuleNode(ModuleNode *node) { if (node == nullptr) return std::string(); @@ -1953,6 +1968,18 @@ std::string Emitter::EmitAttrNode(AttrNode *node) { return HandleTreeNode(str, node); } +std::string Emitter::EmitArrayTypeNode(ArrayTypeNode *node) { + // TODO + std::string str = ""; + return str; +} + +std::string Emitter::EmitFunctionTypeNode(FunctionTypeNode *node) { + // TODO + std::string str = ""; + return str; +} + std::string Emitter::EmitPrimTypeNode(PrimTypeNode *node) { if (node == nullptr) return std::string(); @@ -1986,12 +2013,6 @@ std::string Emitter::EmitPrimArrayTypeNode(PrimArrayTypeNode *node) { return HandleTreeNode(str, node); } -std::string Emitter::EmitArrayTypeNode(ArrayTypeNode *node) { - // TODO - std::string str = ""; - return str; -} - std::string Emitter::EmitTreeNode(TreeNode *node) { if (node == nullptr) return std::string(); @@ -2041,6 +2062,9 @@ std::string Emitter::EmitTreeNode(TreeNode *node) { case NK_ArrayType: return EmitArrayTypeNode(static_cast(node)); break; + case NK_FunctionType: + return EmitFunctionTypeNode(static_cast(node)); + break; case NK_UserType: return EmitUserTypeNode(static_cast(node)); break; @@ -2140,6 +2164,9 @@ std::string Emitter::EmitTreeNode(TreeNode *node) { case NK_Infer: return EmitInferNode(static_cast(node)); break; + case NK_TripleSlash: + return EmitTripleSlashNode(static_cast(node)); + break; case NK_Block: return EmitBlockNode(static_cast(node)); break; @@ -2405,4 +2432,22 @@ const char *Emitter::GetEnumOprId(OprId k) { return "UNEXPECTED OprId"; } +const char *Emitter::GetEnumTripleSlashProp(TripleSlashProp k) { + switch (k) { + case TSP_Path: + return "path"; + case TSP_Types: + return "types"; + case TSP_Lib: + return "lib"; + case TSP_NoDefaultLib: + return "no-default-lib"; + case TSP_NA: + return "TSP_NA"; + default: + MASSERT(0 && "Unexpected enumerator"); + } + return "UNEXPECTED TripleSlashProp"; +} + } // namespace maplefe diff --git a/src/MapleFE/ast2cpp/src/helper.cpp b/src/MapleFE/ast2cpp/src/helper.cpp index 5ee7e1b5f90db1160d66573baa814b8228c9af0f..1222f2341802e47bf06284101f033cd65dd21376 100644 --- a/src/MapleFE/ast2cpp/src/helper.cpp +++ b/src/MapleFE/ast2cpp/src/helper.cpp @@ -16,6 +16,9 @@ namespace maplefe { +FuncTable hFuncTable; +GeneratorLabels GenFnLabels; + std::unordered_mapTypeIdToJSTypeCXX = { // AST TypeId to t2crt JS_Type mapping for JS_Val type of obj props that pts to CXX class fields {TY_Object, "t2crt::TY_CXX_Object"}, @@ -30,15 +33,25 @@ std::unordered_mapTypeIdToJSTypeCXX = { {TY_Any, "t2crt::TY_CXX_Any"}, }; -FuncTable hFuncTable; +std::string GeneratorFn_start = R"""( + if (yield != nullptr) + goto *yield; +)"""; + +std::string GeneratorFn_return = R"""( + res.value = undefined; + res.done = true; + return; +)"""; // Used to build GetProp for calls to get Object (class Object in ts2cpp.h) property std::string hlpGetJSValTypeStr(TypeId typeId) { switch(typeId) { case TY_Object: case TY_Class: - case TY_Any: return "Obj"; + case TY_Any: + return ""; case TY_Function: return "Func"; case TY_Boolean: @@ -95,6 +108,66 @@ std::string GenClassFldAddProp(std::string objName, return str; } +// From TS func param info, generate param and arg list for corresponding mapped C++ func. +// +// Different formats of arg list as needed by C++ mapping of function/class/generators +// - args for function class functor and generation class constructor +// () - generator class constructor field init list +// & - args passed by reference to generation function _body method +// ; - generator class fields for capturing closure +// +std::string FunctionParams(unsigned nodeId, bool handleThis, bool argsOnly, bool byRef, bool fdInit, bool capture) { + std::vector> funcParams = hFuncTable.GetArgInfo(nodeId); + std::string ObjT = "t2crt::Object*"; + std::string str; + + // "this" in TS function paramter mapping to C++: + // + // TS2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list + // which will be generated from AST if "this" is declared as a TS func parameter + // as required by TS strict mode. However TS funcs that do not reference 'this' + // are not required to declare it, in which case emitter has to insert one. + // + // Cases: + // if TS func has no param + // - insert param "ts2crt::Object* _this" + // if 1st TS func param is not "this" + // - insert param "ts2crt::Object* _this" + // if 1st TS func param is "this" + // - rename to "_this" + // - if type is Any (JS_Val), change to "ts2crt::Object*" + // + if (handleThis) { + if (funcParams.size() == 0) // func has no param + return argsOnly ? "_this"s : (ObjT + " _this"); + } + + for (bool first=true; auto elem : funcParams) { + std::string type = elem.first, name = elem.second; + if (!first) + str += ", "s; + else { // 1st param of TS func + if (handleThis) { + if (name.compare("this") != 0) // if not "this", insert _this + str += argsOnly? ("_this, "s): (ObjT + " _this, "s); + else { // if "this" + name = "_this"; // rename to "_this" + if (type.compare("t2crt::JS_Val") == 0) + type = ObjT; // change type Any to Object* + } + } + first = false; + } + if (fdInit) + str += name + "(" + name + ")"; + else if (capture) + str += type + " " + name + ";\n"; + else + str += argsOnly? name: (type + (byRef?"\&":"") + " "s + name); + } + return str; +} + // Each first level function is instantiated from a corresponding class generated with interfaces below: // Body - user defined function code // () - functor for OrdinaryCallEvaluteBody [9.2.1.3] @@ -108,19 +181,22 @@ std::string GenClassFldAddProp(std::string objName, // for ctor(), it calls _body() but ignores return val from _body(), and instead returns _this // per TS/JS spec. -std::string FunctionTemplate(std::string retType, std::string funcName, std::string params, std::string args) { - std::string str; +std::string FunctionClassDecl(std::string retType, std::string funcName, unsigned nodeId) { + std::string str, args, params, thisType; + std::string clsName = ClsName(funcName); - std::string functorArgs = args; + params = FunctionParams(nodeId, true, false); + args = FunctionParams(nodeId, true, true); + thisType = params.substr(0, params.find(" ")); // extract return type of "this" parameter + std::string functorParams = params; - std::string thisType; + std::string functorArgs = args; functorArgs.replace(0, 5, "_thisArg"); // replace _this with _thisArg size_t pos; if ((pos = functorParams.find("_this, ")) != std::string::npos) functorParams.erase(0, pos+7); else if ((pos = functorParams.find("_this")) != std::string::npos) functorParams.erase(0, pos+5); - thisType = params.substr(0, pos-1); str = R"""( class )""" + clsName + R"""( : public t2crt::Function { @@ -146,65 +222,87 @@ class )""" + clsName + R"""( : public t2crt::Function { return str; } -// Template for generating Generators and Generator Functions: +// build generator function header for _body +std::string GeneratorFuncHeader(std::string cls, unsigned nodeId) { + std::string params = FunctionParams(nodeId, false, false, true); // pass params by ref into _body() + if (!params.empty()) + params = ", " + params; + return "void " + cls + "_body(t2crt::Object* _this, void*& yield, t2crt::IteratorResult& res" + params + ")"; +} + +// Generating Generators and Generator Functions: // For each TS generator function, 2 C++ classes: generator and generator function are emitted. // The generator function has only a single instance. It is called to create generator instances. -std::string GenGeneratorClass(std::string funcName, std::vector> args) { +std::string GeneratorClassDecl(std::string funcName, unsigned nodeId) { std::string str; std::string generatorName = GeneratorName(funcName); std::string generatorFuncName = GeneratorFuncName(funcName); - // Different formats of arg list as needed by generator and generator function interfaces: - // - args for function class functor and generation class constructor - // () - generator class constructor field init list - // & - args passed by reference to generation function _body method - // ; - generator class fields for capturing closure - std::string functorArgs, ctorArgs, refArgs, initList, captureFields; - - for (bool hasArg=false; auto elem : args) { - if (!hasArg) - hasArg = true; - else { - functorArgs += ", "s; - refArgs += ", "s; - initList += ", "s; - } - std::string type = elem.first, name = elem.second; - functorArgs += type + " " + name; - refArgs += type + "& "+ name; - initList += name + "("s+ name + ")"s; - captureFields += tab(1) + type + " " + name + ";\n"s; - } - if (!refArgs.empty()) - refArgs = ", " + refArgs; - if (!initList.empty()) - initList = ", " + initList; - ctorArgs = functorArgs.empty()? std::string(): (", "s + functorArgs); + std::string functorArgs = FunctionParams(nodeId, false, false); + std::string initList = FunctionParams(nodeId, false, false, false, true) ; + std::string captureFields = FunctionParams(nodeId, false, false, false, false, true); + std::string ctorArgs = functorArgs.empty()? std::string(): (", "s + functorArgs); + initList = initList.empty()? "": (", "s + initList); - str = R"""( -// )""" + funcName + R"""( generators -class )""" + generatorName + R"""( : public t2crt::GeneratorProto { -public: - )""" + generatorName + R"""((t2crt::Function* ctor, t2crt::Object* proto)""" + ctorArgs + R"""() : t2crt::GeneratorProto(ctor, proto))""" + initList + R"""( {} - ~)""" + generatorName + R"""(() {} - - // closure capture fields -)""" + captureFields + R"""( - // iterator interface (override _return and _throw when needed) - t2crt::IteratorResult _next(t2crt::JS_Val* arg) override; -}; + std::string genClsDecl[] = { +"// " +funcName+ " generators", +"class " +generatorName+ " : public t2crt::GeneratorProto {", +"public:", +" " +generatorName+ "(t2crt::Function* ctor, t2crt::Object* proto" +ctorArgs+ ") : t2crt::GeneratorProto(ctor, proto)" +initList+ " {}", +" ~" +generatorName+ "() {}", +" // closure capture fields", +" " +captureFields, +" // iterator interface (override _return and _throw when needed)", +" t2crt::IteratorResult* next(t2crt::JS_Val* arg = nullptr) override;", +"};", +"// " +funcName+ " generator function", +"class " +generatorFuncName+ " : public t2crt::GeneratorFuncPrototype {", +"public:", +" " +generatorFuncName+ "() : t2crt::GeneratorFuncPrototype(&t2crt::GeneratorFunction, &t2crt::Generator, t2crt::GeneratorPrototype) {}", +" ~" +generatorFuncName+ "() {}", +" // call operator returns generator instances", +" " +generatorName+ "* operator()(" +functorArgs+ ");", +" // generator function body", +" " +GeneratorFuncHeader("", nodeId)+ ";", +"};", +"" + }; -// )""" + funcName + R"""( generator function -class )""" + generatorFuncName + R"""( : public t2crt::GeneratorFuncPrototype { -public: - )""" + generatorFuncName + R"""(() : t2crt::GeneratorFuncPrototype(&t2crt::GeneratorFunction, &t2crt::Generator, t2crt::GeneratorPrototype) {} - ~)""" + generatorFuncName + R"""(() {} + str += "\n"; + for (auto elem : genClsDecl) + str += elem + "\n"; + return str; +} - // call operator returns generator instances - )""" + generatorName + R"""(* operator()()""" + functorArgs + R"""(); - // generator function body - t2crt::IteratorResult _body(t2crt::Object* _this, void*& yield)""" + refArgs + R"""(); -}; +std::string GeneratorClassDef(std::string ns, std::string funcName, unsigned nodeId) { + std::string str; + std::string generatorName = ns + GeneratorName(funcName); + std::string generatorFuncName = ns + GeneratorFuncName(funcName); + + if (!ns.empty()) + funcName = ns + "::" + funcName; + + std::string params = FunctionParams(nodeId, false, false); + std::string args = FunctionParams(nodeId, false, true); + if (!args.empty()) + args = ", " + args; + + str = R"""( +t2crt::IteratorResult* )""" + generatorName + R"""(::next(t2crt::JS_Val* arg) { + if (_finished) { + _res.done = true; + return &_res; + } + // iterate by calling generation function with captures in generator + )""" + funcName + R"""(->_body(this, _yield, _res)""" + args + R"""(); + if (_res.done == true) + _finished = true; + return &_res; +} + +)""" + generatorName + "* "s + generatorFuncName + R"""(::operator()()""" + params + R"""() { + return new )""" + generatorName + R"""((&t2crt::Generator, foo->prototype)""" + args + R"""(); +} )"""; return str; @@ -222,29 +320,6 @@ std::string GenAnonFuncName(TreeNode* node) { return "_anon_func_"s + std::to_string(node->GetNodeId()); } -// Check 1st param of top level function for "this" and do substitution. -void HandleThisParam(unsigned nParams, TreeNode* node, std::string& params, std::string&args) { - if (nParams == 0) { - // ts2cpp's C++ mapping for TS func has a "this" obj in the c++ func param list - // which will be generated from AST if "this" is declared as a TS func parameter - // as required by TS strict mode. However TS funcs that do not reference 'this' - // are not required to declare it, so emitter has to check and insert one. - params = "t2crt::Object* _this"s; - args = "_this"s; - return; - } - - if (node->IsThis()) { - args = "_this"; - Emitter::Replace(params, "this", "_this"); // change this to _this to avoid c++ keyword - Emitter::Replace(params, "t2crt::JS_Val", "t2crt::Object*"); // change type any (JS_Val) to Object* per ts2cpp func mapping to C++ interface - } else { - // if 1st func param is not "this", insert one to work with c++ mapping for TS func - args = "_this, "s + args; - params = "t2crt::Object* _this, "s + params; - } -} - // return array constructor name of given type // format: // 1D array: t2crt::Array::ctor @@ -263,4 +338,18 @@ std::string ArrayCtorName(int dim, std::string type) { return str; } +// note: entries below are to match values from ast nodes. Do not prepend with "t2crt::" +std::vectorbuiltins = {"Object", "Function", "Number", "Array", "Record"}; + +bool IsBuiltinObj(std::string name) { + return std::find(builtins.begin(), builtins.end(), name) != builtins.end(); +} + +std::string ObjectTypeStr(std::string name) { + if (IsBuiltinObj(name)) + return "t2crt::" + name + "*"; + else + return name + "*"; +} + } // namespace maplefe diff --git a/src/MapleFE/ast2mpl/src/mpl_processor.cpp b/src/MapleFE/ast2mpl/src/mpl_processor.cpp index e66c75643e45e1dd2d50e92777fdf1c50cf68cb8..378c18860ff09647cbe0d32e5dd21e526a94b0f3 100644 --- a/src/MapleFE/ast2mpl/src/mpl_processor.cpp +++ b/src/MapleFE/ast2mpl/src/mpl_processor.cpp @@ -609,6 +609,14 @@ maple::BaseNode *Ast2MplBuilder::ProcessInfer(StmtExprKind skind, TreeNode *tnod return nullptr; } +maple::BaseNode *Ast2MplBuilder::ProcessTripleSlash(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { + return nullptr; +} + +maple::BaseNode *Ast2MplBuilder::ProcessFunctionType(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { + return nullptr; +} + maple::BaseNode *Ast2MplBuilder::ProcessBlockDecl(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { BlockNode *ast_block = static_cast(tnode); for (int i = 0; i < ast_block->GetChildrenNum(); i++) { @@ -650,7 +658,7 @@ maple::BaseNode *Ast2MplBuilder::ProcessFuncDecl(StmtExprKind skind, TreeNode *t // SmallVector mAttrs; // SmallVector mAnnotations; //annotation or pragma // SmallVector mThrows; // exceptions it can throw - TreeNode *ast_rettype = ast_func->GetType(); // return type + TreeNode *ast_rettype = ast_func->GetRetType(); // return type // SmallVector mParams; // BlockNode *ast_body = ast_func->GetBody(); // DimensionNode *mDims; diff --git a/src/MapleFE/astopt/include/ast_info.h b/src/MapleFE/astopt/include/ast_info.h index 4753f50dace00bff128a2e2753bec54cd5d5773f..83a0fc37122e10231fdde2f6d7050bd0eaf908ff 100644 --- a/src/MapleFE/astopt/include/ast_info.h +++ b/src/MapleFE/astopt/include/ast_info.h @@ -77,6 +77,7 @@ class AST_INFO { TypeAliasNode *CreateTypeAliasNode(TreeNode *to, TreeNode *from); StructNode *CreateStructFromStructLiteral(StructLiteralNode *node); + unsigned GetAnonymousName(); TreeNode *GetAnonymousStruct(TreeNode *node); bool IsInterface(TreeNode *node); @@ -153,6 +154,21 @@ class ClassStructVisitor : public AstVisitor { FunctionNode *VisitFunctionNode(FunctionNode *node); }; +class FunctionVisitor : public AstVisitor { + private: + Module_Handler *mHandler; + AST_INFO *mInfo; + + public: + explicit FunctionVisitor(Module_Handler *h, unsigned f, bool base = false) + : AstVisitor((f & FLG_trace_1) && base), mHandler(h) { + mInfo= mHandler->GetINFO(); + } + ~FunctionVisitor() = default; + + FunctionNode *VisitFunctionNode(FunctionNode *node); +}; + class FindStrIdxVisitor : public AstVisitor { private: Module_Handler *mHandler; diff --git a/src/MapleFE/astopt/include/ast_scp.h b/src/MapleFE/astopt/include/ast_scp.h index fd2dcb485df20f92f96bb929b1b4fc31c5662012..1a9a7124a2adbd4d89b4da617fa21fbb57763f6a 100644 --- a/src/MapleFE/astopt/include/ast_scp.h +++ b/src/MapleFE/astopt/include/ast_scp.h @@ -93,7 +93,7 @@ class BuildScopeVisitor : public BuildScopeBaseVisitor { void SetRunIt(bool b) { mRunIt = b; } void InitInternalTypes(); - ClassNode *AddClass(std::string name, unsigned tyidx = 0); + ClassNode *AddClass(unsigned stridx, unsigned tyidx = 0); FunctionNode *AddFunction(std::string name); void AddType(ASTScope *scope, TreeNode *node); diff --git a/src/MapleFE/astopt/src/ast_adj.cpp b/src/MapleFE/astopt/src/ast_adj.cpp index d7015ef214abb17ceabce1118442277c042c16e6..64b8e82bf1f0de9ea9ecc9c1e7f3ef79609bd954 100644 --- a/src/MapleFE/astopt/src/ast_adj.cpp +++ b/src/MapleFE/astopt/src/ast_adj.cpp @@ -53,6 +53,18 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { (void) AstVisitor::VisitClassNode(node); CheckAndRenameCppKeywords(node); AssignPseudoName(node); + + // record names + gStringPool.AddAltStrIdx(node->GetStrIdx()); + for (unsigned i = 0; i < node->GetFieldsNum(); i++) { + TreeNode *n = node->GetField(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + for (unsigned i = 0; i < node->GetMethodsNum(); i++) { + TreeNode *n = node->GetMethod(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperClassesNum() || node->GetSuperInterfacesNum() || node->GetSuperClassesNum() || node->GetTypeParamsNum()) { @@ -76,6 +88,18 @@ ClassNode *AdjustASTVisitor::VisitClassNode(ClassNode *node) { InterfaceNode *AdjustASTVisitor::VisitInterfaceNode(InterfaceNode *node) { (void) AstVisitor::VisitInterfaceNode(node); CheckAndRenameCppKeywords(node); + + // record names + gStringPool.AddAltStrIdx(node->GetStrIdx()); + for (unsigned i = 0; i < node->GetFieldsNum(); i++) { + TreeNode *n = node->GetField(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + for (unsigned i = 0; i < node->GetMethodsNum(); i++) { + TreeNode *n = node->GetMethod(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + // skip getting canonical type if not only fields if (node->GetMethodsNum() || node->GetSuperInterfacesNum()) { return node; @@ -108,6 +132,7 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n } TreeNode *newnode = mInfo->GetCanonicStructNode(node); + gStringPool.AddAltStrIdx(newnode->GetStrIdx()); if (newnode != node) { node->SetTypeIdx(newnode->GetTypeIdx()); } @@ -118,6 +143,18 @@ StructLiteralNode *AdjustASTVisitor::VisitStructLiteralNode(StructLiteralNode *n StructNode *AdjustASTVisitor::VisitStructNode(StructNode *node) { (void) AstVisitor::VisitStructNode(node); CheckAndRenameCppKeywords(node); + + // record names + gStringPool.AddAltStrIdx(node->GetStrIdx()); + for (unsigned i = 0; i < node->GetFieldsNum(); i++) { + TreeNode *n = node->GetField(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + for (unsigned i = 0; i < node->GetMethodsNum(); i++) { + TreeNode *n = node->GetMethod(i); + gStringPool.AddAltStrIdx(n->GetStrIdx()); + } + // skip getting canonical type for TypeAlias TreeNode *parent_orig = node->GetParent(); TreeNode *p = parent_orig; @@ -214,6 +251,7 @@ UserTypeNode *AdjustASTVisitor::VisitUserTypeNode(UserTypeNode *node) { ArrayTypeNode *arr = mHandler->NewTreeNode(); arr->SetDims(dim); arr->SetElemType(etype); + node->SetDims(NULL); node = (UserTypeNode *)arr; } @@ -283,7 +321,14 @@ FunctionNode *AdjustASTVisitor::VisitFunctionNode(FunctionNode *node) { (void) AstVisitor::VisitFunctionNode(node); CheckAndRenameCppKeywords(node); - TreeNode *type = node->GetType(); + gStringPool.AddAltStrIdx(node->GetStrIdx()); + + for(unsigned i = 0; i < node->GetParamsNum(); i++) { + TreeNode *it = node->GetParam(i); + gStringPool.AddAltStrIdx(it->GetStrIdx()); + } + + TreeNode *type = node->GetRetType(); if (type && type->IsUserType()) { type->SetParent(node); } @@ -313,6 +358,7 @@ DeclNode *AdjustASTVisitor::VisitDeclNode(DeclNode *node) { unsigned stridx = inode->GetStrIdx(); if (stridx) { node->SetStrIdx(stridx); + gStringPool.AddAltStrIdx(stridx); mUpdated = true; } @@ -508,7 +554,7 @@ LambdaNode *AdjustASTVisitor::VisitLambdaNode(LambdaNode *node) { if (tn) { if (tn->IsBlock()) { func->SetBody(static_cast(tn)); - func->SetType(node->GetType()); + func->SetRetType(node->GetRetType()); } else { BlockNode *blk = mHandler->NewTreeNode(); ReturnNode *ret = mHandler->NewTreeNode(); @@ -520,8 +566,8 @@ LambdaNode *AdjustASTVisitor::VisitLambdaNode(LambdaNode *node) { } // func return type - if (node->GetType()) { - func->SetType(node->GetType()); + if (node->GetRetType()) { + func->SetRetType(node->GetRetType()); } mUpdated = true; diff --git a/src/MapleFE/astopt/src/ast_info.cpp b/src/MapleFE/astopt/src/ast_info.cpp index e841e0d65a0c061c6c4ee9df7481a9b74f4b654b..5c8ef881ec5d39d5ac2f54f6a6cae737fbb8cb82 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -67,15 +67,31 @@ void AST_INFO::CollectInfo() { mPass = 2; MSGNOLOC0("============== merge class/interface/struct =============="); visitor.Visit(module); + + // collect function types + FunctionVisitor func_visitor(mHandler, mFlags, true); + func_visitor.Visit(module); } void AST_INFO::AddBuiltInTypes() { + unsigned size = gTypeTable.size(); + for (unsigned idx = 1; idx < size; idx++) { + TreeNode *node = gTypeTable.GetTypeFromTypeIdx(idx); + if (node->IsUserType()) { + mStrIdx2TypeIdxMap[node->GetStrIdx()] = node->GetTypeIdx(); + } + } + // add language builtin types TreeNode *node = NULL; + unsigned stridx = 0; #define BUILTIN(T) \ - node = gTypeTable.CreateBuiltinType(#T, TY_Class);\ - gTypeTable.AddType(node);\ - mStrIdx2TypeIdxMap[node->GetStrIdx()] = node->GetTypeIdx(); + stridx = gStringPool.GetStrIdx(#T);\ + if (mStrIdx2TypeIdxMap.find(stridx) == mStrIdx2TypeIdxMap.end()) {\ + node = gTypeTable.CreateBuiltinType(#T, TY_Class);\ + gTypeTable.AddType(node);\ + mStrIdx2TypeIdxMap[stridx] = node->GetTypeIdx();\ + } #include "lang_builtin.def" } @@ -245,16 +261,16 @@ bool AST_INFO::IsTypeCompatible(TreeNode *node1, TreeNode *node2) { if ((!node1 && node2) || (node1 && !node2)) { return false; } + // not same kind + if (node1->GetKind() != node2->GetKind()) { + return false; + } // at least one is prim if (node1->IsPrimType() || node2->IsPrimType()) { TypeId tid_field = GetTypeId(node2); TypeId tid_target = GetTypeId(node1); return (tid_field == tid_target); } - // not same kind - if (node1->GetKind() != node2->GetKind()) { - return false; - } bool result = false; // same kind NodeKind nk = node1->GetKind(); @@ -490,10 +506,15 @@ StructNode *AST_INFO::CreateStructFromStructLiteral(StructLiteralNode *node) { return newnode; } -TreeNode *AST_INFO::GetAnonymousStruct(TreeNode *node) { - std::string str("AnonymousStruct_"); +unsigned AST_INFO::GetAnonymousName() { + std::string str("AnonymousStruct__"); str += std::to_string(mNum++); unsigned stridx = gStringPool.GetStrIdx(str); + return stridx; +} + +TreeNode *AST_INFO::GetAnonymousStruct(TreeNode *node) { + unsigned stridx = GetAnonymousName(); TreeNode *newnode = node; if (newnode->IsStructLiteral()) { StructLiteralNode *sl = static_cast(node); @@ -665,7 +686,7 @@ IdentifierNode *FillNodeInfoVisitor::VisitIdentifierNode(IdentifierNode *node) { FunctionNode *FillNodeInfoVisitor::VisitFunctionNode(FunctionNode *node) { (void) AstVisitor::VisitFunctionNode(node); - TreeNode *type = node->GetType(); + TreeNode *type = node->GetRetType(); if (type) { mInfo->SetTypeId(node, type->GetTypeId()); mInfo->SetTypeIdx(node, type->GetTypeIdx()); @@ -673,7 +694,7 @@ FunctionNode *FillNodeInfoVisitor::VisitFunctionNode(FunctionNode *node) { unsigned stridx = gStringPool.GetStrIdx("Generator"); unsigned tidx = mInfo->GetBuiltInTypeIdx(stridx); UserTypeNode *ut = mInfo->CreateUserTypeNode(stridx); - node->SetType(ut); + node->SetRetType(ut); } return node; } @@ -729,7 +750,15 @@ LiteralNode *FillNodeInfoVisitor::VisitLiteralNode(LiteralNode *node) { PrimTypeNode *FillNodeInfoVisitor::VisitPrimTypeNode(PrimTypeNode *node) { (void) AstVisitor::VisitPrimTypeNode(node); - mInfo->SetTypeIdx(node, node->GetPrimType()); + TypeId prim = node->GetPrimType(); + bool isprim = gTypeTable.IsPrimTypeId(prim); + + if (isprim) { + mInfo->SetTypeIdx(node, prim); + } else { + TreeNode *type = gTypeTable.GetTypeFromTypeId(prim); + mInfo->SetTypeIdx(node, type->GetTypeIdx()); + } return node; } @@ -739,7 +768,6 @@ UserTypeNode *FillNodeInfoVisitor::VisitUserTypeNode(UserTypeNode *node) { if (id) { unsigned tidx = mInfo->GetBuiltInTypeIdx(id); if (tidx) { - mInfo->SetTypeId(id, TY_Class); mInfo->SetTypeIdx(id, tidx); } if (!id->IsTypeIdNone()) { @@ -793,6 +821,9 @@ StructNode *ClassStructVisitor::VisitStructNode(StructNode *node) { if (id && node->GetStrIdx() == 0) { node->SetStrIdx(id->GetStrIdx()); } + if (node->GetStrIdx() == 0) { + node->SetStrIdx(mInfo->GetAnonymousName()); + } mInfo->SetStrIdx2Struct(node->GetStrIdx(), node); for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { if (TreeNode *t = node->GetField(i)) { @@ -823,6 +854,9 @@ ClassNode *ClassStructVisitor::VisitClassNode(ClassNode *node) { mInfo->SetTypeId(node, TY_Class); (void) AstVisitor::VisitClassNode(node); if (mInfo->GetPass() == 0) { + if (node->GetStrIdx() == 0) { + node->SetStrIdx(mInfo->GetAnonymousName()); + } gTypeTable.AddType(node); mInfo->SetStrIdx2Struct(node->GetStrIdx(), node); for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { @@ -854,6 +888,9 @@ InterfaceNode *ClassStructVisitor::VisitInterfaceNode(InterfaceNode *node) { mInfo->SetTypeId(node, TY_Class); (void) AstVisitor::VisitInterfaceNode(node); if (mInfo->GetPass() == 0) { + if (node->GetStrIdx() == 0) { + node->SetStrIdx(mInfo->GetAnonymousName()); + } gTypeTable.AddType(node); mInfo->SetStrIdx2Struct(node->GetStrIdx(), node); for (unsigned i = 0; i < node->GetFieldsNum(); ++i) { @@ -903,6 +940,24 @@ FunctionNode *ClassStructVisitor::VisitFunctionNode(FunctionNode *node) { return node; } +FunctionNode *FunctionVisitor::VisitFunctionNode(FunctionNode *node) { + FunctionTypeNode *functype = mHandler->NewTreeNode(); + TreeNode *n = NULL; + for (unsigned i = 0; i < node->GetParamsNum(); i++) { + n = node->GetParam(i); + functype->AddParam(n ? n->GetTypeIdx() : 0); + } + + // add return + n = node->GetRetType(); + functype->AddParam(n ? n->GetTypeIdx() : 0); + + unsigned tidx = gTypeTable.GetOrCreateFunctionTypeIdx(functype); + node->SetTypeIdx(tidx); + + return node; +} + IdentifierNode *FindStrIdxVisitor::VisitIdentifierNode(IdentifierNode *node) { (void) AstVisitor::VisitIdentifierNode(node); if (node->GetStrIdx() == mStrIdx) { diff --git a/src/MapleFE/astopt/src/ast_scp.cpp b/src/MapleFE/astopt/src/ast_scp.cpp index 9179704ab7e33a937ccc8b436abd125fe2d06911..fe472ccd5efd3289ee290da38b51789e456a4f01 100644 --- a/src/MapleFE/astopt/src/ast_scp.cpp +++ b/src/MapleFE/astopt/src/ast_scp.cpp @@ -128,29 +128,36 @@ void BuildScopeVisitor::InitInternalTypes() { TreeNode *node = gTypeTable.GetTypeFromTypeIdx(i); node->SetScope(scope); if (node->IsUserType()) { - static_cast(node)->GetId()->SetScope(scope); - AddType(scope, node); - AddDecl(scope, node); + UserTypeNode *ut = static_cast(node); + TreeNode *id = ut->GetId(); + id->SetScope(scope); + AddType(scope, ut); + // id as a decl + AddDecl(scope, id); } else { AddType(scope, node); } } // add dummpy console.log() - ClassNode *console = AddClass("console"); - ASTScope *scp = NewScope(scope, console); - mStrIdx2ScopeMap[console->GetStrIdx()] = scp; - FunctionNode *log = AddFunction("log"); - log->SetTypeIdx(TY_Void); - console->AddMethod(log); - log->SetScope(scp); - AddDecl(scp, log); -} - -ClassNode *BuildScopeVisitor::AddClass(std::string name, unsigned tyidx) { + unsigned size = gStringPool.GetSize(); + unsigned stridx = gStringPool.GetStrIdx("console"); + TreeNode *type = gTypeTable.GetTypeFromStrIdx(stridx); + if (!type) { + ClassNode *console = AddClass(stridx); + ASTScope *scp = NewScope(scope, console); + mStrIdx2ScopeMap[console->GetStrIdx()] = scp; + FunctionNode *log = AddFunction("log"); + log->SetTypeIdx(TY_Void); + console->AddMethod(log); + log->SetScope(scp); + AddDecl(scp, log); + } +} + +ClassNode *BuildScopeVisitor::AddClass(unsigned stridx, unsigned tyidx) { ClassNode *node = mHandler->NewTreeNode(); - unsigned idx = gStringPool.GetStrIdx(name); - node->SetStrIdx(idx); + node->SetStrIdx(stridx); node->SetTypeIdx(tyidx); ModuleNode *module = mHandler->GetASTModule(); @@ -428,6 +435,7 @@ NamespaceNode *BuildScopeVisitor::VisitNamespaceNode(NamespaceNode *node) { DeclNode *BuildScopeVisitor::VisitDeclNode(DeclNode *node) { BuildScopeBaseVisitor::VisitDeclNode(node); ASTScope *scope = NULL; + bool deep = true; if (node->GetProp() == JS_Var) { // promote to use function or module scope scope = mUserScopeStack.top(); @@ -438,10 +446,41 @@ DeclNode *BuildScopeVisitor::VisitDeclNode(DeclNode *node) { node->GetVar()->SetScope(scope); } } else { - // use current scope scope = mScopeStack.top(); + // for body of function use function scope instead of body scope + TreeNode *b = node->GetParent(); + if (b && b->IsBlock()) { + TreeNode *f = b->GetParent(); + if (f && f->IsFunction()) { + scope = mUserScopeStack.top(); + } + } + // restrict to current scope + deep = false; + } + // check if it is already a decl in the scope + unsigned stridx = node->GetStrIdx(); + TreeNode *decl = scope->FindDeclOf(stridx, deep); + if (decl) { + if (decl != node) { + // replace with an assignment if apply + if (node->GetInit()) { + BinOperatorNode *bop = mHandler->NewTreeNode(); + bop->SetOprId(OPR_Assign); + IdentifierNode *id = mHandler->NewTreeNode(); + id->SetStrIdx(stridx); + id->SetScope(scope); + + bop->SetOpndA(id); + bop->SetOpndB(node->GetInit()); + node = (DeclNode *)bop; + } else { + node = NULL; + } + } + } else { + AddDecl(scope, node); } - AddDecl(scope, node); return node; } @@ -453,7 +492,7 @@ UserTypeNode *BuildScopeVisitor::VisitUserTypeNode(UserTypeNode *node) { if (p->IsFunction()) { // exclude function return type FunctionNode *f = static_cast(p); - if (f->GetType() == node) { + if (f->GetRetType() == node) { return node; } } else if (p->IsTypeAlias()) { @@ -726,6 +765,7 @@ void AST_SCP::RenameVar() { str += std::to_string(size); visitor.mOldStrIdx = stridx; visitor.mNewStrIdx = gStringPool.GetStrIdx(str); + gStringPool.AddAltStrIdx(visitor.mNewStrIdx); TreeNode *tn = mHandler->GetAstOpt()->GetNodeFromNodeId(nid); ASTScope *scope = tn->GetScope(); tn = scope->GetTree(); diff --git a/src/MapleFE/astopt/src/ast_ti.cpp b/src/MapleFE/astopt/src/ast_ti.cpp index 22706289ed7bda7a3ff2fc87224962a9d16fc330..99439b59de694b757e30393cd8db4d3a3456d115 100644 --- a/src/MapleFE/astopt/src/ast_ti.cpp +++ b/src/MapleFE/astopt/src/ast_ti.cpp @@ -85,7 +85,7 @@ IdentifierNode *BuildIdNodeToDeclVisitor::VisitIdentifierNode(IdentifierNode *no (void) AstVisitor::VisitIdentifierNode(node); // mHandler->FindDecl() will use/add entries to mNodeId2Decl TreeNode *decl = mHandler->FindDecl(node); - if (decl) { + if (decl && decl != node) { mHandler->GetUtil()->SetTypeId(node, decl->GetTypeId()); mHandler->GetUtil()->SetTypeIdx(node, decl->GetTypeIdx()); } @@ -93,8 +93,10 @@ IdentifierNode *BuildIdNodeToDeclVisitor::VisitIdentifierNode(IdentifierNode *no if (type && type->IsPrimType()) { PrimTypeNode *ptn = static_cast(type); TypeId tid = ptn->GetPrimType(); - // mHandler->GetUtil()->SetTypeId(node, tid); - mHandler->GetUtil()->SetTypeIdx(node, tid); + if (gTypeTable.IsPrimTypeId(tid)) { + // mHandler->GetUtil()->SetTypeId(node, tid); + mHandler->GetUtil()->SetTypeIdx(node, tid); + } } return node; } @@ -226,6 +228,7 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { switch (tia) { case TY_None: result = tib; break; + case TY_Class: case TY_Object: case TY_User: result = tia; break; @@ -233,22 +236,34 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { case TY_Undefined: case TY_String: case TY_Function: - case TY_Class: case TY_Array: result = TY_Merge; break; + case TY_Number: { + switch (tib) { + case TY_Int: + case TY_Long: + case TY_Float: + case TY_Double: result = tib; break; + default: result = TY_Merge; break; + } + break; + } + case TY_Boolean: { switch (tib) { case TY_Int: case TY_Long: case TY_Float: case TY_Double: result = tib; break; + case TY_Number: result = tia; break; default: result = TY_Merge; break; } break; } case TY_Int: { switch (tib) { - case TY_Boolean: result = TY_Int; break; + case TY_Number: + case TY_Boolean: result = tia; break; case TY_Long: case TY_Float: case TY_Double: result = tib; break; @@ -258,8 +273,9 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } case TY_Long: { switch (tib) { + case TY_Number: case TY_Boolean: - case TY_Int: result = TY_Long; break; + case TY_Int: result = tia; break; case TY_Float: case TY_Double: result = TY_Double; break; default: result = TY_Merge; break; @@ -268,8 +284,9 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } case TY_Float: { switch (tib) { + case TY_Number: case TY_Boolean: - case TY_Int: result = TY_Float; break; + case TY_Int: result = tia; break; case TY_Long: case TY_Double: result = TY_Double; break; default: result = TY_Merge; break; @@ -278,10 +295,11 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } case TY_Double: { switch (tib) { + case TY_Number: case TY_Boolean: case TY_Int: case TY_Long: - case TY_Double: result = TY_Double; break; + case TY_Double: result = tia; break; default: result = TY_Merge; break; } break; @@ -302,11 +320,11 @@ TypeId TypeInferVisitor::MergeTypeId(TypeId tia, TypeId tib) { } unsigned TypeInferVisitor::MergeTypeIdx(unsigned tia, unsigned tib) { - if (tia == tib || tib == 0) { + if (tia == tib || tib <= 1) { return tia; } - if (tia == 0) { + if (tia <= 1) { return tib; } @@ -415,7 +433,11 @@ PrimTypeNode *TypeInferVisitor::GetOrClonePrimTypeNode(PrimTypeNode *pt, TypeId new_pt->SetPrimType(pt->GetPrimType()); } SetTypeId(new_pt, tid); - SetTypeIdx(new_pt, tid); + if (IsPrimTypeId(tid)) { + SetTypeIdx(new_pt, tid); + } else { + SetTypeIdx(new_pt, gTypeTable.GetTypeFromTypeId(tid)->GetTypeIdx()); + } SetUpdated(); } return new_pt; @@ -483,7 +505,7 @@ void TypeInferVisitor::UpdateTypeUseNode(TreeNode *target, TreeNode *input) { TypeId new_elemTypeId = GetArrayElemTypeId(target); TreeNode *type = static_cast(target)->GetType(); MASSERT(target->IsIdentifier() && "target node not identifier"); - if (type->IsPrimArrayType()) { + if (type && type->IsPrimArrayType()) { unsigned nid = target->GetNodeId(); mParam2ArgArrayDeclMap[nid].insert(decl); if (old_elemTypeId != new_elemTypeId) { @@ -552,13 +574,13 @@ void TypeInferVisitor::UpdateFuncRetTypeId(FunctionNode *node, TypeId tid, unsig if (!node || (node->GetTypeId() == tid && node->GetTypeIdx() == tidx)) { return; } - TreeNode *type = node->GetType(); + TreeNode *type = node->GetRetType(); // create new return type node if it was shared if (type) { if (type->IsPrimType() && type->IsTypeIdNone()) { type = GetOrClonePrimTypeNode((PrimTypeNode *)type, tid); - node->SetType(type); + node->SetRetType(type); } tid = MergeTypeId(type->GetTypeId(), tid); SetTypeId(type, tid); @@ -625,7 +647,7 @@ bool TypeInferVisitor::UpdateVarTypeWithInit(TreeNode *var, TreeNode *init) { IdentifierNode *idnode = static_cast(var); TreeNode *type = idnode->GetType(); // use init NewNode to set decl type - if (!type && init) { + if (init) { if (init->IsNew()) { NewNode *n = static_cast(init); if (n->GetId()) { @@ -647,28 +669,39 @@ bool TypeInferVisitor::UpdateVarTypeWithInit(TreeNode *var, TreeNode *init) { result = true; } } + } else if (init->IsStructLiteral()) { + if (!type && init->GetTypeIdx() != 0) { + type = gTypeTable.GetTypeFromTypeIdx(init->GetTypeIdx()); + UserTypeNode *utype = mInfo->CreateUserTypeNode(type->GetStrIdx(), var->GetScope()); + utype->SetParent(idnode); + idnode->SetType(utype); + SetUpdated(); + } } else if (init->IsArrayLiteral()) { TypeId tid = GetArrayElemTypeId(init); unsigned tidx = GetArrayElemTypeIdx(init); - if (IsPrimTypeId(tid)) { - PrimTypeNode *pt = mHandler->NewTreeNode(); - pt->SetPrimType(tid); - - PrimArrayTypeNode *pat = mHandler->NewTreeNode(); - pat->SetPrim(pt); - - DimensionNode *dims = mHandler->GetArrayDim(init->GetNodeId()); - pat->SetDims(dims); + if (type) { + if (type->IsArrayType()) { + ArrayTypeNode *pat = static_cast(type); + // update array element type + SetTypeId(pat->GetElemType(), tid); + SetTypeIdx(pat->GetElemType(), tidx); + SetUpdated(); + } else { + NOTYETIMPL("array type not ArrayTypeNode"); + } + return result; + } - pat->SetParent(idnode); - idnode->SetType(pat); - SetUpdated(); + TreeNode *elemtype = NULL; + if (IsPrimTypeId(tid)) { + elemtype = gTypeTable.GetTypeFromTypeId(tid); } else if (tidx != 0) { - TreeNode *t = gTypeTable.GetTypeFromTypeIdx(tidx); - UserTypeNode *utype = mInfo->CreateUserTypeNode(t->GetStrIdx(), var->GetScope()); - + elemtype = gTypeTable.GetTypeFromTypeIdx(tidx); + } + if (elemtype) { ArrayTypeNode *pat = mHandler->NewTreeNode(); - pat->SetElemType(utype); + pat->SetElemType(elemtype); DimensionNode *dims = mHandler->GetArrayDim(init->GetNodeId()); pat->SetDims(dims); @@ -835,15 +868,13 @@ FieldLiteralNode *TypeInferVisitor::VisitFieldLiteralNode(FieldLiteralNode *node ArrayLiteralNode *TypeInferVisitor::VisitArrayLiteralNode(ArrayLiteralNode *node) { UpdateTypeId(node, TY_Array); (void) AstVisitor::VisitArrayLiteralNode(node); - ArrayLiteralNode *al = node; if (node->IsArrayLiteral()) { - al = static_cast(node); - unsigned size = al->GetLiteralsNum(); + unsigned size = node->GetLiteralsNum(); TypeId tid = TY_None; unsigned tidx = 0; bool allElemArray = true; for (unsigned i = 0; i < size; i++) { - TreeNode *n = al->GetLiteral(i); + TreeNode *n = node->GetLiteral(i); TypeId id = n->GetTypeId(); unsigned idx = n->GetTypeIdx(); tid = MergeTypeId(tid, id); @@ -861,9 +892,9 @@ ArrayLiteralNode *TypeInferVisitor::VisitArrayLiteralNode(ArrayLiteralNode *node unsigned elemdim = DEFAULTVALUE; // recalculate element typeid tid = TY_None; - unsigned tidx = 0; + tidx = 0; for (unsigned i = 0; i < size; i++) { - TreeNode *n = al->GetLiteral(i); + TreeNode *n = node->GetLiteral(i); if (n->IsArrayLiteral()) { DimensionNode * dn = mHandler->GetArrayDim(n->GetNodeId()); unsigned currdim = dn ? dn->GetDimensionsNum() : 0; @@ -1062,8 +1093,8 @@ CallNode *TypeInferVisitor::VisitCallNode(CallNode *node) { mHandler->AddGeneratorUsed(node->GetNodeId(), func); } // update call's return type - if (func->GetType()) { - UpdateTypeId(node, func->GetType()->GetTypeId()); + if (func->GetRetType()) { + UpdateTypeId(node, func->GetRetType()->GetTypeId()); } // skip imported and exported functions as they are generic // so should not restrict their types @@ -1125,6 +1156,13 @@ CallNode *TypeInferVisitor::VisitCallNode(CallNode *node) { } } else if (decl->IsLiteral()) { NOTYETIMPL("VisitCallNode literal node"); + } else if (decl->IsTypeIdClass()) { + // object + if (node->GetArgsNum()) { + TreeNode *arg = node->GetArg(0); + SetTypeId(arg, TY_Object); + SetTypeIdx(arg, decl->GetTypeIdx()); + } } else { NOTYETIMPL("VisitCallNode not function node"); } @@ -1158,13 +1196,17 @@ CastNode *TypeInferVisitor::VisitCastNode(CastNode *node) { AsTypeNode *TypeInferVisitor::VisitAsTypeNode(AsTypeNode *node) { (void) AstVisitor::VisitAsTypeNode(node); TreeNode *dest = node->GetType(); - SetTypeId(node, dest); + if (node->GetTypeIdx() == 0) { + SetTypeId(node, dest); + } TreeNode *parent = node->GetParent(); if (parent) { // pass to parent, need refine if multiple AsTypeNode if (parent->GetAsTypesNum() == 1 && parent->GetAsTypeAtIndex(0) == node) { - SetTypeId(parent, dest); + if (parent->GetTypeIdx() == 0) { + SetTypeId(parent, dest); + } } } return node; @@ -1505,9 +1547,6 @@ FunctionNode *TypeInferVisitor::VisitFunctionNode(FunctionNode *node) { if (node->GetFuncName()) { SetTypeId(node->GetFuncName(), node->GetTypeId()); } - if (node->GetType()) { - SetTypeIdx(node, node->GetType()->GetTypeIdx()); - } return node; } @@ -1532,10 +1571,26 @@ IdentifierNode *TypeInferVisitor::VisitIdentifierNode(IdentifierNode *node) { SetUpdated(); } } - if (node->GetInit()) { - UpdateTypeId(node, node->GetInit()->GetTypeId()); - UpdateTypeIdx(node, node->GetInit()->GetTypeIdx()); + TreeNode *init = node->GetInit(); + if (init) { + if (node->GetTypeId() == TY_None) { + SetTypeId(node, init->GetTypeId()); + } + if (node->GetTypeIdx() == 0) { + SetTypeIdx(node, init->GetTypeIdx()); + } SetUpdated(); + if (init->IsArrayLiteral()) { + // pass array element info + TypeId tid = mHandler->GetArrayElemTypeId(init->GetNodeId()); + unsigned tidx = mHandler->GetArrayElemTypeIdx(init->GetNodeId()); + UpdateArrayElemTypeMap(node, tid, tidx); + if (type && type->IsArrayType()) { + TreeNode *et = static_cast(type)->GetElemType(); + et->SetTypeId(tid); + et->SetTypeIdx(tidx); + } + } return node; } TreeNode *parent = node->GetParent(); @@ -1583,6 +1638,8 @@ IdentifierNode *TypeInferVisitor::VisitIdentifierNode(IdentifierNode *node) { UpdateTypeId(node, decl); UpdateTypeIdx(node, decl); } + // pass IsGeneratorUsed + mHandler->UpdateGeneratorUsed(node->GetNodeId(), decl->GetNodeId()); } else { NOTYETIMPL("node not declared"); MSGNOLOC0(node->GetName()); @@ -1607,7 +1664,7 @@ IsNode *TypeInferVisitor::VisitIsNode(IsNode *node) { TreeNode *parent = node->GetParent(); if (parent->IsFunction()) { FunctionNode *func = static_cast(parent); - if (func->GetType() == node) { + if (func->GetRetType() == node) { TreeNode *right = node->GetRight(); if (right->IsUserType()) { TreeNode *id = static_cast(right)->GetId(); @@ -1724,16 +1781,16 @@ ReturnNode *TypeInferVisitor::VisitReturnNode(ReturnNode *node) { if (tn) { FunctionNode *func = static_cast(tn); // use dummy PrimTypeNode as return type of function if not set to carry return TypeId - if (!func->GetType()) { + if (!func->GetRetType()) { PrimTypeNode *type = mHandler->NewTreeNode(); type->SetPrimType(TY_None); - func->SetType(type); + func->SetRetType(type); } if (!func->IsGenerator() && !func->IsIterator()) { UpdateFuncRetTypeId(func, node->GetTypeId(), node->GetTypeIdx()); if (res) { // use res to update function's return type - UpdateTypeUseNode(func->GetType(), res); + UpdateTypeUseNode(func->GetRetType(), res); } } } @@ -1819,7 +1876,10 @@ UserTypeNode *TypeInferVisitor::VisitUserTypeNode(UserTypeNode *node) { SetTypeId(node, TY_Array); SetTypeIdx(node, TY_Array); } else if (node->GetId()) { - UpdateTypeId(node, node->GetId()); + // non-enum user type which keep TY_None + if (node->GetId()->GetTypeId() != TY_None) { + SetTypeId(node, TY_Class); + } UpdateTypeIdx(node, node->GetId()); } TreeNode *parent = node->GetParent(); diff --git a/src/MapleFE/autogen/reserved.spec b/src/MapleFE/autogen/reserved.spec index 445cc388cc7acb78a21415b5119eb36e5e3b8aff..cd258684dc2ad9b79fe06683a1d021930fe3fa98 100644 --- a/src/MapleFE/autogen/reserved.spec +++ b/src/MapleFE/autogen/reserved.spec @@ -34,10 +34,9 @@ rule HEXDIGIT : ONEOF(DIGIT, 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', ' # irregular char like \n, \, DEL, etc. will be handled in lexer.cpp if some language allows them in string literal. rule IRREGULAR_CHAR : "this_is_for_fake_rule" -# We will catch any utf-8 char in lexer in a short-cut. -rule UTF8 : "this_is_for_fake_rule" - -# Below are special rules handled in lexer source code. Since it'll be in lexer code, it means +# Below are special rules handled in lexer.cpp. Since it'll be in lexer code, it means # it's a shared rule of all languages. It has to be in reserved.spec. +rule UTF8 : "this_is_for_fake_rule" rule TemplateLiteral : "this_is_for_fake_rule" rule RegularExpression : "this_is_for_fake_rule" +rule NoLineTerminator : "this_is_for_fake_rule" diff --git a/src/MapleFE/c/src/main.cpp b/src/MapleFE/c/src/main.cpp index f2247efd5cadaca1e2d44f82036d1e305a77ee5f..b055675ccd5e23deec5d5292167d7cea2d3a57a6 100644 --- a/src/MapleFE/c/src/main.cpp +++ b/src/MapleFE/c/src/main.cpp @@ -112,7 +112,7 @@ int main (int argc, char *argv[]) { std::ofstream ofs; std::string fname(module->GetFilename()); - fname += ".mast"; + fname = fname.replace(fname.find(".c"), 2, ".mast"); ofs.open(fname, std::ofstream::out); const char *addr = (const char *)(&(ast_buf[0])); ofs.write(addr, ast_buf.size()); diff --git a/src/MapleFE/c/stmt.spec b/src/MapleFE/c/stmt.spec index 4b640fd0198c0619706904b2bc27c3b6a0b9f6e0..f71d36b960266b2d4a5e42e799f73bf60a0223ff 100644 --- a/src/MapleFE/c/stmt.spec +++ b/src/MapleFE/c/stmt.spec @@ -26,11 +26,14 @@ rule DimExprs : DimExpr + ZEROORMORE(DimExpr) rule DimExpr : '[' + Expression + ']' rule Expression : ONEOF( - PrimaryExpression) + PrimaryExpression, + UnaryExpression) rule UnaryExpression : ONEOF( PreIncrementExpression, - PreDecrementExpression) + PreDecrementExpression, + PostIncrementExpression, + PostDecrementExpression) rule PreIncrementExpression : "++" + PrimaryExpression attr.action : BuildUnaryOperation(%1, %2) @@ -38,6 +41,12 @@ rule PreIncrementExpression : "++" + PrimaryExpression rule PreDecrementExpression : "--" + PrimaryExpression attr.action : BuildUnaryOperation(%1, %2) +rule PostIncrementExpression : PrimaryExpression + "++" + attr.action : BuildPostfixOperation(%2, %1) + +rule PostDecrementExpression : PrimaryExpression + "--" + attr.action : BuildPostfixOperation(%2, %1) + ###################################################################### # Variable # ###################################################################### @@ -85,12 +94,24 @@ rule Dim : '[' + ']' ###################################################################### rule Statement : ONEOF(LocalVariableDeclarationStatement, + ExpressionStatement, ReturnStatement) attr.property: Single +rule ExpressionStatement : StatementExpression + ';' + +rule StatementExpression : ONEOF( + PreIncrementExpression, + PreDecrementExpression, + PostIncrementExpression, + PostDecrementExpression, + ) + attr.property: Single + rule ReturnStatement : "return" + ZEROORONE(Expression) + ';' attr.action : BuildReturn(%2) + ###################################################################### # Function # ###################################################################### diff --git a/src/MapleFE/docs/builtin-constructors.md b/src/MapleFE/docs/builtin-constructors.md index b38060c8add67af8b593b04c5294ecb66a0f55e2..aa844737710707a03f7a67d1b7751fb919b9b24c 100644 --- a/src/MapleFE/docs/builtin-constructors.md +++ b/src/MapleFE/docs/builtin-constructors.md @@ -25,7 +25,7 @@ Not all built-in objects work as object constructors. The following is a list of JavaScript built-in objects that works as object constructors to create objects of corresponding built-in type: -## List of JavaScript built-in object constructors +### 1. List of JavaScript built-in object constructors ``` 1 AggregateError 2 Array @@ -49,30 +49,58 @@ of corresponding built-in type: 20 Int8Array 21 InternalError (Mozilla only) 22 Map - 23 Math - 24 Number - 25 Object - 26 Promise - 27 Proxy - 28 RangeError - 29 ReferenceError - 30 RegExp - 31 Set - 32 SharedArrayBuffer - 33 String - 34 Symbol - 35 SyntaxError - 36 TypeError - 37 Uint16Array - 38 Uint32Array - 39 Uint8Array - 40 Uint8ClampedArray - 41 URIError - 42 WeakMap - 43 WeakRef - 44 WeakSet + 23 Number + 24 Object + 25 Promise + 26 Proxy + 27 RangeError + 28 ReferenceError + 29 RegExp + 30 Set + 31 SharedArrayBuffer + 32 String + 33 Symbol + 34 SyntaxError + 35 TypeError + 36 Uint16Array + 37 Uint32Array + 38 Uint8Array + 39 Uint8ClampedArray + 40 URIError + 41 WeakMap + 42 WeakRef + 43 WeakSet ``` +### 2. JavaScript builtin String/Number/Boolean object constructor and string/number/boolean primitive +https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_primitives_and_string_objects + +"Note that JavaScript distinguishes between String objects and primitive string values. (The same is true of Boolean and Numbers.) + +String literals (denoted by double or single quotes) and strings returned from String calls in a non-constructor context (that is, called without using the new keyword) are primitive strings. JavaScript automatically converts primitives to String objects, so that it's possible to use String object methods for primitive strings. In contexts where a method is to be invoked on a primitive string or a property lookup occurs, JavaScript will automatically wrap the string primitive and call the method or perform the property lookup." +``` + 1 var s1 : string = "test"; // string literal + 2 var s2 : String = "test"; // string literal + 3 var s3 : string = String("test"); // string literal + 4 var s4 : String = String("test"); // string literal + 5 var s5 : String = new String("test"); // String object + 6 console.log(typeof(s1)); // string + 7 console.log(s1.slice(1,2)); // string literal s1 wrapped/converted to String object for call + 8 console.log(typeof(s2)); // string + 9 console.log(typeof(s3)); // string + 10 console.log(typeof(s4)); // string + 11 console.log(typeof(s5)); // object +``` + +For TypeScript to C++ mapping, string primitive maps to std::string, and String objects maples to builtin String object t2crt::String (same for Booelan and Numbers). + +The type returned by JavaScript/TypeScript String/Number/Boolean builtin/constructor function depends on the usage: +- when used as a function, it is a type converter (convert between literal typeis), returns primitve/literal type string/number/boolean +- when used with new op(), it is a constructor and returns an object +- A variable declared as primitve type string/number/boolean will be wrapped/converted to a String/Number/Boolean object if any object property/method is referenced + For TypeScript to C++, this conversion can be done by the runtime, but there is opportunity for optimization if it can be determined at compile time whether a primitive will be used as an object, in which case the primitve literal can be generated as object intead. + + ## TypeScript types Additionally these TypeScript types will be treated as built-in object types too: diff --git a/src/MapleFE/docs/readme b/src/MapleFE/docs/readme index 732f9f3725c3049fc9bbad1ecaa4016af160b2d0..9ff4bbefc70014338c1bd442785b82389db6b262 100644 --- a/src/MapleFE/docs/readme +++ b/src/MapleFE/docs/readme @@ -47,10 +47,19 @@ alias gounit='cd $unit' - For graphic view of JavaScript object inheritance relations: o cd $MFE/docs/util; node proto.js | ./viewdot.sh -3. TypeScript/JavaScript inheritance modeling in C++ +3. Run a single case from .ts + 1) ~/OpenArkCompiler/src/MapleFE/output/typescript/bin/ts2ast while-stmt.ts + This creates while-stmt.ts.ast at the same directory + 2) ~/OpenArkCompiler/src/MapleFE/output/typescript/bin/ast2cpp while-stmt.ts.ast + This generates the while-stmt.cpp + 3) g++ -g -o run -I/home/ubuntu/OpenArkCompiler/src/MapleFE/ast2cpp/runtime/include -I/home/ubuntu/OpenArkCompiler/src/MapleFE/astopt/include -std=c++17 while-stmt.cpp /home/ubuntu/OpenArkCompiler/src/MapleFE/ast2cpp/runtime/src/*.cpp + This generates the executable run. + 4) ./run to test the result. + +4. TypeScript/JavaScript inheritance modeling in C++ ==================================================== -3.1 JavaScript Object Properties +4.1 JavaScript Object Properties JavaScript objects have both instance properties and inherited properties. Instance properties are held in the object's own property @@ -67,7 +76,7 @@ In Javascript, object property lookup order is: - then lookup inherited property (from property list of object pointed to by chain of __proto__ starting from __proto__ of current object -3.2 TypeScript/JavaScript inheritance modeling in C++ +4.2 TypeScript/JavaScript inheritance modeling in C++ The inheritance relationship of TS/JS objects is mapped to C++ as classes derived hierarchically along the __proto__ chain. This allows @@ -100,7 +109,7 @@ instead of a prototype object, there is still only a single copy of inheited properties, because in JavaScript, there is only 1 single instance of each function constructor. -3.3 Property inheritance with __proto__ chain +4.3 Property inheritance with __proto__ chain See environment section in readme for instruction to view graphic display of JavaScript object inheritance relationship. The following diff --git a/src/MapleFE/scripts/maplefe-autogen.py b/src/MapleFE/scripts/maplefe-autogen.py index 1dd330b3171d70be47f029bddf72fa28b7e02749..f0ffce0cf1f8723de889853653e340c32e058df9 100755 --- a/src/MapleFE/scripts/maplefe-autogen.py +++ b/src/MapleFE/scripts/maplefe-autogen.py @@ -818,7 +818,7 @@ bool PutNode(TreeNode *n) {{ case NK_UserType: *mOs << EnumVal(UserTypeNode, UT_Type, Type); break; case NK_XXportAsPair: *mOs << (static_cast(n)->IsDefault() ? "default" : ""); *mOs << (static_cast(n)->IsRef() ? " ref" : " copy"); break; - case NK_Struct: *mOs << EnumVal(StructNode, StructProp, Prop); break; + case NK_Struct: *mOs << EnumVal(StructNode, StructProp, Prop); *mOs << "\\\\n" << n->GetName(); break; }} if(n->IsStmt()) *mOs << "\\",penwidth=2,color=\\"tomato"; diff --git a/src/MapleFE/scripts/perf-java.sh b/src/MapleFE/scripts/perf-java.sh new file mode 100755 index 0000000000000000000000000000000000000000..b838fd3675cf0b76f7ba0a6bc9aee3d477e59d70 --- /dev/null +++ b/src/MapleFE/scripts/perf-java.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# This script is to measure the runtime performance of java2ast and other executables +# If perf is not installed yet, please install the package linux-tools-common with all dependencies +TS2AST=$(dirname $0)/../output/java/bin/java2ast +CMD="sudo perf record -e cpu-cycles,cache-misses --call-graph fp -F 10000 -o perf.data" +if [ $# -eq 0 ]; then + echo "Usage: $0 " + echo " $0 " + exit 1 +elif [ $# -eq 1 -a "$(basename $1)" != "$(basename $1 .ts)" ]; then + echo $CMD $TS2AST "$@" + $CMD $TS2AST "$@" +else + echo $CMD "$@" + $CMD "$@" +fi +echo sudo perf report +sudo perf report diff --git a/src/MapleFE/shared/include/ast.h b/src/MapleFE/shared/include/ast.h index 58d327ce4fc805b2834e182011b870f95f73f99f..347f8d443493ec5bb3bf048c33a8f7d29e0328a6 100644 --- a/src/MapleFE/shared/include/ast.h +++ b/src/MapleFE/shared/include/ast.h @@ -1830,7 +1830,7 @@ private: SmallVector mThrows; // exceptions it can throw SmallVector mTypeParams; TreeNode *mFuncName; // function name, usually an identifier - TreeNode *mType; // return type + TreeNode *mRetType; // return type SmallVector mParams; // BlockNode *mBody; DimensionNode *mDims; @@ -1909,8 +1909,8 @@ public: void SetTypeParamAtIndex(unsigned i, TreeNode* n) {*(mTypeParams.RefAtIndex(i)) = n; SETPARENT(n);} void AddTypeParam(TreeNode *); - void SetType(TreeNode *t) {mType = t; SETPARENT(t);} - TreeNode* GetType(){return mType;} + void SetRetType(TreeNode *t) {mRetType = t; SETPARENT(t);} + TreeNode* GetRetType(){return mRetType;} DimensionNode* GetDims() {return mDims;} void SetDims(DimensionNode *t) {mDims = t;} @@ -2120,7 +2120,7 @@ enum LambdaProperty { class LambdaNode : public TreeNode { private: LambdaProperty mProperty; - TreeNode *mType; // The return type. nullptr as Java Lambda. + TreeNode *mRetType; // The return type. nullptr as Java Lambda. SmallVector mParams; // A param could be an IdentifierNode or DeclNode. TreeNode *mBody; // the body could be an expression, or block. // nullptr as TS FunctionType and ConstructorType @@ -2128,7 +2128,7 @@ private: SmallVector mAttrs; public: LambdaNode() : TreeNode(NK_Lambda), - mBody(nullptr), mProperty(LP_JSArrowFunction), mType(nullptr) {} + mBody(nullptr), mProperty(LP_JSArrowFunction), mRetType(nullptr) {} ~LambdaNode(){Release();} @@ -2138,8 +2138,8 @@ public: LambdaProperty GetProperty() {return mProperty;} void SetProperty(LambdaProperty p) {mProperty = p;} - TreeNode* GetType() {return mType;} - void SetType(TreeNode* t) {mType = t; SETPARENT(t);} + TreeNode* GetRetType() {return mRetType;} + void SetRetType(TreeNode* t) {mRetType = t; SETPARENT(t);} unsigned GetParamsNum() {return mParams.GetNum();} TreeNode* GetParam(unsigned i) {return mParams.ValueAtIndex(i);} @@ -2388,5 +2388,35 @@ public: void Dump(unsigned); }; +////////////////////////////////////////////////////// +// Triple Slash Directive +////////////////////////////////////////////////////// + +enum TripleSlashProp { + TSP_Path, + TSP_Types, + TSP_Lib, + TSP_NoDefaultLib, + TSP_NA +}; + +class TripleSlashNode : public TreeNode { +private: + TripleSlashProp mProp; + TreeNode *mValue; +public: + TripleSlashNode() : TreeNode(NK_TripleSlash) {mValue = NULL; mProp = TSP_NA;} + ~TripleSlashNode() {} + + TreeNode* GetValue() {return mValue;} + void SetValue(TreeNode *n) {mValue = n; SETPARENT(n);} + + TripleSlashProp GetProp() {return mProp;} + void SetProp(TripleSlashProp p) {mProp = p;} + + void Dump(unsigned); +}; + + } #endif diff --git a/src/MapleFE/shared/include/ast_nk.def b/src/MapleFE/shared/include/ast_nk.def index df99869326ebf7eb81550f2a848277d7d739c885..091b6931090a7a6a88b7c0b802624032fbf30ddc 100644 --- a/src/MapleFE/shared/include/ast_nk.def +++ b/src/MapleFE/shared/include/ast_nk.def @@ -43,6 +43,7 @@ NODEKIND(AsType) NODEKIND(TypeAlias) NODEKIND(ConditionalType) // Conditional types in Typescript NODEKIND(TupleType) // tuple types in Typescript +NODEKIND(FunctionType) // NODEKIND(Cast) @@ -88,6 +89,8 @@ NODEKIND(In) NODEKIND(Is) NODEKIND(Infer) +NODEKIND(TripleSlash) // TS triple-slash directive + NODEKIND(Block) NODEKIND(Function) NODEKIND(Class) diff --git a/src/MapleFE/shared/include/ast_scope.h b/src/MapleFE/shared/include/ast_scope.h index 32131f660cd0b39e07589e967b8660f1f9c5c7b0..088072c362f6c492203110f4d0689223a2281428 100644 --- a/src/MapleFE/shared/include/ast_scope.h +++ b/src/MapleFE/shared/include/ast_scope.h @@ -83,7 +83,7 @@ public: TreeNode* GetExportedDecl(unsigned i) {return mExportedDecls.ValueAtIndex(i);} TreeNode* GetType(unsigned i) {return mTypes.ValueAtIndex(i);} - TreeNode* FindDeclOf(unsigned stridx); + TreeNode* FindDeclOf(unsigned stridx, bool deep = true); TreeNode* FindExportedDeclOf(unsigned stridx); TreeNode* FindTypeOf(unsigned stridx); diff --git a/src/MapleFE/shared/include/ast_type.h b/src/MapleFE/shared/include/ast_type.h index d120eafa87e479250a90ad64622fc82126e45fbc..0f4afe5ee73d61dff5d91d629ab2d40b51d7d471 100644 --- a/src/MapleFE/shared/include/ast_type.h +++ b/src/MapleFE/shared/include/ast_type.h @@ -103,7 +103,7 @@ public: void SetId(TreeNode *n) {mId = n; SETPARENT(n);} unsigned GetUnionInterTypesNum() {return mUnionInterTypes.GetNum();} - void AddUnionInterType(TreeNode *n); + void AddUnionInterType(TreeNode *n, bool front = false); TreeNode* GetUnionInterType(unsigned i) {return mUnionInterTypes.ValueAtIndex(i);} void SetUnionInterType(unsigned i, TreeNode* n) {*(mUnionInterTypes.RefAtIndex(i)) = n; SETPARENT(n);} @@ -136,6 +136,11 @@ public: void Dump(unsigned); }; +/////////////////////////////////////////////////////////////////////////////// +// ArrayTypeNode +// It is used to specify Array types, including element type and dimensions +/////////////////////////////////////////////////////////////////////////////// + class ArrayTypeNode : public TreeNode { private: TreeNode *mElemType; @@ -160,6 +165,29 @@ public: void Dump(unsigned); }; +/////////////////////////////////////////////////////////////////////////////// +// FunctionTypeNode +// It is used to specify function types with its parameters and return type +/////////////////////////////////////////////////////////////////////////////// +class FunctionTypeNode : public TreeNode { +private: + SmallVector mParams; // type index of formal parameters + // and return which is the last one + +public: + FunctionTypeNode() : TreeNode(NK_FunctionType) {} + ~FunctionTypeNode(){} + + unsigned GetParamsNum() {return mParams.GetNum();} + unsigned GetParam(unsigned i) {return mParams.ValueAtIndex(i);} + void SetParam(unsigned i, unsigned n) {*(mParams.RefAtIndex(i)) = n;} + void AddParam(unsigned i) {mParams.PushBack(i);} + void ClearParam() {mParams.Clear();} + + bool IsEqual(FunctionTypeNode *f); + void Dump(unsigned); +}; + /////////////////////////////////////////////////////////////////////////////// // PrimTypeNode & PrimTypePool // The size of PrimTypeNode is fixed, so it's good to use container for the storage. diff --git a/src/MapleFE/shared/include/container.h b/src/MapleFE/shared/include/container.h index 39066b4e9a211b7f2ce0b102e307216ce8099dd9..828a8379e00034339b1eeca24fbc55045b9a79f9 100644 --- a/src/MapleFE/shared/include/container.h +++ b/src/MapleFE/shared/include/container.h @@ -1,5 +1,6 @@ /* * Copyright (C) [2020] Futurewei Technologies, Inc. All rights reverved. +* Copyright (C) 2022 Tencent. All rights reverved. * * OpenArkFE is licensed under the Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -33,6 +34,7 @@ #define __CONTAINER_H__ #include +#include #include "mempool.h" #include "massert.h" #include "macros.h" @@ -777,6 +779,338 @@ public: } }; +//////////////////////////////////////////////////////////////////////// +// GuamianFast uses unordered map to store the Knob-s in order to +// speed up the searching with big number of data. +//////////////////////////////////////////////////////////////////////// + +template class GuamianFast { +private: + struct Elem{ + E mData; + Elem *mNext; + }; + + // Sometimes people need save certain additional information to + // each knob. So we define mData. + struct Knob{ + D mData; + Elem *mChildren; // pointing to the first child + }; + + MemPool mMemPool; + std::unordered_map mKnobs; + + // allocate a new knob + Knob* NewKnob() { + Knob *knob = (Knob*)mMemPool.Alloc(sizeof(Knob)); + knob->mData = 0; + knob->mChildren = NULL; + return knob; + } + + // allocate a new element + Elem* NewElem() { + Elem *elem = (Elem*)mMemPool.Alloc(sizeof(Elem)); + elem->mNext = NULL; + elem->mData = 0; + return elem; + } + + // Sometimes people want to have a sequence of operations like, + // Get the knob, + // Add one element, on the knob + // Add more elements, on the knob. + // This is common scenario. To implement, it requires a temporary + // pointer to the located knob. This temp knob is used ONLY when + // paired operations, PairedFindOrCreateKnob() and PairedAddElem() + struct { + Knob *mKnob; + K mKey; + }mTempKnob; + +private: + // Just try to find the Knob. + // return NULL if fails. + Knob* FindKnob(K key) { + Knob *result = NULL; + auto search = mKnobs.find(key); + if (search != mKnobs.end()) + result = search->second; + return result; + } + + // Try to find the Knob. Create one if failed. + Knob* FindOrCreateKnob(K key) { + Knob *knob = FindKnob(key); + if (!knob) { + knob = NewKnob(); + mKnobs.insert(std::make_pair(key, knob)); + } + return knob; + } + + // Add an element to knob. It's the caller's duty to assure + // knob is not NULL. + void AddElem(Knob *knob, E data) { + Elem *elem = knob->mChildren; + Elem *found = NULL; + while (elem) { + if (elem->mData == data) { + found = elem; + break; + } + elem = elem->mNext; + } + + if (!found) { + Elem *e = NewElem(); + e->mData = data; + e->mNext = knob->mChildren; + knob->mChildren = e; + } + } + + // return true : if find the element + // false : if fail + bool FindElem(Knob *knob, E data) { + Elem *elem = knob->mChildren; + while (elem) { + if (elem->mData == data) + return true; + elem = elem->mNext; + } + return false; + } + + // Remove elem from the list. If elem doesn't exist, exit quietly. + // It's caller's duty to assure elem exists. + void RemoveElem(Knob *knob, E data) { + Elem *elem = knob->mChildren; + Elem *elem_prev = NULL; + Elem *target = NULL; + while (elem) { + if (elem->mData == data) { + target = elem; + break; + } + elem_prev = elem; + elem = elem->mNext; + } + + if (target) { + if (target == knob->mChildren) + knob->mChildren = target->mNext; + else + elem_prev->mNext = target->mNext; + } + } + + // Move the element to be the first child of knob. + // It's the caller's duty to make sure 'data' does exist + // in knob's children. + void MoveElemToHead(Knob *knob, E data) { + Elem *target_elem = NULL; + Elem *elem = knob->mChildren; + Elem *elem_prev = NULL; + while (elem) { + if (elem->mData == data) { + target_elem = elem; + break; + } + elem_prev = elem; + elem = elem->mNext; + } + + if (target_elem && (target_elem != knob->mChildren)) { + elem_prev->mNext = target_elem->mNext; + target_elem->mNext = knob->mChildren; + knob->mChildren = target_elem; + } + } + + // Try to find the first child of Knob k. Return the data. + // found is set to false if fails, or true. + // [NOTE] It's the user's responsibilty to make sure the Knob + // of 'key' exists. + E FindFirstElem(Knob *knob, bool &found) { + Elem *e = knob->mChildren; + if (!e) { + found = false; + return 0; + } + found = true; + return e->mData; + } + + // return num of elements in knob. + // It's caller's duty to assure knob is not NULL. + unsigned NumOfElem(Knob *knob) { + Elem *e = knob->mChildren; + unsigned c = 0; + while(e) { + c++; + e = e->mNext; + } + return c; + } + + // Return the idx-th element in knob. + // It's caller's duty to assure the validity of return value. + // It doesn't check validity here. + // Index starts from 0. + E GetElemAtIndex(Knob *knob, unsigned idx) { + Elem *e = knob->mChildren; + unsigned c = 0; + E data; + while(e) { + if (c == idx) { + data = e->mData; + break; + } + c++; + e = e->mNext; + } + return data; + } + +public: + GuamianFast() {mTempKnob.mKnob = NULL;} + ~GuamianFast(){Release();} + + void AddElem(K key, E data) { + Knob *knob = FindOrCreateKnob(key); + AddElem(knob, data); + } + + // If 'data' doesn't exist, it ends quietly + void RemoveElem(K key, E data) { + Knob *knob = FindOrCreateKnob(key); + RemoveElem(knob, data); + } + + // Try to find the first child of Knob k. Return the data. + // found is set to false if fails, or true. + // [NOTE] It's the user's responsibilty to make sure the Knob + // of 'key' exists. + E FindFirstElem(K key, bool &found) { + Knob *knob = FindKnob(key); + if (!knob) { + found = false; + return 0; // return value doesn't matter when fails. + } + E data = FindFirstElem(knob, found); + return data; + } + + // return true : if find the element + // false : if fail + bool FindElem(K key, E data) { + Knob *knob = FindKnob(key); + if (!knob) + return false; + return FindElem(knob, data); + } + + // Move element to be the header + // If 'data' doesn't exist, it ends quietly. + void MoveElemToHead(K key, E data) { + Knob *knob = FindKnob(key); + if (!knob) + return; + MoveElemToHead(knob, data); + } + + ///////////////////////////////////////////////////////// + // Paired operations start with finding a knob. It can + // be either PairedFindKnob() or PairedFindOrCreateKnob() + // Following that, there could be any number of operations + // like searching, adding, moving an element. + ///////////////////////////////////////////////////////// + + void PairedFindOrCreateKnob(K key) { + mTempKnob.mKnob = FindOrCreateKnob(key); + mTempKnob.mKey = key; + } + + bool PairedFindKnob(K key) { + mTempKnob.mKnob = FindKnob(key); + mTempKnob.mKey = key; + if (mTempKnob.mKnob) + return true; + else + return false; + } + + void PairedAddElem(E data) { + AddElem(mTempKnob.mKnob, data); + } + + // If 'data' doesn't exist, it ends quietly + void PairedRemoveElem(E data) { + RemoveElem(mTempKnob.mKnob, data); + } + + bool PairedFindElem(E data) { + return FindElem(mTempKnob.mKnob, data); + } + + // If 'data' doesn't exist, it ends quietly. + void PairedMoveElemToHead(E data) { + MoveElemToHead(mTempKnob.mKnob, data); + } + + E PairedFindFirstElem(bool &found) { + return FindFirstElem(mTempKnob.mKnob, found); + } + + // return num of elements in current temp knob. + // It's caller's duty to assure knob is not NULL. + unsigned PairedNumOfElem() { + return NumOfElem(mTempKnob.mKnob); + } + + // Return the idx-th element in knob. + // It's caller's duty to assure the validity of return value. + // It doesn't check validity here. + // Index starts from 0. + E PairedGetElemAtIndex(unsigned idx) { + return GetElemAtIndex(mTempKnob.mKnob, idx); + } + + // Reduce the element at index exc_idx. + // It's caller's duty to assure the element exists. + void PairedReduceElems(unsigned exc_idx) { + ReduceElems(mTempKnob.mKnob, exc_idx); + } + + void PairedSetKnobData(D d) { + mTempKnob.mKnob->mData = d; + } + + D PairedGetKnobData() { + return mTempKnob.mKnob->mData; + } + + K PairedGetKnobKey() { + return mTempKnob.mKey; + } + + ///////////////////////////////////////////////////////// + // Other functions + ///////////////////////////////////////////////////////// + + void Clear(){ + mTempKnob.mKnob = NULL; + mKnobs.clear(); + mMemPool.Clear(); + } + + void Release(){ + mMemPool.Release(); + } +}; + ////////////////////////////////////////////////////////////////////////////////////// // Tree // This is a regular tree. It simply maintains the basic operations of a tree, like diff --git a/src/MapleFE/shared/include/lexer.h b/src/MapleFE/shared/include/lexer.h index 151f55b258b5ebb5e8a6c92faecead47c5edb363..00a3f708629d9e8e8d347b56e6e942b241c768fb 100644 --- a/src/MapleFE/shared/include/lexer.h +++ b/src/MapleFE/shared/include/lexer.h @@ -135,6 +135,8 @@ public: virtual bool FindNextTLFormat(unsigned start, std::string& s, unsigned& end) {return false;} virtual bool FindNextTLPlaceHolder(unsigned start, std::string& s, unsigned& end) {return false;} + virtual bool FindTripleSlash() {return false;} + // replace keyword/opr/sep... with tokens //void PlantTokens(); //void PlantTraverseRuleTable(RuleTable*); diff --git a/src/MapleFE/shared/include/parser.h b/src/MapleFE/shared/include/parser.h index a747c23656ba23838301a06b86ad6ed762098a68..5b4a1072bc48fd4bce6da0d79d0ffe37756fbfdb 100644 --- a/src/MapleFE/shared/include/parser.h +++ b/src/MapleFE/shared/include/parser.h @@ -1,7 +1,8 @@ /* * Copyright (C) [2020-2022] Futurewei Technologies, Inc. All rights reverved. +* Copyright 2022 Tencent. All rights reverved. * -* OpenArkFE is licensed under the Mulan PSL v2. +* MapleFE is licensed under the Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * @@ -43,6 +44,7 @@ class TreeNode; typedef enum AppealStatus { FailWasFailed, FailNotRightToken, + FailNotRightString, FailNotIdentifier, FailNotLiteral, FailNotRegExpr, @@ -302,6 +304,7 @@ public: // 1. If the target is a token, we just need compare mCurToken with it. // 2. If the target is a special rule table, like literal, identifier, we just // need check the type of mCurToken. + bool TraverseStringSucc(Token*, AppealNode*, AppealNode *&); bool TraverseToken(Token*, AppealNode*, AppealNode *&); bool TraverseLiteral(RuleTable*, AppealNode*); bool TraverseIdentifier(RuleTable*, AppealNode*); diff --git a/src/MapleFE/shared/include/rule_summary.h b/src/MapleFE/shared/include/rule_summary.h index 5487d3d070eaa4751915bc26ecf5e23303fddbcc..e6803bcd73b5f35eb5b870cb2e33d32d6c272942 100644 --- a/src/MapleFE/shared/include/rule_summary.h +++ b/src/MapleFE/shared/include/rule_summary.h @@ -1,3 +1,19 @@ +/* +* Copyright (C) [2020-2022] Futurewei Technologies, Inc. All rights reverved. +* Copyright 2022 Tencent. All rights reverved. +* +* MapleFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + #ifndef __RULE_SUMMARY_H__ #define __RULE_SUMMARY_H__ #include "ruletable.h" @@ -28,6 +44,7 @@ extern RuleTable TblHEXDIGIT; extern RuleTable TblUTF8; extern RuleTable TblIRREGULAR_CHAR; +extern RuleTable TblNoLineTerminator; extern RuleTable TblTemplateLiteral; extern RuleTable TblRegularExpression; extern RuleTable TblExpression; diff --git a/src/MapleFE/shared/include/stringpool.h b/src/MapleFE/shared/include/stringpool.h index 259e33e6209f4e48f58465f7c7ba4ef7b7cc5cb7..fd8dfee8ab8012e29a2bf5586db57f588e7d1721 100644 --- a/src/MapleFE/shared/include/stringpool.h +++ b/src/MapleFE/shared/include/stringpool.h @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include "massert.h" @@ -45,18 +47,32 @@ private: StringMap *mMap; std::vector mBlocks; int mFirstAvail; // -1 means no available. + bool mUseAltStr; // use alter string std::vector mLongStrings; // for strings longer than block size, // we allocate them by malloc. std::vector mStringTable; + // alternate string which can be used for obfuscation + std::unordered_set mAltStrIdxSet; + std::unordered_map mAltStrIdxMap; + friend class StringMap; public: StringPool(); ~StringPool(); + void SetUseAltStr(bool b) { mUseAltStr = b; } + void AddAltStrIdx(unsigned idx) { mAltStrIdxSet.insert(idx); } + unsigned GetAltStrSize() { return mAltStrIdxSet.size(); } + bool IsAltStrIdx(unsigned idx) { + return mAltStrIdxSet.find(idx) != mAltStrIdxSet.end(); + } + void AddAltStrIdxMap(unsigned orig, unsigned alt) { mAltStrIdxMap[orig] = alt; } + void SetAltStrIdxMap(); + char* AllocBlock(); char* Alloc(const size_t); char* Alloc(const std::string&); @@ -71,12 +87,12 @@ public: unsigned GetStrIdx(const char*); unsigned GetStrIdx(const char*, size_t); - const char *GetStringFromStrIdx(unsigned idx) { - MASSERT(idx < mStringTable.size() && "string index out of range"); - return mStringTable[idx]; - } + unsigned GetSize() {return mStringTable.size();} + + const char *GetStringFromStrIdx(unsigned idx); void Dump(); + void DumpAlt(); }; // Lexing, Parsing, AST Building and IR Building all share one global diff --git a/src/MapleFE/shared/include/succ_match.h b/src/MapleFE/shared/include/succ_match.h index fe78a9ecb27f05f2b4480742b4f3c9998d4556f3..648dc0be294fdb3a04afba79679b5ecb3596c819 100644 --- a/src/MapleFE/shared/include/succ_match.h +++ b/src/MapleFE/shared/include/succ_match.h @@ -1,7 +1,8 @@ /* * Copyright (C) [2020] Futurewei Technologies, Inc. All rights reverved. +* Copyright 2022 Tencent. All rights reverved. * -* OpenArkFE is licensed under the Mulan PSL v2. +* MapleFE is licensed under the Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * @@ -47,8 +48,8 @@ namespace maplefe { class AppealNode; class SuccMatch { private: - Guamian mNodes; - Guamian mMatches; + GuamianFast mNodes; + GuamianFast mMatches; public: SuccMatch(){} diff --git a/src/MapleFE/shared/include/supported_actions.def b/src/MapleFE/shared/include/supported_actions.def index 1b3f48505e78db1c50ff16b47ee3e1e016e44553..ef4710d3862514ff281d00f5f277cbf93d708a66 100644 --- a/src/MapleFE/shared/include/supported_actions.def +++ b/src/MapleFE/shared/include/supported_actions.def @@ -237,5 +237,7 @@ ACTION(AddTypeParameterExtends) ACTION(BuildNameTypePair) +ACTION(BuildTripleSlash) // TS triple-slash directive. + // This is a special action to pass a child to parent ACTION(PassChild) diff --git a/src/MapleFE/shared/include/supported_operators.def b/src/MapleFE/shared/include/supported_operators.def index b09021d0b2e245794d97cc4a420c3e0898afdc3b..2ffa34dd44fa1f53b361757b863c4d9ae861e8b4 100644 --- a/src/MapleFE/shared/include/supported_operators.def +++ b/src/MapleFE/shared/include/supported_operators.def @@ -81,4 +81,5 @@ OPERATOR(StNe, Binary) OPERATOR(ArrowFunction, Binary) OPERATOR(NullCoalesce, Binary) OPERATOR(NullAssign, Binary) +OPERATOR(TripleSlash, Binary) // triple slash directive diff --git a/src/MapleFE/shared/include/typetable.h b/src/MapleFE/shared/include/typetable.h index 2817fadd4efbb22a9dd34536abdabc411f503f5d..d53b17719156f086fefca6fbc7d2f9ec02844e92 100644 --- a/src/MapleFE/shared/include/typetable.h +++ b/src/MapleFE/shared/include/typetable.h @@ -22,10 +22,12 @@ #define __TYPETABLE_H__ #include +#include #include #include #include "massert.h" #include "ast.h" +#include "ast_type.h" namespace maplefe { @@ -51,6 +53,8 @@ private: std::vector mTypeTable; std::unordered_map mNodeId2TypeIdxMap; std::unordered_map mTypeId2TypeMap; + std::unordered_set mPrimTypeId; + std::unordered_set mFuncTypeIdx; unsigned mPrimSize; unsigned mPreBuildSize; @@ -60,14 +64,23 @@ public: unsigned size() { return mTypeTable.size(); } unsigned GetPreBuildSize() { return mPreBuildSize; } + + bool IsPrimTypeId(TypeId tid) { return mPrimTypeId.find(tid) != mPrimTypeId.end(); } unsigned GetPrimSize() { return mPrimSize; } TreeNode *CreatePrimType(std::string name, TypeId tid); TreeNode *CreateBuiltinType(std::string name, TypeId tid); + + void AddPrimTypeId(TypeId tid); void AddPrimAndBuiltinTypes(); bool AddType(TreeNode *node); + TypeEntry *GetTypeEntryFromTypeIdx(unsigned tidx); TreeNode *GetTypeFromTypeIdx(unsigned tidx); TreeNode *GetTypeFromTypeId(TypeId tid) { return mTypeId2TypeMap[tid]; } + TreeNode *GetTypeFromStrIdx(unsigned strid); + + unsigned GetOrCreateFunctionTypeIdx(FunctionTypeNode *type); + void Dump(); }; diff --git a/src/MapleFE/shared/src/ast.cpp b/src/MapleFE/shared/src/ast.cpp index d0772ef4090bbd156e7069f79e4068d715da7edf..f42e21d7ff0442a6825f5ca3dcb6e92968630f91 100644 --- a/src/MapleFE/shared/src/ast.cpp +++ b/src/MapleFE/shared/src/ast.cpp @@ -1775,7 +1775,7 @@ void ClassNode::Dump(unsigned indent) { ////////////////////////////////////////////////////////////////////////////////////// FunctionNode::FunctionNode() : TreeNode(NK_Function), - mFuncName(NULL), mType(NULL), mBody(NULL), mDims(NULL), + mFuncName(NULL), mRetType(NULL), mBody(NULL), mDims(NULL), mIsConstructor(false), mIsGenerator(false), mIsIterator(false), mIsGetAccessor(false), mIsSetAccessor(false), mIsCallSignature(false), mIsConstructSignature(false), mAssert(NULL) {} @@ -1797,7 +1797,7 @@ void FunctionNode::AddTypeParam(TreeNode *param) { // and parameter types. So languages require Type Erasure at first, like Java. // Type erasure should be done earlier in language specific process. bool FunctionNode::OverrideEquivalent(FunctionNode *fun) { - if (!mType->TypeEquivalent(fun->GetType())) + if (!mRetType->TypeEquivalent(fun->GetRetType())) return false; if (GetStrIdx() != fun->GetStrIdx()) return false; @@ -2153,4 +2153,30 @@ void InterfaceNode::Dump(unsigned indent) { } } +void TripleSlashNode::Dump(unsigned indent) { + DumpIndentation(indent); + DUMP0_NORETURN("trip-slash reference "); + + switch(mProp) { + case TSP_Path: + DUMP0_NORETURN("path = "); + break; + case TSP_Types: + DUMP0_NORETURN("types = "); + break; + case TSP_NoDefaultLib: + DUMP0_NORETURN("no-default-lib = "); + break; + case TSP_Lib: + DUMP0_NORETURN("lib = "); + break; + case TSP_NA: + default: + DUMP0_NORETURN("NA = "); + break; + } + + mValue->Dump(0); +} + } diff --git a/src/MapleFE/shared/src/ast_builder.cpp b/src/MapleFE/shared/src/ast_builder.cpp index 8657146ac7d6991cbbd1fc9724777133e07a4f91..016d6a9ae7466c363596d053f3a6e289141f05e6 100644 --- a/src/MapleFE/shared/src/ast_builder.cpp +++ b/src/MapleFE/shared/src/ast_builder.cpp @@ -176,14 +176,14 @@ static void add_type_to(TreeNode *tree, TreeNode *type) { lit->SetType(type); } else if (tree->IsLambda()) { LambdaNode *lam = (LambdaNode*)tree; - lam->SetType(type); + lam->SetRetType(type); } else if (tree->IsVarList()) { VarListNode *vl = (VarListNode*)tree; for (unsigned i = 0; i < vl->GetVarsNum(); i++) vl->GetVarAtIndex(i)->SetType(type); } else if (tree->IsFunction()) { FunctionNode *func = (FunctionNode*)tree; - func->SetType(type); + func->SetRetType(type); } else if (tree->IsBindingPattern()) { BindingPatternNode *bp = (BindingPatternNode*)tree; bp->SetType(type); @@ -1040,6 +1040,8 @@ TreeNode* ASTBuilder::SetIsConst() { } treenode->SetIsConst(); + + mLastTreeNode = treenode; return mLastTreeNode; } @@ -1672,9 +1674,9 @@ TreeNode* ASTBuilder::AddAsType() { if (tree_type) { node->AddAsTypes(tree_type); - mLastTreeNode = node; } + mLastTreeNode = node; return mLastTreeNode; } @@ -3819,7 +3821,7 @@ TreeNode* ASTBuilder::BuildUnionUserType() { // assert, both children cannot be UnionUserType at the same time. MASSERT(!user_type); user_type = ut; - user_type->AddUnionInterType(child_a); + user_type->AddUnionInterType(child_a, true); } } @@ -3865,7 +3867,7 @@ TreeNode* ASTBuilder::BuildInterUserType() { // assert, both children cannot be UnionUserType at the same time. MASSERT(!user_type); user_type = ut; - user_type->AddUnionInterType(child_a); + user_type->AddUnionInterType(child_a, true); } } @@ -4256,6 +4258,50 @@ TreeNode* ASTBuilder::BuildInfer() { return mLastTreeNode; } +//////////////////////////////////////////////////////////////////////////////// +// Triple Slash Directive of TypeScript +//////////////////////////////////////////////////////////////////////////////// + +TreeNode* ASTBuilder::BuildTripleSlash() { + if (mTrace) + std::cout << "In BuildTripleSlash" << std::endl; + + Param l_param = mParams[0]; + MASSERT(!l_param.mIsEmpty); + MASSERT(l_param.mIsTreeNode); + TreeNode *left = l_param.mData.mTreeNode; + + Param r_param = mParams[1]; + MASSERT(!r_param.mIsEmpty); + MASSERT(r_param.mIsTreeNode); + TreeNode *right = r_param.mData.mTreeNode; + + TripleSlashNode *tsnode = (TripleSlashNode*)gTreePool.NewTreeNode(sizeof(TripleSlashNode)); + new (tsnode) TripleSlashNode(); + + TripleSlashProp prop = TSP_NA; + if (left->IsIdentifier()) { + // no-default-lib + if ((strlen(left->GetName()) == 14) && !strncmp(left->GetName(), "no-default-lib", 14)) + prop = TSP_NoDefaultLib; + // lib + if ((strlen(left->GetName()) == 3) && !strncmp(left->GetName(), "lib", 3)) + prop = TSP_Lib; + // types + if ((strlen(left->GetName()) == 5) && !strncmp(left->GetName(), "types", 5)) + prop = TSP_Types; + // path + if ((strlen(left->GetName()) == 4) && !strncmp(left->GetName(), "path", 4)) + prop = TSP_Path; + } + tsnode->SetProp(prop); + + tsnode->SetValue(right); + + mLastTreeNode = tsnode; + return mLastTreeNode; +} + //////////////////////////////////////////////////////////////////////////////// // Await //////////////////////////////////////////////////////////////////////////////// diff --git a/src/MapleFE/shared/src/ast_scope.cpp b/src/MapleFE/shared/src/ast_scope.cpp index 7441ddac5ef88164751bc1e475463b9ff510dbc7..f1e5505be67a6b5e36140edc8200f9c4c4f62fd3 100644 --- a/src/MapleFE/shared/src/ast_scope.cpp +++ b/src/MapleFE/shared/src/ast_scope.cpp @@ -31,7 +31,7 @@ void ASTScope::AddChild(ASTScope *s) { // This is to find the decl having the name as stridx // starting from local scope -TreeNode* ASTScope::FindDeclOf(unsigned stridx) { +TreeNode* ASTScope::FindDeclOf(unsigned stridx, bool deep) { ASTScope *scope = this; while (scope) { for (unsigned i = 0; i < scope->GetDeclNum(); i++) { @@ -46,8 +46,8 @@ TreeNode* ASTScope::FindDeclOf(unsigned stridx) { return tree; } } - // search parent scope - scope = scope->mParent; + // search parent scope if deep is set + scope = deep ? scope->mParent : NULL; } return NULL; } diff --git a/src/MapleFE/shared/src/ast_type.cpp b/src/MapleFE/shared/src/ast_type.cpp index 48744a1850407b0574586ad28d1e4eb1a7da73e7..74ab86984068083463faea968862b181c685d6b0 100644 --- a/src/MapleFE/shared/src/ast_type.cpp +++ b/src/MapleFE/shared/src/ast_type.cpp @@ -27,7 +27,7 @@ namespace maplefe { // UserTypeNode // ////////////////////////////////////////////////////////////////////////// -void UserTypeNode::AddUnionInterType(TreeNode *args) { +void UserTypeNode::AddUnionInterType(TreeNode *args, bool front) { if (args->IsIdentifier() || args->IsPrimType() || args->IsPrimArrayType() || @@ -42,8 +42,14 @@ void UserTypeNode::AddUnionInterType(TreeNode *args) { args->IsKeyOf() || args->IsImport() || args->IsField() || + args->IsTemplateLiteral() || args->IsStruct()) { mUnionInterTypes.PushBack(args); + if (front) { + for(unsigned i = mUnionInterTypes.GetNum() - 1; i > 0; --i) + mUnionInterTypes.SetElem(i, mUnionInterTypes.ValueAtIndex(i-1)); + mUnionInterTypes.SetElem(0, args); + } SETPARENT(args); } else if (args->IsPass()) { PassNode *p = (PassNode*)args; @@ -175,6 +181,29 @@ static TypeId FindPrimTypeId(const char *keyword) { return TY_NA; } +////////////////////////////////////////////////////////////////////////// +// FunctionTypeNode // +////////////////////////////////////////////////////////////////////////// + +bool FunctionTypeNode::IsEqual(FunctionTypeNode *node) { + bool result = true; + if (node->GetParamsNum() != GetParamsNum()) { + result = false; + } else { + for (unsigned i = 0; i < GetParamsNum(); i++) { + if (node->GetParam(i) != GetParam(i)) { + result = false; + break; + } + } + } + return result; +} + +void FunctionTypeNode::Dump(unsigned ind) { + DUMP0_NORETURN("functiontype-TBD"); +} + ////////////////////////////////////////////////////////////////////////// // PrimTypeNode // ////////////////////////////////////////////////////////////////////////// diff --git a/src/MapleFE/shared/src/lexer.cpp b/src/MapleFE/shared/src/lexer.cpp index ccd8a5a2550bfde4a62a4a98b4df4660e8a2d61f..694f86a8edafedea9ff0584a140a9b0e25777951 100644 --- a/src/MapleFE/shared/src/lexer.cpp +++ b/src/MapleFE/shared/src/lexer.cpp @@ -541,6 +541,9 @@ LitData Lexer::GetLiteral() { // // Return true if a comment is read. The contents are ignore. bool Lexer::GetComment() { + if (FindTripleSlash()) + return false; + if (line[curidx] == '/' && line[curidx+1] == '/') { curidx = current_line_size; return true; @@ -654,7 +657,9 @@ bool Lexer::TraverseTableData(TableData *data) { // Need to make sure the following text is a separator curidx += strlen(data->mData.mString); if (mCheckSeparator || special_need_check) { - if ((TraverseSepTable() != SEP_NA) || (TraverseOprTable() != OPR_NA)) { + if ((TraverseSepTable() != SEP_NA) || + (TraverseOprTable() != OPR_NA) || + EndOfLine()) { // TraverseSepTable() moves 'curidx', need restore it curidx = old_pos + strlen(data->mData.mString); // Put into gStringPool diff --git a/src/MapleFE/shared/src/parser.cpp b/src/MapleFE/shared/src/parser.cpp index 12e8d953dc4e61a8ad5ddeb8efc18b7c7d9251a4..a3f8139a95310f5d692004b8e687b0ca5c6bbca6 100644 --- a/src/MapleFE/shared/src/parser.cpp +++ b/src/MapleFE/shared/src/parser.cpp @@ -576,14 +576,6 @@ ParseStatus Parser::ParseStmt() { mRootNode = mAppealNodePool.NewAppealNode(); mAppealNodes.push_back(mRootNode); - // mActiveTokens contain some un-matched tokens from last time of TraverseStmt(), - // because at the end of every TraverseStmt() when it finishes its matching it always - // MoveCurToken() which in turn calls LexOneLine() to read new tokens of a new line. - // - // This means in LexOneLine() we also need check if there are already tokens pending. - // - // [TODO] Later on, we will move thoes pending tokens to a separate data structure. - unsigned token_num = LexOneLine(); // No more token, end of file if (!token_num) @@ -806,6 +798,8 @@ void Parser::DumpExitTable(const char *table_name, unsigned indent, std::cout << " fail@WasFailed" << "}" << std::endl; else if (reason == FailNotRightToken) std::cout << " fail@NotRightToken" << "}" << std::endl; + else if (reason == FailNotRightString) + std::cout << " fail@NotRightString" << "}" << std::endl; else if (reason == FailNotIdentifier) std::cout << " fail@NotIdentifer" << "}" << std::endl; else if (reason == FailNotLiteral) @@ -876,6 +870,10 @@ bool Parser::LookAheadFail(RuleTable *rule_table, unsigned token) { if (curr_token->IsTempLit() || curr_token->IsRegExpr()) found = true; } + if (rule_table == &TblNoLineTerminator) { + if (!curr_token->mLineBegin) + found = true; + } } break; case LA_Identifier: @@ -1210,6 +1208,14 @@ bool Parser::TraverseRuleTableRegular(RuleTable *rule_table, AppealNode *appeal) if ((rule_table == &TblRegularExpression)) return TraverseRegularExpression(rule_table, appeal); + if (rule_table == &TblNoLineTerminator) { + Token *token = mActiveTokens.ValueAtIndex(mCurToken); + if (token->mLineBegin) + return false; + else + return true; + } + EntryType type = rule_table->mType; switch(type) { case ET_Oneof: @@ -1260,6 +1266,41 @@ bool Parser::TraverseRuleTableRegular(RuleTable *rule_table, AppealNode *appeal) } } +// Returns 1. true if succ. +// 2. child_node which represents 'token'. +bool Parser::TraverseStringSucc(Token *token, AppealNode *parent, AppealNode *&child_node) { + AppealNode *appeal = NULL; + mIndentation += 2; + + if (mTraceTable) { + std::string name = "string:"; + name += token->GetName(); + name += " curr_token matches"; + DumpEnterTable(name.c_str(), mIndentation); + } + + appeal = mAppealNodePool.NewAppealNode(); + child_node = appeal; + mAppealNodes.push_back(appeal); + appeal->SetToken(token); + appeal->SetStartIndex(mCurToken); + appeal->SetParent(parent); + parent->AddChild(appeal); + appeal->mResult = Succ; + appeal->AddMatch(mCurToken); + MoveCurToken(); + + if (mTraceTable) { + std::string name; + name = "string:"; + name += token->GetName(); + DumpExitTable(name.c_str(), mIndentation, appeal); + } + + mIndentation -= 2; + return true; +} + // Returns 1. true if succ. // 2. child_node which represents 'token'. bool Parser::TraverseToken(Token *token, AppealNode *parent, AppealNode *&child_node) { @@ -1668,17 +1709,21 @@ bool Parser::TraverseConcatenate(RuleTable *rule_table, AppealNode *appeal) { bool turned_on_AltToken = false; for (unsigned i = 0; i < rule_table->mNum; i++) { - bool is_zeroxxx = false; + bool is_zeroxxx = false; // If the table is Zeroorxxx(), or NoLineTerminator. + bool no_line_term = false; // If the table is NoLineTerminator + bool no_line_term_met = false; // If the table is NoLineTerminator and token is no line term. bool is_asi = false; bool is_token = false; bool old_mInAltTokensMatching = mInAltTokensMatching; TableData *data = rule_table->mData + i; if (data->mType == DT_Subtable) { - RuleTable *zero_rt = data->mData.mEntry; - if (zero_rt->mType == ET_Zeroormore || zero_rt->mType == ET_Zeroorone) + RuleTable *curr_rt = data->mData.mEntry; + if (curr_rt == &TblNoLineTerminator) + no_line_term = true; + if (curr_rt->mType == ET_Zeroormore || curr_rt->mType == ET_Zeroorone) is_zeroxxx = true; - if (zero_rt->mType == ET_ASI) + if (curr_rt->mType == ET_ASI) is_asi = true; } else if (data->mType == DT_Token) { is_token = true; @@ -1720,11 +1765,18 @@ bool Parser::TraverseConcatenate(RuleTable *rule_table, AppealNode *appeal) { } } + if ((prev_succ_tokens.GetNum() == 1) && no_line_term) { + unsigned prev = prev_succ_tokens.ValueAtIndex(0); + Token *t = GetActiveToken(prev + 1); + if (!t->mLineBegin) + no_line_term_met = true; + } + // for Zeroorone/Zeroormore node it always returns true. NO matter how // many tokens it really matches, 'zero' is also a correct match. we // need take it into account so that the next rule table can try // on it. - if (!is_zeroxxx) + if (!is_zeroxxx && !no_line_term_met) prev_succ_tokens.Clear(); // is_zeroxxx seems redundant because the traversal should always be true. @@ -1806,10 +1858,14 @@ bool Parser::TraverseTableData(TableData *data, AppealNode *appeal, AppealNode * switch (data->mType) { case DT_Char: + MASSERT(0 && "Hit Char in TableData during matching!"); + break; case DT_String: - //MASSERT(0 && "Hit Char/String in TableData during matching!"); - //TODO: Need compare literal. But so far looks like it's impossible to - // have a literal token able to match a string/char in rules. + if (curr_token->IsIdentifier() && + !strncmp(curr_token->GetName(), data->mData.mString, strlen(data->mData.mString)) && + strlen(curr_token->GetName()) == strlen(data->mData.mString) ){ + found = TraverseStringSucc(curr_token, appeal, child_node); + } break; // separator, operator, keywords are generated as DT_Token. // just need check the pointer of token @@ -1854,8 +1910,10 @@ void Parser::SetIsDone(RuleTable *rt, unsigned start_token) { SuccMatch *succ = &gSucc[rt->mIndex]; bool found = succ->GetStartToken(start_token); - MASSERT(found); - succ->SetIsDone(); + if (rt != &TblNoLineTerminator) { + MASSERT(found); + succ->SetIsDone(); + } } ///////////////////////////////////////////////////////////////////////////// @@ -2243,7 +2301,7 @@ void Parser::SortOutConcatenate(AppealNode *parent) { if (!child) { if (data->mType == DT_Subtable) { RuleTable *table = data->mData.mEntry; - if (table->mType == ET_Zeroorone || table->mType == ET_Zeroormore) + if (table->mType == ET_Zeroorone || table->mType == ET_Zeroormore || table == &TblNoLineTerminator) good_child = true; if (table->mType == ET_ASI) good_child = true; diff --git a/src/MapleFE/shared/src/stringpool.cpp b/src/MapleFE/shared/src/stringpool.cpp index 1c96f4553e687943d4a866b4be67693bcb9dc7ab..3b6e292486e4199e33c3347bc6bc941298d08b41 100644 --- a/src/MapleFE/shared/src/stringpool.cpp +++ b/src/MapleFE/shared/src/stringpool.cpp @@ -20,6 +20,7 @@ #include #include +#include #include "stringpool.h" #include "stringmap.h" @@ -31,6 +32,7 @@ namespace maplefe { StringPool gStringPool; StringPool::StringPool() { + mUseAltStr = false; mMap = new StringMap(); mMap->SetPool(this); mFirstAvail = -1; @@ -173,11 +175,107 @@ unsigned StringPool::GetStrIdx(const char *str, size_t len) { return mMap->LookupEntryFor(s)->GetStrIdx(); } +const char *StringPool::GetStringFromStrIdx(unsigned idx) { + MASSERT(idx < mStringTable.size() && "string index out of range"); + if (mUseAltStr) { + if (mAltStrIdxMap.find(idx) != mAltStrIdxMap.end()) { + idx = mAltStrIdxMap[idx]; + } + } + return mStringTable[idx]; +} + +// This is the public interface to setup AltStrIdxMap used for obfuscation +// a name is mapped to a fixed length random unused name. +// starting from 2-letter names, [a-zA-Z] [a-zA-Z], which will cover over 2K names +// AA Aa AB Ab, ...., zz +// if not enough will extend to use 3-letter or 4-letter for over 7 million names +void StringPool::SetAltStrIdxMap() { + // starting from 2-letter names + unsigned len = 2; + bool done = false; + + // names use [A-Z] and [a-z] total 52 letters + int k = 52; + + // total number of names can be handled for len = 4, 3, 2, 1 respectively + int Size[4] = {k*k*k*k, k*k*k, k*k, k}; + + // names, trailing '\0' + char A[5] = {0, 0, 0, 0, 0}; + + // names already encounted, either existing name or new names + std::unordered_set used; + + for (auto stridx : mAltStrIdxSet) { + done = false; + while (!done) { + unsigned offset = 4 - len; + int mod = Size[offset]; + + int n = rand(); + int r = n % mod; + + // check if already encounted + if (used.find(r) != used.end()) { + // expand to use one more leter if close to limit + if (used.size() > mod - Size[offset + 1]) { + len++; + MASSERT(len < 5 && "Need more names"); + } + continue; + } + + // have un-encounted name + used.insert(r); + + int q; + bool odd; + int i = 0; + while (i < len - 1) { + mod = Size[offset + 1 + i]; + q = r / mod; + r = r % mod; + + // char, use upper case for odd number + odd = q%2; + A[i++] = (odd ? 'A' : 'a') + q/2; + } + + // last char, use upper case for odd number + odd = r%2; + A[i] = (odd ? 'A' : 'a') + r/2; + + unsigned size = GetSize(); + unsigned alt = GetStrIdx(A); + // make sure alt is a new string + if (alt == size) { + mAltStrIdxMap[stridx] = alt; + done = true; + } + } + } +} + void StringPool::Dump() { std::cout << "===================== StringTable =====================" << std::endl; for (unsigned idx = 1; idx < mStringTable.size(); idx++) { std::cout << " " << idx << " : " << mStringTable[idx] << std::endl; } } + +void StringPool::DumpAlt() { + std::cout << "================= Alt String Map ======================" << std::endl; + unsigned count = 0; + for (auto stridx : mAltStrIdxSet) { + unsigned alt = mAltStrIdxMap[stridx]; + std::cout << "count #" << stridx + << " str " << GetStringFromStrIdx(stridx) + << " --> " + << " alt " << GetStringFromStrIdx(alt) + << std::endl; + } +} + } diff --git a/src/MapleFE/shared/src/typetable.cpp b/src/MapleFE/shared/src/typetable.cpp index ad58543fd809f6c4f6a31c1204ba28f853c1db07..8a1d8a93e96c53f2c8636eafbdebf5d22e352a57 100644 --- a/src/MapleFE/shared/src/typetable.cpp +++ b/src/MapleFE/shared/src/typetable.cpp @@ -69,7 +69,8 @@ TreeNode *TypeTable::CreateBuiltinType(std::string name, TypeId tid) { unsigned stridx = gStringPool.GetStrIdx(name); IdentifierNode *id = (IdentifierNode*)gTreePool.NewTreeNode(sizeof(IdentifierNode)); new (id) IdentifierNode(stridx); - id->SetTypeId(tid); + // use TY_Class for Object type + (tid == TY_Object) ? id->SetTypeId(TY_Class) : id->SetTypeId(tid); UserTypeNode *utype = (UserTypeNode*)gTreePool.NewTreeNode(sizeof(UserTypeNode)); new (utype) UserTypeNode(id); @@ -82,18 +83,25 @@ TreeNode *TypeTable::CreateBuiltinType(std::string name, TypeId tid) { } bool TypeTable::AddType(TreeNode *node) { - unsigned id = node->GetNodeId(); - if (mNodeId2TypeIdxMap.find(id) != mNodeId2TypeIdxMap.end()) { + unsigned nid = node->GetNodeId(); + if (mNodeId2TypeIdxMap.find(nid) != mNodeId2TypeIdxMap.end()) { return false; } - unsigned tid = mTypeTable.size(); - mNodeId2TypeIdxMap[id] = tid; - node->SetTypeIdx(tid); + unsigned tidx = mTypeTable.size(); + mNodeId2TypeIdxMap[nid] = tidx; + node->SetTypeIdx(tidx); + if (node->IsUserType()) { + static_cast(node)->GetId()->SetTypeIdx(tidx); + } TypeEntry *entry = new TypeEntry(node); mTypeTable.push_back(entry); return true; } +void TypeTable::AddPrimTypeId(TypeId tid) { + mPrimTypeId.insert(tid); +} + #undef TYPE #undef PRIMTYPE void TypeTable::AddPrimAndBuiltinTypes() { @@ -109,7 +117,7 @@ void TypeTable::AddPrimAndBuiltinTypes() { // first are primitive types, and their typeid TY_Xyz is their typeidx as well #define TYPE(T) -#define PRIMTYPE(T) node = CreatePrimType(#T, TY_##T); AddType(node); +#define PRIMTYPE(T) node = CreatePrimType(#T, TY_##T); AddType(node); AddPrimTypeId(TY_##T); #include "supported_types.def" // add additional primitive types for number and string PRIMTYPE(Number); @@ -117,7 +125,7 @@ void TypeTable::AddPrimAndBuiltinTypes() { mPrimSize = size(); -#define TYPE(T) node = CreateBuiltinType(#T, TY_##T); AddType(node); +#define TYPE(T) node = CreateBuiltinType(#T, TY_##T); AddType(node); #define PRIMTYPE(T) // additional usertype Boolean TYPE(Boolean); @@ -127,14 +135,46 @@ void TypeTable::AddPrimAndBuiltinTypes() { return; } -TypeEntry *TypeTable::GetTypeEntryFromTypeIdx(unsigned idx) { - MASSERT(idx < mTypeTable.size() && "type index out of range"); - return mTypeTable[idx]; +TypeEntry *TypeTable::GetTypeEntryFromTypeIdx(unsigned tidx) { + MASSERT(tidx < mTypeTable.size() && "type index out of range"); + return mTypeTable[tidx]; +} + +TreeNode *TypeTable::GetTypeFromTypeIdx(unsigned tidx) { + MASSERT(tidx < mTypeTable.size() && "type index out of range"); + return mTypeTable[tidx]->GetType(); +} + +TreeNode *TypeTable::GetTypeFromStrIdx(unsigned stridx) { + for (auto entry : mTypeTable) { + TreeNode *node = entry->GetType(); + if (node && node->GetStrIdx() == stridx) { + return node; + } + } + return NULL; } -TreeNode *TypeTable::GetTypeFromTypeIdx(unsigned idx) { - MASSERT(idx < mTypeTable.size() && "type index out of range"); - return mTypeTable[idx]->GetType(); +unsigned TypeTable::GetOrCreateFunctionTypeIdx(FunctionTypeNode *node) { + for (auto tidx: mFuncTypeIdx) { + TreeNode *type = GetTypeFromTypeIdx(tidx); + FunctionTypeNode *functype = static_cast(type); + bool found = functype->IsEqual(node); + if (found) { + return tidx; + } + } + bool status = AddType(node); + MASSERT(status && "failed to add a functiontype"); + unsigned tidx = node->GetTypeIdx(); + mFuncTypeIdx.insert(tidx); + + std::string str("FuncType__"); + str += std::to_string(tidx); + unsigned stridx = gStringPool.GetStrIdx(str); + node->SetStrIdx(stridx); + + return tidx; } void TypeTable::Dump() { diff --git a/src/MapleFE/shared/src/vfy.cpp b/src/MapleFE/shared/src/vfy.cpp index cb03fb5439385aabf65f7bf4684633acb8c0cb85..07809d0f89ed58d2191117ee254c9fe0ca949449 100644 --- a/src/MapleFE/shared/src/vfy.cpp +++ b/src/MapleFE/shared/src/vfy.cpp @@ -568,4 +568,12 @@ void Verifier::VerifyArrayType(ArrayTypeNode *tree){ return; } +void Verifier::VerifyTripleSlash(TripleSlashNode *tree){ + return; +} + +void Verifier::VerifyFunctionType(FunctionTypeNode *tree){ + return; +} + } diff --git a/src/MapleFE/test/astdump.sh b/src/MapleFE/test/astdump.sh index db62279ca83707ad71e16a7c3827851c59a1cebb..2260c58f95c703efdf91b6bb871d883f67219a3f 100755 --- a/src/MapleFE/test/astdump.sh +++ b/src/MapleFE/test/astdump.sh @@ -110,8 +110,6 @@ for ts in $LIST; do T=$(sed -e "s/\(.*\)\(\.d\)\(\.ts-$PROCID.out\)/\1\2\3\2/" <<< "$ts-$PROCID.out.ts") eval $cmd <<< "$out" > "$T" [ -z "$NAME" ] || sed -i 's/__v[0-9][0-9]*//g' "$T" - clang-format-10 -i --style="{ColumnLimit: 120, JavaScriptWrapImports: false, AlignOperands: false}" "$T" - sed -i -e 's/?? =/??=/g' -e 's/ int\[/ number[/g' "$T" echo -e "\n====== TS Reformatted ======\n" $HIGHLIGHT "$T" echo TREEDIFF=$TREEDIFF @@ -132,8 +130,6 @@ for ts in $LIST; do [ -n "$KEEP" ] || rm -f "$T" else cp $ts $ts.tmp.ts - clang-format-10 -i --style="{ColumnLimit: 120, JavaScriptWrapImports: false, AlignOperands: false, JavaScriptQuotes: Double}" $ts.tmp.ts - sed -i 's/?? =/??=/g' $ts.tmp.ts $TS2AST $ts.tmp.ts if [ $? -eq 0 ]; then $AST2CPP $ts.tmp.ts.ast $TREEDIFF | sed -n '/^AstDump:/,/^}/p' | sed 's/\(mStrIdx: unsigned int, \)[0-9]* =>/\1=>/' diff --git a/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result b/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result index 73efc592e98fb5a4c189e1b0bf162db5ebfcec9a..06e1681196983bfca57f375df768dced69a0d430 100644 --- a/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result +++ b/src/MapleFE/test/typescript/ms_tests/checkInterfaceBases.ts.result @@ -1,10 +1,13 @@ Matched 16 tokens. Matched 24 tokens. Matched 32 tokens. +Matched 40 tokens. ============= Module =========== == Sub Tree == ts_interface: JQueryEventObjectTest {data;which;metaKey } == Sub Tree == +trip-slash reference path = "jquery.d.ts" +== Sub Tree == ts_interface: SecondEvent {data } == Sub Tree == ts_interface: Third { } diff --git a/src/MapleFE/test/typescript/unit_tests/class6.ts b/src/MapleFE/test/typescript/unit_tests/class6.ts new file mode 100644 index 0000000000000000000000000000000000000000..ad924fc06795ae44aa9fc447ddf7a8480482c9f2 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/class6.ts @@ -0,0 +1,20 @@ +class Klass { + public num: number = 1; + + if(n: number): boolean { + return this.num == n; + } + + try(n: number): void { + if(n == this.num) + console.log("EQ"); + else + console.log("NE"); + } +} + +var obj: Klass = new Klass(); +console.log(obj.if(0)); +console.log(obj.if(1)); +obj.try(0); +obj.try(1); diff --git a/src/MapleFE/test/typescript/unit_tests/class6.ts.result b/src/MapleFE/test/typescript/unit_tests/class6.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..08a20f91d9cb7bde8eba40afc7635cd73adeb7ca --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/class6.ts.result @@ -0,0 +1,34 @@ +Matched 61 tokens. +Matched 71 tokens. +Matched 83 tokens. +Matched 95 tokens. +Matched 102 tokens. +Matched 109 tokens. +============= Module =========== +== Sub Tree == +class Klass + Fields: + num=1 + Instance Initializer: + Constructors: + Methods: + func if(n) throws: + return this.num EQ n + func try(n) throws: + cond-branch cond:n EQ this.num + true branch : + console.log("EQ") false branch : + console.log("NE") + LocalClasses: + LocalInterfaces: + +== Sub Tree == +js_var Decl: obj=new Klass() +== Sub Tree == +console.log(obj.if(0)) +== Sub Tree == +console.log(obj.if(1)) +== Sub Tree == +obj.try(0) +== Sub Tree == +obj.try(1) diff --git a/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts new file mode 100644 index 0000000000000000000000000000000000000000..dd9965a57cfc8382a32c2ae6a50b371fa371ef6d --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts @@ -0,0 +1,6 @@ +class Klass { + else: number = 0; +} + +var obj: Klass = new Klass(); +console.log(obj, obj.else); diff --git a/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..b14f7e7d22946f638f60fdd316acf89110a295ee --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/else-as-prop-name.ts.result @@ -0,0 +1,18 @@ +Matched 10 tokens. +Matched 20 tokens. +Matched 31 tokens. +============= Module =========== +== Sub Tree == +class Klass + Fields: + else=0 + Instance Initializer: + Constructors: + Methods: + LocalClasses: + LocalInterfaces: + +== Sub Tree == +js_var Decl: obj=new Klass() +== Sub Tree == +console.log(obj,obj.else) diff --git a/src/MapleFE/test/typescript/unit_tests/import-ambient-module.ts.result b/src/MapleFE/test/typescript/unit_tests/import-ambient-module.ts.result index 42db4d50cd1948ed6342f61d5646f75724f35a84..c71e900f9a1c38da2856901eb5858a378b61611c 100644 --- a/src/MapleFE/test/typescript/unit_tests/import-ambient-module.ts.result +++ b/src/MapleFE/test/typescript/unit_tests/import-ambient-module.ts.result @@ -1,7 +1,10 @@ -Matched 7 tokens. -Matched 14 tokens. +Matched 8 tokens. +Matched 15 tokens. +Matched 22 tokens. ============= Module =========== == Sub Tree == +trip-slash reference path = "import-in-module.ts" +== Sub Tree == import {X} "M1" == Sub Tree == import {NS} "M2" diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts new file mode 100644 index 0000000000000000000000000000000000000000..a21a6ce8a1190aa1bc6a8f85e5d85179ee1dbbb8 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts @@ -0,0 +1,16 @@ +var n: number = 1; +switch (true) { + case n < 5: + console.log(n, " is less than 5"); + case n > 2 && n < 5: + console.log(n, " + 1 is equal to", n + 1); + break; + case n == 6: + console.log(n, " is equal to 6"); + break; + case n < 8: + console.log(n, " is greater than 4 and less than 8"); + break + default: + console.log(n, " is greater than 7"); +} diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..78c460f980018fd17fd60b48153b7b3b98ca4a9e --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing15.ts.result @@ -0,0 +1,8 @@ +Matched 7 tokens. +Matched 93 tokens. +============= Module =========== +== Sub Tree == +js_var Decl: n=1 +== Sub Tree == +A switch + diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts b/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts new file mode 100644 index 0000000000000000000000000000000000000000..3caad616a659fe6951afcd48192e7063c6a0f87c --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts @@ -0,0 +1,8 @@ +function func(arg: number): number | undefined { + if(arg < 1) return + for(let i = 0; i < arg; i++) + console.log(i); + return arg * 10; +} +console.log(func(3)); + diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts.result b/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..5a85dd3971104c3fd5b7e648634c0a1e7b0ff316 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing16.ts.result @@ -0,0 +1,15 @@ +Matched 46 tokens. +Matched 56 tokens. +============= Module =========== +== Sub Tree == +func func(arg) throws: + cond-branch cond:arg LT 1 + true branch : + return false branch : + + for ( ) + console.log(i) + return arg Mul 10 + +== Sub Tree == +console.log(func(3)) diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5c4aff91fda35a3bfecf34ccd70dfe72cdf7624 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts @@ -0,0 +1,9 @@ +function func(arg: number): number | undefined { + for(let i = 0; i < arg; i++) { + if(i % 2 > 0) continue + console.log(i); + } + return arg * 10; +} +console.log(func(5)); + diff --git a/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..6de52c4b72ce0abb85198d4eeeaf62bc051bb110 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/semicolon-missing17.ts.result @@ -0,0 +1,17 @@ +Matched 50 tokens. +Matched 60 tokens. +============= Module =========== +== Sub Tree == +func func(arg) throws: + for ( ) + cond-branch cond:i Mod 2 GT 0 + true branch : + continue: + false branch : + + console.log(i) + + return arg Mul 10 + +== Sub Tree == +console.log(func(5)) diff --git a/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts new file mode 100644 index 0000000000000000000000000000000000000000..073bae7598a49870fb29a75da43f6c479ed99402 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts @@ -0,0 +1,12 @@ +class Num { + neg: boolean = false; + val: number = 0; +} + +function func(v: Num): `${string}n` | `-${string}n` { + return `${v.neg ? '-' : ''}${v.val}n`; +} + +var obj : Num = {neg: true, val: 123}; +console.log(func(obj)); +console.log(typeof func(obj)); diff --git a/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..70ca48c63fb79ef537785175df99a5d33a80e5f2 --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/template-literal-type.ts.result @@ -0,0 +1,30 @@ +Matched 16 tokens. +Matched 32 tokens. +Matched 47 tokens. +Matched 57 tokens. +Matched 68 tokens. +Matched 69 tokens. +Matched 70 tokens. +Matched 77 tokens. +Matched 80 tokens. +============= Module =========== +== Sub Tree == +class Num + Fields: + neg=false val=0 + Instance Initializer: + Constructors: + Methods: + LocalClasses: + LocalInterfaces: + +== Sub Tree == +func func(v) throws: + return template-literal: NULL,v.neg ? "-" : "",NULL,v.val,"n",NULL + +== Sub Tree == +js_var Decl: obj= {neg:true, val:123} +== Sub Tree == +console.log(func(obj)) +== Sub Tree == +console.log( typeof func(obj)) diff --git a/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts new file mode 100644 index 0000000000000000000000000000000000000000..29e5a31ca3b3a3ba94f49fbc89206d3bd06ec68c --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts @@ -0,0 +1,10 @@ +enum ET { + TOP = "top", /// < top string + BOTTOM = "bottom", ///< bottom string +} + +/// +/// + +let et = ET.TOP; +console.log(et); diff --git a/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..e4afff30c02415e10dfeab2420a63675b1286d5d --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/triple-slash-comment.ts.result @@ -0,0 +1,10 @@ +Matched 12 tokens. +Matched 19 tokens. +Matched 26 tokens. +============= Module =========== +== Sub Tree == +ts_enum: ET {TOP="top";BOTTOM="bottom" } +== Sub Tree == +js_let Decl: et=ET.TOP +== Sub Tree == +console.log(et) diff --git a/src/MapleFE/test/typescript/unit_tests/triple-slash-dir.d.ts.result b/src/MapleFE/test/typescript/unit_tests/triple-slash-dir.d.ts.result index f9052bd4b2db8b75cc78e04aad0acd979d29b938..0e74c743cd4c0c3b70270bc58d388ad13603002f 100644 --- a/src/MapleFE/test/typescript/unit_tests/triple-slash-dir.d.ts.result +++ b/src/MapleFE/test/typescript/unit_tests/triple-slash-dir.d.ts.result @@ -1 +1,7 @@ +Matched 8 tokens. +Matched 16 tokens. ============= Module =========== +== Sub Tree == +trip-slash reference no-default-lib = "true" +== Sub Tree == +trip-slash reference lib = "es5" diff --git a/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd97f5cab3b2af51e3f45bca1c7320496a53b5ff --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts @@ -0,0 +1,10 @@ +const obj = { + else() { + return this; + }, + var() { + console.log("var"); + } +} + +obj.else().var(); diff --git a/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result new file mode 100644 index 0000000000000000000000000000000000000000..7fcef6b23a7beaf3d03a4115b40cfebcf5da9d1f --- /dev/null +++ b/src/MapleFE/test/typescript/unit_tests/var-as-prop-name.ts.result @@ -0,0 +1,11 @@ +Matched 26 tokens. +Matched 36 tokens. +============= Module =========== +== Sub Tree == +js_const Decl: obj= {else:func else() throws: + return this +, var:func var() throws: + console.log("var") +} +== Sub Tree == +obj.else().var() diff --git a/src/MapleFE/tools/obfuscate/include/obfuscate.h b/src/MapleFE/tools/obfuscate/include/obfuscate.h new file mode 100644 index 0000000000000000000000000000000000000000..63574ba6d02657eb5293605a36236e4a14374fe3 --- /dev/null +++ b/src/MapleFE/tools/obfuscate/include/obfuscate.h @@ -0,0 +1,52 @@ +/* +* Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +* +* OpenArkFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +////////////////////////////////////////////////////////////////////////////////////////////// +// This is the interface to translate AST to C++ +////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef __OBFUSCATE_HEADER__ +#define __OBFUSCATE_HEADER__ + +#include "astopt.h" +#include "ast_handler.h" +#include "ast_module.h" + +namespace maplefe { + +class Obfuscate : public AstOpt { +private: + AST_Handler *mASTHandler; + unsigned mFlags; + unsigned mIndexImported; + +public: + explicit Obfuscate(AST_Handler *h, unsigned flags) : + AstOpt(h, flags), + mASTHandler(h), + mFlags(flags), + mIndexImported(0) {} + ~Obfuscate() = default; + + void EmitTS(); + bool LoadImportedModules(); + + // return 0 if successful + // return non-zero if failed + int ProcessAST(); +}; + +} +#endif diff --git a/src/MapleFE/tools/obfuscate/src/main.cpp b/src/MapleFE/tools/obfuscate/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0865f8545ed5116743448c3bb710b7e33cb9289a --- /dev/null +++ b/src/MapleFE/tools/obfuscate/src/main.cpp @@ -0,0 +1,109 @@ +/* +* Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +* Copyright (C) [2022] Tencent. All rights reverved. +* +* OpenArkFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#include +#include +#include +#include "gen_astload.h" +#include "ast_handler.h" +#include "obfuscate.h" + +static void help() { + std::cout << "obfuscate a.ast[,b.ast] [options]:" << std::endl; + std::cout << " --out=x.ts : ts output file" << std::endl; + std::cout << " --help : print this help" << std::endl; + std::cout << " --trace=n : Emit trace with 4-bit combo levels 1...15" << std::endl; + std::cout << " 1 : Emit ast tree visits" << std::endl; + std::cout << " 2 : Emit graph" << std::endl; + std::cout << " --emit-ts-only : Emit ts code only" << std::endl; + std::cout << " --emit-ts : Emit ts code" << std::endl; + std::cout << " --format-cpp : Format cpp" << std::endl; + std::cout << " --no-imported : Do not process the imported modules" << std::endl; + std::cout << "default out name uses the first input name: a.cpp" << std::endl; +} + +int main (int argc, char *argv[]) { + if (argc == 1 || (!strncmp(argv[1], "--help", 6) && (strlen(argv[1]) == 6))) { + help(); + exit(-1); + } + + unsigned flags; + // one or more input .ast files separated by ',' + const char *inputname = argv[1]; + // output .ast file + const char *outputname = nullptr; + + // Parse the argument + for (unsigned i = 2; i < argc; i++) { + if (!strncmp(argv[i], "--trace=", 8)) { + int val = atoi(argv[i] + 8); + if (val < 1 || val > 15) { + help(); + exit(-1); + } + flags |= val; + } else if (!strncmp(argv[i], "--emit-ts-only", 14)) { + flags |= maplefe::FLG_emit_ts_only; + } else if (!strncmp(argv[i], "--emit-ts", 9)) { + flags |= maplefe::FLG_emit_ts; + } else if (!strncmp(argv[i], "--format-cpp", 12)) { + flags |= maplefe::FLG_format_cpp; + } else if (!strncmp(argv[i], "--no-imported", 13)) { + flags |= maplefe::FLG_no_imported; + } else if (!strncmp(argv[i], "--in=", 5)) { + inputname = argv[i]+5; + } else if (!strncmp(argv[i], "--out=", 6)) { + outputname = argv[i]+6; + } else { + std::cerr << "unknown option " << argv[i] << std::endl; + exit(-1); + } + } + + // input ast files + std::vector inputfiles; + if (inputname) { + std::stringstream ss; + ss.str(inputname); + std::string item; + while (std::getline(ss, item, ',')) { + // std::cout << "item " << item << " xxx"<< std::endl; + inputfiles.push_back(item); + } + } + + unsigned trace = (flags & maplefe::FLG_trace); + maplefe::AST_Handler handler(trace); + for (auto astfile: inputfiles) { + std::ifstream input(astfile, std::ifstream::binary); + input >> std::noskipws; + std::istream_iterator s(input), e; + maplefe::AstBuffer vec(s, e); + maplefe::AstLoad loadAst; + maplefe::ModuleNode *mod = loadAst.LoadFromAstBuf(vec); + // add mod to the vector + while(mod) { + handler.AddModule(mod); + mod = loadAst.Next(); + } + } + + maplefe::Obfuscate *obfuscate = new maplefe::Obfuscate(&handler, flags); + int res = obfuscate->ProcessAST(); + + return res; +} diff --git a/src/MapleFE/tools/obfuscate/src/obfuscate.cpp b/src/MapleFE/tools/obfuscate/src/obfuscate.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cec38cbc9cd61b600310f72967651b849431cc77 --- /dev/null +++ b/src/MapleFE/tools/obfuscate/src/obfuscate.cpp @@ -0,0 +1,168 @@ +/* +* Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +* Copyright (C) [2022] Tencent. All rights reverved. +* +* OpenArkFE is licensed under the Mulan PSL v2. +* You can use this software according to the terms and conditions of the Mulan PSL v2. +* You may obtain a copy of Mulan PSL v2 at: +* +* http://license.coscl.org.cn/MulanPSL2 +* +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR +* FIT FOR A PARTICULAR PURPOSE. +* See the Mulan PSL v2 for more details. +*/ + +#include +#include +#include +#include +#include + +#include "obfuscate.h" +#include "ast_handler.h" +#include "gen_astdump.h" +#include "gen_astgraph.h" +#include "gen_aststore.h" +#include "gen_astload.h" +#include "cpp_definition.h" +#include "cpp_declaration.h" +#include "a2c_util.h" + +namespace maplefe { + +bool Obfuscate::LoadImportedModules() { + std::queue queue; + for (HandlerIndex i = 0; i < GetModuleNum(); i++) { + Module_Handler *handler = mASTHandler->GetModuleHandler(i); + ModuleNode *module = handler->GetASTModule(); + ImportedFiles imported(module); + imported.VisitTreeNode(module); + for(const auto &e: imported.mFilenames) + queue.push(e); + } + + bool err = false; + while(!queue.empty()) { + std::string filename = queue.front(); + queue.pop(); + if(mASTHandler->GetHandlerIndex(filename.c_str()) == HandlerNotFound) { + std::ifstream input(filename, std::ifstream::binary); + if(input.fail()) { + std::cerr << "Error: File " << filename << " not found for imported module" << std::endl; + err = true; + continue; + } + input >> std::noskipws; + std::istream_iterator s(input), e; + maplefe::AstBuffer vec(s, e); + maplefe::AstLoad loadAst; + maplefe::ModuleNode *mod = loadAst.LoadFromAstBuf(vec); + // add mod to the vector + while(mod) { + mASTHandler->AddModule(mod); + ImportedFiles imported(mod); + imported.VisitTreeNode(mod); + for(const auto &e: imported.mFilenames) + queue.push(e); + mod = loadAst.Next(); + } + } + } + return err; +} + +// starting point of AST +int Obfuscate::ProcessAST() { + mIndexImported = GetModuleNum(); + + // load all imported modules + if (!(mFlags & FLG_no_imported)) { + if (LoadImportedModules()) { + return 1; + } + } + + // loop through module handlers + for (HandlerIndex i = 0; i < GetModuleNum(); i++) { + Module_Handler *handler = mASTHandler->GetModuleHandler(i); + ModuleNode *module = handler->GetASTModule(); + + if (mFlags & FLG_trace_1) { + std::cout << "============= in ProcessAST ===========" << std::endl; + std::cout << "srcLang : " << module->GetSrcLangString() << std::endl; + + for(unsigned k = 0; k < module->GetTreesNum(); k++) { + TreeNode *tnode = module->GetTree(k); + if (mFlags & FLG_trace_1) { + tnode->Dump(0); + std::cout << std::endl; + } + } + } + + if (mFlags & FLG_trace_2) { + std::cout << "============= AstGraph ===========" << std::endl; + AstGraph graph(module); + graph.DumpGraph("After LoadFromAstBuf()", &std::cout); + } + } + + // build dependency of modules + PreprocessModules(); + + // loop through module handlers in import/export dependency order + for (auto handler: mHandlersInOrder) { + ModuleNode *module = handler->GetASTModule(); + + // basic analysis + handler->BasicAnalysis(); + + if (mFlags & FLG_trace_2) { + std::cout << "============= After BasicAnalysis ===========" << std::endl; + for(unsigned k = 0; k < module->GetTreesNum(); k++) { + TreeNode *tnode = module->GetTree(k); + if (mFlags & FLG_trace_1) { + tnode->Dump(0); + std::cout << std::endl; + } + } + AstGraph graph(module); + graph.DumpGraph("After BasicAnalysis()", &std::cout); + } + } + + if (mFlags & FLG_trace_3) { + gStringPool.Dump(); + } + + gStringPool.SetAltStrIdxMap(); + + if (mFlags & FLG_trace_3) { + gStringPool.Dump(); + gStringPool.DumpAlt(); + } + + gStringPool.SetUseAltStr(true); + + for (auto handler: mHandlersInOrder) { + ModuleNode *module = handler->GetASTModule(); + + std::cout << "============= Emitter ===========" << std::endl; + maplefe::Emitter emitter(handler); + std::string code = emitter.Emit("Convert AST to TypeScript code"); + + // Emit to file + std::string of_name(module->GetFilename()); + of_name += ".obf"; + std::ofstream ofs; + ofs.open(of_name.c_str(), std::ofstream::out); + ofs << code; + ofs.close(); + } + + return 0; +} + +} // namespace maplefe diff --git a/src/MapleFE/typescript/identifier.spec b/src/MapleFE/typescript/identifier.spec index 6cfe3baf6e1b7b01004cdd387139257599dd0990..5723b480b3cd59e04d86d6d935f9bd949971c926 100644 --- a/src/MapleFE/typescript/identifier.spec +++ b/src/MapleFE/typescript/identifier.spec @@ -16,4 +16,5 @@ # rule JavaChar : ONEOF(CHAR, '_' , '$') rule CharOrDigit : ONEOF(JavaChar, DIGIT) -rule Identifier : JavaChar + ZEROORMORE(CharOrDigit) +rule Identifier : ONEOF("no-default-lib", + JavaChar + ZEROORMORE(CharOrDigit)) diff --git a/src/MapleFE/typescript/include/lang_builtin.def b/src/MapleFE/typescript/include/lang_builtin.def index 3b529b2cbb3922b4cb24343f2f10422991afe1ee..791452525da5c9d65a88608d27840c712bfd885e 100644 --- a/src/MapleFE/typescript/include/lang_builtin.def +++ b/src/MapleFE/typescript/include/lang_builtin.def @@ -37,7 +37,6 @@ BUILTIN(Int32Array) BUILTIN(Int8Array) BUILTIN(InternalError (Mozilla only)) BUILTIN(Map) -BUILTIN(Math) BUILTIN(Number) BUILTIN(Object) BUILTIN(Promise) diff --git a/src/MapleFE/typescript/include/lang_spec.h b/src/MapleFE/typescript/include/lang_spec.h index 929de87c24b46706d9964306411a854a052ce0e2..96aef8bf12195fd32df8cf8630e6beb6632f8c9a 100644 --- a/src/MapleFE/typescript/include/lang_spec.h +++ b/src/MapleFE/typescript/include/lang_spec.h @@ -49,6 +49,7 @@ public: TempLitData* GetTempLit(); bool FindNextTLFormat(unsigned start, std::string& s, unsigned& end); bool FindNextTLPlaceHolder(unsigned start, std::string& s, unsigned& end); + bool FindTripleSlash(); }; //////////////////////////////////////////////////////////////////////////////////// diff --git a/src/MapleFE/typescript/operator.spec b/src/MapleFE/typescript/operator.spec index 48d5037f5a9897174513ea3644d3a34ffcabee28..d09db223d3cdc7069e1300fde8861a08f6ff9b8d 100644 --- a/src/MapleFE/typescript/operator.spec +++ b/src/MapleFE/typescript/operator.spec @@ -72,5 +72,8 @@ STRUCT Operator : ( ("|=", BorAssign), ("^=", BxorAssign), (">>>=", ZextAssign), + + ("///", TripleSlash), + # arrow function ("=>", ArrowFunction)) diff --git a/src/MapleFE/typescript/src/lang_spec.cpp b/src/MapleFE/typescript/src/lang_spec.cpp index b2022817b90b2ef798909c39710dcb1cc7649f29..d51d1f312d0184badb28eac07e422c6a24a65632 100644 --- a/src/MapleFE/typescript/src/lang_spec.cpp +++ b/src/MapleFE/typescript/src/lang_spec.cpp @@ -394,6 +394,37 @@ bool TypescriptLexer::FindNextTLPlaceHolder(unsigned start_idx, std::string& str return true; } +// This is to catch TS triple-slash directives : /// ' + MemberExpression, - PrimaryExpression + "as" + "const", MemberExpression + '.' + KeywordPropName) attr.action.%1 : AddAsType(%1, %2) attr.action.%2 : BuildArrayElement(%1, %3) @@ -407,12 +403,9 @@ rule MemberExpression : ONEOF( attr.action.%8 : AddAsType(%6) attr.action.%10: BuildArrayElement(%1, %3) attr.action.%11: SetIsNonNull(%1) - attr.action.%12: BuildField(%1, %3) - attr.action.%12: SetIsConst() + attr.action.%12: SetIsConst(%1) attr.action.%13: BuildCast(%2, %4) - attr.action.%14: PassChild(%1) - attr.action.%14: SetIsConst() - attr.action.%15 : BuildField(%1, %3) + attr.action.%14 : BuildField(%1, %3) rule IsExpression: ONEOF(PrimaryExpression + "is" + Type, ArrowFunction + "is" + Type) @@ -472,7 +465,8 @@ rule CallExpression : ONEOF( "set" + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), "get" + ZEROORONE(TypeArguments) + Arguments + ZEROORMORE(AsType), CallExpression + "?." + Arguments + ZEROORMORE(AsType), - ImportFunction) + ImportFunction, + CallExpression + '.' + KeywordPropName + ZEROORMORE(AsType)) attr.action.%1,%3,%10,%11 : BuildCall(%1) attr.action.%1,%10,%11 : AddAsType(%4) attr.action.%1,%10,%11 : AddTypeGenerics(%2) @@ -481,8 +475,8 @@ rule CallExpression : ONEOF( attr.action.%3 : AddAsType(%3) attr.action.%4 : BuildArrayElement(%1, %3) attr.action.%4 : AddAsType(%5) - attr.action.%5 : BuildField(%1, %3) - attr.action.%5 : AddAsType(%4) + attr.action.%5,%14 : BuildField(%1, %3) + attr.action.%5,%14 : AddAsType(%4) attr.action.%7 : SetIsNonNull(%1) attr.action.%7 : AddAsType(%1, %3) attr.action.%8 : SetIsOptional(%1) @@ -790,6 +784,12 @@ rule Expression : ONEOF( # Statements #------------------------------------------------------------------------------- +rule TripleSlash : ONEOF( "///" + '<' + "reference" + "path" + '=' + Literal + '/' + '>', + "///" + '<' + "reference" + "types" + '=' + Literal + '/' + '>', + "///" + '<' + "reference" + "lib" + '=' + Literal + '/' + '>', + "///" + '<' + "reference" + "no-default-lib" + '=' + Literal + '/' + '>') + attr.action.%1,%2,%3,%4 : BuildTripleSlash(%4, %6) + ##----------------------------------- ##rule Statement[Yield, Return] : ## BlockStatement[?Yield, ?Return] @@ -820,7 +820,8 @@ rule Statement : ONEOF( # WithStatement[?Yield, ?Return] LabelledStatement, ThrowStatement, - TryStatement) + TryStatement, + TripleSlash) # DebuggerStatement attr.property : Top attr.property : Single # This is extremely important to give CallExpression the @@ -1137,9 +1138,9 @@ rule ForBinding : ONEOF(BindingIdentifier, ## continue [no LineTerminator here] LabelIdentifier[?Yield] ; rule ContinueStatement : ONEOF( "continue" + ZEROORONE(';'), - "continue" + LabelIdentifier + ZEROORONE(';')) + "continue" + NoLineTerminator + LabelIdentifier + ZEROORONE(';')) attr.action.%1 : BuildContinue() - attr.action.%2 : BuildContinue(%2) + attr.action.%2 : BuildContinue(%3) ##----------------------------------- ##rule BreakStatement[Yield] : @@ -1147,18 +1148,18 @@ rule ContinueStatement : ONEOF( ## break [no LineTerminator here] LabelIdentifier[?Yield] ; rule BreakStatement : ONEOF( "break" + ZEROORONE(';'), - "break" + LabelIdentifier + ZEROORONE(';')) + "break" + NoLineTerminator + LabelIdentifier + ZEROORONE(';')) attr.action.%1 : BuildBreak() - attr.action.%2 : BuildBreak(%2) + attr.action.%2 : BuildBreak(%3) ##----------------------------------- ##rule ReturnStatement[Yield] : ## return ; ## return [no LineTerminator here] Expression[In, ?Yield] ; rule ReturnStatement :ONEOF("return" + ZEROORONE(';'), - "return" + Expression + ZEROORONE(';')) + "return" + NoLineTerminator + Expression + ZEROORONE(';')) attr.action.%1 : BuildReturn() - attr.action.%2 : BuildReturn(%2) + attr.action.%2 : BuildReturn(%3) ##----------------------------------- ##rule WithStatement[Yield, Return] : @@ -1734,11 +1735,8 @@ rule Type : ONEOF(UnionOrIntersectionOrPrimaryType, InferType, IsExpression, PrimaryType + '[' + TypeQuery + ']', - TemplateLiteral, - ImportFunction, - ImportFunction + '.' + TypeReference) + TemplateLiteral) attr.action.%7,%11 : BuildArrayElement(%1, %3) - attr.action.%14 : BuildField(%1, %3) #rule UnionOrIntersectionOrPrimaryType: ONEOF(UnionType, # IntersectionOrPrimaryType) @@ -1847,9 +1845,10 @@ rule TupleElementType: ONEOF(ZEROORONE(JSIdentifier + ':') + Type, rule UnionType : ONEOF(ZEROORONE('|') + UnionOrIntersectionOrPrimaryType + '|' + IntersectionOrPrimaryType, UnionOrIntersectionOrPrimaryType + '|' + KeyOf, KeyOf + '|' + UnionOrIntersectionOrPrimaryType, - TypeQuery + '|' + UnionOrIntersectionOrPrimaryType) + TypeQuery + '|' + UnionOrIntersectionOrPrimaryType, + TemplateLiteral + '|' + TemplateLiteral) attr.action.%1 : BuildUnionUserType(%2, %4) - attr.action.%2,%3,%4 : BuildUnionUserType(%1, %3) + attr.action.%2,%3,%4,%5 : BuildUnionUserType(%1, %3) ## rule IntersectionType: IntersectionOrPrimaryType & PrimaryType rule IntersectionType: ONEOF(IntersectionOrPrimaryType + '&' + PrimaryType, @@ -2215,11 +2214,11 @@ rule PropertyMemberDeclaration: ONEOF(MemberVariableDeclaration, ## MemberVariableDeclaration: AccessibilityModifieropt staticopt PropertyName TypeAnnotationopt Initializeropt ; rule MemberVariableDeclaration: ONEOF( - ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertyName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), - ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertyName + '?' + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), + ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertySignatureName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), + ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + PropertySignatureName + '?' + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + "get" + '=' + ArrowFunction + ZEROORONE(';'), ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + "set" + '=' + ArrowFunction + ZEROORONE(';'), - '#' + PropertyName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), + '#' + PropertySignatureName + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), '#' + "private" + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';'), ZEROORMORE(Annotation) + ZEROORMORE(AccessibilityModifier) + "if" + ZEROORONE(TypeAnnotation) + ZEROORONE(Initializer) + ZEROORONE(';')) attr.action.%1: AddInitTo(%3, %5) @@ -2256,6 +2255,13 @@ rule KeywordMemberFunctionName : ONEOF("return", "set", "continue", "break", + "const", + "let", + "var", + "if", + "else", + "for", + "try", "export") attr.action : BuildIdentifier() diff --git a/src/hir2mpl/BUILD.gn b/src/hir2mpl/BUILD.gn index 80b4e5e920ecc003426b7bf3ef3ded50aad58a32..66d2e6f2a6d9b98c16d163e5b75be9f07ee78894 100644 --- a/src/hir2mpl/BUILD.gn +++ b/src/hir2mpl/BUILD.gn @@ -23,6 +23,13 @@ cflags += [ "-DJAVA_OBJ_IN_MFILE=1", ] +if (ONLY_C == 1) { + cflags += [ + "-w", + "-DONLY_C", + ] +} + if (MAST == 1) { cflags += [ "-w", @@ -97,10 +104,12 @@ static_library("lib_hir2mpl_common") { "${HIR2MPL_ROOT}/common/src/hir2mpl_compiler_component.cpp", "${HIR2MPL_ROOT}/common/src/hir2mpl_env.cpp", "${HIR2MPL_ROOT}/common/src/hir2mpl_options.cpp", + "${HIR2MPL_ROOT}/common/src/hir2mpl_option.cpp", "${HIR2MPL_ROOT}/common/src/simple_xml.cpp", "${HIR2MPL_ROOT}/common/src/simple_zip.cpp", "${HIR2MPL_ROOT}/common/src/generic_attrs.cpp", "${HIR2MPL_ROOT}/common/src/enhance_c_checker.cpp", + "${HIR2MPL_ROOT}/common/src/feir_scope.cpp", ] include_dirs = include_directories output_dir = "${root_out_dir}/ar" @@ -151,19 +160,26 @@ executable("hir2mpl") { deps = [ ":lib_hir2mpl_ast_input_clang", ":lib_hir2mpl_ast_input_common", - ":lib_hir2mpl_bytecode_input_common", - ":lib_hir2mpl_bytecode_input_dex", ":lib_hir2mpl_input_helper", - ":lib_hir2mpl_bytecode_input_class", ":lib_hir2mpl_common", ":lib_hir2mpl_optimize", "${MAPLEALL_ROOT}/maple_driver:libdriver_option", + "${MAPLEALL_ROOT}/maple_driver:libmaple_driver", "${MAPLEALL_ROOT}/maple_ir:libmplir", "${MAPLEALL_ROOT}/maple_util:libmplutil", "${MAPLEALL_ROOT}/mempool:libmempool", "${MAPLEALL_ROOT}/mpl2mpl:libmpl2mpl", "${THIRD_PARTY_ROOT}/bounds_checking_function:libHWSecureC", ] + + if (ONLY_C != 1) { + deps += [ + ":lib_hir2mpl_bytecode_input_common", + ":lib_hir2mpl_bytecode_input_dex", + ":lib_hir2mpl_bytecode_input_class", + ] + } + if (MAST == 1) { deps += [ ":lib_hir2mpl_ast_input_maple", @@ -181,6 +197,13 @@ executable("hir2mpl") { "-L${MAPLE_PARSER_PATH}/output/c/ast_gen/shared", ] } + if (COV == 1) { + ldflags += ["--coverage"] + cflags_cc += [ + "-fprofile-arcs", + "-ftest-coverage" + ] + } } include_bytecode_input_jbc_directories = [ @@ -218,96 +241,98 @@ static_library("lib_hir2mpl_bytecode_input_class") { output_dir = "${root_out_dir}/ar" } -include_bytecode_input_common_directories = [ - "${HIR2MPL_ROOT}/common/include", - "${HIR2MPL_ROOT}/optimize/include", - "${HIR2MPL_ROOT}/bytecode_input/common/include", - "${HIR2MPL_ROOT}/bytecode_input/dex/include", - "${MAPLEALL_ROOT}/maple_ir/include", - "${MAPLEALL_ROOT}/maple_util/include", - "${MAPLEALL_ROOT}/maple_driver/include", - "${MAPLEALL_ROOT}/mempool/include", - "${THIRD_PARTY_ROOT}/bounds_checking_function/include", -] - -static_library("lib_hir2mpl_bytecode_input_common") { - sources = [ - "${HIR2MPL_ROOT}/bytecode_input/common/src/ark_annotation_map.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/ark_annotation_processor.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_class.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_class2fe_helper.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_function.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_instruction.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_io.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_parser_base.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_pragma.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_util.cpp", - "${HIR2MPL_ROOT}/bytecode_input/common/src/rc_setter.cpp", +if (ONLY_C != 1) { + include_bytecode_input_common_directories = [ + "${HIR2MPL_ROOT}/common/include", + "${HIR2MPL_ROOT}/optimize/include", + "${HIR2MPL_ROOT}/bytecode_input/common/include", + "${HIR2MPL_ROOT}/bytecode_input/dex/include", + "${MAPLEALL_ROOT}/maple_ir/include", + "${MAPLEALL_ROOT}/maple_util/include", + "${MAPLEALL_ROOT}/maple_driver/include", + "${MAPLEALL_ROOT}/mempool/include", + "${THIRD_PARTY_ROOT}/bounds_checking_function/include", ] - include_dirs = include_bytecode_input_common_directories - output_dir = "${root_out_dir}/ar" -} -include_bytecode_input_dex_directories = [ - "${HIR2MPL_ROOT}/common/include", - "${HIR2MPL_ROOT}/optimize/include", - "${HIR2MPL_ROOT}/bytecode_input/common/include", - "${HIR2MPL_ROOT}/bytecode_input/dex/include", - "${MAPLEALL_ROOT}/maple_ir/include", - "${MAPLEALL_ROOT}/maple_util/include", - "${MAPLEALL_ROOT}/maple_driver/include", - "${MAPLEALL_ROOT}/mempool/include", - "${THIRD_PARTY_ROOT}/bounds_checking_function/include", -] + static_library("lib_hir2mpl_bytecode_input_common") { + sources = [ + "${HIR2MPL_ROOT}/bytecode_input/common/src/ark_annotation_map.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/ark_annotation_processor.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_class.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_class2fe_helper.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_function.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_instruction.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_io.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_parser_base.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_pragma.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/bc_util.cpp", + "${HIR2MPL_ROOT}/bytecode_input/common/src/rc_setter.cpp", + ] + include_dirs = include_bytecode_input_common_directories + output_dir = "${root_out_dir}/ar" + } -static_library("lib_hir2mpl_bytecode_input_dex") { - sources = [ - "${HIR2MPL_ROOT}/bytecode_input/dex/src/class_linker.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/class_loader_context.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_class.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_class2fe_helper.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_encode_value.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_file_util.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_op.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_pragma.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_strfac.cpp", + include_bytecode_input_dex_directories = [ + "${HIR2MPL_ROOT}/common/include", + "${HIR2MPL_ROOT}/optimize/include", + "${HIR2MPL_ROOT}/bytecode_input/common/include", + "${HIR2MPL_ROOT}/bytecode_input/dex/include", + "${MAPLEALL_ROOT}/maple_ir/include", + "${MAPLEALL_ROOT}/maple_util/include", + "${MAPLEALL_ROOT}/maple_driver/include", + "${MAPLEALL_ROOT}/mempool/include", + "${THIRD_PARTY_ROOT}/bounds_checking_function/include", ] - # for libdexfile - include_dirs_dex = [ "${THIRD_PARTY_ROOT}/aosp_modified/system/core/include" ] - include_dirs_libdexfile = [ - #for libdexfile -start - "${THIRD_PARTY_ROOT}/aosp_modified/system/core/liblog/include", - "${THIRD_PARTY_ROOT}/aosp_modified/system/core/libutils/include", - "${THIRD_PARTY_ROOT}/aosp_modified/system/core/base/include", - "${THIRD_PARTY_ROOT}/aosp_modified/system/core/libziparchive/include", - "${THIRD_PARTY_ROOT}/aosp_modified/art/libartpalette/include", - "${THIRD_PARTY_ROOT}/aosp_modified/art/libartbase", - "${THIRD_PARTY_ROOT}/aosp_modified/art/libdexfile", - "${THIRD_PARTY_ROOT}/aosp_modified/include", - "${THIRD_PARTY_ROOT}/aosp_modified/libnativehelper/include_jni", - - #for libdexfile -end - ] + static_library("lib_hir2mpl_bytecode_input_dex") { + sources = [ + "${HIR2MPL_ROOT}/bytecode_input/dex/src/class_linker.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/class_loader_context.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_class.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_class2fe_helper.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_encode_value.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_file_util.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_op.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_pragma.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_strfac.cpp", + ] - sources += [ - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_parser.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_reader.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dexfile_factory.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dexfile_interface.cpp", - "${HIR2MPL_ROOT}/bytecode_input/dex/src/dexfile_libdexfile.cpp", - ] - deps_libdexfile = [ - "${THIRD_PARTY_ROOT}/aosp_modified/art/libdexfile:libdexfile", - "${THIRD_PARTY_ROOT}/aosp_modified/system/core/libziparchive:libziparchive", - "${THIRD_PARTY_ROOT}/aosp_modified/system/core/base:libbase", - ] - lib_dex = [ "${THIRD_PARTY_ROOT}/aosp_modified/system/core/liblog/liblog.a" ] - deps = deps_libdexfile - libs = lib_dex - include_dirs = - include_bytecode_input_dex_directories + include_dirs_libdexfile + include_dirs_dex - output_dir = "${root_out_dir}/ar" + # for libdexfile + include_dirs_dex = [ "${THIRD_PARTY_ROOT}/aosp_modified/system/core/include" ] + include_dirs_libdexfile = [ + #for libdexfile -start + "${THIRD_PARTY_ROOT}/aosp_modified/system/core/liblog/include", + "${THIRD_PARTY_ROOT}/aosp_modified/system/core/libutils/include", + "${THIRD_PARTY_ROOT}/aosp_modified/system/core/base/include", + "${THIRD_PARTY_ROOT}/aosp_modified/system/core/libziparchive/include", + "${THIRD_PARTY_ROOT}/aosp_modified/art/libartpalette/include", + "${THIRD_PARTY_ROOT}/aosp_modified/art/libartbase", + "${THIRD_PARTY_ROOT}/aosp_modified/art/libdexfile", + "${THIRD_PARTY_ROOT}/aosp_modified/include", + "${THIRD_PARTY_ROOT}/aosp_modified/libnativehelper/include_jni", + + #for libdexfile -end + ] + + sources += [ + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_parser.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dex_reader.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dexfile_factory.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dexfile_interface.cpp", + "${HIR2MPL_ROOT}/bytecode_input/dex/src/dexfile_libdexfile.cpp", + ] + deps_libdexfile = [ + "${THIRD_PARTY_ROOT}/aosp_modified/art/libdexfile:libdexfile", + "${THIRD_PARTY_ROOT}/aosp_modified/system/core/libziparchive:libziparchive", + "${THIRD_PARTY_ROOT}/aosp_modified/system/core/base:libbase", + ] + lib_dex = [ "${THIRD_PARTY_ROOT}/aosp_modified/system/core/liblog/liblog.a" ] + deps = deps_libdexfile + libs = lib_dex + include_dirs = + include_bytecode_input_dex_directories + include_dirs_libdexfile + include_dirs_dex + output_dir = "${root_out_dir}/ar" + } } static_library("lib_hir2mpl_ast_input_clang_lib") { diff --git a/src/hir2mpl/ast_input/clang/include/ast_builtin_func.def b/src/hir2mpl/ast_input/clang/include/ast_builtin_func.def index 08747d4fbf5d36c34644539de5625b80938a342b..1ecffd079cffd062a14b1d5783ffa88302ca2f11 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_builtin_func.def +++ b/src/hir2mpl/ast_input/clang/include/ast_builtin_func.def @@ -6,6 +6,7 @@ BUILTIN_FUNC(strcpy) BUILTIN_FUNC(strcmp) BUILTIN_FUNC(strlen) BUILTIN_FUNC(strchr) +BUILTIN_FUNC(strrchr) BUILTIN_FUNC(memcmp) BUILTIN_FUNC(memcpy) BUILTIN_FUNC(memset) diff --git a/src/hir2mpl/ast_input/clang/include/ast_expr.h b/src/hir2mpl/ast_input/clang/include/ast_expr.h index 9c7c52ad3e183080ba57b8bdf250fd7fe4349a29..d21561c0ce23faadfe68149ab0cb24e7b21a9338 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_expr.h +++ b/src/hir2mpl/ast_input/clang/include/ast_expr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -45,12 +45,18 @@ struct ASTValue { MIRConst *Translate2MIRConst() const; }; -enum ParentFlag { +enum class ParentFlag { kNoParent, kArrayParent, kStructParent }; +enum EvaluatedFlag : uint8 { + kEvaluatedAsZero, + kEvaluatedAsNonZero, + kNotEvaluated +}; + class ASTExpr { public: explicit ASTExpr(ASTOp o) : op(o) {} @@ -95,17 +101,41 @@ class ASTExpr { return GenerateMIRConstImpl(); } - void SetSrcLOC(uint32 fileIdx, uint32 lineNum) { - srcFileIdx = fileIdx; - srcFileLineNum = lineNum; + void SetSrcLoc(const Loc &l) { + loc = l; + } + + Loc GetSrcLoc() const { + return loc; } uint32 GetSrcFileIdx() const { - return srcFileIdx; + return loc.fileIdx; } uint32 GetSrcFileLineNum() const { - return srcFileLineNum; + return loc.line; + } + + uint32 GetSrcFileColumn() const { + return loc.column; + } + + void SetEvaluatedFlag(EvaluatedFlag flag) { + evaluatedflag = flag; + return; + } + + EvaluatedFlag GetEvaluatedFlag() const { + return evaluatedflag; + } + + bool IsRValue() const { + return isRValue; + } + + void SetRValue(bool flag) { + isRValue = flag; } virtual void SetShortCircuitIdx(uint32 leftIdx, uint32 rightIdx) {} @@ -126,14 +156,16 @@ class ASTExpr { ASTDecl *refedDecl = nullptr; bool isConstantFolded = false; ASTValue *value = nullptr; - - uint32 srcFileIdx = 0; - uint32 srcFileLineNum = 0; + Loc loc = {0, 0, 0}; + EvaluatedFlag evaluatedflag = kNotEvaluated; + bool isRValue = false; }; class ASTCastExpr : public ASTExpr { public: - ASTCastExpr() : ASTExpr(kASTOpCast) {} + explicit ASTCastExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpCast) { + (void)allocatorIn; + } ~ASTCastExpr() = default; void SetASTExpr(ASTExpr *expr) { @@ -219,7 +251,6 @@ class ASTCastExpr : public ASTExpr { MIRConst *GenerateMIRFloatConst() const; MIRConst *GenerateMIRIntConst() const; UniqueFEIRExpr EmitExprVdupVector(PrimType primtype, UniqueFEIRExpr &subExpr) const; - void CheckNonnullFieldInStruct() const; ASTExpr *child = nullptr; MIRType *src = nullptr; @@ -236,7 +267,9 @@ class ASTCastExpr : public ASTExpr { class ASTDeclRefExpr : public ASTExpr { public: - ASTDeclRefExpr() : ASTExpr(kASTOpRef) {} + explicit ASTDeclRefExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpRef) { + (void)allocatorIn; + } ~ASTDeclRefExpr() = default; protected: @@ -247,8 +280,11 @@ class ASTDeclRefExpr : public ASTExpr { class ASTUnaryOperatorExpr : public ASTExpr { public: explicit ASTUnaryOperatorExpr(ASTOp o) : ASTExpr(o) {} + ASTUnaryOperatorExpr(MapleAllocator &allocatorIn, ASTOp o) : ASTExpr(o) { + (void)allocatorIn; + } virtual ~ASTUnaryOperatorExpr() = default; - void SetUOExpr(ASTExpr*); + void SetUOExpr(ASTExpr *astExpr); const ASTExpr *GetUOExpr() const { return expr; @@ -297,7 +333,7 @@ class ASTUnaryOperatorExpr : public ASTExpr { class ASTUOMinusExpr: public ASTUnaryOperatorExpr { public: - ASTUOMinusExpr() : ASTUnaryOperatorExpr(kASTOpMinus) {} + explicit ASTUOMinusExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpMinus) {} ~ASTUOMinusExpr() = default; private: @@ -306,7 +342,7 @@ class ASTUOMinusExpr: public ASTUnaryOperatorExpr { class ASTUONotExpr: public ASTUnaryOperatorExpr { public: - ASTUONotExpr() : ASTUnaryOperatorExpr(kASTOpNot) {} + explicit ASTUONotExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpNot) {} ~ASTUONotExpr() = default; private: @@ -315,7 +351,7 @@ class ASTUONotExpr: public ASTUnaryOperatorExpr { class ASTUOLNotExpr: public ASTUnaryOperatorExpr { public: - ASTUOLNotExpr() : ASTUnaryOperatorExpr(kASTOpLNot) {} + explicit ASTUOLNotExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpLNot) {} ~ASTUOLNotExpr() = default; void SetShortCircuitIdx(uint32 leftIdx, uint32 rightIdx) override { @@ -331,7 +367,8 @@ class ASTUOLNotExpr: public ASTUnaryOperatorExpr { class ASTUOPostIncExpr: public ASTUnaryOperatorExpr { public: - ASTUOPostIncExpr() : ASTUnaryOperatorExpr(kASTOpPostInc), tempVarName(FEUtils::GetSequentialName("postinc_")) {} + explicit ASTUOPostIncExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPostInc), + tempVarName(FEUtils::GetSequentialName("postinc_")) {} ~ASTUOPostIncExpr() = default; private: @@ -341,7 +378,8 @@ class ASTUOPostIncExpr: public ASTUnaryOperatorExpr { class ASTUOPostDecExpr: public ASTUnaryOperatorExpr { public: - ASTUOPostDecExpr() : ASTUnaryOperatorExpr(kASTOpPostDec), tempVarName(FEUtils::GetSequentialName("postdec_")) {} + explicit ASTUOPostDecExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPostDec), + tempVarName(FEUtils::GetSequentialName("postdec_")) {} ~ASTUOPostDecExpr() = default; private: @@ -351,7 +389,7 @@ class ASTUOPostDecExpr: public ASTUnaryOperatorExpr { class ASTUOPreIncExpr: public ASTUnaryOperatorExpr { public: - ASTUOPreIncExpr() : ASTUnaryOperatorExpr(kASTOpPreInc) {} + explicit ASTUOPreIncExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPreInc) {} ~ASTUOPreIncExpr() = default; private: @@ -360,7 +398,7 @@ class ASTUOPreIncExpr: public ASTUnaryOperatorExpr { class ASTUOPreDecExpr: public ASTUnaryOperatorExpr { public: - ASTUOPreDecExpr() : ASTUnaryOperatorExpr(kASTOpPreDec) {} + explicit ASTUOPreDecExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPreDec) {} ~ASTUOPreDecExpr() = default; private: @@ -371,6 +409,7 @@ class ASTUOPreDecExpr: public ASTUnaryOperatorExpr { class ASTUOAddrOfExpr: public ASTUnaryOperatorExpr { public: ASTUOAddrOfExpr() : ASTUnaryOperatorExpr(kASTOpAddrOf) {} + explicit ASTUOAddrOfExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpAddrOf) {} ~ASTUOAddrOfExpr() = default; protected: @@ -382,24 +421,29 @@ class ASTUOAddrOfExpr: public ASTUnaryOperatorExpr { class ASTUOAddrOfLabelExpr : public ASTUnaryOperatorExpr { public: - ASTUOAddrOfLabelExpr() : ASTUnaryOperatorExpr(kASTOpAddrOfLabel) {} + explicit ASTUOAddrOfLabelExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpAddrOfLabel), + labelName("", allocatorIn.GetMemPool()) {} ~ASTUOAddrOfLabelExpr() = default; void SetLabelName(const std::string &name) { labelName = name; } + const std::string GetLabelName() const { + return labelName.c_str() == nullptr ? "" : labelName.c_str(); + } + protected: MIRConst *GenerateMIRConstImpl() const override; private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; - std::string labelName; + MapleString labelName; }; class ASTUODerefExpr: public ASTUnaryOperatorExpr { public: - ASTUODerefExpr() : ASTUnaryOperatorExpr(kASTOpDeref) {} + explicit ASTUODerefExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpDeref) {} ~ASTUODerefExpr() = default; private: @@ -410,7 +454,7 @@ class ASTUODerefExpr: public ASTUnaryOperatorExpr { class ASTUOPlusExpr: public ASTUnaryOperatorExpr { public: - ASTUOPlusExpr() : ASTUnaryOperatorExpr(kASTOpPlus) {} + explicit ASTUOPlusExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPlus) {} ~ASTUOPlusExpr() = default; private: @@ -419,7 +463,7 @@ class ASTUOPlusExpr: public ASTUnaryOperatorExpr { class ASTUORealExpr: public ASTUnaryOperatorExpr { public: - ASTUORealExpr() : ASTUnaryOperatorExpr(kASTOpReal) {} + explicit ASTUORealExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpReal) {} ~ASTUORealExpr() = default; void SetElementType(MIRType *type) { @@ -433,7 +477,7 @@ class ASTUORealExpr: public ASTUnaryOperatorExpr { class ASTUOImagExpr: public ASTUnaryOperatorExpr { public: - ASTUOImagExpr() : ASTUnaryOperatorExpr(kASTOpImag) {} + explicit ASTUOImagExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpImag) {} ~ASTUOImagExpr() = default; void SetElementType(MIRType *type) { @@ -447,7 +491,7 @@ class ASTUOImagExpr: public ASTUnaryOperatorExpr { class ASTUOExtensionExpr: public ASTUnaryOperatorExpr { public: - ASTUOExtensionExpr() : ASTUnaryOperatorExpr(kASTOpExtension) {} + explicit ASTUOExtensionExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpExtension) {} ~ASTUOExtensionExpr() = default; private: @@ -456,7 +500,7 @@ class ASTUOExtensionExpr: public ASTUnaryOperatorExpr { class ASTUOCoawaitExpr: public ASTUnaryOperatorExpr { public: - ASTUOCoawaitExpr() : ASTUnaryOperatorExpr(kASTOpCoawait) {} + explicit ASTUOCoawaitExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpCoawait) {} ~ASTUOCoawaitExpr() = default; private: @@ -465,9 +509,11 @@ class ASTUOCoawaitExpr: public ASTUnaryOperatorExpr { class ASTPredefinedExpr : public ASTExpr { public: - ASTPredefinedExpr() : ASTExpr(kASTOpPredefined) {} + explicit ASTPredefinedExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpPredefined) { + (void)allocatorIn; + } ~ASTPredefinedExpr() = default; - void SetASTExpr(ASTExpr*); + void SetASTExpr(ASTExpr *astExpr); private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; @@ -476,9 +522,11 @@ class ASTPredefinedExpr : public ASTExpr { class ASTOpaqueValueExpr : public ASTExpr { public: - ASTOpaqueValueExpr() : ASTExpr(kASTOpOpaqueValue) {} + explicit ASTOpaqueValueExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpOpaqueValue) { + (void)allocatorIn; + } ~ASTOpaqueValueExpr() = default; - void SetASTExpr(ASTExpr*); + void SetASTExpr(ASTExpr *astExpr); private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; @@ -487,7 +535,9 @@ class ASTOpaqueValueExpr : public ASTExpr { class ASTNoInitExpr : public ASTExpr { public: - ASTNoInitExpr() : ASTExpr(kASTOpNoInitExpr) {} + explicit ASTNoInitExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpNoInitExpr) { + (void)allocatorIn; + } ~ASTNoInitExpr() = default; void SetNoInitType(MIRType *type); @@ -498,39 +548,31 @@ class ASTNoInitExpr : public ASTExpr { class ASTCompoundLiteralExpr : public ASTExpr { public: - ASTCompoundLiteralExpr() : ASTExpr(kASTOpCompoundLiteralExp) {} + explicit ASTCompoundLiteralExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpCompoundLiteralExpr) { + (void)allocatorIn; + } ~ASTCompoundLiteralExpr() = default; void SetCompoundLiteralType(MIRType *clType); + void SetASTExpr(ASTExpr *astExpr); - MIRType *GetCompoundLiteralType() const { - return compoundLiteralType; - } - - void SetASTExpr(ASTExpr*); - - const ASTExpr *GetASTExpr() const { - return child; - } - - void SetInitName(const std::string &argInitName) { - initName = argInitName; - } - - const std::string &GetInitName() const { - return initName; + void SetAddrof(bool flag) { + isAddrof = flag; } private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; MIRConst *GenerateMIRConstImpl() const override; + MIRConst *GenerateMIRPtrConst() const; ASTExpr *child = nullptr; MIRType *compoundLiteralType = nullptr; - std::string initName; + bool isAddrof = false; }; class ASTOffsetOfExpr : public ASTExpr { public: - ASTOffsetOfExpr() : ASTExpr(kASTOpOffsetOfExpr) {} + explicit ASTOffsetOfExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpOffsetOfExpr) { + (void)allocatorIn; + } ~ASTOffsetOfExpr() = default; void SetStructType(MIRType *stype); void SetFieldName(const std::string &fName); @@ -548,7 +590,8 @@ class ASTOffsetOfExpr : public ASTExpr { class ASTInitListExpr : public ASTExpr { public: - ASTInitListExpr() : ASTExpr(kASTOpInitListExpr) {} + explicit ASTInitListExpr(MapleAllocator &allocatorIn) + : ASTExpr(kASTOpInitListExpr), initExprs(allocatorIn.Adapter()), varName("", allocatorIn.GetMemPool()) {} ~ASTInitListExpr() = default; void SetInitExprs(ASTExpr *astExpr); void SetInitListType(MIRType *type); @@ -557,7 +600,7 @@ class ASTInitListExpr : public ASTExpr { return initListType; } - std::vector GetInitExprs() const { + MapleVector GetInitExprs() const { return initExprs; } @@ -565,8 +608,8 @@ class ASTInitListExpr : public ASTExpr { varName = argVarName; } - const std::string &GetInitListVarName() const { - return varName; + const std::string GetInitListVarName() const { + return varName.c_str() == nullptr ? "" : varName.c_str(); } void SetParentFlag(ParentFlag argParentFlag) { @@ -616,37 +659,45 @@ class ASTInitListExpr : public ASTExpr { private: MIRConst *GenerateMIRConstImpl() const override; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; - void ProcessInitList(std::variant, UniqueFEIRExpr> &base, ASTInitListExpr *initList, - std::list &stmts) const; - void ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, ASTInitListExpr *initList, + void ProcessInitList(std::variant, UniqueFEIRExpr> &base, + const ASTInitListExpr *initList, std::list &stmts) const; + void ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, const ASTInitListExpr *initList, std::list &stmts) const; void ProcessStructInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, std::list &stmts) const; + const ASTInitListExpr *initList, std::list &stmts) const; + std::tuple GetStructFieldInfo(uint32 fieldIndex, uint32 baseFieldID, + MIRStructType &structMirType) const; + UniqueFEIRExpr CalculateStartAddressForMemset(const UniqueFEIRVar &varIn, uint32 initSizeIn, uint32 fieldIDIn, + const std::variant, UniqueFEIRExpr> &baseIn) const; + UniqueFEIRExpr GetAddrofArrayFEExprByStructArrayField(MIRType *fieldType, UniqueFEIRExpr addrOfArrayField) const; void ProcessVectorInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, std::list &stmts) const; + const ASTInitListExpr *initList, std::list &stmts) const; MIRIntrinsicID SetVectorSetLane(const MIRType &type) const; void ProcessDesignatedInitUpdater(std::variant, UniqueFEIRExpr> &base, ASTExpr *expr, std::list &stmts) const; void ProcessStringLiteralInitList(const UniqueFEIRExpr &addrOfCharArray, const UniqueFEIRExpr &addrOfStringLiteral, size_t stringLength, std::list &stmts) const; void ProcessImplicitInit(const UniqueFEIRExpr &addrExpr, uint32 initSize, uint32 total, uint32 elemSize, - std::list &stmts) const; + std::list &stmts, Loc loc = {0, 0, 0}) const; MIRConst *GenerateMIRConstForArray() const; MIRConst *GenerateMIRConstForStruct() const; - std::vector initExprs; + MapleVector initExprs; ASTExpr *arrayFillerExpr = nullptr; MIRType *initListType = nullptr; - std::string varName; - ParentFlag parentFlag = kNoParent; + MapleString varName; + ParentFlag parentFlag = ParentFlag::kNoParent; uint32 unionInitFieldIdx = UINT32_MAX; bool hasArrayFiller = false; bool isTransparent = false; bool hasVectorType = false; + mutable bool isGenerating = false; }; class ASTBinaryConditionalOperator : public ASTExpr { public: - ASTBinaryConditionalOperator() : ASTExpr(kASTOpBinaryConditionalOperator) {} + explicit ASTBinaryConditionalOperator(MapleAllocator &allocatorIn) : ASTExpr(kASTOpBinaryConditionalOperator) { + (void)allocatorIn; + } ~ASTBinaryConditionalOperator() = default; void SetCondExpr(ASTExpr *expr); void SetFalseExpr(ASTExpr *expr); @@ -659,9 +710,11 @@ class ASTBinaryConditionalOperator : public ASTExpr { class ASTBinaryOperatorExpr : public ASTExpr { public: - explicit ASTBinaryOperatorExpr(ASTOp o) : ASTExpr(o) {} - ASTBinaryOperatorExpr() - : ASTExpr(kASTOpBO), varName(FEUtils::GetSequentialName("shortCircuit_")) {} + ASTBinaryOperatorExpr(MapleAllocator &allocatorIn, ASTOp o) : ASTExpr(o) { + (void)allocatorIn; + } + explicit ASTBinaryOperatorExpr(MapleAllocator &allocatorIn) + : ASTExpr(kASTOpBO), varName(FEUtils::GetSequentialName("shortCircuit_"), allocatorIn.GetMemPool()) {} ~ASTBinaryOperatorExpr() override = default; @@ -718,6 +771,10 @@ class ASTBinaryOperatorExpr : public ASTExpr { falseIdx = rightIdx; } + std::string GetVarName() const { + return varName.c_str() == nullptr ? "" : varName.c_str(); + } + UniqueFEIRType SelectBinaryOperatorType(UniqueFEIRExpr &left, UniqueFEIRExpr &right) const; protected: @@ -738,14 +795,16 @@ class ASTBinaryOperatorExpr : public ASTExpr { ASTExpr *rightRealExpr = nullptr; ASTExpr *rightImagExpr = nullptr; bool cvtNeeded = false; - std::string varName; + MapleString varName; uint32 trueIdx = 0; uint32 falseIdx = 0; }; class ASTImplicitValueInitExpr : public ASTExpr { public: - ASTImplicitValueInitExpr() : ASTExpr(kASTImplicitValueInitExpr) {} + explicit ASTImplicitValueInitExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTImplicitValueInitExpr) { + (void)allocatorIn; + } ~ASTImplicitValueInitExpr() = default; protected: @@ -757,7 +816,8 @@ class ASTImplicitValueInitExpr : public ASTExpr { class ASTStringLiteral : public ASTExpr { public: - ASTStringLiteral() : ASTExpr(kASTStringLiteral) {} + explicit ASTStringLiteral(MapleAllocator &allocatorIn) : ASTExpr(kASTStringLiteral), + codeUnits(allocatorIn.Adapter()), str(allocatorIn.Adapter()) {} ~ASTStringLiteral() = default; void SetLength(size_t len) { @@ -768,14 +828,26 @@ class ASTStringLiteral : public ASTExpr { return length; } - void SetCodeUnits(std::vector &units) { + void SetCodeUnits(MapleVector &units) { codeUnits = std::move(units); } - const std::vector &GetCodeUnits() const { + const MapleVector &GetCodeUnits() const { return codeUnits; } + void SetStr(const std::string &strIn) { + if (str.size() > 0) { + str.clear(); + str.shrink_to_fit(); + } + str.insert(str.end(), strIn.cbegin(), strIn.cend()); + } + + const std::string GetStr() const { + return std::string(str.cbegin(), str.cend()); + } + void SetIsArrayToPointerDecay(bool argIsArrayToPointerDecay) { isArrayToPointerDecay = argIsArrayToPointerDecay; } @@ -790,13 +862,16 @@ class ASTStringLiteral : public ASTExpr { private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; size_t length = 0; - std::vector codeUnits; + MapleVector codeUnits; + MapleVector str; // Ascii string bool isArrayToPointerDecay = false; }; class ASTArraySubscriptExpr : public ASTExpr { public: - ASTArraySubscriptExpr() : ASTExpr(kASTSubscriptExpr) {} + explicit ASTArraySubscriptExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTSubscriptExpr) { + (void)allocatorIn; + } ~ASTArraySubscriptExpr() = default; void SetBaseExpr(ASTExpr *astExpr) { @@ -829,13 +904,17 @@ class ASTArraySubscriptExpr : public ASTExpr { isVLA = flag; } + void SetVLASizeExpr(ASTExpr *expr) { + vlaSizeExpr = expr; + } + private: ASTExpr *FindFinalBase() const; MIRConst *GenerateMIRConstImpl() const override; bool CheckFirstDimIfZero(const MIRType *arrayType) const; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; - void InsertNonnullChecking(std::list &stmts, const UniqueFEIRExpr &idxExpr, - const UniqueFEIRExpr &addrOfArray) const; + void InsertNonnullChecking(std::list &stmts, const UniqueFEIRExpr &indexExpr, + const UniqueFEIRExpr &baseAddrExpr) const; bool InsertBoundaryChecking(std::list &stmts, UniqueFEIRExpr indexExpr, UniqueFEIRExpr baseAddrFEExpr) const; @@ -843,11 +922,14 @@ class ASTArraySubscriptExpr : public ASTExpr { MIRType *arrayType = nullptr; ASTExpr *idxExpr = nullptr; bool isVLA = false; + ASTExpr *vlaSizeExpr = nullptr; }; class ASTExprUnaryExprOrTypeTraitExpr : public ASTExpr { public: - ASTExprUnaryExprOrTypeTraitExpr() : ASTExpr(kASTExprUnaryExprOrTypeTraitExpr) {} + explicit ASTExprUnaryExprOrTypeTraitExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTExprUnaryExprOrTypeTraitExpr) { + (void)allocatorIn; + } ~ASTExprUnaryExprOrTypeTraitExpr() = default; void SetIsType(bool type) { @@ -871,14 +953,15 @@ class ASTExprUnaryExprOrTypeTraitExpr : public ASTExpr { class ASTMemberExpr : public ASTExpr { public: - ASTMemberExpr() : ASTExpr(kASTMemberExpr) {} + explicit ASTMemberExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTMemberExpr), + memberName("", allocatorIn.GetMemPool()) {} ~ASTMemberExpr() = default; void SetBaseExpr(ASTExpr *astExpr) { baseExpr = astExpr; } - ASTExpr *GetBaseExpr() const { + const ASTExpr *GetBaseExpr() const { return baseExpr; } @@ -887,7 +970,7 @@ class ASTMemberExpr : public ASTExpr { } std::string GetMemberName() const { - return memberName; + return memberName.c_str() == nullptr ? "" : memberName.c_str(); } void SetMemberType(MIRType *type) { @@ -929,7 +1012,7 @@ class ASTMemberExpr : public ASTExpr { void InsertNonnullChecking(std::list &stmts, UniqueFEIRExpr baseFEExpr) const; ASTExpr *baseExpr = nullptr; - std::string memberName; + MapleString memberName; MIRType *memberType = nullptr; MIRType *baseType = nullptr; bool isArrow = false; @@ -938,14 +1021,16 @@ class ASTMemberExpr : public ASTExpr { class ASTDesignatedInitUpdateExpr : public ASTExpr { public: - ASTDesignatedInitUpdateExpr() : ASTExpr(kASTASTDesignatedInitUpdateExpr) {} + explicit ASTDesignatedInitUpdateExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTASTDesignatedInitUpdateExpr) { + (void)allocatorIn; + } ~ASTDesignatedInitUpdateExpr() = default; void SetBaseExpr(ASTExpr *astExpr) { baseExpr = astExpr; } - ASTExpr *GetBaseExpr() const{ + const ASTExpr *GetBaseExpr() const{ return baseExpr; } @@ -953,7 +1038,7 @@ class ASTDesignatedInitUpdateExpr : public ASTExpr { updaterExpr = astExpr; } - ASTExpr *GetUpdaterExpr() const{ + const ASTExpr *GetUpdaterExpr() const{ return updaterExpr; } @@ -961,11 +1046,11 @@ class ASTDesignatedInitUpdateExpr : public ASTExpr { initListType = type; } - MIRType *GetInitListType() const { + const MIRType *GetInitListType() const { return initListType; } - void SetInitListVarName (const std::string &name) { + void SetInitListVarName(const std::string &name) { initListVarName = name; } @@ -984,7 +1069,8 @@ class ASTDesignatedInitUpdateExpr : public ASTExpr { class ASTAssignExpr : public ASTBinaryOperatorExpr { public: - ASTAssignExpr() : ASTBinaryOperatorExpr(kASTOpAssign), isCompoundAssign(false) {} + explicit ASTAssignExpr(MapleAllocator &allocatorIn) : ASTBinaryOperatorExpr(allocatorIn, kASTOpAssign), + isCompoundAssign(false) {} ~ASTAssignExpr() override = default; void SetIsCompoundAssign(bool argIsCompoundAssign) { @@ -1000,7 +1086,7 @@ class ASTAssignExpr : public ASTBinaryOperatorExpr { class ASTBOComma : public ASTBinaryOperatorExpr { public: - ASTBOComma() : ASTBinaryOperatorExpr(kASTOpComma) {} + explicit ASTBOComma(MapleAllocator &allocatorIn) : ASTBinaryOperatorExpr(allocatorIn, kASTOpComma) {} ~ASTBOComma() override = default; private: @@ -1009,7 +1095,7 @@ class ASTBOComma : public ASTBinaryOperatorExpr { class ASTBOPtrMemExpr : public ASTBinaryOperatorExpr { public: - ASTBOPtrMemExpr() : ASTBinaryOperatorExpr(kASTOpPtrMemD) {} + explicit ASTBOPtrMemExpr(MapleAllocator &allocatorIn) : ASTBinaryOperatorExpr(allocatorIn, kASTOpPtrMemD) {} ~ASTBOPtrMemExpr() override = default; private: @@ -1018,21 +1104,23 @@ class ASTBOPtrMemExpr : public ASTBinaryOperatorExpr { class ASTCallExpr : public ASTExpr { public: - ASTCallExpr() : ASTExpr(kASTOpCall), varName(FEUtils::GetSequentialName("retVar_")) {} + explicit ASTCallExpr(MapleAllocator &allocatorIn) + : ASTExpr(kASTOpCall), args(allocatorIn.Adapter()), funcName("", allocatorIn.GetMemPool()), + varName(FEUtils::GetSequentialName("retVar_"), allocatorIn.GetMemPool()) {} ~ASTCallExpr() = default; void SetCalleeExpr(ASTExpr *astExpr) { calleeExpr = astExpr; } - ASTExpr *GetCalleeExpr() const { + const ASTExpr *GetCalleeExpr() const { return calleeExpr; } - void SetArgs(std::vector &argsVector){ + void SetArgs(MapleVector &argsVector){ args = std::move(argsVector); } - const std::vector &GetArgsExpr() const { + const MapleVector &GetArgsExpr() const { return args; } @@ -1044,16 +1132,16 @@ class ASTCallExpr : public ASTExpr { return retType; } - const std::string &GetRetVarName() const { - return varName; + const std::string GetRetVarName() const { + return varName.c_str() == nullptr ? "" : varName.c_str(); } void SetFuncName(const std::string &name) { funcName = name; } - const std::string &GetFuncName() const { - return funcName; + const std::string GetFuncName() const { + return funcName.c_str() == nullptr ? "" : funcName.c_str(); } void SetFuncAttrs(const FuncAttrs &attrs) { @@ -1085,6 +1173,14 @@ class ASTCallExpr : public ASTExpr { funcDecl = decl; } + void SetReturnVarAttrs(const GenericAttrs &attrs) { + returnVarAttrs = attrs; + } + + const GenericAttrs &GetReturnVarAttrs() const { + return returnVarAttrs; + } + std::string CvtBuiltInFuncName(std::string builtInName) const; UniqueFEIRExpr ProcessBuiltinFunc(std::list &stmts, bool &isFinish) const; std::unique_ptr GenCallStmt() const; @@ -1101,6 +1197,7 @@ class ASTCallExpr : public ASTExpr { static std::unordered_map InitBuiltinFuncPtrMap(); UniqueFEIRExpr CreateIntrinsicopForC(std::list &stmts, MIRIntrinsicID argIntrinsicID, bool genTempVar = true) const; + UniqueFEIRExpr CreateIntrinsicCallAssignedForC(std::list &stmts, MIRIntrinsicID argIntrinsicID) const; UniqueFEIRExpr CreateBinaryExpr(std::list &stmts, Opcode op) const; UniqueFEIRExpr EmitBuiltinFunc(std::list &stmts) const; UniqueFEIRExpr EmitBuiltinVectorZip(std::list &stmts, bool &isFinish) const; @@ -1137,7 +1234,6 @@ class ASTCallExpr : public ASTExpr { UniqueFEIRExpr EMIT_BUILTIIN_FUNC(VaEnd); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(VaCopy); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Prefetch); - UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Unreachable); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Abs); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(ACos); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(ACosf); @@ -1180,23 +1276,71 @@ class ASTCallExpr : public ASTExpr { UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAddAndFetch8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAddAndFetch4); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAddAndFetch2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAddAndFetch1); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncSubAndFetch8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncSubAndFetch4); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncSubAndFetch2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncSubAndFetch1); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndSub8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndSub4); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndSub2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndSub1); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAdd8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAdd4); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAdd2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAdd1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncBoolCompareAndSwap1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncBoolCompareAndSwap2); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncBoolCompareAndSwap4); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncBoolCompareAndSwap8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockTestAndSet8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockTestAndSet4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockTestAndSet2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockTestAndSet1); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncValCompareAndSwap8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncValCompareAndSwap4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncValCompareAndSwap2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncValCompareAndSwap1); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockRelease8); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockRelease4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockRelease2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncLockRelease1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAnd1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAnd2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAnd4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndAnd8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndOr1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndOr2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndOr4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndOr8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndXor1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndXor2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndXor4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndXor8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndNand1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndNand2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndNand4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncFetchAndNand8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAndAndFetch1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAndAndFetch2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAndAndFetch4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncAndAndFetch8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncOrAndFetch1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncOrAndFetch2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncOrAndFetch4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncOrAndFetch8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncXorAndFetch1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncXorAndFetch2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncXorAndFetch4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncXorAndFetch8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncNandAndFetch1); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncNandAndFetch2); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncNandAndFetch4); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncNandAndFetch8); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(SyncSynchronize); + + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(AtomicExchangeN); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(ReturnAddress); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(ExtractReturnAddr); @@ -1209,19 +1353,22 @@ UniqueFEIRExpr EmitBuiltin##STR(std::list &stmts) const; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; static std::unordered_map builtingFuncPtrMap; - std::vector args; + MapleVector args; ASTExpr *calleeExpr = nullptr; MIRType *retType = nullptr; - std::string funcName; + MapleString funcName; FuncAttrs funcAttrs; bool isIcall = false; - std::string varName; + MapleString varName; ASTFunc *funcDecl = nullptr; + GenericAttrs returnVarAttrs; }; class ASTParenExpr : public ASTExpr { public: - ASTParenExpr() : ASTExpr(kASTParen) {} + explicit ASTParenExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTParen) { + (void)allocatorIn; + } ~ASTParenExpr() = default; void SetASTExpr(ASTExpr *astExpr) { @@ -1252,7 +1399,9 @@ class ASTParenExpr : public ASTExpr { class ASTIntegerLiteral : public ASTExpr { public: - ASTIntegerLiteral() : ASTExpr(kASTIntegerLiteral) {} + explicit ASTIntegerLiteral(MapleAllocator &allocatorIn) : ASTExpr(kASTIntegerLiteral) { + (void)allocatorIn; + } ~ASTIntegerLiteral() = default; int64 GetVal() const { @@ -1272,14 +1421,16 @@ class ASTIntegerLiteral : public ASTExpr { int64 val = 0; }; -enum FloatKind { +enum class FloatKind { F32, F64 }; class ASTFloatingLiteral : public ASTExpr { public: - ASTFloatingLiteral() : ASTExpr(kASTFloatingLiteral) {} + explicit ASTFloatingLiteral(MapleAllocator &allocatorIn) : ASTExpr(kASTFloatingLiteral) { + (void)allocatorIn; + } ~ASTFloatingLiteral() = default; double GetVal() const { @@ -1302,12 +1453,14 @@ class ASTFloatingLiteral : public ASTExpr { UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; MIRConst *GenerateMIRConstImpl() const override; double val = 0; - FloatKind kind = F32; + FloatKind kind = FloatKind::F32; }; class ASTCharacterLiteral : public ASTExpr { public: - ASTCharacterLiteral() : ASTExpr(kASTCharacterLiteral) {} + explicit ASTCharacterLiteral(MapleAllocator &allocatorIn) : ASTExpr(kASTCharacterLiteral) { + (void)allocatorIn; + } ~ASTCharacterLiteral() = default; int64 GetVal() const { @@ -1340,7 +1493,9 @@ struct VaArgInfo { class ASTVAArgExpr : public ASTExpr { public: - ASTVAArgExpr() : ASTExpr(kASTVAArgExpr) {} + explicit ASTVAArgExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTVAArgExpr) { + (void)allocatorIn; + } ~ASTVAArgExpr() = default; void SetASTExpr(ASTExpr *astExpr) { @@ -1363,12 +1518,18 @@ class ASTVAArgExpr : public ASTExpr { class ASTConstantExpr : public ASTExpr { public: - ASTConstantExpr() : ASTExpr(kConstantExpr) {} + explicit ASTConstantExpr(MapleAllocator &allocatorIn) : ASTExpr(kConstantExpr) { + (void)allocatorIn; + } ~ASTConstantExpr() = default; void SetASTExpr(ASTExpr *astExpr) { child = astExpr; } + const ASTExpr *GetChild() const{ + return child; + } + protected: MIRConst *GenerateMIRConstImpl() const override; @@ -1379,7 +1540,9 @@ class ASTConstantExpr : public ASTExpr { class ASTImaginaryLiteral : public ASTExpr { public: - ASTImaginaryLiteral() : ASTExpr(kASTImaginaryLiteral) {} + explicit ASTImaginaryLiteral(MapleAllocator &allocatorIn) : ASTExpr(kASTImaginaryLiteral) { + (void)allocatorIn; + } ~ASTImaginaryLiteral() = default; void SetASTExpr(ASTExpr *astExpr) { child = astExpr; @@ -1402,7 +1565,9 @@ class ASTImaginaryLiteral : public ASTExpr { class ASTConditionalOperator : public ASTExpr { public: - ASTConditionalOperator() : ASTExpr(kASTConditionalOperator) {} + explicit ASTConditionalOperator(MapleAllocator &allocatorIn) : ASTExpr(kASTConditionalOperator) { + (void)allocatorIn; + } ~ASTConditionalOperator() = default; void SetCondExpr(ASTExpr *astExpr) { @@ -1437,7 +1602,9 @@ class ASTConditionalOperator : public ASTExpr { class ASTArrayInitLoopExpr : public ASTExpr { public: - ASTArrayInitLoopExpr() : ASTExpr(kASTOpArrayInitLoop) {} + explicit ASTArrayInitLoopExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpArrayInitLoop) { + (void)allocatorIn; + } ~ASTArrayInitLoopExpr() = default; void SetCommonExpr(ASTExpr *expr) { @@ -1455,7 +1622,9 @@ class ASTArrayInitLoopExpr : public ASTExpr { class ASTArrayInitIndexExpr : public ASTExpr { public: - ASTArrayInitIndexExpr() : ASTExpr(kASTOpArrayInitLoop) {} + explicit ASTArrayInitIndexExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpArrayInitLoop) { + (void)allocatorIn; + } ~ASTArrayInitIndexExpr() = default; void SetPrimType(MIRType *pType) { @@ -1482,7 +1651,9 @@ class ASTArrayInitIndexExpr : public ASTExpr { class ASTExprWithCleanups : public ASTExpr { public: - ASTExprWithCleanups() : ASTExpr(kASTOpExprWithCleanups) {} + explicit ASTExprWithCleanups(MapleAllocator &allocatorIn) : ASTExpr(kASTOpExprWithCleanups) { + (void)allocatorIn; + } ~ASTExprWithCleanups() = default; void SetSubExpr(ASTExpr *sub) { @@ -1500,7 +1671,9 @@ class ASTExprWithCleanups : public ASTExpr { class ASTMaterializeTemporaryExpr : public ASTExpr { public: - ASTMaterializeTemporaryExpr() : ASTExpr(kASTOpMaterializeTemporary) {} + explicit ASTMaterializeTemporaryExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpMaterializeTemporary) { + (void)allocatorIn; + } ~ASTMaterializeTemporaryExpr() = default; private: @@ -1509,7 +1682,9 @@ class ASTMaterializeTemporaryExpr : public ASTExpr { class ASTSubstNonTypeTemplateParmExpr : public ASTExpr { public: - ASTSubstNonTypeTemplateParmExpr() : ASTExpr(kASTOpSubstNonTypeTemplateParm) {} + explicit ASTSubstNonTypeTemplateParmExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpSubstNonTypeTemplateParm) { + (void)allocatorIn; + } ~ASTSubstNonTypeTemplateParmExpr() = default; private: @@ -1518,7 +1693,9 @@ class ASTSubstNonTypeTemplateParmExpr : public ASTExpr { class ASTDependentScopeDeclRefExpr : public ASTExpr { public: - ASTDependentScopeDeclRefExpr() : ASTExpr(kASTOpDependentScopeDeclRef) {} + explicit ASTDependentScopeDeclRefExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpDependentScopeDeclRef) { + (void)allocatorIn; + } ~ASTDependentScopeDeclRefExpr() = default; private: @@ -1527,7 +1704,9 @@ class ASTDependentScopeDeclRefExpr : public ASTExpr { class ASTAtomicExpr : public ASTExpr { public: - ASTAtomicExpr() : ASTExpr(kASTOpAtomic) {} + explicit ASTAtomicExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpAtomic) { + (void)allocatorIn; + } ~ASTAtomicExpr() = default; void SetRefType(MIRType *ref) { @@ -1609,7 +1788,9 @@ class ASTAtomicExpr : public ASTExpr { class ASTExprStmtExpr : public ASTExpr { public: - ASTExprStmtExpr() : ASTExpr(kASTOpStmtExpr) {} + explicit ASTExprStmtExpr(MapleAllocator &allocatorIn) : ASTExpr(kASTOpStmtExpr) { + (void)allocatorIn; + } ~ASTExprStmtExpr() = default; void SetCompoundStmt(ASTStmt *sub) { cpdStmt = sub; diff --git a/src/hir2mpl/ast_input/clang/include/ast_op.h b/src/hir2mpl/ast_input/clang/include/ast_op.h index 795a9181daf91f5b909f2facc9b631668f6f1d94..a1f8802e8aae2d2aa71398e33509e905f8cd676c 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_op.h +++ b/src/hir2mpl/ast_input/clang/include/ast_op.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -112,7 +112,7 @@ enum ASTOp { kASTOpOpaqueValue, kASTOpBinaryConditionalOperator, kASTOpNoInitExpr, - kASTOpCompoundLiteralExp, + kASTOpCompoundLiteralExpr, kASTOpOffsetOfExpr, kASTOpGenericSelectionExpr, kASTOpInitListExpr, @@ -135,6 +135,7 @@ enum ASTStmtOp { kASTStmtIndirectGoto, kASTStmtLabel, + kASTStmtAddrOfLabelExpr, kASTStmtDo, kASTStmtFor, @@ -169,6 +170,8 @@ enum ASTStmtOp { kASTOffsetOfStmt, kASTGenericSelectionExprStmt, kASTStmtAttributed, + kASTStmtDeclRefExpr, + kASTStmtUnaryExprOrTypeTraitExpr, }; } // namespace maple #endif // HIR2MPL_AST_INPUT_INCLUDE_AST_OP_H diff --git a/src/hir2mpl/ast_input/clang/include/ast_parser.h b/src/hir2mpl/ast_input/clang/include/ast_parser.h index 7d05e26fc4f69d5bdb28dfc379dbb40268cf98d2..689c1b750bf3f987437864597d658e7b4e76de1f 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_parser.h +++ b/src/hir2mpl/ast_input/clang/include/ast_parser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -26,13 +26,15 @@ class ASTParser { ASTParser(MapleAllocator &allocatorIn, uint32 fileIdxIn, const std::string &fileNameIn, MapleList &astStructsIn, MapleList &astFuncsIn, MapleList &astVarsIn, MapleList &astFileScopeAsmsIn) - : fileIdx(fileIdxIn), fileName(fileNameIn), globalVarDecles(allocatorIn.Adapter()), + : fileIdx(fileIdxIn), fileName(fileNameIn, allocatorIn.GetMemPool()), globalVarDecles(allocatorIn.Adapter()), funcDecles(allocatorIn.Adapter()), recordDecles(allocatorIn.Adapter()), globalEnumDecles(allocatorIn.Adapter()), globalTypeDefDecles(allocatorIn.Adapter()), globalFileScopeAsm(allocatorIn.Adapter()), astStructs(astStructsIn), astFuncs(astFuncsIn), astVars(astVarsIn), astFileScopeAsms(astFileScopeAsmsIn) {} virtual ~ASTParser() = default; - bool OpenFile(); + bool OpenFile(MapleAllocator &allocator); + bool Release(); + bool Verify() const; bool PreProcessAST(); @@ -43,12 +45,12 @@ class ASTParser { bool ProcessGlobalTypeDef(MapleAllocator &allocator); - const std::string &GetSourceFileName() const; + const std::string GetSourceFileName() const; const uint32 GetFileIdx() const; // ProcessStmt ASTStmt *ProcessStmt(MapleAllocator &allocator, const clang::Stmt &stmt); - ASTStmt *ProcessFunctionBody(MapleAllocator &allocator, const clang::CompoundStmt &cpdStmt); + ASTStmt *ProcessFunctionBody(MapleAllocator &allocator, const clang::CompoundStmt &compoundStmt); #define PROCESS_STMT(CLASS) ProcessStmt##CLASS(MapleAllocator&, const clang::CLASS&) ASTStmt *PROCESS_STMT(AttributedStmt); ASTStmt *PROCESS_STMT(UnaryOperator); @@ -84,6 +86,9 @@ class ASTParser { ASTStmt *PROCESS_STMT(GCCAsmStmt); ASTStmt *PROCESS_STMT(OffsetOfExpr); ASTStmt *PROCESS_STMT(GenericSelectionExpr); + ASTStmt *PROCESS_STMT(DeclRefExpr); + ASTStmt *PROCESS_STMT(UnaryExprOrTypeTraitExpr); + ASTStmt *PROCESS_STMT(AddrLabelExpr); bool HasDefault(const clang::Stmt &stmt); // ProcessExpr @@ -93,6 +98,7 @@ class ASTParser { ASTValue *AllocASTValue(const MapleAllocator &allocator) const; ASTValue *TranslateExprEval(MapleAllocator &allocator, const clang::Expr *expr) const; ASTExpr *EvaluateExprAsConst(MapleAllocator &allocator, const clang::Expr *expr); + bool HasLabelStmt(const clang::Stmt *expr); ASTExpr *ProcessExpr(MapleAllocator &allocator, const clang::Expr *expr); ASTExpr *ProcessExprInType(MapleAllocator &allocator, const clang::QualType &qualType); ASTBinaryOperatorExpr *AllocBinaryOperatorExpr(MapleAllocator &allocator, const clang::BinaryOperator &bo); @@ -158,10 +164,11 @@ class ASTParser { ASTDecl *PROCESS_DECL(StaticAssert); static ASTExpr *GetAddrShiftExpr(MapleAllocator &allocator, ASTExpr *expr, uint32 typeSize); + static ASTExpr *GetSizeMulExpr(MapleAllocator &allocator, ASTExpr *expr, ASTExpr *ptrSizeExpr); private: void ProcessNonnullFuncAttrs(const clang::FunctionDecl &funcDecl, ASTFunc &astFunc); - void ProcessNonnullFuncPtrAttrs(const clang::ValueDecl &valueDecl, ASTDecl &astVar); + void ProcessNonnullFuncPtrAttrs(MapleAllocator &allocator, const clang::ValueDecl &valueDecl, ASTDecl &astVar); void ProcessBoundaryFuncAttrs(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, ASTFunc &astFunc); void ProcessByteBoundaryFuncAttrs(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, ASTFunc &astFunc); void ProcessBoundaryFuncAttrsByIndex(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, @@ -179,11 +186,11 @@ class ASTParser { template bool ProcessBoundaryFuncPtrAttrsForRet(T *attr, MapleAllocator &allocator, const MIRFuncType &funcType, const clang::FunctionType &clangFuncType, TypeAttrs &retAttr); - void ProcessBoundaryFuncPtrAttrsByIndex(const clang::ValueDecl &valueDecl, ASTDecl &astDecl, - const MIRFuncType &funcType); + void ProcessBoundaryFuncPtrAttrsByIndex(MapleAllocator &allocator, const clang::ValueDecl &valueDecl, + ASTDecl &astDecl, const MIRFuncType &funcType); template bool ProcessBoundaryFuncPtrAttrsByIndexForParams(T *attr, ASTDecl &astDecl, const MIRFuncType &funcType, - std::vector &attrsVec); + std::vector &attrsVec) const; void ProcessBoundaryLenExpr(MapleAllocator &allocator, ASTDecl &ptrDecl, const clang::QualType &qualType, const std::function &getLenExprFromStringLiteral, ASTExpr *lenExpr, bool isSize); @@ -238,8 +245,8 @@ ASTExpr *ParseBuiltinFunc(MapleAllocator &allocator, const clang::CallExpr &expr static std::map builtingFuncPtrMap; uint32 fileIdx; - const std::string fileName; - std::unique_ptr astFile; + const MapleString fileName; + LibAstFile *astFile = nullptr; AstUnitDecl *astUnitDecl = nullptr; MapleList globalVarDecles; MapleList funcDecles; diff --git a/src/hir2mpl/ast_input/clang/include/ast_stmt.h b/src/hir2mpl/ast_input/clang/include/ast_stmt.h index 4a053bb43957715bdcf1de748b3fb429c28cfe38..c0e5f7199353d9fb4f351fdb9cabfaf30d3fecc7 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_stmt.h +++ b/src/hir2mpl/ast_input/clang/include/ast_stmt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -21,7 +21,7 @@ namespace maple { class ASTDecl; -enum SafeSS { +enum class SafeSS { kNoneSS, kSafeSS, kUnsafeSS, @@ -29,47 +29,54 @@ enum SafeSS { class ASTStmt { public: - explicit ASTStmt(ASTStmtOp o = kASTStmtNone) : op(o) {} + explicit ASTStmt(MapleAllocator &allocatorIn, ASTStmtOp o = kASTStmtNone) : exprs(allocatorIn.Adapter()), op(o) {} virtual ~ASTStmt() = default; void SetASTExpr(ASTExpr* astExpr); std::list Emit2FEStmt() const { - return Emit2FEStmtImpl(); + auto stmts = Emit2FEStmtImpl(); + for (UniqueFEIRStmt &stmt : stmts) { + if (stmt != nullptr && !stmt->HasSetLOCInfo()) { + stmt->SetSrcLoc(loc); + } + } + return stmts; } ASTStmtOp GetASTStmtOp() const { return op; } - const std::vector &GetExprs() const { + const MapleVector &GetExprs() const { return exprs; } - void SetSrcLOC(uint32 fileIdx, uint32 lineNum) { - srcFileIdx = fileIdx; - srcFileLineNum = lineNum; + void SetSrcLoc(const Loc &l) { + loc = l; + } + + const Loc &GetSrcLoc() const { + return loc; } uint32 GetSrcFileIdx() const { - return srcFileIdx; + return loc.fileIdx; } uint32 GetSrcFileLineNum() const { - return srcFileLineNum; + return loc.line; } protected: virtual std::list Emit2FEStmtImpl() const = 0; + MapleVector exprs; ASTStmtOp op; - std::vector exprs; - - uint32 srcFileIdx = 0; - uint32 srcFileLineNum = 0; + Loc loc = {0, 0, 0}; }; class ASTStmtDummy : public ASTStmt { public: - ASTStmtDummy() : ASTStmt(kASTStmtDummy) {} + explicit ASTStmtDummy(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtDummy) {} ~ASTStmtDummy() = default; private: @@ -78,11 +85,12 @@ class ASTStmtDummy : public ASTStmt { class ASTCompoundStmt : public ASTStmt { public: - ASTCompoundStmt() : ASTStmt(kASTStmtCompound) {} + explicit ASTCompoundStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCompound), + astStmts(allocatorIn.Adapter()) {} ~ASTCompoundStmt() = default; - void SetASTStmt(ASTStmt*); + void SetASTStmt(ASTStmt *astStmt); void InsertASTStmtsAtFront(const std::list &stmts); - const std::list &GetASTStmtList() const; + const MapleList &GetASTStmtList() const; void SetSafeSS(SafeSS state) { safeSS = state; @@ -92,16 +100,26 @@ class ASTCompoundStmt : public ASTStmt { return safeSS; } + void SetEndLoc(const Loc &loc) { + endLoc = loc; + } + + const Loc &GetEndLoc() const { + return endLoc; + } + private: - SafeSS safeSS = kNoneSS; - std::list astStmts; // stmts + SafeSS safeSS = SafeSS::kNoneSS; + MapleList astStmts; // stmts + Loc endLoc = {0, 0, 0}; std::list Emit2FEStmtImpl() const override; + mutable bool hasEmitted2MIRScope = false; }; // Any other expressions or stmts should be extended here class ASTReturnStmt : public ASTStmt { public: - ASTReturnStmt() : ASTStmt(kASTStmtReturn) {} + explicit ASTReturnStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtReturn) {} ~ASTReturnStmt() = default; private: @@ -110,7 +128,7 @@ class ASTReturnStmt : public ASTStmt { class ASTAttributedStmt : public ASTStmt { public: - ASTAttributedStmt() : ASTStmt(kASTStmtAttributed) {} + explicit ASTAttributedStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtAttributed) {} ~ASTAttributedStmt() override = default; private: @@ -119,7 +137,7 @@ class ASTAttributedStmt : public ASTStmt { class ASTIfStmt : public ASTStmt { public: - ASTIfStmt() : ASTStmt(kASTStmtIf) {} + explicit ASTIfStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtIf) {} ~ASTIfStmt() override = default; void SetCondExpr(ASTExpr *astExpr) { @@ -143,7 +161,7 @@ class ASTIfStmt : public ASTStmt { class ASTForStmt : public ASTStmt { public: - ASTForStmt() : ASTStmt(kASTStmtFor) {} + explicit ASTForStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtFor) {} ~ASTForStmt() override = default; void SetInitStmt(ASTStmt *astStmt) { @@ -162,17 +180,26 @@ class ASTForStmt : public ASTStmt { bodyStmt = astStmt; } + void SetEndLoc(const Loc &loc) { + endLoc = loc; + } + + const Loc &GetEndLoc() const { + return endLoc; + } private: std::list Emit2FEStmtImpl() const override; ASTStmt *initStmt = nullptr; ASTExpr *condExpr = nullptr; ASTExpr *incExpr = nullptr; ASTStmt *bodyStmt = nullptr; + Loc endLoc = {0, 0, 0}; + mutable bool hasEmitted2MIRScope = false; }; class ASTWhileStmt : public ASTStmt { public: - ASTWhileStmt() : ASTStmt(kASTStmtWhile) {} + explicit ASTWhileStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtWhile) {} ~ASTWhileStmt() override = default; void SetCondExpr(ASTExpr *astExpr) { @@ -191,26 +218,26 @@ class ASTWhileStmt : public ASTStmt { class ASTDoStmt : public ASTStmt { public: - ASTDoStmt() : ASTStmt(kASTStmtDo) {} + explicit ASTDoStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtDo) {} ~ASTDoStmt() override = default; - void SetCondExpr(ASTExpr *astExpr) { - condExpr = astExpr; - } - void SetBodyStmt(ASTStmt *astStmt) { bodyStmt = astStmt; } + void SetCondExpr(ASTExpr *astExpr) { + condExpr = astExpr; + } + private: std::list Emit2FEStmtImpl() const override; - ASTExpr *condExpr = nullptr; ASTStmt *bodyStmt = nullptr; + ASTExpr *condExpr = nullptr; }; class ASTBreakStmt : public ASTStmt { public: - ASTBreakStmt() : ASTStmt(kASTStmtBreak) {} + explicit ASTBreakStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtBreak) {} ~ASTBreakStmt() override = default; private: @@ -219,26 +246,35 @@ class ASTBreakStmt : public ASTStmt { class ASTLabelStmt : public ASTStmt { public: - ASTLabelStmt() : ASTStmt(kASTStmtLabel) {} + explicit ASTLabelStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtLabel), + labelName("", allocatorIn.GetMemPool()) {} ~ASTLabelStmt() override = default; void SetSubStmt(ASTStmt *stmt) { subStmt = stmt; } + const ASTStmt* GetSubStmt() const { + return subStmt; + } + void SetLabelName(const std::string &name) { labelName = name; } + const std::string GetLabelName() const { + return labelName.c_str() == nullptr ? "" : labelName.c_str(); + } + private: std::list Emit2FEStmtImpl() const override; - std::string labelName; + MapleString labelName; ASTStmt *subStmt = nullptr; }; class ASTContinueStmt : public ASTStmt { public: - ASTContinueStmt() : ASTStmt(kASTStmtContinue) {} + explicit ASTContinueStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtContinue) {} ~ASTContinueStmt() override = default; private: @@ -247,7 +283,7 @@ class ASTContinueStmt : public ASTStmt { class ASTUnaryOperatorStmt : public ASTStmt { public: - ASTUnaryOperatorStmt() : ASTStmt(kASTStmtUO) {} + explicit ASTUnaryOperatorStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtUO) {} ~ASTUnaryOperatorStmt() = default; private: @@ -256,7 +292,7 @@ class ASTUnaryOperatorStmt : public ASTStmt { class ASTBinaryOperatorStmt : public ASTStmt { public: - ASTBinaryOperatorStmt() : ASTStmt(kASTStmtBO) {} + explicit ASTBinaryOperatorStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtBO) {} ~ASTBinaryOperatorStmt() override = default; private: @@ -265,11 +301,12 @@ class ASTBinaryOperatorStmt : public ASTStmt { class ASTGotoStmt : public ASTStmt { public: - ASTGotoStmt() : ASTStmt(kASTStmtGoto) {} + explicit ASTGotoStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtGoto), + labelName("", allocatorIn.GetMemPool()) {} ~ASTGotoStmt() = default; std::string GetLabelName() const { - return labelName; + return labelName.c_str() == nullptr ? "" : labelName.c_str(); } void SetLabelName(const std::string &name) { @@ -278,12 +315,12 @@ class ASTGotoStmt : public ASTStmt { private: std::list Emit2FEStmtImpl() const override; - std::string labelName; + MapleString labelName; }; class ASTIndirectGotoStmt : public ASTStmt { public: - ASTIndirectGotoStmt() : ASTStmt(kASTStmtIndirectGoto) {} + explicit ASTIndirectGotoStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtIndirectGoto) {} ~ASTIndirectGotoStmt() = default; protected: @@ -292,7 +329,7 @@ class ASTIndirectGotoStmt : public ASTStmt { class ASTSwitchStmt : public ASTStmt { public: - ASTSwitchStmt() : ASTStmt(kASTStmtSwitch) {} + explicit ASTSwitchStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtSwitch) {} ~ASTSwitchStmt() = default; void SetCondStmt(ASTStmt *cond) { @@ -342,7 +379,7 @@ class ASTSwitchStmt : public ASTStmt { class ASTCaseStmt : public ASTStmt { public: - ASTCaseStmt() : ASTStmt(kASTStmtCase) {} + explicit ASTCaseStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCase) {} ~ASTCaseStmt() = default; void SetLHS(ASTExpr *l) { @@ -396,7 +433,7 @@ class ASTCaseStmt : public ASTStmt { class ASTDefaultStmt : public ASTStmt { public: - ASTDefaultStmt() : ASTStmt(kASTStmtDefault) {} + explicit ASTDefaultStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtDefault) {} ~ASTDefaultStmt() = default; void SetChildStmt(ASTStmt* ch) { @@ -414,7 +451,7 @@ class ASTDefaultStmt : public ASTStmt { class ASTNullStmt : public ASTStmt { public: - ASTNullStmt() : ASTStmt(kASTStmtNull) {} + explicit ASTNullStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtNull) {} ~ASTNullStmt() = default; private: @@ -423,14 +460,15 @@ class ASTNullStmt : public ASTStmt { class ASTDeclStmt : public ASTStmt { public: - ASTDeclStmt() : ASTStmt(kASTStmtDecl) {} + explicit ASTDeclStmt(MapleAllocator &allocatorIn) + : ASTStmt(allocatorIn, kASTStmtDecl), subDecls(allocatorIn.Adapter()) {} ~ASTDeclStmt() = default; void SetSubDecl(ASTDecl *decl) { subDecls.emplace_back(decl); } - const std::list& GetSubDecls() const { + const MapleList& GetSubDecls() const { return subDecls; } @@ -438,12 +476,12 @@ class ASTDeclStmt : public ASTStmt { std::list Emit2FEStmtImpl() const override; void InsertBoundaryVar(ASTDecl *ptrDecl, std::list &stmts) const; - std::list subDecls; + MapleList subDecls; }; class ASTCompoundAssignOperatorStmt : public ASTStmt { public: - ASTCompoundAssignOperatorStmt() : ASTStmt(kASTStmtCAO) {} + explicit ASTCompoundAssignOperatorStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCAO) {} ~ASTCompoundAssignOperatorStmt() override = default; private: @@ -452,7 +490,7 @@ class ASTCompoundAssignOperatorStmt : public ASTStmt { class ASTImplicitCastExprStmt : public ASTStmt { public: - ASTImplicitCastExprStmt() : ASTStmt(kASTStmtImplicitCastExpr) {} + explicit ASTImplicitCastExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtImplicitCastExpr) {} ~ASTImplicitCastExprStmt() override = default; private: @@ -461,7 +499,7 @@ class ASTImplicitCastExprStmt : public ASTStmt { class ASTParenExprStmt : public ASTStmt { public: - ASTParenExprStmt() : ASTStmt(kASTStmtParenExpr) {} + explicit ASTParenExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtParenExpr) {} ~ASTParenExprStmt() override = default; private: @@ -470,7 +508,7 @@ class ASTParenExprStmt : public ASTStmt { class ASTIntegerLiteralStmt : public ASTStmt { public: - ASTIntegerLiteralStmt() : ASTStmt(kASTStmtIntegerLiteral) {} + explicit ASTIntegerLiteralStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtIntegerLiteral) {} ~ASTIntegerLiteralStmt() override = default; private: @@ -479,7 +517,7 @@ class ASTIntegerLiteralStmt : public ASTStmt { class ASTFloatingLiteralStmt : public ASTStmt { public: - ASTFloatingLiteralStmt() : ASTStmt(kASTStmtFloatingLiteral) {} + explicit ASTFloatingLiteralStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtFloatingLiteral) {} ~ASTFloatingLiteralStmt() override = default; private: @@ -488,7 +526,7 @@ class ASTFloatingLiteralStmt : public ASTStmt { class ASTVAArgExprStmt : public ASTStmt { public: - ASTVAArgExprStmt() : ASTStmt(kASTStmtVAArgExpr) {} + explicit ASTVAArgExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtVAArgExpr) {} ~ASTVAArgExprStmt() override = default; private: @@ -497,7 +535,7 @@ class ASTVAArgExprStmt : public ASTStmt { class ASTConditionalOperatorStmt : public ASTStmt { public: - ASTConditionalOperatorStmt() : ASTStmt(kASTStmtConditionalOperator) {} + explicit ASTConditionalOperatorStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtConditionalOperator) {} ~ASTConditionalOperatorStmt() override = default; private: @@ -506,7 +544,7 @@ class ASTConditionalOperatorStmt : public ASTStmt { class ASTCharacterLiteralStmt : public ASTStmt { public: - ASTCharacterLiteralStmt() : ASTStmt(kASTStmtCharacterLiteral) {} + explicit ASTCharacterLiteralStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCharacterLiteral) {} ~ASTCharacterLiteralStmt() override = default; private: @@ -515,14 +553,14 @@ class ASTCharacterLiteralStmt : public ASTStmt { class ASTStmtExprStmt : public ASTStmt { public: - ASTStmtExprStmt() : ASTStmt(kASTStmtStmtExpr) {} + explicit ASTStmtExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtStmtExpr) {} ~ASTStmtExprStmt() override = default; void SetBodyStmt(ASTStmt *stmt) { cpdStmt = stmt; } - ASTStmt *GetBodyStmt() { + const ASTStmt *GetBodyStmt() const { return cpdStmt; } @@ -534,7 +572,7 @@ class ASTStmtExprStmt : public ASTStmt { class ASTCStyleCastExprStmt : public ASTStmt { public: - ASTCStyleCastExprStmt() : ASTStmt(kASTStmtCStyleCastExpr) {} + explicit ASTCStyleCastExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCStyleCastExpr) {} ~ASTCStyleCastExprStmt() override = default; private: @@ -543,7 +581,8 @@ class ASTCStyleCastExprStmt : public ASTStmt { class ASTCallExprStmt : public ASTStmt { public: - ASTCallExprStmt() : ASTStmt(kASTStmtCallExpr), varName(FEUtils::GetSequentialName("retVar_")) {} + ASTCallExprStmt(MapleAllocator &allocatorIn, const std::string &varNameIn) + : ASTStmt(allocatorIn, kASTStmtCallExpr), varName(varNameIn) {} ~ASTCallExprStmt() override = default; private: @@ -556,7 +595,7 @@ class ASTCallExprStmt : public ASTStmt { class ASTAtomicExprStmt : public ASTStmt { public: - ASTAtomicExprStmt() : ASTStmt(kASTStmtAtomicExpr) {} + explicit ASTAtomicExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtAtomicExpr) {} ~ASTAtomicExprStmt() override = default; private: @@ -565,13 +604,19 @@ class ASTAtomicExprStmt : public ASTStmt { class ASTGCCAsmStmt : public ASTStmt { public: - ASTGCCAsmStmt() : ASTStmt(kASTStmtGCCAsmStmt) {} + explicit ASTGCCAsmStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtGCCAsmStmt), + asmStr("", allocatorIn.GetMemPool()), outputs(allocatorIn.Adapter()), inputs(allocatorIn.Adapter()), + clobbers(allocatorIn.Adapter()), labels(allocatorIn.Adapter()) {} ~ASTGCCAsmStmt() override = default; void SetAsmStr(const std::string &str) { asmStr = str; } + const std::string GetAsmStr() const { + return asmStr.c_str() == nullptr ? "" : asmStr.c_str(); + } + void InsertOutput(std::tuple &&output) { outputs.emplace_back(output); } @@ -598,18 +643,18 @@ class ASTGCCAsmStmt : public ASTStmt { private: std::list Emit2FEStmtImpl() const override; - std::string asmStr; - std::vector> outputs; - std::vector> inputs; - std::vector clobbers; - std::vector labels; + MapleString asmStr; + MapleVector> outputs; + MapleVector> inputs; + MapleVector clobbers; + MapleVector labels; bool isGoto = false; bool isVolatile = false; }; class ASTOffsetOfStmt : public ASTStmt { public: - ASTOffsetOfStmt() : ASTStmt(kASTOffsetOfStmt) {} + explicit ASTOffsetOfStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTOffsetOfStmt) {} ~ASTOffsetOfStmt() override = default; private: @@ -618,11 +663,38 @@ class ASTOffsetOfStmt : public ASTStmt { class ASTGenericSelectionExprStmt : public ASTStmt { public: - ASTGenericSelectionExprStmt() : ASTStmt(kASTGenericSelectionExprStmt) {} + explicit ASTGenericSelectionExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTGenericSelectionExprStmt) {} ~ASTGenericSelectionExprStmt() override = default; private: std::list Emit2FEStmtImpl() const override; }; + +class ASTDeclRefExprStmt : public ASTStmt { + public: + explicit ASTDeclRefExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtDeclRefExpr) {} + ~ASTDeclRefExprStmt() override = default; + + private: + std::list Emit2FEStmtImpl() const override; +}; + +class ASTUnaryExprOrTypeTraitExprStmt : public ASTStmt { + public: + explicit ASTUnaryExprOrTypeTraitExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtDeclRefExpr) {} + ~ASTUnaryExprOrTypeTraitExprStmt() override = default; + + private: + std::list Emit2FEStmtImpl() const override; +}; + +class ASTUOAddrOfLabelExprStmt : public ASTStmt { + public: + explicit ASTUOAddrOfLabelExprStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtAddrOfLabelExpr) {} + ~ASTUOAddrOfLabelExprStmt() override = default; + + private: + std::list Emit2FEStmtImpl() const override; +}; } // namespace maple #endif // HIR2MPL_AST_INPUT_INCLUDE_AST_STMT_H diff --git a/src/hir2mpl/ast_input/clang/include/ast_struct2fe_helper.h b/src/hir2mpl/ast_input/clang/include/ast_struct2fe_helper.h index 772a0639055c5cc70f6fd4e8fbae97b8f9002fd9..6f3388145a31e130fb2b16e5cfc424a378394e88 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_struct2fe_helper.h +++ b/src/hir2mpl/ast_input/clang/include/ast_struct2fe_helper.h @@ -21,7 +21,7 @@ namespace maple { class ASTStruct2FEHelper : public FEInputStructHelper { public: - ASTStruct2FEHelper(MapleAllocator &allocator, const ASTStruct &structIn); + ASTStruct2FEHelper(MapleAllocator &allocator, ASTStruct &structIn); ~ASTStruct2FEHelper() = default; protected: @@ -36,11 +36,11 @@ class ASTStruct2FEHelper : public FEInputStructHelper { std::string GetSourceFileNameImpl() const override; MIRStructType *CreateMIRStructTypeImpl(bool &error) const override; uint64 GetRawAccessFlagsImpl() const override; - virtual GStrIdx GetIRSrcFileSigIdxImpl() const override; - virtual bool IsMultiDefImpl() const override; + GStrIdx GetIRSrcFileSigIdxImpl() const override; + bool IsMultiDefImpl() const override; std::string GetSrcFileNameImpl() const override; - const ASTStruct &astStruct; + ASTStruct &astStruct; }; class ASTGlobalVar2FEHelper : public FEInputGlobalVarHelper { @@ -69,7 +69,7 @@ class ASTFileScopeAsm2FEHelper : public FEInputFileScopeAsmHelper { class ASTStructField2FEHelper : public FEInputFieldHelper { public: - ASTStructField2FEHelper(MapleAllocator &allocator, const ASTField &fieldIn, const MIRType &structTypeIn) + ASTStructField2FEHelper(MapleAllocator &allocator, ASTField &fieldIn, const MIRType &structTypeIn) : FEInputFieldHelper(allocator), field(fieldIn), structType(structTypeIn) {} ~ASTStructField2FEHelper() = default; @@ -77,7 +77,7 @@ class ASTStructField2FEHelper : public FEInputFieldHelper { protected: bool ProcessDeclImpl(MapleAllocator &allocator) override; bool ProcessDeclWithContainerImpl(MapleAllocator &allocator) override; - const ASTField &field; + ASTField &field; const MIRType &structType; }; @@ -93,7 +93,7 @@ class ASTFunc2FEHelper : public FEInputMethodHelper { return func; } - const std::string &GetSrcFileName() const; + const std::string GetSrcFileName() const; protected: bool ProcessDeclImpl(MapleAllocator &allocator) override; diff --git a/src/hir2mpl/ast_input/clang/include/builtin_func_emit.def b/src/hir2mpl/ast_input/clang/include/builtin_func_emit.def index 1b4efe5299d793b87aa3a9fd3fcc82b927877245..3387838cf3f606c187474fb55cb606ff32b8b8ed 100644 --- a/src/hir2mpl/ast_input/clang/include/builtin_func_emit.def +++ b/src/hir2mpl/ast_input/clang/include/builtin_func_emit.def @@ -34,7 +34,6 @@ BUILTIN_FUNC_EMIT("__builtin_fabsf16", &ASTCallExpr::EmitBuiltinAbs) BUILTIN_FUNC_EMIT("__builtin_fabsf128", &ASTCallExpr::EmitBuiltinAbs) BUILTIN_FUNC_EMIT("__builtin_labs", &ASTCallExpr::EmitBuiltinAbs) BUILTIN_FUNC_EMIT("__builtin_llabs", &ASTCallExpr::EmitBuiltinAbs) -BUILTIN_FUNC_EMIT("__builtin_unreachable", &ASTCallExpr::EmitBuiltinUnreachable) BUILTIN_FUNC_EMIT("abs", &ASTCallExpr::EmitBuiltinAbs) BUILTIN_FUNC_EMIT("labs", &ASTCallExpr::EmitBuiltinAbs) BUILTIN_FUNC_EMIT("llabs", &ASTCallExpr::EmitBuiltinAbs) @@ -110,22 +109,73 @@ BUILTIN_FUNC_EMIT("__builtin_rotateright64", &ASTCallExpr::EmitBuiltinRotateRigh BUILTIN_FUNC_EMIT("__sync_add_and_fetch_8", &ASTCallExpr::EmitBuiltinSyncAddAndFetch8) BUILTIN_FUNC_EMIT("__sync_add_and_fetch_4", &ASTCallExpr::EmitBuiltinSyncAddAndFetch4) BUILTIN_FUNC_EMIT("__sync_add_and_fetch_2", &ASTCallExpr::EmitBuiltinSyncAddAndFetch2) +BUILTIN_FUNC_EMIT("__sync_add_and_fetch_1", &ASTCallExpr::EmitBuiltinSyncAddAndFetch1) BUILTIN_FUNC_EMIT("__sync_sub_and_fetch_8", &ASTCallExpr::EmitBuiltinSyncSubAndFetch8) BUILTIN_FUNC_EMIT("__sync_sub_and_fetch_4", &ASTCallExpr::EmitBuiltinSyncSubAndFetch4) BUILTIN_FUNC_EMIT("__sync_sub_and_fetch_2", &ASTCallExpr::EmitBuiltinSyncSubAndFetch2) +BUILTIN_FUNC_EMIT("__sync_sub_and_fetch_1", &ASTCallExpr::EmitBuiltinSyncSubAndFetch1) BUILTIN_FUNC_EMIT("__sync_fetch_and_sub_8", &ASTCallExpr::EmitBuiltinSyncFetchAndSub8) BUILTIN_FUNC_EMIT("__sync_fetch_and_sub_4", &ASTCallExpr::EmitBuiltinSyncFetchAndSub4) BUILTIN_FUNC_EMIT("__sync_fetch_and_sub_2", &ASTCallExpr::EmitBuiltinSyncFetchAndSub2) +BUILTIN_FUNC_EMIT("__sync_fetch_and_sub_1", &ASTCallExpr::EmitBuiltinSyncFetchAndSub1) BUILTIN_FUNC_EMIT("__sync_fetch_and_add_8", &ASTCallExpr::EmitBuiltinSyncFetchAndAdd8) BUILTIN_FUNC_EMIT("__sync_fetch_and_add_4", &ASTCallExpr::EmitBuiltinSyncFetchAndAdd4) BUILTIN_FUNC_EMIT("__sync_fetch_and_add_2", &ASTCallExpr::EmitBuiltinSyncFetchAndAdd2) +BUILTIN_FUNC_EMIT("__sync_fetch_and_add_1", &ASTCallExpr::EmitBuiltinSyncFetchAndAdd1) BUILTIN_FUNC_EMIT("__sync_bool_compare_and_swap_8", &ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap8) BUILTIN_FUNC_EMIT("__sync_bool_compare_and_swap_4", &ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap4) +BUILTIN_FUNC_EMIT("__sync_bool_compare_and_swap_2", &ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap2) +BUILTIN_FUNC_EMIT("__sync_bool_compare_and_swap_1", &ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap1) BUILTIN_FUNC_EMIT("__sync_val_compare_and_swap_8", &ASTCallExpr::EmitBuiltinSyncValCompareAndSwap8) BUILTIN_FUNC_EMIT("__sync_val_compare_and_swap_4", &ASTCallExpr::EmitBuiltinSyncValCompareAndSwap4) +BUILTIN_FUNC_EMIT("__sync_val_compare_and_swap_2", &ASTCallExpr::EmitBuiltinSyncValCompareAndSwap2) +BUILTIN_FUNC_EMIT("__sync_val_compare_and_swap_1", &ASTCallExpr::EmitBuiltinSyncValCompareAndSwap1) BUILTIN_FUNC_EMIT("__sync_lock_test_and_set_8", &ASTCallExpr::EmitBuiltinSyncLockTestAndSet8) BUILTIN_FUNC_EMIT("__sync_lock_test_and_set_4", &ASTCallExpr::EmitBuiltinSyncLockTestAndSet4) +BUILTIN_FUNC_EMIT("__sync_lock_test_and_set_2", &ASTCallExpr::EmitBuiltinSyncLockTestAndSet2) +BUILTIN_FUNC_EMIT("__sync_lock_test_and_set_1", &ASTCallExpr::EmitBuiltinSyncLockTestAndSet1) BUILTIN_FUNC_EMIT("__sync_lock_release_8", &ASTCallExpr::EmitBuiltinSyncLockRelease8) BUILTIN_FUNC_EMIT("__sync_lock_release_4", &ASTCallExpr::EmitBuiltinSyncLockRelease4) +BUILTIN_FUNC_EMIT("__sync_lock_release_2", &ASTCallExpr::EmitBuiltinSyncLockRelease2) +BUILTIN_FUNC_EMIT("__sync_lock_release_1", &ASTCallExpr::EmitBuiltinSyncLockRelease1) +BUILTIN_FUNC_EMIT("__sync_fetch_and_and_1", &ASTCallExpr::EmitBuiltinSyncFetchAndAnd1) +BUILTIN_FUNC_EMIT("__sync_fetch_and_and_2", &ASTCallExpr::EmitBuiltinSyncFetchAndAnd2) +BUILTIN_FUNC_EMIT("__sync_fetch_and_and_4", &ASTCallExpr::EmitBuiltinSyncFetchAndAnd4) +BUILTIN_FUNC_EMIT("__sync_fetch_and_and_8", &ASTCallExpr::EmitBuiltinSyncFetchAndAnd8) +BUILTIN_FUNC_EMIT("__sync_fetch_and_or_1", &ASTCallExpr::EmitBuiltinSyncFetchAndOr1) +BUILTIN_FUNC_EMIT("__sync_fetch_and_or_2", &ASTCallExpr::EmitBuiltinSyncFetchAndOr2) +BUILTIN_FUNC_EMIT("__sync_fetch_and_or_4", &ASTCallExpr::EmitBuiltinSyncFetchAndOr4) +BUILTIN_FUNC_EMIT("__sync_fetch_and_or_8", &ASTCallExpr::EmitBuiltinSyncFetchAndOr8) +BUILTIN_FUNC_EMIT("__sync_fetch_and_xor_1", &ASTCallExpr::EmitBuiltinSyncFetchAndXor1) +BUILTIN_FUNC_EMIT("__sync_fetch_and_xor_2", &ASTCallExpr::EmitBuiltinSyncFetchAndXor2) +BUILTIN_FUNC_EMIT("__sync_fetch_and_xor_4", &ASTCallExpr::EmitBuiltinSyncFetchAndXor4) +BUILTIN_FUNC_EMIT("__sync_fetch_and_xor_8", &ASTCallExpr::EmitBuiltinSyncFetchAndXor8) +BUILTIN_FUNC_EMIT("__sync_fetch_and_nand_1", &ASTCallExpr::EmitBuiltinSyncFetchAndNand1) +BUILTIN_FUNC_EMIT("__sync_fetch_and_nand_2", &ASTCallExpr::EmitBuiltinSyncFetchAndNand2) +BUILTIN_FUNC_EMIT("__sync_fetch_and_nand_4", &ASTCallExpr::EmitBuiltinSyncFetchAndNand4) +BUILTIN_FUNC_EMIT("__sync_fetch_and_nand_8", &ASTCallExpr::EmitBuiltinSyncFetchAndNand8) +BUILTIN_FUNC_EMIT("__sync_and_and_fetch_1", &ASTCallExpr::EmitBuiltinSyncAndAndFetch1) +BUILTIN_FUNC_EMIT("__sync_and_and_fetch_2", &ASTCallExpr::EmitBuiltinSyncAndAndFetch2) +BUILTIN_FUNC_EMIT("__sync_and_and_fetch_4", &ASTCallExpr::EmitBuiltinSyncAndAndFetch4) +BUILTIN_FUNC_EMIT("__sync_and_and_fetch_8", &ASTCallExpr::EmitBuiltinSyncAndAndFetch8) +BUILTIN_FUNC_EMIT("__sync_or_and_fetch_1", &ASTCallExpr::EmitBuiltinSyncOrAndFetch1) +BUILTIN_FUNC_EMIT("__sync_or_and_fetch_2", &ASTCallExpr::EmitBuiltinSyncOrAndFetch2) +BUILTIN_FUNC_EMIT("__sync_or_and_fetch_4", &ASTCallExpr::EmitBuiltinSyncOrAndFetch4) +BUILTIN_FUNC_EMIT("__sync_or_and_fetch_8", &ASTCallExpr::EmitBuiltinSyncOrAndFetch8) +BUILTIN_FUNC_EMIT("__sync_xor_and_fetch_1", &ASTCallExpr::EmitBuiltinSyncXorAndFetch1) +BUILTIN_FUNC_EMIT("__sync_xor_and_fetch_2", &ASTCallExpr::EmitBuiltinSyncXorAndFetch2) +BUILTIN_FUNC_EMIT("__sync_xor_and_fetch_4", &ASTCallExpr::EmitBuiltinSyncXorAndFetch4) +BUILTIN_FUNC_EMIT("__sync_xor_and_fetch_8", &ASTCallExpr::EmitBuiltinSyncXorAndFetch8) +BUILTIN_FUNC_EMIT("__sync_nand_and_fetch_1", &ASTCallExpr::EmitBuiltinSyncNandAndFetch1) +BUILTIN_FUNC_EMIT("__sync_nand_and_fetch_2", &ASTCallExpr::EmitBuiltinSyncNandAndFetch2) +BUILTIN_FUNC_EMIT("__sync_nand_and_fetch_4", &ASTCallExpr::EmitBuiltinSyncNandAndFetch4) +BUILTIN_FUNC_EMIT("__sync_nand_and_fetch_8", &ASTCallExpr::EmitBuiltinSyncNandAndFetch8) +BUILTIN_FUNC_EMIT("__sync_synchronize", &ASTCallExpr::EmitBuiltinSyncSynchronize) + +BUILTIN_FUNC_EMIT("__atomic_exchange_1", &ASTCallExpr::EmitBuiltinAtomicExchangeN) +BUILTIN_FUNC_EMIT("__atomic_exchange_2", &ASTCallExpr::EmitBuiltinAtomicExchangeN) +BUILTIN_FUNC_EMIT("__atomic_exchange_4", &ASTCallExpr::EmitBuiltinAtomicExchangeN) +BUILTIN_FUNC_EMIT("__atomic_exchange_8", &ASTCallExpr::EmitBuiltinAtomicExchangeN) + BUILTIN_FUNC_EMIT("__builtin_return_address", &ASTCallExpr::EmitBuiltinReturnAddress) BUILTIN_FUNC_EMIT("__builtin_extract_return_addr", &ASTCallExpr::EmitBuiltinExtractReturnAddr) \ No newline at end of file diff --git a/src/hir2mpl/ast_input/clang/lib/ast_alias.h b/src/hir2mpl/ast_input/clang/lib/ast_alias.h index 548c22d36e43dfc270bf41164e316ae1bc019c8e..e877a685fa0e66fcce0d2f70a6829cb2b6cffd65 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_alias.h +++ b/src/hir2mpl/ast_input/clang/lib/ast_alias.h @@ -14,7 +14,6 @@ */ #ifndef HIR2MPL_AST_FILE_INCLUDE_AST_ALIAS_H #define HIR2MPL_AST_FILE_INCLUDE_AST_ALIAS_H -#include "clang-c/Index.h" #include "libclang/CIndexer.h" #include "libclang/CXTranslationUnit.h" #include "clang/Frontend/ASTUnit.h" @@ -27,8 +26,6 @@ #include "clang/AST/Mangle.h" #include "clang/AST/VTableBuilder.h" #include "clang/AST/VTTBuilder.h" -#include "clang/Lex/Lexer.h" -#include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/AST/DeclBase.h" diff --git a/src/hir2mpl/ast_input/clang/lib/ast_interface.cpp b/src/hir2mpl/ast_input/clang/lib/ast_interface.cpp index 0315f2e402663b8e5fa260327ebaca32e5454451..f46056a394e6611353c93eb9b9281e771660a2a4 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_interface.cpp +++ b/src/hir2mpl/ast_input/clang/lib/ast_interface.cpp @@ -19,11 +19,41 @@ #include "fe_manager.h" namespace maple { -bool LibAstFile::Open(const std::string &fileName, +const std::unordered_map kUnsupportedFuncAttrsMap = { + {clang::attr::NoInstrumentFunction, "no_instrument_function"}, + {clang::attr::StdCall, "stdcall"}, + {clang::attr::CDecl, "cdecl"}, + {clang::attr::MipsLongCall, "mips_long_call"}, + {clang::attr::MipsShortCall, "mips_short_call"}, + {clang::attr::ARMInterrupt, "arm_interrupt"}, + {clang::attr::AnyX86Interrupt, "x86_interrupt"}, + {clang::attr::Naked, "naked"}, + {clang::attr::AllocAlign, "alloc_align"}, + {clang::attr::AssumeAligned, "assume_aligned"}, + {clang::attr::Flatten, "flatten"}, + {clang::attr::GNUInline, "gnu_inline"}, + {clang::attr::Cold, "cold"}, + {clang::attr::IFunc, "ifunc"}, + {clang::attr::NoSanitize, "no_sanitize"}, + {clang::attr::NoSplitStack, "no_split_stack"}, + {clang::attr::PatchableFunctionEntry, "patchable_function_entry"}, + {clang::attr::Target, "target"}}; +const std::unordered_map kUnsupportedVarAttrsMap = { + {clang::attr::Mode, "mode"}, + {clang::attr::NoCommon, "nocommon"}, + {clang::attr::TransparentUnion, "transparent_union"}, + {clang::attr::Alias, "alias"}, + {clang::attr::Cleanup, "cleanup"}, + {clang::attr::Common, "common"}, + {clang::attr::Uninitialized, "uninitialized"}}; +const std::unordered_map kUnsupportedTypeAttrsMap = { + {clang::attr::MSStruct, "ms_struct"}}; + +bool LibAstFile::Open(const MapleString &fileName, int excludeDeclFromPCH, int displayDiagnostics) { astFileName = fileName; - CXIndex index = clang_createIndex(excludeDeclFromPCH, displayDiagnostics); - CXTranslationUnit translationUnit = clang_createTranslationUnit(index, fileName.c_str()); + index = clang_createIndex(excludeDeclFromPCH, displayDiagnostics); + translationUnit = clang_createTranslationUnit(index, fileName.c_str()); if (translationUnit == nullptr) { return false; } @@ -46,6 +76,15 @@ bool LibAstFile::Open(const std::string &fileName, return true; } +void LibAstFile::DisposeTranslationUnit() { + clang_disposeIndex(index); + clang_disposeTranslationUnit(translationUnit); + delete mangleContext; + mangleContext = nullptr; + translationUnit = nullptr; + index = nullptr; +} + const AstASTContext *LibAstFile::GetAstContext() const { return astContext; } @@ -58,7 +97,7 @@ AstUnitDecl *LibAstFile::GetAstUnitDecl() { return astUnitDecl; } -std::string LibAstFile::GetMangledName(const clang::NamedDecl &decl) { +std::string LibAstFile::GetMangledName(const clang::NamedDecl &decl) const { std::string mangledName; if (!mangleContext->shouldMangleDeclName(&decl)) { mangledName = decl.getNameAsString(); @@ -84,42 +123,43 @@ Pos LibAstFile::GetDeclPosInfo(const clang::Decl &decl) const { static_cast(fullLocation.getSpellingColumnNumber())); } -Pos LibAstFile::GetStmtLOC(const clang::Stmt &stmt) const { +Loc LibAstFile::GetStmtLOC(const clang::Stmt &stmt) const { return GetLOC(stmt.getBeginLoc()); } -Pos LibAstFile::GetExprLOC(const clang::Expr &expr) const { +Loc LibAstFile::GetExprLOC(const clang::Expr &expr) const { return GetLOC(expr.getExprLoc()); } -Pos LibAstFile::GetLOC(const clang::SourceLocation &srcLoc) const { +Loc LibAstFile::GetLOC(const clang::SourceLocation &srcLoc) const { if (srcLoc.isInvalid()) { - return std::make_pair(0, 0); + return {0, 0, 0}; } if (srcLoc.isFileID()) { - clang::PresumedLoc pLOC = astContext->getSourceManager().getPresumedLoc(srcLoc); - if (pLOC.isInvalid()) { - return std::make_pair(0, 0); + std::string fileName = astContext->getSourceManager().getFilename(srcLoc).str(); + if (fileName.empty()) { + return {0, 0, 0}; } - std::string fileName = pLOC.getFilename(); + unsigned line = astContext->getSourceManager().getSpellingLineNumber(srcLoc); + unsigned colunm = astContext->getSourceManager().getSpellingColumnNumber(srcLoc); GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(fileName); for (const auto &info : FEManager::GetModule().GetSrcFileInfo()) { if (info.first == strIdx) { - return std::make_pair(info.second, static_cast(pLOC.getLine())); + return {info.second, static_cast(line), static_cast(colunm)}; } } if (FEManager::GetModule().GetSrcFileInfo().empty()) { // src files start from 2, 1 is mpl file FEManager::GetModule().PushbackFileInfo(MIRInfoPair(strIdx, 2)); - return std::make_pair(2, static_cast(pLOC.getLine())); + return {2, static_cast(line), static_cast(colunm)}; } else { auto last = FEManager::GetModule().GetSrcFileInfo().rbegin(); FEManager::GetModule().PushbackFileInfo(MIRInfoPair(strIdx, last->second + 1)); - return std::make_pair(last->second + 1, static_cast(pLOC.getLine())); + return {last->second + 1, static_cast(line), static_cast(colunm)}; } + } else { // For macro line: The expansion location is the line in the source code where the macro was expanded + return GetLOC(astContext->getSourceManager().getExpansionLoc(srcLoc)); } - - return GetLOC(astContext->getSourceManager().getExpansionLoc(srcLoc)); } uint32 LibAstFile::GetMaxAlign(const clang::Decl &decl) const { @@ -146,14 +186,14 @@ uint32 LibAstFile::RetrieveAggTypeAlign(const clang::Type *ty) const { return 0; } -void LibAstFile::GetCVRAttrs(uint32_t qualifiers, GenericAttrs &genAttrs) { - if (qualifiers & clang::Qualifiers::Const) { +void LibAstFile::GetCVRAttrs(uint32_t qualifiers, GenericAttrs &genAttrs) const { + if ((qualifiers & clang::Qualifiers::Const) != 0) { genAttrs.SetAttr(GENATTR_const); } - if (qualifiers & clang::Qualifiers::Restrict) { + if ((qualifiers & clang::Qualifiers::Restrict) != 0) { genAttrs.SetAttr(GENATTR_restrict); } - if (qualifiers & clang::Qualifiers::Volatile) { + if ((qualifiers & clang::Qualifiers::Volatile) != 0) { genAttrs.SetAttr(GENATTR_volatile); } } @@ -179,6 +219,14 @@ void LibAstFile::GetStorageAttrs(const clang::NamedDecl &decl, GenericAttrs &gen const auto *funcDecl = llvm::cast(&decl); const clang::StorageClass storageClass = funcDecl->getStorageClass(); GetSClassAttrs(storageClass, genAttrs); + // static or extern maybe missing in current FunctionDecls, + // Since a given function can be declared several times in a program, + // Only one of those FunctionDecls will be found when traversing the list of declarations in the context. + const clang::FunctionDecl *prev = funcDecl->getPreviousDecl(); + while (prev != nullptr && prev->isDefined()) { + GetStorageAttrs(*prev, genAttrs); + prev = prev->getPreviousDecl(); + } break; } case clang::Decl::ParmVar: @@ -195,7 +243,7 @@ void LibAstFile::GetStorageAttrs(const clang::NamedDecl &decl, GenericAttrs &gen return; } -void LibAstFile::GetAccessAttrs(AccessKind access, GenericAttrs &genAttrs) { +void LibAstFile::GetAccessAttrs(AccessKind access, GenericAttrs &genAttrs) const { switch (access) { case kPublic: genAttrs.SetAttr(GENATTR_public); @@ -258,6 +306,12 @@ void LibAstFile::CollectAttrs(const clang::NamedDecl &decl, GenericAttrs &genAtt } } +void LibAstFile::CollectFuncReturnVarAttrs(const clang::CallExpr &expr, GenericAttrs &genAttrs) const { + if (LibAstFile::IsOneElementVector(expr.getCallReturnType(*astContext))) { + genAttrs.SetAttr(GenericAttrKind::GENATTR_oneelem_simd); + } +} + void LibAstFile::CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs &genAttrs, AccessKind access) { CollectAttrs(decl, genAttrs, access); if (decl.isVirtualAsWritten()) { @@ -274,6 +328,9 @@ void LibAstFile::CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs } else if (decl.hasAttr()) { genAttrs.SetAttr(GENATTR_noinline); } + if (decl.hasAttr()) { + genAttrs.SetAttr(GENATTR_always_inline); + } if (decl.isDefaulted()) { genAttrs.SetAttr(GENATTR_default); } @@ -309,31 +366,21 @@ void LibAstFile::CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs } void LibAstFile::CheckUnsupportedFuncAttrs(const clang::FunctionDecl &decl) { - std::string unsupportedFuncAttrs = ""; - if (decl.hasAttr()) { - unsupportedFuncAttrs += " no_instrument_function"; - } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " stdcall"; + if (!decl.hasAttrs()) { + return; } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " cdecl"; - } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " long_call"; - } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " short_call"; - } - if(decl.hasAttr() || decl.hasAttr()) { - unsupportedFuncAttrs += " interrupt"; - } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " naked"; + std::string unsupportedFuncAttrs = ""; + const clang::AttrVec &funcAttrs = decl.getAttrs(); + for (const auto *attr : funcAttrs) { + clang::attr::Kind attrKind = attr->getKind(); + auto iterator = kUnsupportedFuncAttrsMap.find(attrKind); + if (iterator != kUnsupportedFuncAttrsMap.end()) { + unsupportedFuncAttrs += iterator->second + " "; + } } CHECK_FATAL(unsupportedFuncAttrs.empty(), "%s:%d error: The function %s has unsupported attribute(s): %s", - FEManager::GetModule().GetFileNameFromFileNum(GetLOC(decl.getLocation()).first).c_str(), - GetLOC(decl.getLocation()).second, + FEManager::GetModule().GetFileNameFromFileNum(GetLOC(decl.getLocation()).fileIdx).c_str(), + GetLOC(decl.getLocation()).line, GetMangledName(decl).c_str(), unsupportedFuncAttrs.c_str()); } @@ -354,23 +401,69 @@ void LibAstFile::CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAt } void LibAstFile::CheckUnsupportedVarAttrs(const clang::VarDecl &decl) { - std::string unsupportedVarAttrs = ""; - if(decl.hasAttr()) { - unsupportedVarAttrs += " mode"; - } - if(decl.hasAttr()) { - unsupportedVarAttrs += " nocommon"; + if (!decl.hasAttrs()) { + return; } - if(decl.hasAttr()) { - unsupportedVarAttrs += " transparent_union"; + std::string unsupportedVarAttrs = ""; + const clang::AttrVec &varAttrs = decl.getAttrs(); + for (const auto *attr : varAttrs) { + clang::attr::Kind attrKind = attr->getKind(); + auto iterator = kUnsupportedVarAttrsMap.find(attrKind); + if (iterator != kUnsupportedVarAttrsMap.end()) { + unsupportedVarAttrs += iterator->second + " "; + } } CHECK_FATAL(unsupportedVarAttrs.empty(), "%s:%d error: The variable %s has unsupported attribute(s): %s", - FEManager::GetModule().GetFileNameFromFileNum(GetLOC(decl.getLocation()).first).c_str(), - GetLOC(decl.getLocation()).second, + FEManager::GetModule().GetFileNameFromFileNum(GetLOC(decl.getLocation()).fileIdx).c_str(), + GetLOC(decl.getLocation()).line, GetMangledName(decl).c_str(), unsupportedVarAttrs.c_str()); } +void LibAstFile::CollectRecordAttrs(const clang::RecordDecl &decl, GenericAttrs &genAttrs) { + clang::PackedAttr *packedAttr = decl.getAttr(); + if (packedAttr != nullptr) { + genAttrs.SetAttr(GENATTR_pack); + genAttrs.InsertIntContentMap(GENATTR_pack, 1); // 1 byte + } + clang::MaxFieldAlignmentAttr *maxFieldAlignAttr = decl.getAttr(); + if (maxFieldAlignAttr != nullptr) { + genAttrs.SetAttr(GENATTR_pack); + int value = static_cast(maxFieldAlignAttr->getAlignment() / 8); // bits to byte + genAttrs.InsertIntContentMap(GENATTR_pack, value); + } + CheckUnsupportedTypeAttrs(decl); +} + +void LibAstFile::CheckUnsupportedTypeAttrs(const clang::RecordDecl &decl) { + if (!decl.hasAttrs()) { + return; + } + std::string unsupportedTypeAttrs = ""; + const clang::AttrVec &typeAttrs = decl.getAttrs(); + for (const auto *attr : typeAttrs) { + clang::attr::Kind attrKind = attr->getKind(); + auto iterator = kUnsupportedTypeAttrsMap.find(attrKind); + if (iterator != kUnsupportedTypeAttrsMap.end()) { + unsupportedTypeAttrs += iterator->second + " "; + } + } + CHECK_FATAL(unsupportedTypeAttrs.empty(), "%s:%d error: struct or union %s has unsupported type attribute(s): %s", + FEManager::GetModule().GetFileNameFromFileNum(GetLOC(decl.getLocation()).fileIdx).c_str(), + GetLOC(decl.getLocation()).line, + GetMangledName(decl).c_str(), + unsupportedTypeAttrs.c_str()); +} + +void LibAstFile::CollectFieldAttrs(const clang::FieldDecl &decl, GenericAttrs &genAttrs, AccessKind access) { + CollectAttrs(decl, genAttrs, access); + clang::PackedAttr *packedAttr = decl.getAttr(); + if (packedAttr != nullptr) { + genAttrs.SetAttr(GENATTR_pack); + genAttrs.InsertIntContentMap(GENATTR_pack, 1); // 1 byte + } +} + void LibAstFile::EmitTypeName(const clang::QualType qualType, std::stringstream &ss) { switch (qualType->getTypeClass()) { case clang::Type::LValueReference: { @@ -398,42 +491,30 @@ void LibAstFile::EmitTypeName(const clang::QualType qualType, std::stringstream } } -void LibAstFile::EmitQualifierName(const clang::QualType qualType, std::stringstream &ss) { +void LibAstFile::EmitQualifierName(const clang::QualType qualType, std::stringstream &ss) const { uint32_t cvrQual = qualType.getCVRQualifiers(); if ((cvrQual & clang::Qualifiers::Const) != 0) { ss << "K"; } - if (cvrQual & clang::Qualifiers::Volatile) { + if ((cvrQual & clang::Qualifiers::Volatile) != 0) { ss << "U"; } } const std::string LibAstFile::GetOrCreateMappedUnnamedName(uint32_t id) { - std::map::iterator it = unnamedSymbolMap.find(id); + std::map::const_iterator it = unnamedSymbolMap.find(id); if (it == unnamedSymbolMap.end()) { std::string name = FEUtils::GetSequentialName("unNamed"); - if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - name = name + GetAstFileNameHashStr(); - } unnamedSymbolMap[id] = name; } return unnamedSymbolMap[id]; } -const std::string LibAstFile::GetOrCreateCompoundLiteralExprInitName(uint32_t id) { - std::map::iterator it = CompoundLiteralExprInitSymbolMap.find(id); - if (it == CompoundLiteralExprInitSymbolMap.end()) { - const std::string name = FEUtils::GetSequentialName("unNamedInit"); - CompoundLiteralExprInitSymbolMap[id] = name; - } - return CompoundLiteralExprInitSymbolMap[id]; -} - -void LibAstFile::EmitTypeName(const clang::RecordType &recoType, std::stringstream &ss) { - clang::RecordDecl *recoDecl = recoType.getDecl(); - std::string str = recoType.desugar().getAsString(); - if (!recoDecl->isAnonymousStructOrUnion() && str.find("anonymous") == std::string::npos) { - clang::DeclContext *ctx = recoDecl->getDeclContext(); +void LibAstFile::EmitTypeName(const clang::RecordType &recordType, std::stringstream &ss) { + clang::RecordDecl *recordDecl = recordType.getDecl(); + std::string str = recordType.desugar().getAsString(); + if (!recordDecl->isAnonymousStructOrUnion() && str.find("anonymous") == std::string::npos) { + clang::DeclContext *ctx = recordDecl->getDeclContext(); MapleStack nsStack(module->GetMPAllocator().Adapter()); while (!ctx->isTranslationUnit()) { auto *primCtxNsDc = llvm::dyn_cast(ctx->getPrimaryContext()); @@ -457,20 +538,32 @@ void LibAstFile::EmitTypeName(const clang::RecordType &recoType, std::stringstre } nsStack.pop(); } - auto nameStr = recoDecl->getName().str(); + auto nameStr = recordDecl->getName().str(); if (nameStr.empty()) { - uint32_t id = recoType.getDecl()->getLocation().getRawEncoding(); + nameStr = GetTypedefNameFromUnnamedStruct(*recordDecl); + } + if (nameStr.empty()) { + uint32_t id = recordType.getDecl()->getLocation().getRawEncoding(); nameStr = GetOrCreateMappedUnnamedName(id); } ss << nameStr; } else { - uint32_t id = recoType.getDecl()->getLocation().getRawEncoding(); + uint32_t id = recordType.getDecl()->getLocation().getRawEncoding(); ss << GetOrCreateMappedUnnamedName(id); } - if (!recoDecl->isDefinedOutsideFunctionOrMethod()) { - Pos p = GetDeclPosInfo(*recoDecl); + if (!recordDecl->isDefinedOutsideFunctionOrMethod()) { + Pos p = GetDeclPosInfo(*recordDecl); ss << "_" << p.first << "_" << p.second; } } + +// get TypedefDecl name for the unnamed struct, e.g. typedef struct {} foo; +std::string LibAstFile::GetTypedefNameFromUnnamedStruct(const clang::RecordDecl &recoDecl) const { + auto *defnameDcel = recoDecl.getTypedefNameForAnonDecl(); + if (defnameDcel != nullptr) { + return defnameDcel->getQualifiedNameAsString(); + } + return std::string(); +} } // namespace maple diff --git a/src/hir2mpl/ast_input/clang/lib/ast_interface.h b/src/hir2mpl/ast_input/clang/lib/ast_interface.h index 5f0255b41ca52a2fc48a6666ff73b1c62383b4c6..1e49e2e66e50f9950dd904afaeb42c1dff8840e9 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_interface.h +++ b/src/hir2mpl/ast_input/clang/lib/ast_interface.h @@ -21,6 +21,7 @@ #include "mpl_logging.h" #include "generic_attrs.h" #include "fe_utils.h" +#include "clang/Basic/AttrKinds.h" namespace maple { using Pos = std::pair; @@ -33,52 +34,58 @@ enum AccessKind { class LibAstFile { public: - explicit LibAstFile(MapleList &recordDeclesIn) : recordDecles(recordDeclesIn) {} + explicit LibAstFile(MapleAllocator &allocatorIn, MapleList &recordDeclesIn) + : recordDeclMap(allocatorIn.Adapter()), recordDeclSet(allocatorIn.Adapter()), + unnamedSymbolMap(allocatorIn.Adapter()), compoundLiteralExprInitSymbolMap(allocatorIn.Adapter()), + recordDecles(recordDeclesIn), astFileName("", allocatorIn.GetMemPool()) {} ~LibAstFile() = default; - bool Open(const std::string &fileName, + bool Open(const MapleString &fileName, int excludeDeclFromPCH, int displayDiagnostics); + void DisposeTranslationUnit(); const AstASTContext *GetAstContext() const; AstASTContext *GetNonConstAstContext() const; AstUnitDecl *GetAstUnitDecl(); - std::string GetMangledName(const clang::NamedDecl &decl); + std::string GetMangledName(const clang::NamedDecl &decl) const; const std::string GetOrCreateMappedUnnamedName(uint32_t id); - const std::string GetOrCreateCompoundLiteralExprInitName(uint32_t id); void EmitTypeName(const clang::QualType qualType, std::stringstream &ss); - void EmitTypeName(const clang::RecordType &qualType, std::stringstream &ss); - void EmitQualifierName(const clang::QualType qualType, std::stringstream &ss); - - void CollectBaseEltTypeAndSizesFromConstArrayDecl(const clang::QualType &qualType, MIRType *&elemType, + void EmitTypeName(const clang::RecordType &recordType, std::stringstream &ss); + void EmitQualifierName(const clang::QualType qualType, std::stringstream &ss) const; + std::string GetTypedefNameFromUnnamedStruct(const clang::RecordDecl &recoDecl) const; + void CollectBaseEltTypeAndSizesFromConstArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, TypeAttrs &elemAttr, std::vector &operands); - void CollectBaseEltTypeAndDimFromVariaArrayDecl(const clang::QualType &qualType, MIRType *&elemType, + void CollectBaseEltTypeAndDimFromVariaArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, TypeAttrs &elemAttr, uint8_t &dim); - - void CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(const clang::QualType qualType, MIRType *&elemType, + void CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(const clang::QualType currQualType, MIRType *&elemType, TypeAttrs &elemAttr, std::vector &operands); - - void GetCVRAttrs(uint32_t qualifiers, GenericAttrs &genAttrs); + void CollectBaseEltTypeFromArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, TypeAttrs &elemAttr); + void GetCVRAttrs(uint32_t qualifiers, GenericAttrs &genAttrs) const; void GetSClassAttrs(const clang::StorageClass storageClass, GenericAttrs &genAttrs) const; void GetStorageAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs) const; - void GetAccessAttrs(AccessKind access, GenericAttrs &genAttrs); + void GetAccessAttrs(AccessKind access, GenericAttrs &genAttrs) const; void GetQualAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs); void CollectAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs, AccessKind access); void CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs &genAttrs, AccessKind access); + void CollectFuncReturnVarAttrs(const clang::CallExpr &expr, GenericAttrs &genAttrs) const; void CheckUnsupportedFuncAttrs(const clang::FunctionDecl &decl); void CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAttrs, AccessKind access); void CheckUnsupportedVarAttrs(const clang::VarDecl &decl); + void CollectRecordAttrs(const clang::RecordDecl &decl, GenericAttrs &genAttrs); + void CheckUnsupportedTypeAttrs(const clang::RecordDecl &decl); + void CollectFieldAttrs(const clang::FieldDecl &decl, GenericAttrs &genAttrs, AccessKind access); MIRType *CvtPrimType(const clang::QualType qualType) const; - PrimType CvtPrimType(const clang::BuiltinType::Kind) const; + PrimType CvtPrimType(const clang::BuiltinType::Kind kind) const; MIRType *CvtType(const clang::QualType qualType); MIRType *CvtOtherType(const clang::QualType srcType); MIRType *CvtArrayType(const clang::QualType srcType); MIRType *CvtFunctionType(const clang::QualType srcType); MIRType *CvtRecordType(const clang::QualType srcType); MIRType *CvtFieldType(const clang::NamedDecl &decl); - MIRType *CvtComplexType(const clang::QualType srcType); + MIRType *CvtComplexType(const clang::QualType srcType) const; MIRType *CvtVectorType(const clang::QualType srcType); - bool TypeHasMayAlias(const clang::QualType srcType); + bool TypeHasMayAlias(const clang::QualType srcType) const; static bool IsOneElementVector(const clang::QualType &qualType); static bool IsOneElementVector(const clang::Type &type); @@ -87,22 +94,23 @@ class LibAstFile { } const std::string GetAstFileNameHashStr() const { - return FEUtils::GetFileNameHashStr(astFileName); + std::string fileName = (astFileName.c_str() == nullptr ? "" : astFileName.c_str()); + return FEUtils::GetFileNameHashStr(fileName); } Pos GetDeclPosInfo(const clang::Decl &decl) const; - Pos GetStmtLOC(const clang::Stmt &stmt) const; - Pos GetExprLOC(const clang::Expr &expr) const; - Pos GetLOC(const clang::SourceLocation &srcLoc) const; + Loc GetStmtLOC(const clang::Stmt &stmt) const; + Loc GetExprLOC(const clang::Expr &expr) const; + Loc GetLOC(const clang::SourceLocation &srcLoc) const; uint32 GetMaxAlign(const clang::Decl &decl) const; uint32 RetrieveAggTypeAlign(const clang::Type *ty) const; private: - using RecordDeclMap = std::map; + using RecordDeclMap = MapleMap; RecordDeclMap recordDeclMap; - std::set recordDeclSet; - std::map unnamedSymbolMap; - std::map CompoundLiteralExprInitSymbolMap; + MapleSet recordDeclSet; + MapleMap unnamedSymbolMap; + MapleMap compoundLiteralExprInitSymbolMap; MIRModule *module = nullptr; MapleList &recordDecles; @@ -110,7 +118,9 @@ class LibAstFile { clang::ASTContext *astContext = nullptr; clang::TranslationUnitDecl *astUnitDecl = nullptr; clang::MangleContext *mangleContext = nullptr; - std::string astFileName; + CXTranslationUnit translationUnit = nullptr; + CXIndex index = nullptr; + MapleString astFileName; }; } // namespace maple #endif // HIR2MPL_AST_FILE_INCLUDE_AST_INTERFACE_H diff --git a/src/hir2mpl/ast_input/clang/lib/ast_macros.h b/src/hir2mpl/ast_input/clang/lib/ast_macros.h index 9e319854d0f8d7f5140c7f1df3e43732a13ac7ed..f4afbaf17f808d4aae4614e5be91b9eb3a7003d6 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_macros.h +++ b/src/hir2mpl/ast_input/clang/lib/ast_macros.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -16,8 +16,8 @@ #ifndef AST2MPL_INCLUDE_ASTMACROS_H #define AST2MPL_INCLUDE_ASTMACROS_H #include -#include +namespace maple { const uint32_t kSrcFileNum = 2; // ast2mpl options @@ -55,7 +55,7 @@ const int kDefaultIndent = 1; #define NOTYETHANDLED(s) \ std::cout << "\n" << LOCATION << " <<<<<<<<<<<<<<<<<< Not Yet Handled: " << s << "<<<<<<<<<<<<<<<<<<" << '\n'; \ - if (maple::ast2mplOption & kCheckAssertion) { \ + if ((maple::ast2mplOption & kCheckAssertion) != 0) { \ ASSERT(false, "Not yet handled"); \ } \ // print empty line @@ -249,5 +249,5 @@ const int kDefaultIndent = 1; #define SET_INFO_PAIR(a, b, c, d, e) \ a.emplace_back(builder->GetOrCreateStringIndex(b), c); \ d.emplace_back(e) - +} // namespace maple #endif // AST2MPL_INCLUDE_ASTMACROS_H diff --git a/src/hir2mpl/ast_input/clang/lib/ast_type.cpp b/src/hir2mpl/ast_input/clang/lib/ast_type.cpp index 4d935dba70536748cdfb5726424bab181ab681fe..5158c84c4f16f97372de915d4c58df439de9723e 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_type.cpp +++ b/src/hir2mpl/ast_input/clang/lib/ast_type.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -17,6 +17,8 @@ #include "ast_util.h" #include "fe_manager.h" #include "fe_options.h" +#include "driver_options.h" +#include "triple.h" namespace maple { MIRType *LibAstFile::CvtPrimType(const clang::QualType qualType) const { @@ -49,11 +51,11 @@ PrimType LibAstFile::CvtPrimType(const clang::BuiltinType::Kind kind) const { case clang::BuiltinType::UInt: return PTY_u32; case clang::BuiltinType::ULong: -#if ILP32 - return PTY_u32; -#else - return PTY_u64; -#endif + if (Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) { + return PTY_u32; + } else { + return PTY_u64; + } case clang::BuiltinType::ULongLong: return PTY_u64; case clang::BuiltinType::UInt128: @@ -69,16 +71,15 @@ PrimType LibAstFile::CvtPrimType(const clang::BuiltinType::Kind kind) const { case clang::BuiltinType::Int: return PTY_i32; case clang::BuiltinType::Long: -#if ILP32 - return PTY_i32; -#else - return PTY_i64; -#endif + if (Triple::GetTriple().GetEnvironment() == Triple::GNUILP32) { + return PTY_i32; + } else { + return PTY_i64; + } case clang::BuiltinType::LongLong: return PTY_i64; case clang::BuiltinType::Int128: return PTY_i128; - case clang::BuiltinType::Half: // PTY_f16, NOTYETHANDLED case clang::BuiltinType::Float: return PTY_f32; case clang::BuiltinType::Double: @@ -88,13 +89,17 @@ PrimType LibAstFile::CvtPrimType(const clang::BuiltinType::Kind kind) const { return PTY_f64; case clang::BuiltinType::NullPtr: // default 64-bit, need to update return PTY_a64; + case clang::BuiltinType::Half: // PTY_f16, NOTYETHANDLED + case clang::BuiltinType::Float16: + CHECK_FATAL(false, "Float16 types not implemented yet"); + return PTY_void; case clang::BuiltinType::Void: default: return PTY_void; } } -bool LibAstFile::TypeHasMayAlias(const clang::QualType srcType) { +bool LibAstFile::TypeHasMayAlias(const clang::QualType srcType) const { auto *td = srcType->getAsTagDecl(); if (td != nullptr && td->hasAttr()) { return true; @@ -132,9 +137,9 @@ MIRType *LibAstFile::CvtType(const clang::QualType qualType) { TypeAttrs attrs; // Get alignment from the pointee type uint32 alignmentBits = astContext->getTypeAlignIfKnown(srcPteType); - if (alignmentBits) { + if (alignmentBits != 0) { if (alignmentBits > astContext->getTypeUnadjustedAlign(srcPteType)) { - attrs.SetAlign(alignmentBits / 8); + attrs.SetAlign(alignmentBits / 8); // bits to byte } } if (IsOneElementVector(srcPteType)) { @@ -146,13 +151,17 @@ MIRType *LibAstFile::CvtType(const clang::QualType qualType) { if (TypeHasMayAlias(qualType->getPointeeType())) { attrs.SetAttr(ATTR_may_alias); } - - MIRPtrType *prtType; + // Variably Modified type is the type of a Variable Length Array. (C99 6.7.5) + // Convert the vla to a single-dimensional pointer, e.g. int(*)[N] + if (qualType->isVariablyModifiedType() && mirPointeeType->IsMIRPtrType()) { + static_cast(mirPointeeType)->SetTypeAttrs(attrs); + return mirPointeeType; + } + MIRType *prtType; if (attrs == TypeAttrs()) { - prtType = static_cast(GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirPointeeType)); + prtType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirPointeeType); } else { - prtType = static_cast( - GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirPointeeType, PTY_ptr, attrs)); + prtType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirPointeeType, PTY_ptr, attrs); } return prtType; } @@ -188,8 +197,8 @@ MIRType *LibAstFile::CvtOtherType(const clang::QualType srcType) { MIRType *LibAstFile::CvtRecordType(const clang::QualType srcType) { const auto *recordType = llvm::cast(srcType); clang::RecordDecl *recordDecl = recordType->getDecl(); - if (!recordDecl->isLambda() && recordDeclSet.emplace(recordDecl).second == true) { - auto itor = std::find(recordDecles.begin(), recordDecles.end(), recordDecl); + if (!recordDecl->isLambda() && recordDeclSet.emplace(recordDecl).second) { + auto itor = std::find(recordDecles.cbegin(), recordDecles.cend(), recordDecl); if (itor == recordDecles.end()) { recordDecles.emplace_back(recordDecl); } @@ -202,10 +211,16 @@ MIRType *LibAstFile::CvtRecordType(const clang::QualType srcType) { uint32_t id = recordType->getDecl()->getLocation().getRawEncoding(); name = GetOrCreateMappedUnnamedName(id); } else if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - name = name + GetAstFileNameHashStr(); + std::string recordLayoutStr = recordDecl->getDefinition() == nullptr ? "" : + ASTUtil::GetRecordLayoutString(astContext->getASTRecordLayout(recordDecl->getDefinition())); + std::string filename = astContext->getSourceManager().getFilename(recordDecl->getLocation()).str(); + name = name + FEUtils::GetFileNameHashStr(filename + recordLayoutStr); } type = FEManager::GetTypeManager().GetOrCreateStructType(name); type->SetMIRTypeKind(srcType->isUnionType() ? kTypeUnion : kTypeStruct); + if (recordDecl->getDefinition() == nullptr) { + type->SetMIRTypeKind(kTypeStructIncomplete); + } return recordDecl->isLambda() ? GlobalTables::GetTypeTable().GetOrCreatePointerType(*type) : type; } @@ -227,6 +242,7 @@ MIRType *LibAstFile::CvtArrayType(const clang::QualType srcType) { CollectBaseEltTypeAndDimFromVariaArrayDecl(srcType, elemType, elemAttrs, dim); } else if (srcType->isDependentSizedArrayType()) { CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(srcType, elemType, elemAttrs, operands); + ASSERT(operands.size() < kMaxArrayDim, "The max array dimension is kMaxArrayDim"); dim = static_cast(operands.size()); } else { NOTYETHANDLED(srcType.getAsString().c_str()); @@ -240,8 +256,10 @@ MIRType *LibAstFile::CvtArrayType(const clang::QualType srcType) { tempSizeArray[k] = operands[k]; } sizeArray = tempSizeArray; + retType = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dim, sizeArray, elemAttrs); + } else { + retType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*elemType, PTY_ptr, elemAttrs); } - retType = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dim, sizeArray, elemAttrs); } else { bool asFlag = srcType->isIncompleteArrayType(); CHECK_FATAL(asFlag, "Incomplete Array Type"); @@ -256,7 +274,7 @@ MIRType *LibAstFile::CvtArrayType(const clang::QualType srcType) { return retType; } -MIRType *LibAstFile::CvtComplexType(const clang::QualType srcType) { +MIRType *LibAstFile::CvtComplexType(const clang::QualType srcType) const { clang::QualType srcElemType = llvm::cast(srcType)->getElementType(); MIRType *destElemType = CvtPrimType(srcElemType); CHECK_NULL_FATAL(destElemType); @@ -306,17 +324,7 @@ void LibAstFile::CollectBaseEltTypeAndSizesFromConstArrayDecl(const clang::QualT operands.push_back(size.getSExtValue()); CollectBaseEltTypeAndSizesFromConstArrayDecl(constArrayType->getElementType(), elemType, elemAttr, operands); } else { - elemType = CvtType(currQualType); - // Get alignment from the element type - uint32 alignmentBits = astContext->getTypeAlignIfKnown(currQualType); - if (alignmentBits) { - if (alignmentBits > astContext->getTypeUnadjustedAlign(currQualType)) { - elemAttr.SetAlign(alignmentBits / 8); - } - } - if (IsOneElementVector(currQualType)) { - elemAttr.SetAttr(ATTR_oneelem_simd); - } + CollectBaseEltTypeFromArrayDecl(currQualType, elemType, elemAttr); } } @@ -329,17 +337,7 @@ void LibAstFile::CollectBaseEltTypeAndDimFromVariaArrayDecl(const clang::QualTyp CollectBaseEltTypeAndDimFromVariaArrayDecl(arrayType->getElementType(), elemType, elemAttr, dim); ++dim; } else { - elemType = CvtType(currQualType); - // Get alignment from the element type - uint32 alignmentBits = astContext->getTypeAlignIfKnown(currQualType); - if (alignmentBits) { - if (alignmentBits > astContext->getTypeUnadjustedAlign(currQualType)) { - elemAttr.SetAlign(alignmentBits / 8); - } - } - if (IsOneElementVector(currQualType)) { - elemAttr.SetAttr(ATTR_oneelem_simd); - } + CollectBaseEltTypeFromArrayDecl(currQualType, elemType, elemAttr); } } @@ -354,18 +352,24 @@ void LibAstFile::CollectBaseEltTypeAndDimFromDependentSizedArrayDecl( operands.push_back(0); CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(arrayType->getElementType(), elemType, elemAttr, operands); } else { - elemType = CvtType(currQualType); - // Get alignment from the element type - uint32 alignmentBits = astContext->getTypeAlignIfKnown(currQualType); - if (alignmentBits) { - if (alignmentBits > astContext->getTypeUnadjustedAlign(currQualType)) { - elemAttr.SetAlign(alignmentBits / 8); - } - } - if (IsOneElementVector(currQualType)) { - elemAttr.SetAttr(ATTR_oneelem_simd); + CollectBaseEltTypeFromArrayDecl(currQualType, elemType, elemAttr); + } +} + +void LibAstFile::CollectBaseEltTypeFromArrayDecl(const clang::QualType &currQualType, + MIRType *&elemType, + TypeAttrs &elemAttr) { + elemType = CvtType(currQualType); + // Get alignment from the element type + uint32 alignmentBits = astContext->getTypeAlignIfKnown(currQualType); + if (alignmentBits != 0) { + if (alignmentBits > astContext->getTypeUnadjustedAlign(currQualType)) { + elemAttr.SetAlign(alignmentBits / 8); // bits to byte } } + if (IsOneElementVector(currQualType)) { + elemAttr.SetAttr(ATTR_oneelem_simd); + } } MIRType *LibAstFile::CvtVectorType(const clang::QualType srcType) { diff --git a/src/hir2mpl/ast_input/clang/lib/ast_util.cpp b/src/hir2mpl/ast_input/clang/lib/ast_util.cpp index 99fe86588548c1169119d5e8927a64e940ac1eb0..007eab98cadbd9c4c7096f42a15a65bb0e9b99fb 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_util.cpp +++ b/src/hir2mpl/ast_input/clang/lib/ast_util.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -328,4 +328,15 @@ bool ASTUtil::InsertFuncSet(const GStrIdx &idx) { static std::set funcIdxSet; return funcIdxSet.insert(idx).second; } + +std::string ASTUtil::GetRecordLayoutString(const clang::ASTRecordLayout &recordLayout) { + std::string recordLayoutStr = ""; + unsigned int fieldCount = recordLayout.getFieldCount(); + uint64_t recordSize = static_cast(recordLayout.getSize().getQuantity()); + recordLayoutStr += (std::to_string(fieldCount) + std::to_string(recordSize)); + for (unsigned int i = 0; i < fieldCount; ++i) { + recordLayoutStr += std::to_string(recordLayout.getFieldOffset(i)); + } + return recordLayoutStr; +} } // namespace maple diff --git a/src/hir2mpl/ast_input/clang/lib/ast_util.h b/src/hir2mpl/ast_input/clang/lib/ast_util.h index 503193269c6e283e0940a771c874d8cc6da81560..40d151685e565473691e3291f034043a7f246ab2 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_util.h +++ b/src/hir2mpl/ast_input/clang/lib/ast_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -15,6 +15,7 @@ #ifndef AST2MPL_INCLUDE_ASTUTIL_H #define AST2MPL_INCLUDE_ASTUTIL_H #include "clang/AST/AST.h" +#include "clang/AST/RecordLayout.h" #include "mir_type.h" #include "ast_macros.h" @@ -66,6 +67,7 @@ class ASTUtil { } return os.str(); } + static std::string GetRecordLayoutString(const clang::ASTRecordLayout &recordLayout); }; } // namespace maple #endif // AST2MPL_INCLUDE_ASTUTIL_H_ diff --git a/src/hir2mpl/ast_input/clang/src/ast_expr.cpp b/src/hir2mpl/ast_input/clang/src/ast_expr.cpp index b2082dd8a4487761eb4ea6f79773c1e08a4048ba..ffdb9752e136c407e2f269b3d4e23e8a5eab29c5 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_expr.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_expr.cpp @@ -27,8 +27,105 @@ #include "ror.h" #include "conditional_operator.h" +#include + namespace maple { + +namespace { + const uint32 kOneByte = 8; + +template +std::optional GenerateConstCommon(Opcode op, T p0, T p1) { + switch (op) { + case OP_add: { + return p0 + p1; + } + case OP_sub: { + return p0 - p1; + } + case OP_mul: { + return p0 * p1; + } + case OP_div: { + return p0 / p1; + } + default: { + return std::nullopt; + } + } +} + +template , bool> = true> +T GenerateConst(Opcode op, T p0, T p1) { + auto res = GenerateConstCommon(op, p0, p1); + ASSERT(res, "invalid operations for floating point values"); + return *res; +} + +IntVal GenerateConst(Opcode op, const IntVal &p0, const IntVal &p1) { + ASSERT(p0.GetBitWidth() == p1.GetBitWidth() && p0.IsSigned() == p1.IsSigned(), "width and sign must be the same"); + + if (auto res = GenerateConstCommon(op, p0, p1)) { + return *res; + } + + switch (op) { + case OP_rem: { + return p0 % p1; + } + case OP_shl: { + return p0 << p1; + } + case OP_lshr: + case OP_ashr: { + return p0 >> p1; + } + case OP_bior: { + return p0 | p1; + } + case OP_band: { + return p0 & p1; + } + case OP_bxor: { + return p0 ^ p1; + } + case OP_land: + case OP_cand: { + return IntVal(p0.GetExtValue() && p1.GetExtValue(), p0.GetBitWidth(), p0.IsSigned()); + } + case OP_lior: + case OP_cior: { + return IntVal(p0.GetExtValue() || p1.GetExtValue(), p0.GetBitWidth(), p0.IsSigned()); + } + default: + CHECK_FATAL(false, "unsupported operation"); + } +} + +MIRConst *MIRConstGenerator(MemPool *mp, MIRConst *konst0, MIRConst *konst1, Opcode op) { +#define RET_VALUE_IF_CONST_TYPE_IS(TYPE) \ + { \ + auto *c0 = safe_cast(konst0); \ + if (c0) { \ + auto *c1 = safe_cast(konst1); \ + ASSERT(c1, "invalid const type"); \ + ASSERT(c0->GetType().GetPrimType() == c1->GetType().GetPrimType(), "types are not equal"); \ + return mp->New(GenerateConst(op, c0->GetValue(), c1->GetValue()), c0->GetType()); \ + } \ + } + + RET_VALUE_IF_CONST_TYPE_IS(MIRIntConst) + RET_VALUE_IF_CONST_TYPE_IS(MIRFloatConst) + RET_VALUE_IF_CONST_TYPE_IS(MIRDoubleConst) + +#undef RET_VALUE_IF_CONST_TYPE_IS + + CHECK_FATAL(false, "unreachable code"); +} + +} // anonymous namespace + // ---------- ASTValue ---------- MIRConst *ASTValue::Translate2MIRConst() const { switch (pty) { @@ -89,9 +186,12 @@ MIRConst *ASTValue::Translate2MIRConst() const { // ---------- ASTExpr ---------- UniqueFEIRExpr ASTExpr::Emit2FEExpr(std::list &stmts) const { auto feirExpr = Emit2FEExprImpl(stmts); + if (feirExpr != nullptr) { + feirExpr->SetLoc(loc); + } for (auto &stmt : stmts) { if (!stmt->HasSetLOCInfo()) { - stmt->SetSrcFileInfo(srcFileIdx, srcFileLineNum); + stmt->SetSrcLoc(loc); } } return feirExpr; @@ -198,6 +298,12 @@ UniqueFEIRExpr ASTDeclRefExpr::Emit2FEExprImpl(std::list &stmts) feirRefExpr = FEIRBuilder::CreateExprDRead(std::move(feirVar)); } } + if (refedDecl->IsParam() && refedDecl->GetDeclKind() == kASTVar) { + PrimType promoted = static_cast(refedDecl)->GetPromotedType(); + if (promoted != PTY_void) { + feirRefExpr = FEIRBuilder::CreateExprCastPrim(std::move(feirRefExpr), promoted); + } + } return feirRefExpr; } @@ -226,7 +332,7 @@ void ASTCallExpr::AddArgsExpr(const std::unique_ptr &callStmt, s callStmt->AddExprArgReverse(std::move(expr)); } if (IsFirstArgRet()) { - UniqueFEIRVar var = FEIRBuilder::CreateVarNameForC(varName, *retType, false, false); + UniqueFEIRVar var = FEIRBuilder::CreateVarNameForC(GetRetVarName(), *retType, false, false); UniqueFEIRExpr expr = FEIRBuilder::CreateExprAddrofVar(var->Clone()); callStmt->AddExprArgReverse(std::move(expr)); } @@ -245,12 +351,12 @@ void ASTCallExpr::InsertNonnullCheckingForIcall(const UniqueFEIRExpr &expr, std: return; } UniqueFEIRStmt stmt = std::make_unique(OP_assertnonnull, expr->Clone()); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } UniqueFEIRExpr ASTCallExpr::AddRetExpr(const std::unique_ptr &callStmt) const { - UniqueFEIRVar var = FEIRBuilder::CreateVarNameForC(varName, *retType, false, false); + UniqueFEIRVar var = FEIRBuilder::CreateVarNameForC(GetRetVarName(), *retType, false, false); + var->SetAttrs(GetReturnVarAttrs()); UniqueFEIRVar dreadVar = var->Clone(); if (!IsFirstArgRet()) { callStmt->SetVar(var->Clone()); @@ -264,9 +370,11 @@ std::unique_ptr ASTCallExpr::GenCallStmt() const { if (isIcall) { callStmt = std::make_unique(); } else { - StructElemNameIdx *nameIdx = mp->New(funcName); + StructElemNameIdx *nameIdx = mp->New(GetFuncName()); + ASSERT_NOT_NULL(nameIdx); FEStructMethodInfo *info = static_cast( FEManager::GetTypeManager().RegisterStructMethodInfo(*nameIdx, kSrcLangC, false)); + ASSERT_NOT_NULL(info); info->SetFuncAttrs(funcAttrs); FEIRTypeNative *retTypeInfo = nullptr; if (IsFirstArgRet()) { @@ -283,7 +391,6 @@ std::unique_ptr ASTCallExpr::GenCallStmt() const { } callStmt = std::make_unique(*info, op, nullptr, false); } - callStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); return callStmt; } @@ -319,6 +426,9 @@ MIRConst *ASTCastExpr::GenerateMIRConstImpl() const { MIRSymbol *mirSymbol = static_cast(astDecl)->Translate2MIRSymbol(); return FEManager::GetModule().GetMemPool()->New(mirSymbol->GetStIdx(), 0, *(astDecl->GetTypeDesc().front())); + } else if (isArrayToPointerDecay && child->GetASTOp() == kASTOpCompoundLiteralExpr) { + static_cast(child)->SetAddrof(true); + return child->GenerateMIRConst(); } else if (isNeededCvt) { if (dst->GetPrimType() == PTY_f64) { return GenerateMIRDoubleConst(); @@ -334,6 +444,9 @@ MIRConst *ASTCastExpr::GenerateMIRConstImpl() const { MIRConst *ASTCastExpr::GenerateMIRDoubleConst() const { MIRConst *childConst = child->GenerateMIRConst(); + if (childConst == nullptr) { + return nullptr; + } switch (childConst->GetKind()) { case kConstFloatConst: { return FEManager::GetModule().GetMemPool()->New( @@ -342,7 +455,7 @@ MIRConst *ASTCastExpr::GenerateMIRDoubleConst() const { } case kConstInt: { return FEManager::GetModule().GetMemPool()->New( - static_cast(static_cast(childConst)->GetValue()), + static_cast(static_cast(childConst)->GetExtValue()), *GlobalTables::GetTypeTable().GetPrimType(PTY_f64)); } case kConstDoubleConst: { @@ -359,6 +472,9 @@ MIRConst *ASTCastExpr::GenerateMIRDoubleConst() const { MIRConst *ASTCastExpr::GenerateMIRFloatConst() const { MIRConst *childConst = child->GenerateMIRConst(); + if (childConst == nullptr) { + return nullptr; + } switch (childConst->GetKind()) { case kConstDoubleConst: { return FEManager::GetModule().GetMemPool()->New( @@ -367,7 +483,7 @@ MIRConst *ASTCastExpr::GenerateMIRFloatConst() const { } case kConstInt: { return FEManager::GetModule().GetMemPool()->New( - static_cast(static_cast(childConst)->GetValue()), + static_cast(static_cast(childConst)->GetExtValue()), *GlobalTables::GetTypeTable().GetPrimType(PTY_f32)); } default: { @@ -379,12 +495,15 @@ MIRConst *ASTCastExpr::GenerateMIRFloatConst() const { MIRConst *ASTCastExpr::GenerateMIRIntConst() const { MIRConst *childConst = child->GenerateMIRConst(); + if (childConst == nullptr) { + return nullptr; + } switch (childConst->GetKind()) { case kConstDoubleConst: case kConstInt: { - int64 val = childConst->GetKind() == kConstDoubleConst ? - static_cast(static_cast(childConst)->GetValue()) : - static_cast(childConst)->GetValue(); + int64 val = childConst->GetKind() == kConstDoubleConst + ? static_cast(static_cast(childConst)->GetValue()) + : static_cast(childConst)->GetExtValue(); PrimType destPrimType = mirType->GetPrimType(); switch (destPrimType) { @@ -506,7 +625,12 @@ UniqueFEIRExpr ASTCastExpr::Emit2FEExprImpl(std::list &stmts) co } UniqueFEIRExpr subExpr = childExpr->Emit2FEExpr(stmts); if (isUnoinCast && dst->GetKind() == kTypeUnion) { - return subExpr; + std::string varName = FEUtils::GetSequentialName("anon.union."); + UniqueFEIRType dstType = std::make_unique(*dst); + UniqueFEIRVar unionVar = FEIRBuilder::CreateVarNameForC(varName, std::move(dstType)); + UniqueFEIRStmt unionStmt = FEIRBuilder::CreateStmtDAssign(unionVar->Clone(), subExpr->Clone()); + stmts.emplace_back(std::move(unionStmt)); + return FEIRBuilder::CreateExprDRead(std::move(unionVar)); } if (isBitCast) { if (src->GetPrimType() == dst->GetPrimType() && src->IsScalarType()) { @@ -515,7 +639,6 @@ UniqueFEIRExpr ASTCastExpr::Emit2FEExprImpl(std::list &stmts) co } UniqueFEIRType dstType = std::make_unique(*dst); if (dst->GetKind() == kTypePointer) { - CheckNonnullFieldInStruct(); return subExpr; } else { return std::make_unique(std::move(dstType), OP_retype, std::move(subExpr)); @@ -645,7 +768,9 @@ UniqueFEIRExpr ASTUnaryOperatorExpr::ASTUOSideEffectExpr(Opcode op, std::listClone(), childFEIRExpr->Clone()); - readSelfstmt->SetDummy(); + if (!IsRValue()) { + readSelfstmt->SetDummy(); + } stmts.emplace_back(std::move(readSelfstmt)); } @@ -680,20 +805,9 @@ UniqueFEIRExpr ASTUOPreDecExpr::Emit2FEExprImpl(std::list &stmts MIRConst *ASTUOAddrOfExpr::GenerateMIRConstImpl() const { switch (expr->GetASTOp()) { - case kASTOpCompoundLiteralExp: { - auto astCompoundLiteralExpr = static_cast(expr); - // CompoundLiteral Symbol - MIRSymbol *compoundLiteralMirSymbol = FEManager::GetMIRBuilder().GetOrCreateGlobalDecl( - astCompoundLiteralExpr->GetInitName(), - *astCompoundLiteralExpr->GetCompoundLiteralType()); - - auto child = static_cast(expr)->GetASTExpr(); - auto mirConst = child->GenerateMIRConst(); // InitListExpr in CompoundLiteral gen struct - compoundLiteralMirSymbol->SetKonst(mirConst); - - MIRAddrofConst *mirAddrofConst = FEManager::GetModule().GetMemPool()->New( - compoundLiteralMirSymbol->GetStIdx(), 0, *astCompoundLiteralExpr->GetCompoundLiteralType()); - return mirAddrofConst; + case kASTOpCompoundLiteralExpr: { + static_cast(expr)->SetAddrof(true); + return expr->GenerateMIRConst(); } case kASTOpRef: case kASTSubscriptExpr: @@ -731,6 +845,12 @@ UniqueFEIRExpr ASTUOAddrOfExpr::Emit2FEExprImpl(std::list &stmts } else if (childFEIRExpr->GetKind() == kExprIAddrof || childFEIRExpr->GetKind() == kExprAddrofVar || childFEIRExpr->GetKind() == kExprAddrofFunc || childFEIRExpr->GetKind() == kExprAddrof) { return childFEIRExpr; + } else if (childFEIRExpr->GetKind() == kExprConst) { + std::string tmpName = FEUtils::GetSequentialName("tmpvar_"); + UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, childFEIRExpr->GetType()->Clone()); + auto tmpStmt = FEIRBuilder::CreateStmtDAssign(tmpVar->Clone(), std::move(childFEIRExpr)); + stmts.emplace_back(std::move(tmpStmt)); + return FEIRBuilder::CreateExprAddrofVar(std::move(tmpVar)); } else { CHECK_FATAL(false, "unsupported expr kind %d", childFEIRExpr->GetKind()); } @@ -740,14 +860,14 @@ UniqueFEIRExpr ASTUOAddrOfExpr::Emit2FEExprImpl(std::list &stmts // ---------- ASTUOAddrOfLabelExpr --------- MIRConst *ASTUOAddrOfLabelExpr::GenerateMIRConstImpl() const { return FEManager::GetMIRBuilder().GetCurrentFuncCodeMp()->New( - FEManager::GetMIRBuilder().GetOrCreateMIRLabel(labelName), + FEManager::GetMIRBuilder().GetOrCreateMIRLabel(GetLabelName()), FEManager::GetMIRBuilder().GetCurrentFunction()->GetPuidx(), // GetCurrentFunction need to be optimized *GlobalTables::GetTypeTable().GetVoidPtr()); // when parallel features } UniqueFEIRExpr ASTUOAddrOfLabelExpr::Emit2FEExprImpl(std::list &stmts) const { (void)stmts; - return FEIRBuilder::CreateExprAddrofLabel(labelName, std::make_unique(*uoType)); + return FEIRBuilder::CreateExprAddrofLabel(GetLabelName(), std::make_unique(*uoType)); } UniqueFEIRExpr ASTUODerefExpr::Emit2FEExprImpl(std::list &stmts) const { @@ -775,7 +895,6 @@ void ASTUODerefExpr::InsertNonnullChecking(std::list &stmts, Uni } if (baseExpr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique(OP_assertnonnull, std::move(baseExpr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } } @@ -924,11 +1043,17 @@ void ASTNoInitExpr::SetNoInitType(MIRType *type) { // ---------- ASTCompoundLiteralExpr ---------- UniqueFEIRExpr ASTCompoundLiteralExpr::Emit2FEExprImpl(std::list &stmts) const { UniqueFEIRExpr feirExpr; - if (child->GetASTOp() == kASTOpInitListExpr) { // other potential expr should concern + if (!IsRValue() || child->GetASTOp() == kASTOpInitListExpr) { // other potential expr should concern std::string tmpName = FEUtils::GetSequentialName("clvar_"); - static_cast(child)->SetInitListVarName(tmpName); - child->Emit2FEExpr(stmts); + if (child->GetASTOp() == kASTOpInitListExpr) { + static_cast(child)->SetInitListVarName(tmpName); + } UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, *compoundLiteralType); + auto expr = child->Emit2FEExpr(stmts); + if (expr != nullptr) { + auto tmpStmt = FEIRBuilder::CreateStmtDAssign(tmpVar->Clone(), std::move(expr)); + stmts.emplace_back(std::move(tmpStmt)); + } feirExpr = FEIRBuilder::CreateExprDRead(std::move(tmpVar)); } else { feirExpr = child->Emit2FEExpr(stmts); @@ -936,7 +1061,27 @@ UniqueFEIRExpr ASTCompoundLiteralExpr::Emit2FEExprImpl(std::list return feirExpr; } +MIRConst *ASTCompoundLiteralExpr::GenerateMIRPtrConst() const { + CHECK_NULL_FATAL(compoundLiteralType); + std::string tmpName = FEUtils::GetSequentialName("cle."); + if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { + tmpName = tmpName + FEUtils::GetFileNameHashStr(FEManager::GetModule().GetFileName()); + } + // If a var is pointer type, agg value cannot be directly assigned to it + // Create a temporary symbol for addrof agg value + MIRSymbol *cleSymbol = FEManager::GetMIRBuilder().GetOrCreateGlobalDecl( + tmpName, *compoundLiteralType); + auto mirConst = child->GenerateMIRConst(); // InitListExpr in CompoundLiteral gen struct + cleSymbol->SetKonst(mirConst); + MIRAddrofConst *mirAddrofConst = FEManager::GetModule().GetMemPool()->New( + cleSymbol->GetStIdx(), 0, *compoundLiteralType); + return mirAddrofConst; +} + MIRConst *ASTCompoundLiteralExpr::GenerateMIRConstImpl() const { + if (isAddrof) { + return GenerateMIRPtrConst(); + } return child->GenerateMIRConst(); } @@ -964,6 +1109,11 @@ UniqueFEIRExpr ASTOffsetOfExpr::Emit2FEExprImpl(std::list &stmts // ---------- ASTInitListExpr ---------- MIRConst *ASTInitListExpr::GenerateMIRConstImpl() const { + // avoid the infinite loop + if (isGenerating) { + return nullptr; + } + isGenerating = true; if (initListType->GetKind() == kTypeArray) { return GenerateMIRConstForArray(); } else if (initListType->GetKind() == kTypeStruct || initListType->GetKind() == kTypeUnion) { @@ -985,9 +1135,8 @@ MIRConst *ASTInitListExpr::GenerateMIRConstForArray() const { CHECK_FATAL(initExprs.size() <= arrayMirType->GetSizeArrayItem(0), "InitExpr size must less or equal array size"); for (size_t i = 0; i < initExprs.size(); ++i) { auto konst = initExprs[i]->GenerateMIRConst(); - if (konst->GetKind() == kConstLblConst) { - // init by initListExpr, Only MIRConst kind is set here. - return konst; + if (konst == nullptr) { + return nullptr; } aggConst->AddItem(konst, 0); } @@ -1016,23 +1165,30 @@ MIRConst *ASTInitListExpr::GenerateMIRConstForStruct() const { } MIRAggConst *aggConst = FEManager::GetModule().GetMemPool()->New(FEManager::GetModule(), *initListType); CHECK_FATAL(initExprs.size() <= UINT_MAX, "Too large elem size"); + if (initListType->GetKind() == kTypeUnion) { + CHECK_FATAL(initExprs.size() == 1, "union should only have one elem"); + } for (uint32 i = 0; i < static_cast(initExprs.size()); ++i) { if (initExprs[i] == nullptr) { continue; } auto konst = initExprs[i]->GenerateMIRConst(); + if (konst == nullptr) { + continue; + } if (konst->GetKind() == kConstLblConst) { // init by initListExpr, Only MIRConst kind is set here. return konst; } - aggConst->AddItem(konst, i + 1); + uint32 fieldIdx = (initListType->GetKind() == kTypeUnion) ? unionInitFieldIdx : i; + aggConst->AddItem(konst, fieldIdx + 1); } ENCChecker::CheckNullFieldInGlobalStruct(*initListType, *aggConst, initExprs); return aggConst; } UniqueFEIRExpr ASTInitListExpr::Emit2FEExprImpl(std::list &stmts) const { - UniqueFEIRVar feirVar = FEIRBuilder::CreateVarNameForC(varName, *initListType); + UniqueFEIRVar feirVar = FEIRBuilder::CreateVarNameForC(GetInitListVarName(), *initListType); if (initListType->GetKind() == MIRTypeKind::kTypeArray) { UniqueFEIRExpr arrayExpr = FEIRBuilder::CreateExprAddrofVar(feirVar->Clone()); auto base = std::variant, UniqueFEIRExpr>(arrayExpr->Clone()); @@ -1053,7 +1209,7 @@ UniqueFEIRExpr ASTInitListExpr::Emit2FEExprImpl(std::list &stmts } void ASTInitListExpr::ProcessInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, + const ASTInitListExpr *initList, std::list &stmts) const { if (initList->initListType->GetKind() == kTypeArray) { if (std::holds_alternative(base)) { @@ -1097,6 +1253,7 @@ void ASTInitListExpr::ProcessStringLiteralInitList(const UniqueFEIRExpr &addrOfC argExprList->emplace_back(FEIRBuilder::CreateExprConstI32(static_cast(stringLength))); std::unique_ptr memcpyStmt = std::make_unique( INTRN_C_memcpy, nullptr, nullptr, std::move(argExprList)); + memcpyStmt->SetSrcLoc(addrOfStringLiteral->GetLoc()); stmts.emplace_back(std::move(memcpyStmt)); // Handling Implicit Initialization When Incomplete Initialization @@ -1107,17 +1264,18 @@ void ASTInitListExpr::ProcessStringLiteralInitList(const UniqueFEIRExpr &addrOfC MIRType *mirType = type->GenerateMIRType(); if (mirType->GetKind() == kTypeArray) { MIRArrayType *arrayType = static_cast(mirType); - if (arrayType->GetDim() != 2) { // only processing two-dimensional arrays. + if (arrayType->GetDim() > 2) { // only processing one or two dimensional arrays. return; } - uint32 dimSize = arrayType->GetSizeArrayItem(1); + uint32 dimSize = arrayType->GetSizeArrayItem(arrayType->GetDim() - 1); uint32 elemSize = arrayType->GetElemType()->GetSize(); - ProcessImplicitInit(addrOfCharArray->Clone(), stringLength, dimSize, elemSize, stmts); + ProcessImplicitInit(addrOfCharArray->Clone(), stringLength, dimSize, elemSize, stmts, + addrOfStringLiteral->GetLoc()); } } -void ASTInitListExpr::ProcessImplicitInit(const UniqueFEIRExpr &addrExpr, uint32 initSize, - uint32 total, uint32 elemSize, std::list &stmts) const { +void ASTInitListExpr::ProcessImplicitInit(const UniqueFEIRExpr &addrExpr, uint32 initSize, uint32 total, + uint32 elemSize,std::list &stmts, Loc loc) const { if (initSize >= total) { return; } @@ -1142,6 +1300,9 @@ void ASTInitListExpr::ProcessImplicitInit(const UniqueFEIRExpr &addrExpr, uint32 argExprList->emplace_back(std::move(cntExpr)); std::unique_ptr memsetStmt = std::make_unique( INTRN_C_memset, nullptr, nullptr, std::move(argExprList)); + if (loc.fileIdx != 0) { + memsetStmt->SetSrcLoc(loc); + } stmts.emplace_back(std::move(memsetStmt)); } @@ -1149,11 +1310,11 @@ void ASTInitListExpr::ProcessDesignatedInitUpdater( std::variant, UniqueFEIRExpr> &base, ASTExpr *expr, std::list &stmts) const { auto designatedInitUpdateExpr = static_cast(expr); - ASTExpr *baseExpr = designatedInitUpdateExpr->GetBaseExpr(); - ASTExpr *updaterExpr = designatedInitUpdateExpr->GetUpdaterExpr(); + const ASTExpr *baseExpr = designatedInitUpdateExpr->GetBaseExpr(); + const ASTExpr *updaterExpr = designatedInitUpdateExpr->GetUpdaterExpr(); auto feExpr = baseExpr->Emit2FEExpr(stmts); if (std::holds_alternative(base)) { - MIRType *mirType = designatedInitUpdateExpr->GetInitListType(); + const MIRType *mirType = designatedInitUpdateExpr->GetInitListType(); MIRType *mirPtrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType); UniqueFEIRType fePtrType = std::make_unique(*mirPtrType); auto stmt = FEIRBuilder::CreateStmtIAssign(fePtrType->Clone(), std::get(base)->Clone(), @@ -1165,11 +1326,35 @@ void ASTInitListExpr::ProcessDesignatedInitUpdater( auto stmt = FEIRBuilder::CreateStmtDAssignAggField(feirVar->Clone(), feExpr->Clone(), fieldID); stmts.emplace_back(std::move(stmt)); } - ProcessInitList(base, static_cast(updaterExpr), stmts); + ProcessInitList(base, static_cast(updaterExpr), stmts); +} + +UniqueFEIRExpr ASTInitListExpr::CalculateStartAddressForMemset(const UniqueFEIRVar &varIn, uint32 initSizeIn, + uint32 fieldIDIn, const std::variant, UniqueFEIRExpr> &baseIn) const { + UniqueFEIRExpr addrOfExpr; + if (std::holds_alternative(baseIn)) { + UniqueFEIRExpr offsetExpr = FEIRBuilder::CreateExprConstU32(initSizeIn); + addrOfExpr = FEIRBuilder::CreateExprBinary(OP_add, std::get(baseIn)->Clone(), + std::move(offsetExpr)); + } else { + addrOfExpr = std::make_unique(varIn->Clone(), fieldIDIn); + } + return addrOfExpr; +} + +std::tuple ASTInitListExpr::GetStructFieldInfo(uint32 fieldIndex, + uint32 baseFieldID, + MIRStructType &structMirType) const { + FieldID curFieldID = 0; + FEUtils::TraverseToNamedField(structMirType, structMirType.GetElemStrIdx(fieldIndex), curFieldID); + uint32 fieldID = static_cast(baseFieldID + curFieldID); + MIRType *fieldMirType = structMirType.GetFieldType(curFieldID); + uint32 fieldTypeSize = static_cast(fieldMirType->GetSize()); + return std::make_tuple(fieldID, fieldTypeSize, fieldMirType); } void ASTInitListExpr::ProcessStructInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, + const ASTInitListExpr *initList, std::list &stmts) const { MIRType *baseStructMirPtrType = nullptr; MIRStructType *baseStructMirType = nullptr; @@ -1198,7 +1383,23 @@ void ASTInitListExpr::ProcessStructInitList(std::variantinitExprs.size() == 0) { UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), 0); - ProcessImplicitInit(addrOfExpr->Clone(), 0, curStructMirType->GetSize(), 1, stmts); + ProcessImplicitInit(addrOfExpr->Clone(), 0, curStructMirType->GetSize(), 1, stmts, initList->GetSrcLoc()); + return; + } + + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && initList->GetEvaluatedFlag() == kEvaluatedAsZero) { + if (baseStructMirType->GetKind() == kTypeStruct) { + std::tuple fieldInfo = GetStructFieldInfo(0, baseFieldID, *curStructMirType); + uint32 fieldID = std::get<0>(fieldInfo); + // Use 'fieldID - 1' (start address of the nested struct or union) instead of 'fieldID' (start address of the + // first field in the nested struct or union), because even though these two addresses have the same value, + // they have different pointer type. + UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), fieldID - 1); + ProcessImplicitInit(addrOfExpr->Clone(), 0, curStructMirType->GetSize(), 1, stmts, initList->GetSrcLoc()); + } else { // kTypeUnion + UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), 0); + ProcessImplicitInit(addrOfExpr->Clone(), 0, baseStructMirType->GetSize(), 1, stmts, initList->GetSrcLoc()); + } return; } @@ -1209,24 +1410,58 @@ void ASTInitListExpr::ProcessStructInitList(std::variantGetKind() == kTypeUnion) ? initList->GetUnionInitFieldIdx() : i; - FEUtils::TraverseToNamedField(*curStructMirType, curStructMirType->GetElemStrIdx(fieldIdx), curFieldID); - uint32 fieldID = static_cast(baseFieldID + curFieldID); - MIRType *fieldMirType = curStructMirType->GetFieldType(curFieldID); - curFieldTypeSize = static_cast(fieldMirType->GetSize()); + std::tuple fieldInfo = GetStructFieldInfo(fieldIdx, baseFieldID, *curStructMirType); + uint32 fieldID = std::get<0>(fieldInfo); + curFieldTypeSize = std::get<1>(fieldInfo); + MIRType *fieldMirType = std::get<2>(fieldInfo); offset += curFieldTypeSize; - - if (initList->initExprs[i]->GetASTOp() == kASTImplicitValueInitExpr && fieldMirType->GetPrimType() == PTY_agg) { - UniqueFEIRExpr addrOfExpr; - if (std::holds_alternative(base)) { - UniqueFEIRExpr offsetExpr = FEIRBuilder::CreateExprConstU32(offset - curFieldTypeSize); - addrOfExpr = FEIRBuilder::CreateExprBinary(OP_add, std::get(base)->Clone(), - std::move(offsetExpr)); + // use one instrinsic call memset to initialize zero for partial continuous fields of struct to need reduce code + // size need to follow these three rules: (1) offset from the start address of the continuous fields to the start + // addresss of struct should be an integer multiples of 4 bytes (2) size of the continuous fields should be an + // integer multiples of 4 bytes (3) the continuous fields count should be two at least + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && + curStructMirType->GetKind() == kTypeStruct && + fieldMirType->GetKind() != kTypeBitField && // skip bitfield type field because it not follows byte alignment + initList->initExprs[i]->GetEvaluatedFlag() == kEvaluatedAsZero && + (baseStructMirType->GetBitOffsetFromBaseAddr(fieldID) / 8) % 4 == 0) { + uint32 fieldsCount = 0; + int64 initBitSize = baseStructMirType->GetBitOffsetFromBaseAddr(fieldID); // in bit + uint32 fieldSizeOfLastZero = 0; // in byte + uint32 fieldIdOfLastZero = fieldID; + size_t start = i; + while (i < initList->initExprs.size() && + initList->initExprs[i] != nullptr && + initList->initExprs[i]->GetEvaluatedFlag() == kEvaluatedAsZero) { + fieldInfo = GetStructFieldInfo(i, baseFieldID, *curStructMirType); + curFieldTypeSize = std::get<1>(fieldInfo); + fieldMirType = std::get<2>(fieldInfo); + if (fieldMirType->GetKind() == kTypeBitField) { + break; + } + fieldSizeOfLastZero = curFieldTypeSize; + fieldIdOfLastZero = std::get<0>(fieldInfo); + ++fieldsCount; + ++i; + } + // consider struct alignment + int64 fieldsBitSize = (baseStructMirType->GetBitOffsetFromBaseAddr(fieldIdOfLastZero) + + fieldSizeOfLastZero * 8) - initBitSize; + if (fieldsCount >= 2 && fieldsBitSize % 8 == 0 && (fieldsBitSize / 8) % 4 == 0) { + auto addrOfExpr = CalculateStartAddressForMemset(var, static_cast(initBitSize / 8), fieldID, base); + ProcessImplicitInit(addrOfExpr->Clone(), 0, static_cast(fieldsBitSize / 8), 1, stmts, + initList->initExprs[start]->GetSrcLoc()); + --i; + continue; } else { - addrOfExpr = std::make_unique(var->Clone(), fieldID); + i -= fieldsCount; } - ProcessImplicitInit(addrOfExpr->Clone(), 0, fieldMirType->GetSize(), 1, stmts); + } + + if (initList->initExprs[i]->GetASTOp() == kASTImplicitValueInitExpr && fieldMirType->GetPrimType() == PTY_agg) { + auto addrOfExpr = CalculateStartAddressForMemset(var, offset - curFieldTypeSize, fieldID, base); + ProcessImplicitInit(addrOfExpr->Clone(), 0, fieldMirType->GetSize(), 1, stmts, + initList->initExprs[i]->GetSrcLoc()); continue; } @@ -1249,18 +1484,22 @@ void ASTInitListExpr::ProcessStructInitList(std::variantinitExprs[i]->Emit2FEExpr(stmts); + if (elemExpr == nullptr) { + continue; + } if (std::holds_alternative(base)) { if (fieldMirType->GetKind() == kTypeArray && initList->initExprs[i]->GetASTOp() == kASTStringLiteral) { auto addrOfElement = std::make_unique(baseStructFEPtrType->Clone(), fieldID, std::get(base)->Clone()); - ProcessStringLiteralInitList(addrOfElement->Clone(), elemExpr->Clone(), + auto addrOfArrayExpr = GetAddrofArrayFEExprByStructArrayField(fieldMirType, addrOfElement->Clone()); + ProcessStringLiteralInitList(addrOfArrayExpr->Clone(), elemExpr->Clone(), static_cast(initList->initExprs[i])->GetLength(), stmts); } else { auto stmt = std::make_unique(baseStructFEPtrType->Clone(), std::get(base)->Clone(), elemExpr->Clone(), fieldID); - stmt->SetSrcFileInfo(initList->initExprs[i]->GetSrcFileIdx(), initList->initExprs[i]->GetSrcFileLineNum()); + stmt->SetSrcLoc(initList->initExprs[i]->GetSrcLoc()); stmts.emplace_back(std::move(stmt)); } } else { @@ -1268,11 +1507,12 @@ void ASTInitListExpr::ProcessStructInitList(std::variantGetKind() == kTypeArray && initList->initExprs[i]->GetASTOp() == kASTStringLiteral) { auto addrOfElement = std::make_unique(subVar->Clone()); addrOfElement->SetFieldID(static_cast(fieldID)); - ProcessStringLiteralInitList(addrOfElement->Clone(), elemExpr->Clone(), + auto addrOfArrayExpr = GetAddrofArrayFEExprByStructArrayField(fieldMirType, addrOfElement->Clone()); + ProcessStringLiteralInitList(addrOfArrayExpr->Clone(), elemExpr->Clone(), static_cast(initList->initExprs[i])->GetLength(), stmts); } else { auto stmt = std::make_unique(subVar->Clone(), elemExpr->Clone(), fieldID); - stmt->SetSrcFileInfo(initList->initExprs[i]->GetSrcFileIdx(), initList->initExprs[i]->GetSrcFileLineNum()); + stmt->SetSrcLoc(initList->initExprs[i]->GetSrcLoc()); stmts.emplace_back(std::move(stmt)); } } @@ -1281,13 +1521,25 @@ void ASTInitListExpr::ProcessStructInitList(std::variantGetKind() == kTypeUnion) { - UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), 0); + UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), baseFieldID); ProcessImplicitInit(addrOfExpr->Clone(), curFieldTypeSize, - curStructMirType->GetSize(), 1, stmts); + curStructMirType->GetSize(), 1, stmts, initList->GetSrcLoc()); } } -void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, ASTInitListExpr *initList, +UniqueFEIRExpr ASTInitListExpr::GetAddrofArrayFEExprByStructArrayField(MIRType *fieldType, + UniqueFEIRExpr addrOfArrayField) const { + CHECK_FATAL(fieldType->GetKind() == kTypeArray, "invalid field type"); + auto arrayFEType = FEIRTypeHelper::CreateTypeNative(*fieldType); + std::list indexExprs; + auto indexExpr = FEIRBuilder::CreateExprConstI32(0); + indexExprs.emplace_back(std::move(indexExpr)); + auto addrOfArrayExpr = FEIRBuilder::CreateExprAddrofArray(arrayFEType->Clone(), addrOfArrayField->Clone(), + "", indexExprs); + return addrOfArrayExpr; +} + +void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, const ASTInitListExpr *initList, std::list &stmts) const { auto arrayMirType = static_cast(initList->initListType); UniqueFEIRType arrayFEType = FEIRTypeHelper::CreateTypeNative(*arrayMirType); @@ -1305,24 +1557,50 @@ void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, AS auto elementPtrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*elementType); auto elementPtrFEType = FEIRTypeHelper::CreateTypeNative(*elementPtrType); CHECK_FATAL(initExprs.size() <= INT_MAX, "invalid index"); + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && initList->GetEvaluatedFlag() == kEvaluatedAsZero) { + ProcessImplicitInit(addrOfArray->Clone(), 0, arrayMirType->GetSize(), 1, stmts, initList->GetSrcLoc()); + return; + } for (size_t i = 0; i < initList->initExprs.size(); ++i) { std::list indexExprs; UniqueFEIRExpr indexExpr = FEIRBuilder::CreateExprConstI32(static_cast(i)); indexExprs.emplace_back(std::move(indexExpr)); auto addrOfElemExpr = FEIRBuilder::CreateExprAddrofArray(arrayFEType->Clone(), addrOfArray->Clone(), "", indexExprs); - if (initList->initExprs[i]->GetASTOp() == kASTOpInitListExpr) { + const ASTExpr *subExpr = initList->initExprs[i]; + while (subExpr->GetASTOp() == kConstantExpr) { + subExpr = static_cast(subExpr)->GetChild(); + } + if (subExpr->GetASTOp() == kASTOpInitListExpr) { auto base = std::variant, UniqueFEIRExpr>(addrOfElemExpr->Clone()); - ProcessInitList(base, static_cast(initList->initExprs[i]), stmts); + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && subExpr->GetEvaluatedFlag() == kEvaluatedAsZero) { + UniqueFEIRExpr realAddr = addrOfArray->Clone(); + if (i > 0) { + UniqueFEIRExpr idxExpr = FEIRBuilder::CreateExprConstI32(static_cast(i)); + UniqueFEIRExpr elemSizeExpr = FEIRBuilder::CreateExprConstI32(static_cast(elementType->GetSize())); + UniqueFEIRExpr offsetSizeExpr = FEIRBuilder::CreateExprBinary(OP_mul, std::move(idxExpr), + elemSizeExpr->Clone()); + realAddr = FEIRBuilder::CreateExprBinary(OP_add, std::move(realAddr), offsetSizeExpr->Clone()); + } + ProcessImplicitInit(realAddr->Clone(), 0, elementType->GetSize(), 1, stmts, + initList->initExprs[i]->GetSrcLoc()); + } else { + ProcessInitList(base, static_cast(subExpr), stmts); + } } else { - UniqueFEIRExpr elemExpr = initList->initExprs[i]->Emit2FEExpr(stmts); - if (elementType->GetKind() == kTypeArray && initList->initExprs[i]->GetASTOp() == kASTStringLiteral) { + UniqueFEIRExpr elemExpr = subExpr->Emit2FEExpr(stmts); + if ((elementType->GetKind() == kTypeArray || arrayMirType->GetDim() == 1) && + subExpr->GetASTOp() == kASTStringLiteral) { ProcessStringLiteralInitList(addrOfElemExpr->Clone(), elemExpr->Clone(), - static_cast(initList->initExprs[i])->GetLength(), stmts); + static_cast(subExpr)->GetLength(), stmts); + if (arrayMirType->GetDim() == 1) { + return; + } } else { auto stmt = FEIRBuilder::CreateStmtIAssign(elementPtrFEType->Clone(), addrOfElemExpr->Clone(), elemExpr->Clone(), 0); + stmt->SetSrcLoc(initList->initExprs[i]->GetSrcLoc()); stmts.emplace_back(std::move(stmt)); } } @@ -1333,11 +1611,12 @@ void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, AS auto elemSize = elementType->GetSize(); CHECK_FATAL(elemSize != 0, "elemSize should not 0"); auto allElemCnt = allSize / elemSize; - ProcessImplicitInit(addrOfArray->Clone(), initList->initExprs.size(), allElemCnt, elemSize, stmts); + ProcessImplicitInit(addrOfArray->Clone(), initList->initExprs.size(), allElemCnt, elemSize, stmts, + initList->GetSrcLoc()); } void ASTInitListExpr::ProcessVectorInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, std::list &stmts) const { + const ASTInitListExpr *initList, std::list &stmts) const { UniqueFEIRType srcType = FEIRTypeHelper::CreateTypeNative(*initList->initListType); if (std::holds_alternative(base)) { CHECK_FATAL(false, "unsupported case"); @@ -1443,7 +1722,9 @@ MIRConst *ASTStringLiteral::GenerateMIRConstImpl() const { UniqueFEIRExpr ASTStringLiteral::Emit2FEExprImpl(std::list &stmts) const { (void)stmts; MIRType *elemType = static_cast(mirType)->GetElemType(); - UniqueFEIRExpr expr = std::make_unique(codeUnits, elemType); + std::vector codeUnitsVec; + codeUnitsVec.insert(codeUnitsVec.end(), codeUnits.begin(), codeUnits.end()); + UniqueFEIRExpr expr = std::make_unique(codeUnitsVec, elemType, GetStr()); CHECK_NULL_FATAL(expr); return expr; } @@ -1485,8 +1766,8 @@ MIRConst *ASTArraySubscriptExpr::GenerateMIRConstImpl() const { } } -bool ASTArraySubscriptExpr::CheckFirstDimIfZero(const MIRType *arrayType) const { - auto tmpArrayType = static_cast(arrayType); +bool ASTArraySubscriptExpr::CheckFirstDimIfZero(const MIRType *arrType) const { + auto tmpArrayType = static_cast(arrType); uint32 size = tmpArrayType->GetSizeArrayItem(0); uint32 oriDim = tmpArrayType->GetDim(); if (size == 0 && oriDim >= 2) { // 2 is the array dim @@ -1502,7 +1783,7 @@ void ASTArraySubscriptExpr::InsertNonnullChecking(std::list &stm } if (FEIRBuilder::IsZeroConstExpr(indexExpr)) { // insert nonnull checking when ptr[0] UniqueFEIRStmt stmt = std::make_unique(OP_assertnonnull, baseAddrExpr->Clone()); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); } } @@ -1564,9 +1845,13 @@ UniqueFEIRExpr ASTArraySubscriptExpr::Emit2FEExprImpl(std::list } else { sizeType = std::make_unique(*GlobalTables::GetTypeTable().GetPrimType(PTY_ptr)); feIdxExpr = FEIRBuilder::CreateExprCvtPrim(std::move(feIdxExpr), - GetSignedPrimType(GetRegPrimType(indexPty)), PTY_ptr); + GetRegPrimType(indexPty), PTY_ptr); } - if (mirType->GetSize() != 1) { + if (isVLA) { + auto feSizeExpr = vlaSizeExpr->Emit2FEExpr(stmts); + feIdxExpr = FEIRBuilder::CreateExprBinary(sizeType->Clone(), OP_mul, std::move(feIdxExpr), + std::move(feSizeExpr)); + } else if (mirType->GetSize() != 1) { auto typeSizeExpr = std::make_unique(mirType->GetSize(), sizeType->GetPrimType()); feIdxExpr = FEIRBuilder::CreateExprBinary(sizeType->Clone(), OP_mul, std::move(feIdxExpr), std::move(typeSizeExpr)); @@ -1584,9 +1869,6 @@ UniqueFEIRExpr ASTArraySubscriptExpr::Emit2FEExprImpl(std::list } } } - if (isVLA) { - baseAddrFEExpr = FEIRBuilder::CreateExprDRead(baseAddrFEExpr->GetVarUses().front()->Clone()); - } addrOfArray = FEIRBuilder::CreateExprBinary(std::move(sizeType), OP_add, baseAddrFEExpr->Clone(), std::move(offsetExpr)); } @@ -1604,9 +1886,9 @@ UniqueFEIRExpr ASTExprUnaryExprOrTypeTraitExpr::Emit2FEExprImpl(std::listGetASTOp() == kASTMemberExpr) { // find final BaseExpr and calculate FieldOffsets - ASTMemberExpr *memberExpr = static_cast(base); + const ASTMemberExpr *memberExpr = static_cast(base); fieldOffset += memberExpr->GetFieldOffsetBits() / kOneByte; base = memberExpr->GetBaseExpr(); } @@ -1630,7 +1912,7 @@ MIRConst *ASTMemberExpr::GenerateMIRConstImpl() const { const ASTMemberExpr *ASTMemberExpr::FindFinalMember(const ASTMemberExpr *startExpr, std::list &memberNames) const { - memberNames.emplace_back(startExpr->memberName); + memberNames.emplace_back(startExpr->GetMemberName()); if (startExpr->isArrow || startExpr->baseExpr->GetASTOp() != kASTMemberExpr) { return startExpr; } @@ -1643,19 +1925,19 @@ void ASTMemberExpr::InsertNonnullChecking(std::list &stmts, Uniq } if (baseFEExpr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique(OP_assertnonnull, std::move(baseFEExpr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); } } UniqueFEIRExpr ASTMemberExpr::Emit2FEExprImpl(std::list &stmts) const { UniqueFEIRExpr baseFEExpr; - std::string fieldName = memberName; + std::string fieldName = GetMemberName(); bool tmpIsArrow = this->isArrow; MIRType *tmpBaseType = this->baseType; if (baseExpr->GetASTOp() == kASTMemberExpr) { std::list memberNameList; - memberNameList.emplace_back(memberName); + memberNameList.emplace_back(GetMemberName()); const ASTMemberExpr *finalMember = FindFinalMember(static_cast(baseExpr), memberNameList); baseFEExpr = finalMember->baseExpr->Emit2FEExpr(stmts); tmpIsArrow = finalMember->isArrow; @@ -1740,8 +2022,8 @@ MIRConst *ASTBinaryOperatorExpr::GenerateMIRConstImpl() const { } rightConst = rightExpr->GenerateMIRConst(); if (leftConst->GetKind() == kConstLblConst || rightConst->GetKind() == kConstLblConst) { - // init by initListExpr, Only MIRConst kind is set here. - return leftConst->GetKind() == kConstLblConst ? leftConst : rightConst; + // if left or right is label mirconst, not currently implemented + return nullptr; } if (opcode == OP_land || opcode == OP_cand) { if (leftConst->IsZero()) { @@ -1790,7 +2072,7 @@ MIRConst *ASTBinaryOperatorExpr::GenerateMIRConstImpl() const { } else { CHECK_FATAL(false, "Unsupported yet"); } - int64 value = constInt->GetValue(); + int64 value = constInt->GetExtValue(); if (baseConst->GetKind() == kConstStrConst) { std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx(static_cast(baseConst)->GetValue()); @@ -1816,7 +2098,7 @@ MIRConst *ASTBinaryOperatorExpr::GenerateMIRConstImpl() const { auto id = konst->GetFieldID(); auto ty = konst->GetType(); auto offset = konst->GetOffset(); - int64 value = static_cast(rightConst)->GetValue(); + int64 value = static_cast(rightConst)->GetExtValue(); return FEManager::GetModule().GetMemPool()->New(idx, id, ty, offset - value); } else { CHECK_FATAL(false, "NIY"); @@ -1908,7 +2190,7 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperate(std::list(rightCondLabel); - rightCondlabelStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(rightCondlabelStmt)); // brfalse/brtrue label (rightCond) @@ -1967,8 +2248,6 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperate(std::list(fallthrouLabel); auto labelJumpToStmt = std::make_unique(jumpToLabel); auto labelNextStmt = std::make_unique(nextLabel); - labelJumpToStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); - labelNextStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(labelFallthrouStmt)); stmts.emplace_back(op == OP_brtrue ? std::move(falseCircuit) : std::move(trueCircuit)); stmts.emplace_back(std::move(goStmt)); @@ -1987,7 +2266,7 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperateSimplify(std::list< Opcode op = opcode == OP_cior ? OP_brtrue : OP_brfalse; MIRType *tempVarType = GlobalTables::GetTypeTable().GetInt32(); UniqueFEIRType tempFeirType = std::make_unique(*tempVarType); - UniqueFEIRVar shortCircuit = FEIRBuilder::CreateVarNameForC(varName, *tempVarType); + UniqueFEIRVar shortCircuit = FEIRBuilder::CreateVarNameForC(GetVarName(), *tempVarType); std::string labelName = FEUtils::GetSequentialName("shortCircuit_label_"); auto leftFEExpr = leftExpr->Emit2FEExpr(lStmts); leftFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(leftFEExpr)); @@ -2006,7 +2285,6 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperateSimplify(std::list< auto rightStmt = std::make_unique(shortCircuit->Clone(), rightFEExpr->Clone(), 0); rStmts.emplace_back(std::move(rightStmt)); auto labelStmt = std::make_unique(labelName); - labelStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); rStmts.emplace_back(std::move(labelStmt)); stmts.splice(stmts.end(), lStmts); stmts.splice(stmts.end(), cStmts); @@ -2151,7 +2429,7 @@ MIRConst *ASTFloatingLiteral::GenerateMIRConstImpl() const { MemPool *mp = FEManager::GetModule().GetMemPool(); MIRConst *cst; MIRType *type; - if (kind == F32) { + if (kind == FloatKind::F32) { type = GlobalTables::GetTypeTable().GetPrimType(PTY_f32); cst = mp->New(static_cast(val), *type); } else { @@ -2164,7 +2442,7 @@ MIRConst *ASTFloatingLiteral::GenerateMIRConstImpl() const { UniqueFEIRExpr ASTFloatingLiteral::Emit2FEExprImpl(std::list &stmts) const { (void)stmts; UniqueFEIRExpr expr; - if (kind == F32) { + if (kind == FloatKind::F32) { expr = FEIRBuilder::CreateExprConstF32(static_cast(val)); } else { expr = FEIRBuilder::CreateExprConstF64(val); @@ -2192,13 +2470,13 @@ UniqueFEIRExpr ASTConditionalOperator::Emit2FEExprImpl(std::list std::list falseStmts; UniqueFEIRExpr falseFEIRExpr = falseExpr->Emit2FEExpr(falseStmts); // when subExpr is void - if (trueFEIRExpr == nullptr || falseFEIRExpr == nullptr) { + if (trueFEIRExpr == nullptr || falseFEIRExpr == nullptr || mirType->GetPrimType() == PTY_void) { UniqueFEIRStmt stmtIf = FEIRBuilder::CreateStmtIf(std::move(condFEIRExpr), trueStmts, falseStmts); stmts.emplace_back(std::move(stmtIf)); return nullptr; } // Otherwise, (e.g., a < 1 ? 1 : a++) create a temporary var to hold the return trueExpr or falseExpr value - MIRType *retType = trueFEIRExpr->GetType()->GenerateMIRTypeAuto(); + MIRType *retType = mirType; if (retType->GetKind() == kTypeBitField) { retType = GlobalTables::GetTypeTable().GetPrimType(retType->GetPrimType()); } @@ -2206,10 +2484,8 @@ UniqueFEIRExpr ASTConditionalOperator::Emit2FEExprImpl(std::list UniqueFEIRVar tempVarCloned1 = tempVar->Clone(); UniqueFEIRVar tempVarCloned2 = tempVar->Clone(); UniqueFEIRStmt retTrueStmt = FEIRBuilder::CreateStmtDAssign(std::move(tempVar), std::move(trueFEIRExpr)); - retTrueStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); trueStmts.emplace_back(std::move(retTrueStmt)); UniqueFEIRStmt retFalseStmt = FEIRBuilder::CreateStmtDAssign(std::move(tempVarCloned1), std::move(falseFEIRExpr)); - retFalseStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); falseStmts.emplace_back(std::move(retFalseStmt)); UniqueFEIRStmt stmtIf = FEIRBuilder::CreateStmtIf(std::move(condFEIRExpr), trueStmts, falseStmts); stmts.emplace_back(std::move(stmtIf)); @@ -2549,29 +2825,22 @@ UniqueFEIRExpr ASTAtomicExpr::Emit2FEExprImpl(std::list &stmts) // ---------- ASTExprStmtExpr ---------- UniqueFEIRExpr ASTExprStmtExpr::Emit2FEExprImpl(std::list &stmts) const { - std::list stmts0 = cpdStmt->Emit2FEStmt(); - for (auto &stmt : stmts0) { - stmts.emplace_back(std::move(stmt)); - } CHECK_FATAL(cpdStmt->GetASTStmtOp() == kASTStmtCompound, "Invalid in ASTExprStmtExpr"); - stmts0.clear(); - auto *lastCpdStmt = static_cast(cpdStmt); + const auto *lastCpdStmt = static_cast(cpdStmt); while (lastCpdStmt->GetASTStmtList().back()->GetASTStmtOp() == kASTStmtStmtExpr) { auto bodyStmt = static_cast(lastCpdStmt->GetASTStmtList().back())->GetBodyStmt(); - lastCpdStmt = static_cast(bodyStmt); + lastCpdStmt = static_cast(bodyStmt); } + UniqueFEIRExpr feirExpr = nullptr; + std::list stmts0; if (lastCpdStmt->GetASTStmtList().size() != 0 && lastCpdStmt->GetASTStmtList().back()->GetExprs().size() != 0) { - UniqueFEIRExpr feirExpr = lastCpdStmt->GetASTStmtList().back()->GetExprs().back()->Emit2FEExpr(stmts0); - for (size_t i = 0; i < stmts0.size(); ++i) { - if (!stmts.empty()) { - stmts.pop_back(); - } - } - for (auto &stmt : stmts0) { - stmts.emplace_back(std::move(stmt)); - } - return feirExpr; + feirExpr = lastCpdStmt->GetASTStmtList().back()->GetExprs().back()->Emit2FEExpr(stmts0); + lastCpdStmt->GetASTStmtList().back()->GetExprs().back()->SetRValue(true); } - return nullptr; + stmts0 = cpdStmt->Emit2FEStmt(); + for (auto &stmt : stmts0) { + stmts.emplace_back(std::move(stmt)); + } + return feirExpr; } } diff --git a/src/hir2mpl/ast_input/clang/src/ast_function.cpp b/src/hir2mpl/ast_input/clang/src/ast_function.cpp index 5f87736bb3db04381ceda5697557ca449cc000a9..381afbef3ab1e913461cd612d60991316d695433 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_function.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_function.cpp @@ -76,6 +76,14 @@ bool ASTFunction::ProcessFEIRFunction() { } void ASTFunction::FinishImpl() { + if (FEOptions::GetInstance().IsDumpFEIRBB()) { + (void)LowerFunc("low feir func"); + (void)DumpFEIRBBs("dump bb list"); + } + if (FEOptions::GetInstance().IsDumpFEIRCFGGraph(GetGeneralFuncName())) { + (void)LowerFunc("low feir func"); + (void)DumpFEIRCFGGraph("dump cfg graph"); + } (void)EmitToMIR("finish/emit to mir"); (void)GenerateAliasVars("finish/generate alias vars"); } diff --git a/src/hir2mpl/ast_input/clang/src/ast_parser.cpp b/src/hir2mpl/ast_input/clang/src/ast_parser.cpp index 1d578dde1277ec064f58d39d14048f1178b08911..4aa98fa4057b83bf815654559bc363e2f7501b21 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_parser.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_parser.cpp @@ -28,8 +28,8 @@ namespace maple { std::map ASTDeclsBuilder::declesTable; -bool ASTParser::OpenFile() { - astFile = std::make_unique(recordDecles); +bool ASTParser::OpenFile(MapleAllocator &allocator) { + astFile = allocator.GetMemPool()->New(allocator, recordDecles); bool res = astFile->Open(fileName, 0, 0); if (!res) { return false; @@ -38,6 +38,12 @@ bool ASTParser::OpenFile() { return true; } +bool ASTParser::Release() { + astFile->DisposeTranslationUnit(); + ASTDeclsBuilder::Clear(); + return true; +} + bool ASTParser::Verify() const { return true; } @@ -73,6 +79,7 @@ ASTStmt *ASTParser::ProcessFunctionBody(MapleAllocator &allocator, const clang:: ASTStmt *ASTParser::ProcessStmtCompoundStmt(MapleAllocator &allocator, const clang::CompoundStmt &cpdStmt) { ASTCompoundStmt *astCompoundStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astCompoundStmt != nullptr, "astCompoundStmt is nullptr"); + astCompoundStmt->SetEndLoc(astFile->GetLOC(cpdStmt.getEndLoc())); clang::CompoundStmt::const_body_iterator it; ASTStmt *childStmt = nullptr; for (it = cpdStmt.body_begin(); it != cpdStmt.body_end(); ++it) { @@ -87,13 +94,13 @@ ASTStmt *ASTParser::ProcessStmtCompoundStmt(MapleAllocator &allocator, const cla if (FEOptions::GetInstance().IsEnableSafeRegion()) { switch (cpdStmt.getSafeSpecifier()) { case clang::SS_None: - astCompoundStmt->SetSafeSS(kNoneSS); + astCompoundStmt->SetSafeSS(SafeSS::kNoneSS); break; case clang::SS_Unsafe: - astCompoundStmt->SetSafeSS(kUnsafeSS); + astCompoundStmt->SetSafeSS(SafeSS::kUnsafeSS); break; case clang::SS_Safe: - astCompoundStmt->SetSafeSS(kSafeSS); + astCompoundStmt->SetSafeSS(SafeSS::kSafeSS); break; default: break; } @@ -104,8 +111,8 @@ ASTStmt *ASTParser::ProcessStmtCompoundStmt(MapleAllocator &allocator, const cla #define STMT_CASE(CLASS) \ case clang::Stmt::CLASS##Class: { \ ASTStmt *astStmt = ProcessStmt##CLASS(allocator, llvm::cast(stmt)); \ - Pos loc = astFile->GetStmtLOC(stmt); \ - astStmt->SetSrcLOC(loc.first, loc.second); \ + Loc loc = astFile->GetStmtLOC(stmt); \ + astStmt->SetSrcLoc(loc); \ return astStmt; \ } @@ -145,6 +152,9 @@ ASTStmt *ASTParser::ProcessStmt(MapleAllocator &allocator, const clang::Stmt &st STMT_CASE(OffsetOfExpr); STMT_CASE(GenericSelectionExpr); STMT_CASE(AttributedStmt); + STMT_CASE(DeclRefExpr); + STMT_CASE(UnaryExprOrTypeTraitExpr); + STMT_CASE(AddrLabelExpr); default: { CHECK_FATAL(false, "ASTStmt: %s NIY", stmt.getStmtClassName()); return nullptr; @@ -152,8 +162,8 @@ ASTStmt *ASTParser::ProcessStmt(MapleAllocator &allocator, const clang::Stmt &st } } -ASTStmt *ASTParser::ProcessStmtAttributedStmt(MapleAllocator &allocator, const clang::AttributedStmt &AttrStmt) { - ASSERT(clang::hasSpecificAttr(AttrStmt.getAttrs()), "AttrStmt is not fallthrough"); +ASTStmt *ASTParser::ProcessStmtAttributedStmt(MapleAllocator &allocator, const clang::AttributedStmt &attrStmt) { + ASSERT(clang::hasSpecificAttr(attrStmt.getAttrs()), "AttrStmt is not fallthrough"); ASTAttributedStmt *astAttributedStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astAttributedStmt != nullptr, "astAttributedStmt is nullptr"); return astAttributedStmt; @@ -205,12 +215,13 @@ ASTStmt *ASTParser::ProcessStmtBinaryOperator(MapleAllocator &allocator, const c } ASTStmt *ASTParser::ProcessStmtCallExpr(MapleAllocator &allocator, const clang::CallExpr &callExpr) { - ASTCallExprStmt *astCallExprStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); - CHECK_FATAL(astCallExprStmt != nullptr, "astCallExprStmt is nullptr"); ASTExpr *astExpr = ProcessExpr(allocator, &callExpr); if (astExpr == nullptr) { return nullptr; } + ASTCallExprStmt *astCallExprStmt = + allocator.GetMemPool()->New(allocator, static_cast(astExpr)->GetRetVarName()); + CHECK_FATAL(astCallExprStmt != nullptr, "astCallExprStmt is nullptr"); astCallExprStmt->SetASTExpr(astExpr); return astCallExprStmt; } @@ -382,6 +393,7 @@ ASTStmt *ASTParser::ProcessStmtIfStmt(MapleAllocator &allocator, const clang::If ASTStmt *ASTParser::ProcessStmtForStmt(MapleAllocator &allocator, const clang::ForStmt &forStmt) { auto *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); + astStmt->SetEndLoc(astFile->GetLOC(forStmt.getEndLoc())); if (forStmt.getInit() != nullptr) { ASTStmt *initStmt = ProcessStmt(allocator, *forStmt.getInit()); if (initStmt == nullptr) { @@ -430,7 +442,14 @@ ASTStmt *ASTParser::ProcessStmtWhileStmt(MapleAllocator &allocator, const clang: ASTStmt *ASTParser::ProcessStmtGotoStmt(MapleAllocator &allocator, const clang::GotoStmt &gotoStmt) { ASTGotoStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); - astStmt->SetLabelName(gotoStmt.getLabel()->getStmt()->getName()); + std::string name; + if (gotoStmt.getLabel() != nullptr) { + ASTDecl *astDecl = ProcessDecl(allocator, *gotoStmt.getLabel()); + name = astDecl->GetName(); + } else { + name = gotoStmt.getLabel()->getStmt()->getName(); + } + astStmt->SetLabelName(name); return astStmt; } @@ -482,20 +501,24 @@ bool ASTParser::HasDefault(const clang::Stmt &stmt) { const auto *cpdStmt = llvm::cast(&stmt); clang::CompoundStmt::const_body_iterator it; for (it = cpdStmt->body_begin(); it != cpdStmt->body_end(); ++it) { - if (llvm::isa(*it)) { + const auto *bodyStmt = llvm::dyn_cast(*it); + if (bodyStmt == nullptr) { + continue; + } + if (HasDefault(*bodyStmt)) { return true; - } else if (llvm::isa(*it)) { - auto *caseStmt = llvm::cast(*it); - if (HasDefault(*caseStmt->getSubStmt())) { - return true; - } } } } else if (llvm::isa(stmt)) { const auto *caseStmt = llvm::cast(&stmt); - if (HasDefault(*caseStmt->getSubStmt())) { - return true; - } + if (HasDefault(*caseStmt->getSubStmt())) { + return true; + } + } else if (llvm::isa(stmt)) { + const auto *labelStmt = llvm::cast(&stmt); + if (HasDefault(*labelStmt->getSubStmt())) { + return true; + } } return false; } @@ -544,10 +567,28 @@ ASTStmt *ASTParser::ProcessStmtBreakStmt(MapleAllocator &allocator, const clang: ASTStmt *ASTParser::ProcessStmtLabelStmt(MapleAllocator &allocator, const clang::LabelStmt &stmt) { auto *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); + std::string name; ASTStmt *astSubStmt = ProcessStmt(allocator, *stmt.getSubStmt()); - std::string name(stmt.getName()); + if (stmt.getDecl() != nullptr) { + ASTDecl *astDecl = ProcessDecl(allocator, *stmt.getDecl()); + name = astDecl->GetName(); + } else { + name = stmt.getName(); + } astStmt->SetLabelName(name); astStmt->SetSubStmt(astSubStmt); + if (astSubStmt->GetExprs().size() != 0 && astSubStmt->GetExprs().back() != nullptr) { + astStmt->SetASTExpr(astSubStmt->GetExprs().back()); + } + return astStmt; +} + +ASTStmt *ASTParser::ProcessStmtAddrLabelExpr(MapleAllocator &allocator, const clang::AddrLabelExpr &expr) { + ASTUOAddrOfLabelExprStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); + CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); + ASTExpr *astExpr = ProcessExpr(allocator, &expr); + CHECK_FATAL(astExpr != nullptr, "astExpr is nullptr"); + astStmt->SetASTExpr(astExpr); return astStmt; } @@ -636,6 +677,27 @@ ASTStmt *ASTParser::ProcessStmtDeclStmt(MapleAllocator &allocator, const clang:: return astStmt; } +ASTStmt *ASTParser::ProcessStmtDeclRefExpr(MapleAllocator &allocator, const clang::DeclRefExpr &expr) { + ASTDeclRefExprStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); + ASTExpr *astExpr = ProcessExpr(allocator, &expr); + if (astExpr == nullptr) { + return nullptr; + } + astStmt->SetASTExpr(astExpr); + return astStmt; +} + +ASTStmt *ASTParser::ProcessStmtUnaryExprOrTypeTraitExpr(MapleAllocator &allocator, + const clang::UnaryExprOrTypeTraitExpr &expr) { + auto *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); + ASTExpr *astExpr = ProcessExpr(allocator, &expr); + if (astExpr == nullptr) { + return nullptr; + } + astStmt->SetASTExpr(astExpr); + return astStmt; +} + ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, const clang::Expr *expr) const { ASTValue *astValue = nullptr; clang::Expr::EvalResult result; @@ -684,6 +746,13 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, case PTY_i128: astValue->val.i64 = static_cast(result.Val.getInt().getSExtValue()); astValue->pty = PTY_i128; + static bool i128Warning = true; + if (i128Warning) { + WARN(kLncWarn, "%s:%d PTY_i128 is not fully supported", + FEManager::GetModule().GetFileNameFromFileNum(astFile->GetExprLOC(*expr).fileIdx).c_str(), + astFile->GetExprLOC(*expr).line); + i128Warning = false; + } break; case PTY_u8: astValue->val.u8 = static_cast(result.Val.getInt().getExtValue()); @@ -708,6 +777,13 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, case PTY_u128: astValue->val.u64 = static_cast(result.Val.getInt().getZExtValue()); astValue->pty = PTY_u128; + static bool u128Warning = true; + if (u128Warning) { + WARN(kLncWarn, "%s:%d PTY_u128 is not fully supported", + FEManager::GetModule().GetFileNameFromFileNum(astFile->GetExprLOC(*expr).fileIdx).c_str(), + astFile->GetExprLOC(*expr).line); + u128Warning = false; + } break; case PTY_u1: astValue->val.u8 = (result.Val.getInt().getExtValue() == 0 ? 0 : 1); @@ -731,7 +807,16 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, break; case llvm::APFloat::S_IEEEquad: case llvm::APFloat::S_PPCDoubleDouble: - case llvm::APFloat::S_x87DoubleExtended: + case llvm::APFloat::S_x87DoubleExtended: { + auto ty = expr->getType().getCanonicalType(); + static bool f128Warning = true; + if (f128Warning && (ty->isFloat128Type() || + (ty->isRealFloatingType() && astFile->GetAstContext()->getTypeSize(ty) == 128))) { + WARN(kLncWarn, "%s:%d PTY_f128 is not fully supported", + FEManager::GetModule().GetFileNameFromFileNum(astFile->GetExprLOC(*expr).fileIdx).c_str(), + astFile->GetExprLOC(*expr).line); + f128Warning = false; + } bool LosesInfo; if (constMirType->GetPrimType() == PTY_f64) { (void)fValue.convert(llvm::APFloat::IEEEdouble(), @@ -745,6 +830,7 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, astValue->val.f32 = fValue.convertToFloat(); } break; + } default: CHECK_FATAL(false, "unsupported semantics"); } @@ -783,6 +869,13 @@ ASTValue *ASTParser::TranslateLValue2ASTValue( const clang::StringLiteral &strExpr = llvm::cast(*lvExpr); std::string str = ""; if (strExpr.isWide() || strExpr.isUTF16() || strExpr.isUTF32()) { + static bool wcharWarning = true; + if (wcharWarning && strExpr.isWide()) { + WARN(kLncWarn, "%s:%d wchar is not fully supported", + FEManager::GetModule().GetFileNameFromFileNum(astFile->GetExprLOC(*lvExpr).fileIdx).c_str(), + astFile->GetExprLOC(*lvExpr).line); + wcharWarning = false; + } str = strExpr.getBytes().str(); } else { str = strExpr.getString().str(); @@ -837,8 +930,8 @@ ASTValue *ASTParser::TranslateExprEval(MapleAllocator &allocator, const clang::E if (expr->isConstantInitializer(*astFile->GetNonConstAstContext(), false, nullptr)) { \ astExpr->SetConstantValue(TranslateExprEval(allocator, expr)); \ } \ - Pos loc = astFile->GetExprLOC(*expr); \ - astExpr->SetSrcLOC(loc.first, loc.second); \ + Loc loc = astFile->GetExprLOC(*expr); \ + astExpr->SetSrcLoc(loc); \ return astExpr; \ } @@ -848,24 +941,36 @@ ASTExpr *ASTParser::EvaluateExprAsConst(MapleAllocator &allocator, const clang:: return nullptr; } + // Supplement SideEffects for EvaluateAsConstantExpr, + // If the expression contains a LabelStmt, the expression is unfoldable + // e.g. int x = 0 && ({ a : 1; }); goto a; + if (HasLabelStmt(expr)) { + return nullptr; + } + clang::APValue constVal = constResult.Val; if (constVal.isInt()) { - ASTIntegerLiteral *intExpr = allocator.New(); + ASTIntegerLiteral *intExpr = allocator.New(allocator); llvm::APSInt intVal = constVal.getInt(); intExpr->SetVal(intVal.getExtValue()); + if (intVal.getExtValue() == 0) { + intExpr->SetEvaluatedFlag(kEvaluatedAsZero); + } else { + intExpr->SetEvaluatedFlag(kEvaluatedAsNonZero); + } return intExpr; } else if (constVal.isFloat()) { - ASTFloatingLiteral *floatExpr = allocator.New(); + ASTFloatingLiteral *floatExpr = allocator.New(allocator); llvm::APFloat floatVal = constVal.getFloat(); const llvm::fltSemantics &fltSem = floatVal.getSemantics(); double val = 0; if (&fltSem == &llvm::APFloat::IEEEsingle()) { val = static_cast(floatVal.convertToFloat()); - floatExpr->SetKind(F32); + floatExpr->SetKind(FloatKind::F32); floatExpr->SetVal(val); } else if (&fltSem == &llvm::APFloat::IEEEdouble()) { val = static_cast(floatVal.convertToDouble()); - floatExpr->SetKind(F64); + floatExpr->SetKind(FloatKind::F64); floatExpr->SetVal(val); } else if (&fltSem == &llvm::APFloat::IEEEquad() || &fltSem == &llvm::APFloat::x87DoubleExtended()) { bool losesInfo; @@ -873,17 +978,36 @@ ASTExpr *ASTParser::EvaluateExprAsConst(MapleAllocator &allocator, const clang:: llvm::APFloatBase::rmNearestTiesToAway, &losesInfo); val = static_cast(floatVal.convertToDouble()); - floatExpr->SetKind(F64); + floatExpr->SetKind(FloatKind::F64); floatExpr->SetVal(val); } else { return nullptr; } + if (floatVal.isPosZero()) { + floatExpr->SetEvaluatedFlag(kEvaluatedAsZero); + } else { + floatExpr->SetEvaluatedFlag(kEvaluatedAsNonZero); + } return floatExpr; } - return nullptr; } +bool ASTParser::HasLabelStmt(const clang::Stmt *expr) { + if (expr->getStmtClass() == clang::Stmt::LabelStmtClass) { + return true; + } + for (const clang::Stmt *subStmt : expr->children()) { + if (subStmt == nullptr) { + continue; + } + if (HasLabelStmt(subStmt)) { + return true; + } + } + return false; +} + ASTExpr *ASTParser::ProcessExpr(MapleAllocator &allocator, const clang::Expr *expr) { if (expr == nullptr) { return nullptr; @@ -1063,6 +1187,10 @@ ASTExpr *ASTParser::ProcessExprUnaryOperator(MapleAllocator &allocator, const cl if (astExpr == nullptr) { return nullptr; } + // vla as a pointer is not need to be addrof + if (clangOpCode == clang::UO_AddrOf && subExpr->getType()->isVariableArrayType() ) { + return astExpr; + } astUOExpr->SetASTDecl(astExpr->GetASTDecl()); astUOExpr->SetUOExpr(astExpr); return astUOExpr; @@ -1071,8 +1199,9 @@ ASTExpr *ASTParser::ProcessExprUnaryOperator(MapleAllocator &allocator, const cl ASTExpr *ASTParser::ProcessExprAddrLabelExpr(MapleAllocator &allocator, const clang::AddrLabelExpr &expr) { ASTUOAddrOfLabelExpr *astAddrOfLabelExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); const clang::LabelDecl *lbDecl = expr.getLabel(); - std::string labelName = lbDecl->getName().str(); - astAddrOfLabelExpr->SetLabelName(labelName); + CHECK_NULL_FATAL(lbDecl); + ASTDecl *astDecl = ProcessDecl(allocator, *lbDecl); + astAddrOfLabelExpr->SetLabelName(astDecl->GetName()); astAddrOfLabelExpr->SetUOType(GlobalTables::GetTypeTable().GetPrimType(PTY_ptr)); return astAddrOfLabelExpr; } @@ -1135,20 +1264,10 @@ ASTExpr *ASTParser::ProcessExprCompoundLiteralExpr(MapleAllocator &allocator, CHECK_FATAL(initExpr != nullptr, "initExpr is nullptr"); clang::QualType qualType = initExpr->getType(); astCompoundLiteralExpr->SetCompoundLiteralType(astFile->CvtType(qualType)); - - const auto *initListExpr = llvm::dyn_cast(initExpr); - ASTExpr *astExpr = nullptr; - if (initListExpr != nullptr) { - astExpr = ProcessExpr(allocator, initListExpr); - } else { - astExpr = ProcessExpr(allocator, initExpr); - } + ASTExpr *astExpr = ProcessExpr(allocator, initExpr); if (astExpr == nullptr) { return nullptr; } - static uint32 unNamedCount = 0; - auto initListName = astFile->GetOrCreateCompoundLiteralExprInitName(unNamedCount++); - astCompoundLiteralExpr->SetInitName(initListName); astCompoundLiteralExpr->SetASTExpr(astExpr); return astCompoundLiteralExpr; } @@ -1165,6 +1284,7 @@ ASTExpr *ASTParser::ProcessExprInitListExpr(MapleAllocator &allocator, const cla } uint32 n = expr.getNumInits(); clang::Expr * const *le = expr.getInits(); + std::unordered_set evaluatedFlags; if (aggType->isRecordType()) { const auto *recordType = llvm::cast(aggType); clang::RecordDecl *recordDecl = recordType->getDecl(); @@ -1180,6 +1300,7 @@ ASTExpr *ASTParser::ProcessExprInitListExpr(MapleAllocator &allocator, const cla const clang::Expr *eExpr = le[i]; ASTExpr *astExpr = ProcessExpr(allocator, eExpr); CHECK_FATAL(astExpr != nullptr, "Invalid InitListExpr"); + evaluatedFlags.insert(astExpr->GetEvaluatedFlag()); astInitListExpr->SetInitExprs(astExpr); i++; } @@ -1207,9 +1328,15 @@ ASTExpr *ASTParser::ProcessExprInitListExpr(MapleAllocator &allocator, const cla if (astExpr == nullptr) { return nullptr; } + evaluatedFlags.insert(astExpr->GetEvaluatedFlag()); astInitListExpr->SetInitExprs(astExpr); } } + if (evaluatedFlags.count(kNotEvaluated) || evaluatedFlags.count(kEvaluatedAsNonZero)) { + astInitListExpr->SetEvaluatedFlag(kEvaluatedAsNonZero); + } else { + astInitListExpr->SetEvaluatedFlag(kEvaluatedAsZero); + } return astInitListExpr; } @@ -1236,6 +1363,7 @@ ASTExpr *ASTParser::ProcessExprOffsetOfExpr(MapleAllocator &allocator, const cla uint32 idx = comp.getArrayExprIndex(); auto idxExpr = expr.getIndexExpr(idx); auto leftExpr = ProcessExpr(allocator, idxExpr); + ASSERT(i >= 1, "arg should be nonnegative number"); auto arrayType = expr.getComponent(i - 1).getField()->getType(); auto elementType = llvm::cast(arrayType)->getElementType(); uint32 elementSize = GetSizeFromQualType(elementType); @@ -1303,6 +1431,7 @@ ASTExpr *ASTParser::ProcessExprImplicitValueInitExpr(MapleAllocator &allocator, auto *astImplicitValueInitExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); CHECK_FATAL(astImplicitValueInitExpr != nullptr, "astImplicitValueInitExpr is nullptr"); astImplicitValueInitExpr->SetType(astFile->CvtType(expr.getType())); + astImplicitValueInitExpr->SetEvaluatedFlag(kEvaluatedAsZero); return astImplicitValueInitExpr; } @@ -1311,11 +1440,14 @@ ASTExpr *ASTParser::ProcessExprStringLiteral(MapleAllocator &allocator, const cl CHECK_FATAL(astStringLiteral != nullptr, "astStringLiteral is nullptr"); astStringLiteral->SetType(astFile->CvtType(expr.getType())); astStringLiteral->SetLength(expr.getLength()); - std::vector codeUnits; + MapleVector codeUnits(allocator.Adapter()); for (size_t i = 0; i < expr.getLength(); ++i) { codeUnits.emplace_back(expr.getCodeUnit(i)); } astStringLiteral->SetCodeUnits(codeUnits); + if (expr.isAscii()) { + astStringLiteral->SetStr(expr.getString().str()); + } return astStringLiteral; } @@ -1337,10 +1469,10 @@ ASTExpr *ASTParser::ProcessExprArraySubscriptExpr(MapleAllocator &allocator, con astArraySubscriptExpr->SetArrayType(arrayMirType); clang::QualType exprType = expr.getType().getCanonicalType(); - if (llvm::isa(arrayQualType)) { - CHECK_FATAL(FEOptions::GetInstance().IsEnableVariableArray(), - "Intercepts variable arrays, because the backend does not yet support."); + if (arrayQualType->isVariablyModifiedType()) { astArraySubscriptExpr->SetIsVLA(true); + ASTExpr *vlaTypeSizeExpr = BuildExprToComputeSizeFromVLA(allocator, exprType); + astArraySubscriptExpr->SetVLASizeExpr(vlaTypeSizeExpr); } ASTExpr *astBaseExpr = ProcessExpr(allocator, base); astArraySubscriptExpr->SetBaseExpr(astBaseExpr); @@ -1430,6 +1562,24 @@ ASTExpr *ASTParser::GetAddrShiftExpr(MapleAllocator &allocator, ASTExpr *expr, u shiftExpr->SetOpcode(OP_mul); shiftExpr->SetRetType(retType); shiftExpr->SetCvtNeeded(true); + shiftExpr->SetSrcLoc(expr->GetSrcLoc()); + return shiftExpr; +} + +ASTExpr *ASTParser::GetSizeMulExpr(MapleAllocator &allocator, ASTExpr *expr, ASTExpr *ptrSizeExpr) { + MIRType *retType = nullptr; + if (IsSignedInteger(expr->GetType()->GetPrimType())) { + retType = GlobalTables::GetTypeTable().GetInt64(); + } else { + retType = GlobalTables::GetTypeTable().GetPtr(); + } + auto shiftExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + shiftExpr->SetLeftExpr(expr); + shiftExpr->SetRightExpr(ptrSizeExpr); + shiftExpr->SetOpcode(OP_mul); + shiftExpr->SetRetType(retType); + shiftExpr->SetCvtNeeded(true); + shiftExpr->SetSrcLoc(expr->GetSrcLoc()); return shiftExpr; } @@ -1459,6 +1609,7 @@ ASTExpr *ASTParser::BuildExprToComputeSizeFromVLA(MapleAllocator &allocator, con astBOExpr->SetOpcode(OP_mul); astBOExpr->SetLeftExpr(lhs); astBOExpr->SetRightExpr(rhs); + return astBOExpr; } uint32 size = GetSizeFromQualType(qualType); @@ -1668,8 +1819,12 @@ ASTExpr *ASTParser::ProcessExprCallExpr(MapleAllocator &allocator, const clang:: // return MIRType *retType = astFile->CvtType(expr.getCallReturnType(*astFile->GetAstContext())); astCallExpr->SetRetType(retType); + // return var attrs + GenericAttrs returnVarAttrs; + astFile->CollectFuncReturnVarAttrs(expr, returnVarAttrs); + astCallExpr->SetReturnVarAttrs(returnVarAttrs); // args - std::vector args; + MapleVector args(allocator.Adapter()); for (uint32_t i = 0; i < expr.getNumArgs(); ++i) { const clang::Expr *subExpr = expr.getArg(i); ASTExpr *arg = ProcessExpr(allocator, subExpr); @@ -1724,6 +1879,7 @@ ASTExpr *ASTParser::ProcessExprParenExpr(MapleAllocator &allocator, const clang: if (astExpr == nullptr) { return nullptr; } + astParenExpr->SetEvaluatedFlag(astExpr->GetEvaluatedFlag()); astParenExpr->SetASTExpr(astExpr); return astParenExpr; } @@ -1787,11 +1943,11 @@ ASTExpr *ASTParser::ProcessExprFloatingLiteral(MapleAllocator &allocator, const double val = 0; if (&fltSem == &llvm::APFloat::IEEEdouble()) { val = static_cast(apf.convertToDouble()); - astFloatingLiteral->SetKind(F64); + astFloatingLiteral->SetKind(FloatKind::F64); astFloatingLiteral->SetVal(val); } else if (&fltSem == &llvm::APFloat::IEEEsingle()) { val = static_cast(apf.convertToFloat()); - astFloatingLiteral->SetKind(F32); + astFloatingLiteral->SetKind(FloatKind::F32); astFloatingLiteral->SetVal(val); } else if (&fltSem == &llvm::APFloat::IEEEquad() || &fltSem == &llvm::APFloat::x87DoubleExtended()) { bool losesInfo; @@ -1799,7 +1955,7 @@ ASTExpr *ASTParser::ProcessExprFloatingLiteral(MapleAllocator &allocator, const llvm::APFloatBase::rmNearestTiesToAway, &losesInfo); val = static_cast(apf.convertToDouble()); - astFloatingLiteral->SetKind(F64); + astFloatingLiteral->SetKind(FloatKind::F64); astFloatingLiteral->SetVal(val); } else { CHECK_FATAL(false, "unsupported floating literal"); @@ -1820,12 +1976,16 @@ ASTExpr *ASTParser::ProcessExprCastExpr(MapleAllocator &allocator, const clang:: case clang::CK_ToVoid: case clang::CK_FunctionToPointerDecay: case clang::CK_LValueToRValue: + astCastExpr->SetRValue(true); break; case clang::CK_BitCast: astCastExpr->SetBitCast(true); break; case clang::CK_ArrayToPointerDecay: - astCastExpr->SetIsArrayToPointerDecay(true); + if (!(expr.getSubExpr()->getType()->isVariableArrayType() && + expr.getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass)) { + astCastExpr->SetIsArrayToPointerDecay(true); // vla as a pointer is not need to be addrof + } break; case clang::CK_BuiltinFnToFnPtr: astCastExpr->SetBuilinFunc(true); @@ -1883,6 +2043,8 @@ ASTExpr *ASTParser::ProcessExprCastExpr(MapleAllocator &allocator, const clang:: if (astExpr == nullptr) { return nullptr; } + astExpr->SetRValue(astCastExpr->IsRValue()); + astCastExpr->SetEvaluatedFlag(astExpr->GetEvaluatedFlag()); astCastExpr->SetASTExpr(astExpr); return astCastExpr; } @@ -1915,7 +2077,6 @@ ASTExpr *ASTParser::ProcessExprDeclRefExpr(MapleAllocator &allocator, const clan CHECK_FATAL(false, "NIY"); return nullptr; } - return nullptr; } ASTExpr *ASTParser::ProcessExprBinaryOperatorComplex(MapleAllocator &allocator, const clang::BinaryOperator &bo) { @@ -1960,6 +2121,8 @@ ASTExpr *ASTParser::ProcessExprBinaryOperator(MapleAllocator &allocator, const c astBinOpExpr->SetRetType(astFile->CvtType(boType)); if (bo.isCompoundAssignmentOp()) { clangOpCode = clang::BinaryOperator::getOpForCompoundAssignment(clangOpCode); + clang::QualType res = llvm::cast(bo).getComputationLHSType().getCanonicalType(); + astBinOpExpr->SetRetType(astFile->CvtType(res)); } if ((boType->isAnyComplexType() && (clang::BinaryOperator::isAdditiveOp(clangOpCode) || clang::BinaryOperator::isMultiplicativeOp(clangOpCode))) || @@ -1989,18 +2152,26 @@ ASTExpr *ASTParser::ProcessExprBinaryOperator(MapleAllocator &allocator, const c (lhsType->isIntegerType() && rhsType->isPointerType())) && !boType->isVoidPointerType() && GetSizeFromQualType(boType->getPointeeType()) != 1) { auto boMirType = astFile->CvtType(boType); - auto typeSize = GetSizeFromQualType(boType->getPointeeType()); - MIRType *pointedType = GlobalTables::GetTypeTable().GetTypeFromTyIdx( - static_cast(boMirType)->GetPointedTyIdx()); - if (pointedType->GetPrimType() == PTY_f64) { - typeSize = 8; // 8 is f64 byte num, because now f128 also cvt to f64 + auto ptrType = lhsType->isPointerType() ? lhsType : rhsType; + auto astSizeExpr = lhsType->isPointerType() ? astRExpr : astLExpr; + if (ptrType->getPointeeType()->isVariableArrayType()) { + ASTExpr *vlaTypeSizeExpr = BuildExprToComputeSizeFromVLA(allocator, ptrType->getPointeeType()); + astSizeExpr = GetSizeMulExpr(allocator, astSizeExpr, vlaTypeSizeExpr); + } else { + auto typeSize = GetSizeFromQualType(boType->getPointeeType()); + MIRType *pointedType = GlobalTables::GetTypeTable().GetTypeFromTyIdx( + static_cast(boMirType)->GetPointedTyIdx()); + if (pointedType->GetPrimType() == PTY_f64) { + typeSize = 8; // 8 is f64 byte num, because now f128 also cvt to f64 + } + astSizeExpr = GetAddrShiftExpr(allocator, astSizeExpr, typeSize); } + astBinOpExpr->SetCvtNeeded(false); // the type cannot be cvt. if (lhsType->isPointerType()) { - astRExpr = GetAddrShiftExpr(allocator, astRExpr, typeSize); - } else if (rhsType->isPointerType()) { - astLExpr = GetAddrShiftExpr(allocator, astLExpr, typeSize); + astRExpr = astSizeExpr; + } else { + astLExpr = astSizeExpr; } - astBinOpExpr->SetCvtNeeded(false); // the type cannot be cvt. } astBinOpExpr->SetLeftExpr(astLExpr); astBinOpExpr->SetRightExpr(astRExpr); @@ -2191,15 +2362,15 @@ bool ASTParser::PreProcessAST() { return true; } -#define DECL_CASE(CLASS) \ - case clang::Decl::CLASS: { \ +#define DECL_CASE(CLASS) \ + case clang::Decl::CLASS: { \ ASTDecl *astDeclaration = ProcessDecl##CLASS##Decl(allocator, llvm::cast(decl)); \ if (astDeclaration != nullptr) { \ astDeclaration->SetDeclPos(astFile->GetDeclPosInfo(decl)); \ astDeclaration->SetGlobal(decl.isDefinedOutsideFunctionOrMethod()); \ - Pos loc = astFile->GetLOC(decl.getLocation()); \ - astDeclaration->SetSrcLOC(loc.first, loc.second); \ - } \ + Loc loc = astFile->GetLOC(decl.getLocation()); \ + astDeclaration->SetSrcLoc(loc); \ + } \ return astDeclaration; \ } ASTDecl *ASTParser::ProcessDecl(MapleAllocator &allocator, const clang::Decl &decl) { @@ -2223,7 +2394,6 @@ ASTDecl *ASTParser::ProcessDecl(MapleAllocator &allocator, const clang::Decl &de CHECK_FATAL(false, "ASTDecl: %s NIY", decl.getDeclKindName()); return nullptr; } - return nullptr; } ASTDecl *ASTParser::ProcessDeclStaticAssertDecl(MapleAllocator &allocator, const clang::StaticAssertDecl &assertDecl) { @@ -2245,16 +2415,25 @@ ASTDecl *ASTParser::ProcessDeclRecordDecl(MapleAllocator &allocator, const clang return nullptr; } GenericAttrs attrs; - astFile->CollectAttrs(recDecl, attrs, kNone); + astFile->CollectRecordAttrs(recDecl, attrs); std::string structName = recName.str(); if (structName.empty() || !ASTUtil::IsValidName(structName)) { - uint32 id = qType->getAs()->getDecl()->getLocation().getRawEncoding(); - structName = astFile->GetOrCreateMappedUnnamedName(id); + structName = astFile->GetTypedefNameFromUnnamedStruct(recDecl); + if (structName.empty()) { + uint32 id = qType->getAs()->getDecl()->getLocation().getRawEncoding(); + structName = astFile->GetOrCreateMappedUnnamedName(id); + } } else if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - structName = structName + astFile->GetAstFileNameHashStr(); - } - curStructOrUnion = ASTDeclsBuilder::ASTStructBuilder( - allocator, fileName, structName, std::vector{recType}, attrs, recDecl.getID()); + std::string recordLayoutStr = recDecl.getDefinition() == nullptr ? "" : + ASTUtil::GetRecordLayoutString(astFile->GetContext()->getASTRecordLayout(recDecl.getDefinition())); + std::string filename = astFile->GetContext()->getSourceManager().getFilename(recDecl.getLocation()).str(); + structName = structName + FEUtils::GetFileNameHashStr(filename + recordLayoutStr); + } + curStructOrUnion = ASTDeclsBuilder::ASTStructBuilder(allocator, + fileName, + structName,MapleVector({recType}, allocator.Adapter()), + attrs, + recDecl.getID()); if (recDecl.isUnion()) { curStructOrUnion->SetIsUnion(); } @@ -2306,7 +2485,7 @@ ASTDecl *ASTParser::ProcessDeclFunctionDecl(MapleAllocator &allocator, const cla if (!ASTUtil::IsValidName(funcName)) { ASTUtil::AdjustName(funcName); } - std::vector typeDescIn; + MapleVector typeDescIn(allocator.Adapter()); clang::QualType funcQualType = funcDecl.getType(); MIRType *mirFuncType = astFile->CvtType(funcQualType); typeDescIn.push_back(mirFuncType); @@ -2315,7 +2494,7 @@ ASTDecl *ASTParser::ProcessDeclFunctionDecl(MapleAllocator &allocator, const cla if (retType == nullptr) { return nullptr; } - std::vector paramDecls; + MapleVector paramDecls(allocator.Adapter()); typeDescIn.push_back(retType); unsigned int numParam = funcDecl.getNumParams(); std::list implicitStmts; @@ -2372,9 +2551,9 @@ ASTDecl *ASTParser::ProcessDeclFunctionDecl(MapleAllocator &allocator, const cla return nullptr; } #ifndef STMTS_AS_BODY_SIZE - Pos startLoc = astFile->GetLOC(llvm::cast(funcDecl.getBody())->getBeginLoc()); - Pos endLoc = astFile->GetLOC(llvm::cast(funcDecl.getBody())->getEndLoc()); - astFunc->SetSize(static_cast(endLoc.second - startLoc.second)); + Loc startLoc = astFile->GetLOC(llvm::cast(funcDecl.getBody())->getBeginLoc()); + Loc endLoc = astFile->GetLOC(llvm::cast(funcDecl.getBody())->getEndLoc()); + astFunc->SetSize(static_cast(endLoc.line - startLoc.line)); #else astFunc->SetSize(static_cast(static_cast(astCompoundStmt)->GetASTStmtList().size())); #endif @@ -2433,13 +2612,14 @@ ASTDecl *ASTParser::ProcessDeclFieldDecl(MapleAllocator &allocator, const clang: fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(bfTypeIdx); } GenericAttrs attrs; - astFile->CollectAttrs(decl, attrs, kNone); + astFile->CollectFieldAttrs(decl, attrs, kNone); // one elem vector type if (LibAstFile::IsOneElementVector(qualType)) { attrs.SetAttr(GENATTR_oneelem_simd); } auto fieldDecl = ASTDeclsBuilder::ASTFieldBuilder( - allocator, fileName, fieldName, std::vector{fieldType}, attrs, decl.getID(), isAnonymousField); + allocator, fileName, fieldName, MapleVector({fieldType}, allocator.Adapter()), + attrs, decl.getID(), isAnonymousField); clang::CharUnits alignment = astFile->GetContext()->getDeclAlign(&decl); clang::CharUnits unadjust = astFile->GetContext()->toCharUnitsFromBits( astFile->GetContext()->getTypeUnadjustedAlign(qualType)); @@ -2447,7 +2627,7 @@ ASTDecl *ASTParser::ProcessDeclFieldDecl(MapleAllocator &allocator, const clang: fieldDecl->SetAlign(maxAlign); const auto *valueDecl = llvm::dyn_cast(&decl); if (valueDecl != nullptr) { - ProcessNonnullFuncPtrAttrs(*valueDecl, *fieldDecl); + ProcessNonnullFuncPtrAttrs(allocator, *valueDecl, *fieldDecl); ProcessBoundaryFuncPtrAttrs(allocator, *valueDecl, *fieldDecl); } return fieldDecl; @@ -2474,14 +2654,9 @@ ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::V varName = varName + astFile->GetAstFileNameHashStr(); } - if (llvm::isa(varDecl.getType())) { - CHECK_FATAL(FEOptions::GetInstance().IsEnableVariableArray(), - "Intercepts variable arrays, because the backend does not yet support."); - MIRType *elementType = static_cast(varType)->GetElemType(); - varType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*elementType); - } astVar = ASTDeclsBuilder::ASTVarBuilder( - allocator, fileName, varName, std::vector{varType}, attrs, varDecl.getID()); + allocator, fileName, varName, MapleVector({varType}, allocator.Adapter()), attrs, varDecl.getID()); + astVar->SetIsMacro(varDecl.getLocation().isMacroID()); clang::SectionAttr *sa = varDecl.getAttr(); if (sa != nullptr && !sa->isImplicit()) { astVar->SetSectionAttr(sa->getName().str()); @@ -2491,18 +2666,26 @@ ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::V astVar->SetAsmAttr(ala->getLabel().str()); } if (varDecl.hasInit()) { + bool isStaticStorageVar = (varDecl.getStorageDuration() == clang::SD_Static || attrs.GetAttr(GENATTR_tls_static)); astVar->SetDeclPos(astFile->GetDeclPosInfo(varDecl)); auto initExpr = varDecl.getInit(); auto astInitExpr = ProcessExpr(allocator, initExpr); if (initExpr->getStmtClass() == clang::Stmt::InitListExprClass && astInitExpr->GetASTOp() == kASTOpInitListExpr) { static_cast(astInitExpr)->SetInitListVarName(astVar->GenerateUniqueVarName()); } - astVar->SetInitExpr(astInitExpr); + EvaluatedFlag flag = astInitExpr->GetEvaluatedFlag(); + // For thoese global and static local variables initialized with zero or the init list only + // has zero, they won't be set initExpr and will be stored into .bss section instead of .data section + // to reduce code size. However, when passing '-npe-check-dynamic', initExpr should be always set otherwise + // '-npe-check-dynamic' cannot work as expected. + if (FEOptions::GetInstance().IsNpeCheckDynamic() || !isStaticStorageVar || flag != kEvaluatedAsZero) { + astVar->SetInitExpr(astInitExpr); + } else { + astVar->SetAttr(GENATTR_static_init_zero); // used to distinguish with uninitialized vars + } } - if (llvm::isa(varDecl.getType())) { - CHECK_FATAL(FEOptions::GetInstance().IsEnableVariableArray(), - "Intercepts variable arrays, because the backend does not yet support."); - astVar->SetVariableArrayExpr(GetTypeSizeFromQualType(allocator, varDecl.getType())); + if (llvm::isa(qualType.getCanonicalType())) { + astVar->SetVariableArrayExpr(BuildExprToComputeSizeFromVLA(allocator, qualType.getCanonicalType())); } if (!varDecl.getType()->isIncompleteType()) { int64 naturalAlignment = astFile->GetContext()->toCharUnitsFromBits( @@ -2526,7 +2709,7 @@ ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::V } const auto *valueDecl = llvm::dyn_cast(&varDecl); if (valueDecl != nullptr) { - ProcessNonnullFuncPtrAttrs(*valueDecl, *astVar); + ProcessNonnullFuncPtrAttrs(allocator, *valueDecl, *astVar); ProcessBoundaryFuncPtrAttrs(allocator, *valueDecl, *astVar); } ProcessBoundaryVarAttrs(allocator, varDecl, *astVar); @@ -2547,24 +2730,40 @@ ASTDecl *ASTParser::ProcessDeclParmVarDecl(MapleAllocator &allocator, const clan if (paramType == nullptr) { return nullptr; } + // C99 6.5.2.2. + // If the expression that denotes the called function has a type + // that does not include a prototype, the integer promotions are + // performed on each argument, and arguments that have type float + // are promoted to double. + PrimType promotedType = PTY_void; + if (parmVarDecl.isKNRPromoted()) { + promotedType = paramType->GetPrimType(); + paramType = FEUtils::IsInteger(paramType->GetPrimType()) ? + GlobalTables::GetTypeTable().GetInt32() : GlobalTables::GetTypeTable().GetDouble(); + } GenericAttrs attrs; astFile->CollectAttrs(parmVarDecl, attrs, kNone); if (LibAstFile::IsOneElementVector(parmQualType)) { attrs.SetAttr(GENATTR_oneelem_simd); } - parmVar = ASTDeclsBuilder::ASTVarBuilder( - allocator, fileName, parmName, std::vector{paramType}, attrs, parmVarDecl.getID()); + parmVar = ASTDeclsBuilder::ASTVarBuilder(allocator, + fileName, + parmName, + MapleVector({paramType}, allocator.Adapter()), + attrs, + parmVarDecl.getID()); parmVar->SetIsParam(true); + parmVar->SetPromotedType(promotedType); const auto *valueDecl = llvm::dyn_cast(&parmVarDecl); if (valueDecl != nullptr) { - ProcessNonnullFuncPtrAttrs(*valueDecl, *parmVar); + ProcessNonnullFuncPtrAttrs(allocator, *valueDecl, *parmVar); ProcessBoundaryFuncPtrAttrs(allocator, *valueDecl, *parmVar); } return parmVar; } ASTDecl *ASTParser::ProcessDeclFileScopeAsmDecl(MapleAllocator &allocator, const clang::FileScopeAsmDecl &asmDecl) { - ASTFileScopeAsm *astAsmDecl = allocator.GetMemPool()->New(fileName); + ASTFileScopeAsm *astAsmDecl = allocator.GetMemPool()->New(allocator, fileName); astAsmDecl->SetAsmStr(asmDecl.getAsmString()->getString().str()); return astAsmDecl; } @@ -2578,7 +2777,7 @@ ASTDecl *ASTParser::ProcessDeclEnumDecl(MapleAllocator &allocator, const clang:: astFile->CollectAttrs(*clang::dyn_cast(&enumDecl), attrs, kNone); const std::string &enumName = clang::dyn_cast(&enumDecl)->getNameAsString(); localEnumDecl = ASTDeclsBuilder::ASTLocalEnumDeclBuilder(allocator, fileName, enumName, - std::vector{}, attrs, enumDecl.getID()); + MapleVector({}, allocator.Adapter()), attrs, enumDecl.getID()); TraverseDecl(&enumDecl, [&](clang::Decl *child) { CHECK_FATAL(child->getKind() == clang::Decl::EnumConstant, "Unsupported decl kind: %u", child->getKind()); localEnumDecl->PushConstant(static_cast(ProcessDecl(allocator, *child))); @@ -2609,17 +2808,25 @@ ASTDecl *ASTParser::ProcessDeclEnumConstantDecl(MapleAllocator &allocator, const astFile->CollectAttrs(*clang::dyn_cast(&decl), attrs, kNone); const std::string &varName = clang::dyn_cast(&decl)->getNameAsString(); MIRType *mirType = astFile->CvtType(clang::dyn_cast(&decl)->getType()); + CHECK_NULL_FATAL(mirType); astConst = ASTDeclsBuilder::ASTEnumConstBuilder( - allocator, fileName, varName, std::vector{mirType}, attrs, decl.getID()); + allocator, fileName, varName, MapleVector({mirType}, allocator.Adapter()), attrs, decl.getID()); astConst->SetValue(static_cast(clang::dyn_cast(&decl)->getInitVal().getExtValue())); return astConst; } ASTDecl *ASTParser::ProcessDeclLabelDecl(MapleAllocator &allocator, const clang::LabelDecl &decl) { - (void)allocator; - (void)decl; - return nullptr; + ASTDecl *astDecl= static_cast(ASTDeclsBuilder::GetASTDecl(decl.getID())); + if (astDecl != nullptr) { + return astDecl; + } + std::string varName = astFile->GetMangledName(decl); + CHECK_FATAL(!varName.empty(), "label string is null"); + varName = FEUtils::GetSequentialName0(varName + "@", FEUtils::GetSequentialNumber()); + MapleVector typeDescVec(allocator.Adapter()); + astDecl = ASTDeclsBuilder::ASTDeclBuilder(allocator, fileName, varName, typeDescVec, decl.getID()); + return astDecl; } bool ASTParser::RetrieveStructs(MapleAllocator &allocator) { @@ -2650,15 +2857,16 @@ bool ASTParser::RetrieveStructs(MapleAllocator &allocator) { bool ASTParser::RetrieveFuncs(MapleAllocator &allocator) { for (auto &func : funcDecles) { clang::FunctionDecl *funcDecl = llvm::cast(func); + CHECK_NULL_FATAL(funcDecl); if (funcDecl->isDefined()) { clang::SafeScopeSpecifier spec = funcDecl->getSafeSpecifier(); funcDecl = funcDecl->getDefinition(); if (funcDecl->getSafeSpecifier() != spec) { if (funcDecl->getSafeSpecifier() != clang::SS_None && spec != clang::SS_None) { std::string funcName = astFile->GetMangledName(*funcDecl); - Pos loc = astFile->GetLOC(funcDecl->getLocation()); + Loc loc = astFile->GetLOC(funcDecl->getLocation()); FE_ERR(kLncWarn, "%s:%d error: The function %s declaration and definition security attributes " - "are inconsistent.", FEManager::GetModule().GetFileNameFromFileNum(loc.first).c_str(), loc.second, + "are inconsistent.", FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, funcName.c_str()); } else { if (funcDecl->getSafeSpecifier() == clang::SS_None) { @@ -2709,8 +2917,8 @@ bool ASTParser::ProcessGlobalTypeDef(MapleAllocator &allocator) { return true; } -const std::string &ASTParser::GetSourceFileName() const { - return fileName; +const std::string ASTParser::GetSourceFileName() const { + return fileName.c_str() == nullptr ? "" : fileName.c_str(); } const uint32 ASTParser::GetFileIdx() const { diff --git a/src/hir2mpl/ast_input/clang/src/ast_parser_builting_func.cpp b/src/hir2mpl/ast_input/clang/src/ast_parser_builting_func.cpp index 930f628624a592a5d76333c7e35c13ba1cc1ef93..718ebb6096f9a4144b4cd5b11a225185af6d3536 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_parser_builting_func.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_parser_builting_func.cpp @@ -56,7 +56,6 @@ UniqueFEIRExpr ASTCallExpr::CreateIntrinsicopForC(std::list &stm std::list feExprs; feExprs.emplace_back(std::move(feExpr)); UniqueFEIRStmt evalStmt = std::make_unique(OP_eval, std::move(feExprs)); - evalStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(evalStmt)); return nullptr; } else { @@ -66,13 +65,32 @@ UniqueFEIRExpr ASTCallExpr::CreateIntrinsicopForC(std::list &stm std::string tmpName = FEUtils::GetSequentialName("intrinsicop_var_"); UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, *mirType); UniqueFEIRStmt dAssign = std::make_unique(tmpVar->Clone(), std::move(feExpr), 0); - dAssign->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(dAssign)); auto dread = FEIRBuilder::CreateExprDRead(tmpVar->Clone()); return dread; } } +UniqueFEIRExpr ASTCallExpr::CreateIntrinsicCallAssignedForC(std::list &stmts, + MIRIntrinsicID argIntrinsicID) const { + std::unique_ptr> argExprList = std::make_unique>(); + for (auto arg : args) { + argExprList->emplace_back(arg->Emit2FEExpr(stmts)); + } + if (!IsNeedRetExpr()) { + auto stmt = std::make_unique(argIntrinsicID, nullptr, nullptr, + std::move(argExprList)); + stmts.emplace_back(std::move(stmt)); + return nullptr; + } + UniqueFEIRVar retVar = FEIRBuilder::CreateVarNameForC(GetRetVarName(), *retType, false); + auto stmt = std::make_unique(argIntrinsicID, nullptr, retVar->Clone(), + std::move(argExprList)); + stmts.emplace_back(std::move(stmt)); + UniqueFEIRExpr dread = FEIRBuilder::CreateExprDRead(std::move(retVar)); + return dread; +} + UniqueFEIRExpr ASTCallExpr::CreateBinaryExpr(std::list &stmts, Opcode op) const { auto feTy = std::make_unique(*mirType); auto arg1 = args[0]->Emit2FEExpr(stmts); @@ -83,7 +101,7 @@ UniqueFEIRExpr ASTCallExpr::CreateBinaryExpr(std::list &stmts, O UniqueFEIRExpr ASTCallExpr::ProcessBuiltinFunc(std::list &stmts, bool &isFinish) const { // process a kind of builtinFunc std::string prefix = "__builtin_mpl_vector_load"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { auto argExpr = args[0]->Emit2FEExpr(stmts); UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*mirType); UniqueFEIRType ptrType = FEIRTypeHelper::CreateTypeNative( @@ -92,23 +110,22 @@ UniqueFEIRExpr ASTCallExpr::ProcessBuiltinFunc(std::list &stmts, return FEIRBuilder::CreateExprIRead(std::move(type), std::move(ptrType), std::move(argExpr)); } prefix = "__builtin_mpl_vector_store"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { auto arg1Expr = args[0]->Emit2FEExpr(stmts); auto arg2Expr = args[1]->Emit2FEExpr(stmts); UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative( *GlobalTables::GetTypeTable().GetOrCreatePointerType(*args[1]->GetType())); auto stmt = FEIRBuilder::CreateStmtIAssign(std::move(type), std::move(arg1Expr), std::move(arg2Expr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); isFinish = true; return nullptr; } prefix = "__builtin_mpl_vector_zip"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { return EmitBuiltinVectorZip(stmts, isFinish); } prefix = "__builtin_mpl_vector_shli"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { isFinish = true; UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); auto arg1Expr = args[0]->Emit2FEExpr(stmts); @@ -116,7 +133,7 @@ UniqueFEIRExpr ASTCallExpr::ProcessBuiltinFunc(std::list &stmts, return FEIRBuilder::CreateExprBinary(std::move(type), OP_shl, std::move(arg1Expr), std::move(arg2Expr)); } prefix = "__builtin_mpl_vector_shri"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { isFinish = true; UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); auto arg1Expr = args[0]->Emit2FEExpr(stmts); @@ -124,7 +141,7 @@ UniqueFEIRExpr ASTCallExpr::ProcessBuiltinFunc(std::list &stmts, return FEIRBuilder::CreateExprBinary(std::move(type), OP_ashr, std::move(arg1Expr), std::move(arg2Expr)); } prefix = "__builtin_mpl_vector_shru"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { isFinish = true; UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); auto arg1Expr = args[0]->Emit2FEExpr(stmts); @@ -132,7 +149,7 @@ UniqueFEIRExpr ASTCallExpr::ProcessBuiltinFunc(std::list &stmts, return FEIRBuilder::CreateExprBinary(std::move(type), OP_lshr, std::move(arg1Expr), std::move(arg2Expr)); } // process a single builtinFunc - auto ptrFunc = builtingFuncPtrMap.find(funcName); + auto ptrFunc = builtingFuncPtrMap.find(GetFuncName()); if (ptrFunc != builtingFuncPtrMap.end()) { isFinish = true; return EmitBuiltinFunc(stmts); @@ -140,17 +157,17 @@ UniqueFEIRExpr ASTCallExpr::ProcessBuiltinFunc(std::list &stmts, isFinish = false; if (FEOptions::GetInstance().GetDumpLevel() >= FEOptions::kDumpLevelInfo) { prefix = "__builtin"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { FE_INFO_LEVEL(FEOptions::kDumpLevelInfo, "%s:%d BuiltinFunc (%s) has not been implemented", FEManager::GetModule().GetFileNameFromFileNum(GetSrcFileIdx()).c_str(), GetSrcFileLineNum(), - funcName.c_str()); + GetFuncName().c_str()); } } return nullptr; } UniqueFEIRExpr ASTCallExpr::EmitBuiltinFunc(std::list &stmts) const { - return (this->*(builtingFuncPtrMap[funcName]))(stmts); + return (this->*(builtingFuncPtrMap[GetFuncName()]))(stmts); } #define DEF_MIR_INTRINSIC(STR, NAME, INTRN_CLASS, RETURN_TYPE, ...) \ @@ -176,7 +193,7 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorZip(std::list &stmt UniqueFEIRVar retVar = FEIRBuilder::CreateVarNameForC(retName, *retType); #define VECTOR_INTRINSICCALL_TYPE(OP_NAME, VECTY) \ - if (FEUtils::EndsWith(funcName, #VECTY)) { \ + if (FEUtils::EndsWith(GetFuncName(), #VECTY)) { \ stmt = std::make_unique( \ INTRN_vector_##OP_NAME##_##VECTY, nullptr, retVar->Clone(), std::move(argExprList)); \ } @@ -190,7 +207,6 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorZip(std::list &stmt else VECTOR_INTRINSICCALL_TYPE(zip, v8u8) else VECTOR_INTRINSICCALL_TYPE(zip, v2f32) - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); isFinish = true; return FEIRBuilder::CreateExprDRead(std::move(retVar)); @@ -207,7 +223,6 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinVaStart(std::list &stmts) exprArgList->front()->SetAddrof(true); std::unique_ptr stmt = std::make_unique( INTRN_C_va_start, nullptr /* type */, nullptr /* retVar */, std::move(exprArgList)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); return nullptr; } @@ -223,7 +238,6 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinVaEnd(std::list &stmts) c exprArgList.emplace_back(std::move(expr)); } auto stmt = std::make_unique(OP_eval, std::move(exprArgList)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); return nullptr; } @@ -246,7 +260,6 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinVaCopy(std::list &stmts) exprArgList->emplace_back(std::move(sizeExpr)); std::unique_ptr stmt = std::make_unique( INTRN_C_memcpy, nullptr /* type */, nullptr /* retVar */, std::move(exprArgList)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); return nullptr; } @@ -336,83 +349,267 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinAlignDown(std::list &stmt } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAddAndFetch8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_add_and_fetch_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_add_and_fetch_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAddAndFetch4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_add_and_fetch_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_add_and_fetch_4); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAddAndFetch2(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_add_and_fetch_2); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_add_and_fetch_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAddAndFetch1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_add_and_fetch_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncSubAndFetch8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_sub_and_fetch_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_sub_and_fetch_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncSubAndFetch4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_sub_and_fetch_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_sub_and_fetch_4); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncSubAndFetch2(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_sub_and_fetch_2); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_sub_and_fetch_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncSubAndFetch1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_sub_and_fetch_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndSub8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_fetch_and_sub_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_sub_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndSub4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_fetch_and_sub_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_sub_4); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndSub2(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_fetch_and_sub_2); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_sub_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndSub1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_sub_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAdd8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_fetch_and_add_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_add_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAdd4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_fetch_and_add_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_add_4); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAdd2(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_fetch_and_add_2); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_add_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAdd1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_add_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncValCompareAndSwap8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_val_compare_and_swap_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_val_compare_and_swap_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncValCompareAndSwap4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_val_compare_and_swap_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_val_compare_and_swap_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncValCompareAndSwap2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_val_compare_and_swap_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncValCompareAndSwap1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_val_compare_and_swap_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockRelease8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_lock_release_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_release_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockRelease4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_lock_release_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_release_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockRelease2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_release_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockRelease1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_release_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_bool_compare_and_swap_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_bool_compare_and_swap_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_bool_compare_and_swap_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_bool_compare_and_swap_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_bool_compare_and_swap_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncBoolCompareAndSwap1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_bool_compare_and_swap_1); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockTestAndSet8(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_lock_test_and_set_8); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_test_and_set_8); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockTestAndSet4(std::list &stmts) const { - return CreateIntrinsicopForC(stmts, INTRN_C___sync_lock_test_and_set_4); + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_test_and_set_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockTestAndSet2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_test_and_set_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncLockTestAndSet1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_lock_test_and_set_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAnd1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_and_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAnd2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_and_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAnd4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_and_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndAnd8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_and_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndOr1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_or_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndOr2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_or_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndOr4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_or_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndOr8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_or_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndXor1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_xor_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndXor2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_xor_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndXor4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_xor_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndXor8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_xor_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndNand1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_nand_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndNand2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_nand_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndNand4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_nand_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncFetchAndNand8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_fetch_and_nand_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAndAndFetch1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_and_and_fetch_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAndAndFetch2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_and_and_fetch_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAndAndFetch4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_and_and_fetch_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncAndAndFetch8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_and_and_fetch_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncOrAndFetch1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_or_and_fetch_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncOrAndFetch2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_or_and_fetch_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncOrAndFetch4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_or_and_fetch_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncOrAndFetch8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_or_and_fetch_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncXorAndFetch1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_xor_and_fetch_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncXorAndFetch2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_xor_and_fetch_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncXorAndFetch4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_xor_and_fetch_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncXorAndFetch8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_xor_and_fetch_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncNandAndFetch1(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_nand_and_fetch_1); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncNandAndFetch2(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_nand_and_fetch_2); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncNandAndFetch4(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_nand_and_fetch_4); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncNandAndFetch8(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_nand_and_fetch_8); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinSyncSynchronize(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___sync_synchronize); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinAtomicExchangeN(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___atomic_exchange_n); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinReturnAddress(std::list &stmts) const { @@ -435,14 +632,6 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinExpect(std::list &stmts) return CreateIntrinsicopForC(stmts, INTRN_C___builtin_expect, false); } -UniqueFEIRExpr ASTCallExpr::EmitBuiltinUnreachable(std::list &stmts) const { - UniqueFEIRExpr feExpr = nullptr; - UniqueFEIRStmt stmt = std::make_unique(std::move(feExpr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); - stmts.emplace_back(std::move(stmt)); - return nullptr; -} - UniqueFEIRExpr ASTCallExpr::EmitBuiltinAbs(std::list &stmts) const { auto arg = args[0]->Emit2FEExpr(stmts); CHECK_NULL_FATAL(mirType); @@ -690,7 +879,6 @@ ASTExpr *ASTParser::ParseBuiltinSignbit(MapleAllocator &allocator, const clang:: ASTExpr *ASTParser::ParseBuiltinIsinfsign(MapleAllocator &allocator, const clang::CallExpr &expr, std::stringstream &ss) const { (void)allocator; - (void)expr; ss.clear(); ss.str(std::string()); if (astFile->CvtType(expr.getArg(0)->getType())->GetPrimType() == PTY_f64) { @@ -708,7 +896,7 @@ ASTExpr *ASTParser::ParseBuiltinHugeVal(MapleAllocator &allocator, const clang:: (void)expr; (void)ss; ASTFloatingLiteral *astFloatingLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astFloatingLiteral->SetKind(F64); + astFloatingLiteral->SetKind(FloatKind::F64); astFloatingLiteral->SetVal(std::numeric_limits::infinity()); return astFloatingLiteral; } @@ -718,7 +906,7 @@ ASTExpr *ASTParser::ParseBuiltinHugeValf(MapleAllocator &allocator, const clang: (void)expr; (void)ss; ASTFloatingLiteral *astFloatingLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astFloatingLiteral->SetKind(F32); + astFloatingLiteral->SetKind(FloatKind::F32); astFloatingLiteral->SetVal(std::numeric_limits::infinity()); return astFloatingLiteral; } @@ -728,7 +916,7 @@ ASTExpr *ASTParser::ParseBuiltinInf(MapleAllocator &allocator, const clang::Call (void)expr; (void)ss; ASTFloatingLiteral *astFloatingLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astFloatingLiteral->SetKind(F64); + astFloatingLiteral->SetKind(FloatKind::F64); astFloatingLiteral->SetVal(std::numeric_limits::infinity()); return astFloatingLiteral; } @@ -738,7 +926,7 @@ ASTExpr *ASTParser::ParseBuiltinInff(MapleAllocator &allocator, const clang::Cal (void)expr; (void)ss; ASTFloatingLiteral *astFloatingLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astFloatingLiteral->SetKind(F32); + astFloatingLiteral->SetKind(FloatKind::F32); astFloatingLiteral->SetVal(std::numeric_limits::infinity()); return astFloatingLiteral; } @@ -748,7 +936,7 @@ ASTExpr *ASTParser::ParseBuiltinNan(MapleAllocator &allocator, const clang::Call (void)expr; (void)ss; ASTFloatingLiteral *astFloatingLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astFloatingLiteral->SetKind(F64); + astFloatingLiteral->SetKind(FloatKind::F64); astFloatingLiteral->SetVal(nan("")); return astFloatingLiteral; } @@ -758,7 +946,7 @@ ASTExpr *ASTParser::ParseBuiltinNanf(MapleAllocator &allocator, const clang::Cal (void)expr; (void)ss; ASTFloatingLiteral *astFloatingLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astFloatingLiteral->SetKind(F32); + astFloatingLiteral->SetKind(FloatKind::F32); astFloatingLiteral->SetVal(nanf("")); return astFloatingLiteral; } diff --git a/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp b/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp index 4184cc0e7379fb4c0a807c3feee68ee724f28c71..3357d70bf0029b8514f35d61f21e0ca4c6b988c7 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp @@ -48,7 +48,7 @@ void ASTCompoundStmt::InsertASTStmtsAtFront(const std::list &stmts) { astStmts.insert(astStmts.begin(), stmts.begin(), stmts.end()); } -const std::list &ASTCompoundStmt::GetASTStmtList() const { +const MapleList &ASTCompoundStmt::GetASTStmtList() const { return astStmts; } @@ -58,16 +58,36 @@ std::list ASTCompoundStmt::Emit2FEStmtImpl() const { if (!FEOptions::GetInstance().IsEnableSafeRegion()) { return; } - if (safeSS == kSafeSS) { - stmts.emplace_back(std::make_unique(flag)); - } else if (safeSS == kUnsafeSS) { - stmts.emplace_back(std::make_unique(flag)); + UniqueFEIRStmt stmt; + if (safeSS == SafeSS::kSafeSS) { + stmt = std::make_unique(flag); + } else if (safeSS == SafeSS::kUnsafeSS) { + stmt = std::make_unique(flag); + } + if (stmt != nullptr) { + if (flag) { + stmt->SetSrcLoc(endLoc); + } + stmts.emplace_back(std::move(stmt)); } }; insertStmt(false); + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + if (!hasEmitted2MIRScope) { + feFunction.PushStmtScope(GetSrcLoc().Emit2SourcePosition(), GetEndLoc().Emit2SourcePosition()); + } for (auto it : astStmts) { stmts.splice(stmts.end(), it->Emit2FEStmt()); } + if (!hasEmitted2MIRScope) { + UniqueFEIRScope scope = feFunction.PopTopStmtScope(); + if (scope->GetVLASavedStackVar() != nullptr) { + auto stackRestoreStmt = scope->GenVLAStackRestoreStmt(); + stackRestoreStmt->SetSrcLoc(endLoc); + stmts.emplace_back(std::move(stackRestoreStmt)); + } + hasEmitted2MIRScope = true; + } insertStmt(true); return stmts; } @@ -81,7 +101,7 @@ std::list ASTReturnStmt::Emit2FEStmtImpl() const { return stmts; } UniqueFEIRStmt stmt = std::make_unique(std::move(feExpr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); return stmts; } @@ -101,7 +121,7 @@ std::list ASTIfStmt::Emit2FEStmtImpl() const { condFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(condFEExpr)); UniqueFEIRStmt ifStmt; ifStmt = FEIRBuilder::CreateStmtIf(std::move(condFEExpr), thenStmts, elseStmts); - ifStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + ifStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(ifStmt)); return stmts; } @@ -114,6 +134,10 @@ std::list ASTForStmt::Emit2FEStmtImpl() const { AstLoopUtil::Instance().PushBreak(loopEndLabelName); auto labelBodyEndStmt = std::make_unique(loopBodyEndLabelName); auto labelLoopEndStmt = std::make_unique(loopEndLabelName); + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + if (!hasEmitted2MIRScope) { + feFunction.PushStmtScope(GetSrcLoc().Emit2SourcePosition(), GetEndLoc().Emit2SourcePosition()); + } if (initStmt != nullptr) { std::list feStmts = initStmt->Emit2FEStmt(); stmts.splice(stmts.cend(), feStmts); @@ -143,11 +167,20 @@ std::list ASTForStmt::Emit2FEStmtImpl() const { } condFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(condFEExpr)); UniqueFEIRStmt whileStmt = std::make_unique(OP_while, std::move(condFEExpr), std::move(bodyFEStmts)); - whileStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + whileStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(whileStmt)); if (AstLoopUtil::Instance().IsCurrentBreakLabelUsed()) { stmts.emplace_back(std::move(labelLoopEndStmt)); } + if (!hasEmitted2MIRScope) { + UniqueFEIRScope scope = feFunction.PopTopStmtScope(); + if (scope->GetVLASavedStackVar() != nullptr) { + auto stackRestoreStmt = scope->GenVLAStackRestoreStmt(); + stackRestoreStmt->SetSrcLoc(endLoc); + stmts.emplace_back(std::move(stackRestoreStmt)); + } + hasEmitted2MIRScope = true; + } AstLoopUtil::Instance().PopCurrentBreak(); AstLoopUtil::Instance().PopCurrentContinue(); return stmts; @@ -172,7 +205,7 @@ std::list ASTWhileStmt::Emit2FEStmtImpl() const { bodyFEStmts.splice(bodyFEStmts.end(), condPreStmts); condFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(condFEExpr)); auto whileStmt = std::make_unique(OP_while, std::move(condFEExpr), std::move(bodyFEStmts)); - whileStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + whileStmt->SetSrcLoc(loc); stmts.splice(stmts.end(), condStmts); stmts.emplace_back(std::move(whileStmt)); if (AstLoopUtil::Instance().IsCurrentBreakLabelUsed()) { @@ -204,7 +237,7 @@ std::list ASTDoStmt::Emit2FEStmtImpl() const { condFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(condFEExpr)); UniqueFEIRStmt whileStmt = std::make_unique(OP_dowhile, std::move(condFEExpr), std::move(bodyFEStmts)); - whileStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + whileStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(whileStmt)); if (AstLoopUtil::Instance().IsCurrentBreakLabelUsed()) { stmts.emplace_back(std::move(labelLoopEndStmt)); @@ -220,15 +253,15 @@ std::list ASTBreakStmt::Emit2FEStmtImpl() const { if (!AstLoopUtil::Instance().IsBreakLabelsEmpty()) { stmt->SetBreakLabelName(AstLoopUtil::Instance().GetCurrentBreak()); } - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); return stmts; } std::list ASTLabelStmt::Emit2FEStmtImpl() const { std::list stmts; - auto feStmt = std::make_unique(labelName); - feStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + auto feStmt = std::make_unique(GetLabelName()); + feStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(feStmt)); stmts.splice(stmts.end(), subStmt->Emit2FEStmt()); return stmts; @@ -237,7 +270,6 @@ std::list ASTLabelStmt::Emit2FEStmtImpl() const { std::list ASTContinueStmt::Emit2FEStmtImpl() const { std::list stmts; auto stmt = std::make_unique(); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmt->SetLabelName(AstLoopUtil::Instance().GetCurrentContinue()); stmts.emplace_back(std::move(stmt)); return stmts; @@ -255,7 +287,6 @@ std::list ASTUnaryOperatorStmt::Emit2FEStmtImpl() const { } feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -264,8 +295,7 @@ std::list ASTUnaryOperatorStmt::Emit2FEStmtImpl() const { // ---------- ASTGotoStmt ---------- std::list ASTGotoStmt::Emit2FEStmtImpl() const { std::list stmts; - UniqueFEIRStmt stmt = FEIRBuilder::CreateStmtGoto(labelName); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + UniqueFEIRStmt stmt = FEIRBuilder::CreateStmtGoto(GetLabelName()); stmts.emplace_back(std::move(stmt)); return stmts; } @@ -291,7 +321,6 @@ std::list ASTSwitchStmt::Emit2FEStmtImpl() const { auto dread = FEIRBuilder::CreateExprDRead(tmpVar->Clone()); auto switchStmt = std::make_unique(std::move(dread), hasDefualt); switchStmt->SetBreakLabelName(exitName); - switchStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); for (auto &s : bodyStmt->Emit2FEStmt()) { switchStmt.get()->AddFeirStmt(std::move(s)); } @@ -304,7 +333,6 @@ std::list ASTSwitchStmt::Emit2FEStmtImpl() const { std::list ASTCaseStmt::Emit2FEStmtImpl() const { std::list stmts; auto caseStmt = std::make_unique(lCaseTag); - caseStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); caseStmt.get()->AddCaseTag2CaseVec(lCaseTag, rCaseTag); for (auto &s : subStmt->Emit2FEStmt()) { caseStmt.get()->AddFeirStmt(std::move(s)); @@ -317,7 +345,6 @@ std::list ASTCaseStmt::Emit2FEStmtImpl() const { std::list ASTDefaultStmt::Emit2FEStmtImpl() const { std::list stmts; auto defaultStmt = std::make_unique(); - defaultStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); for (auto &s : child->Emit2FEStmt()) { defaultStmt.get()->AddFeirStmt(std::move(s)); } @@ -368,7 +395,6 @@ std::list ASTCallExprStmt::Emit2FEStmtImpl() const { } } std::unique_ptr callStmt = callExpr->GenCallStmt(); - callStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); callExpr->AddArgsExpr(callStmt, stmts); if (callExpr->IsNeedRetExpr()) { UniqueFEIRVar var = FEIRBuilder::CreateVarNameForC(varName, *callExpr->GetRetType(), false, false); @@ -387,7 +413,6 @@ std::list ASTImplicitCastExprStmt::Emit2FEStmtImpl() const { std::list feirExprs; feirExprs.emplace_back(std::move(feirExpr)); auto stmt = std::make_unique(OP_eval, std::move(feirExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -408,7 +433,6 @@ std::list ASTIntegerLiteralStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -422,7 +446,6 @@ std::list ASTFloatingLiteralStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -443,7 +466,6 @@ std::list ASTConditionalOperatorStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -457,7 +479,6 @@ std::list ASTCharacterLiteralStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -477,7 +498,6 @@ std::list ASTCStyleCastExprStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -502,7 +522,6 @@ std::list ASTBinaryOperatorStmt::Emit2FEStmtImpl() const { std::list exprs; exprs.emplace_back(std::move(boFEExpr)); auto stmt = std::make_unique(OP_eval, std::move(exprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } } else { @@ -519,7 +538,6 @@ std::list ASTAtomicExprStmt::Emit2FEStmtImpl() const { auto astExpr = exprs.front(); UniqueFEIRExpr feExpr = astExpr->Emit2FEExpr(stmts); auto stmt = std::make_unique(std::move(feExpr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); return stmts; } @@ -529,13 +547,15 @@ std::list ASTGCCAsmStmt::Emit2FEStmtImpl() const { std::list stmts; std::vector outputsExprs; std::vector inputsExprs; - std::unique_ptr stmt = std::make_unique(asmStr, isGoto, isVolatile); - stmt->SetOutputs(outputs); + std::unique_ptr stmt = std::make_unique(GetAsmStr(), isGoto, isVolatile); + std::vector> outputsVec(outputs.begin(), outputs.end()); + stmt->SetOutputs(outputsVec); for (uint32 i = 0; i < outputs.size(); ++i) { outputsExprs.emplace_back(exprs[i]->Emit2FEExpr(stmts)); } stmt->SetOutputsExpr(outputsExprs); - stmt->SetInputs(inputs); + std::vector> inputsVec(inputs.begin(), inputs.end()); + stmt->SetInputs(inputsVec); for (uint32 i = 0; i < inputs.size(); ++i) { UniqueFEIRExpr expr; if (inputs[i].second == "m") { @@ -548,8 +568,10 @@ std::list ASTGCCAsmStmt::Emit2FEStmtImpl() const { inputsExprs.emplace_back(std::move(expr)); } stmt->SetInputsExpr(inputsExprs); - stmt->SetClobbers(clobbers); - stmt->SetLabels(labels); + std::vector clobbersVec(clobbers.begin(), clobbers.end()); + stmt->SetClobbers(clobbersVec); + std::vector labelsVec(labels.begin(), labels.end()); + stmt->SetLabels(labelsVec); stmts.emplace_back(std::move(stmt)); return stmts; } @@ -562,7 +584,6 @@ std::list ASTOffsetOfStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); } return stmts; @@ -576,7 +597,36 @@ std::list ASTGenericSelectionExprStmt::Emit2FEStmtImpl() const { if (feExpr != nullptr) { feExprs.emplace_back(std::move(feExpr)); auto stmt = std::make_unique(OP_eval, std::move(feExprs)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmts.emplace_back(std::move(stmt)); + } + return stmts; +} + +std::list ASTDeclRefExprStmt::Emit2FEStmtImpl() const { + std::list stmts; + for (auto expr : exprs) { + (void)expr->Emit2FEExpr(stmts); + } + return stmts; +} + +std::list ASTUnaryExprOrTypeTraitExprStmt::Emit2FEStmtImpl() const { + std::list stmts; + for (auto expr : exprs) { + (void)expr->Emit2FEExpr(stmts); + } + return stmts; +} + +std::list ASTUOAddrOfLabelExprStmt::Emit2FEStmtImpl() const { + CHECK_FATAL(exprs.size() == 1, "ASTUOAddrOfLabelExprStmt must contain only one expr!"); + CHECK_FATAL(exprs.front() != nullptr, "child expr must not be nullptr!"); + std::list stmts; + std::list feExprs; + UniqueFEIRExpr feExpr = exprs.front()->Emit2FEExpr(stmts); + if (feExpr != nullptr) { + feExprs.emplace_back(std::move(feExpr)); + UniqueFEIRStmt stmt = std::make_unique(OP_eval, std::move(feExprs)); stmts.emplace_back(std::move(stmt)); } return stmts; diff --git a/src/hir2mpl/ast_input/clang/src/ast_struct2fe_helper.cpp b/src/hir2mpl/ast_input/clang/src/ast_struct2fe_helper.cpp index 1ea52ec118a3b10e1562a719f0732fcab51d6f26..2ff735e61183ff6758ddfd6f82f2cd6f5a9ddad4 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_struct2fe_helper.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_struct2fe_helper.cpp @@ -24,24 +24,28 @@ namespace maple { // ---------- ASTStruct2FEHelper ---------- bool ASTStruct2FEHelper::ProcessDeclImpl() { if (isSkipped) { + astStruct.ClearGenericAttrsContentMap(); return true; } if (mirStructType == nullptr) { + astStruct.ClearGenericAttrsContentMap(); return false; } + mirStructType->SetTypeAttrs(GetStructAttributeFromInput()); // Process Fields InitFieldHelpers(); ProcessFieldDef(); // Process Methods InitMethodHelpers(); ProcessMethodDef(); + astStruct.ClearGenericAttrsContentMap(); return true; } void ASTStruct2FEHelper::InitFieldHelpersImpl() { MemPool *mp = allocator.GetMemPool(); ASSERT(mp != nullptr, "mem pool is nullptr"); - for (const ASTField *field : astStruct.GetFields()) { + for (ASTField *field : astStruct.GetFields()) { ASSERT(field != nullptr, "field is nullptr"); ASTStructField2FEHelper *fieldHelper = mp->New( allocator, *field, *astStruct.GetTypeDesc().front()); @@ -57,7 +61,7 @@ TypeAttrs ASTStruct2FEHelper::GetStructAttributeFromInputImpl() const { return attrs.ConvertToTypeAttrs(); } -ASTStruct2FEHelper::ASTStruct2FEHelper(MapleAllocator &allocator, const ASTStruct &structIn) +ASTStruct2FEHelper::ASTStruct2FEHelper(MapleAllocator &allocator, ASTStruct &structIn) : FEInputStructHelper(allocator), astStruct(structIn) { srcLang = kSrcLangC; } @@ -143,6 +147,7 @@ bool ASTStructField2FEHelper::ProcessDeclWithContainerImpl(MapleAllocator &alloc mirFieldPair.first = idx; mirFieldPair.second.first = fieldType->GetTypeIndex(); mirFieldPair.second.second = attrs; + field.ClearGenericAttrsContentMap(); return true; } @@ -160,12 +165,14 @@ bool ASTGlobalVar2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { if (mirSymbol->GetType()->GetTypeIndex() != type->GetTypeIndex()) { mirSymbol->SetTyIdx(type->GetTypeIndex()); } - mirSymbol->GetSrcPosition().SetFileNum(static_cast(astVar.GetSrcFileIdx())); - mirSymbol->GetSrcPosition().SetLineNum(astVar.GetSrcFileLineNum()); + if (mirSymbol->GetSrcPosition().LineNum() == 0) { + mirSymbol->SetSrcPosition(astVar.GetSrclOC().Emit2SourcePosition()); + } auto typeAttrs = astVar.GetGenericAttrs().ConvertToTypeAttrs(); ENCChecker::InsertBoundaryInAtts(typeAttrs, astVar.GetBoundaryInfo()); // do not allow extern var override global var if (mirSymbol->GetAttrs().GetAttrFlag() != 0 && typeAttrs.GetAttr(ATTR_extern)) { + mirSymbol->AddAttrs(typeAttrs); ASTExpr *initExpr = astVar.GetInitExpr(); if (initExpr == nullptr) { return true; @@ -183,7 +190,7 @@ bool ASTGlobalVar2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { mirSymbol->SetStorageClass(MIRStorageClass::kScGlobal); } typeAttrs.SetAlign(astVar.GetAlign()); - mirSymbol->SetAttrs(typeAttrs); + mirSymbol->AddAttrs(typeAttrs); if (!astVar.GetSectionAttr().empty()) { mirSymbol->sectionAttr = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(astVar.GetSectionAttr()); } @@ -217,6 +224,7 @@ bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { } methodNameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(methodShortName); if (!ASTUtil::InsertFuncSet(methodNameIdx)) { + func.ClearGenericAttrsContentMap(); return true; } SolveReturnAndArgTypes(allocator); @@ -233,8 +241,7 @@ bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { } mirFunc = FEManager::GetTypeManager().CreateFunction(methodNameIdx, retMIRType->GetTypeIndex(), argsTypeIdx, isVarg, isStatic); - mirFunc->GetSrcPosition().SetFileNum(static_cast(func.GetSrcFileIdx())); - mirFunc->GetSrcPosition().SetLineNum(func.GetSrcFileLineNum()); + mirFunc->SetSrcPosition(func.GetSrclOC().Emit2SourcePosition()); MIRSymbol *funSym = mirFunc->GetFuncSymbol(); if (!func.GetSectionAttr().empty()) { funSym->sectionAttr = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(func.GetSectionAttr()); @@ -247,10 +254,10 @@ bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { } funSym->SetWeakrefAttr(std::pair { true, idx }); } - std::vector paramDecls = func.GetParamDecls(); + MapleVector paramDecls = func.GetParamDecls(); if (firstArgRet) { - ASTDecl *returnParamVar = ASTDeclsBuilder::ASTVarBuilder( - allocator, "", "first_arg_return", std::vector{}, GenericAttrs()); + ASTDecl *returnParamVar = ASTDeclsBuilder::ASTVarBuilder(allocator, MapleString("", allocator.GetMemPool()), + "first_arg_return", MapleVector({}, allocator.Adapter()), GenericAttrs()); returnParamVar->SetIsParam(true); paramDecls.insert(paramDecls.begin(), returnParamVar); } @@ -269,16 +276,20 @@ bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { ENCChecker::InsertBoundaryInAtts(attrs, func.GetBoundaryInfo()); mirMethodPair.second.second = attrs; mirFunc->SetFuncAttrs(attrs); + if (firstArgRet) { + mirFunc->GetMIRFuncType()->funcAttrs.SetAttr(FUNCATTR_firstarg_return); + } + func.ClearGenericAttrsContentMap(); return true; } -const std::string &ASTFunc2FEHelper::GetSrcFileName() const { +const std::string ASTFunc2FEHelper::GetSrcFileName() const { return func.GetSrcFileName(); } void ASTFunc2FEHelper::SolveReturnAndArgTypesImpl(MapleAllocator &allocator) { (void)allocator; - const std::vector &returnAndArgTypeNames = func.GetTypeDesc(); + const MapleVector &returnAndArgTypeNames = func.GetTypeDesc(); retMIRType = returnAndArgTypeNames[1]; // skip funcType and returnType argMIRTypes.insert(argMIRTypes.begin(), returnAndArgTypeNames.begin() + 2, returnAndArgTypeNames.end()); @@ -331,9 +342,6 @@ bool ASTFunc2FEHelper::IsNativeImpl() const { } bool ASTFunc2FEHelper::HasCodeImpl() const { - if (func.GetCompoundStmt() == nullptr) { - return false; - } - return true; + return func.HasCode(); } } // namespace maple diff --git a/src/hir2mpl/ast_input/common/include/ast_compiler_component-inl.h b/src/hir2mpl/ast_input/common/include/ast_compiler_component-inl.h index d0996cad26c6dff6b477adb6e382805654c0b594..365f0cfefcd401f5a4b66b25e94eee1212b9e52c 100644 --- a/src/hir2mpl/ast_input/common/include/ast_compiler_component-inl.h +++ b/src/hir2mpl/ast_input/common/include/ast_compiler_component-inl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -53,13 +53,19 @@ bool ASTCompilerComponent::ParseInputImpl() { } for (auto &astFunc : astInput.GetASTFuncs()) { - FEInputMethodHelper *funcHelper = allocator.GetMemPool()->New(allocator, *astFunc); - for (auto &e : globalFuncHelpers) { - if (funcHelper->GetMethodName(false) == e->GetMethodName(false)) { - globalFuncHelpers.remove(e); - break; + auto iter = std::find_if(std::begin(globalFuncHelpers), std::end(globalFuncHelpers), + [&](FEInputMethodHelper* s) -> bool { + return (s->GetMethodName(false) == astFunc->GetName()); + }); + if (iter != globalFuncHelpers.end()) { + // save the function with funcbody + if ((*iter)->HasCode() && !astFunc->HasCode()) { + continue; + } else { + globalFuncHelpers.erase(iter); } } + FEInputMethodHelper *funcHelper = allocator.GetMemPool()->New(allocator, *astFunc); globalFuncHelpers.emplace_back(funcHelper); } diff --git a/src/hir2mpl/ast_input/common/include/ast_decl.h b/src/hir2mpl/ast_input/common/include/ast_decl.h index cc66fac4e766940773cb98f350e0f070c81254ed..75cbd3bb47ab9e0ea937c14cab1008b8fb5fb824 100644 --- a/src/hir2mpl/ast_input/common/include/ast_decl.h +++ b/src/hir2mpl/ast_input/common/include/ast_decl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -45,13 +45,13 @@ struct BoundaryInfo { class ASTDecl { public: - ASTDecl(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn) + ASTDecl(const MapleString &srcFile, const MapleString &nameIn, const MapleVector &typeDescIn) : isGlobalDecl(false), srcFileName(srcFile), name(nameIn), typeDesc(typeDescIn) {} virtual ~ASTDecl() = default; - const std::string &GetSrcFileName() const; - const std::string &GetName() const; - const std::vector &GetTypeDesc() const; - void SetTypeDesc(const std::vector &typeVecIn); + const std::string GetSrcFileName() const; + const std::string GetName() const; + const MapleVector &GetTypeDesc() const; + void SetTypeDesc(const MapleVector &typeVecIn); GenericAttrs GetGenericAttrs() const { return genAttrs; } @@ -72,6 +72,18 @@ class ASTDecl { return isParam; } + void SetIsMacro(bool flag) { + if (flag) { + isMacroID = FEUtils::GetSequentialNumber(); + } else { + isMacroID = flag; + } + } + + uint32 IsMacroID() const { + return isMacroID; + } + void SetAlign(uint32 n) { if (n > align) { align = n; @@ -102,17 +114,24 @@ class ASTDecl { pos = p; } - void SetSrcLOC(uint32 fileIdx, uint32 lineNum) { - srcFileIdx = fileIdx; - srcFileLineNum = lineNum; + void SetSrcLoc(const Loc &l) { + loc = l; + } + + const Loc &GetSrclOC() const { + return loc; } uint32 GetSrcFileIdx() const { - return srcFileIdx; + return loc.fileIdx; } uint32 GetSrcFileLineNum() const { - return srcFileLineNum; + return loc.line; + } + + uint32 GetSrcFileColumn() const { + return loc.column; } DeclKind GetDeclKind() const { @@ -151,6 +170,10 @@ class ASTDecl { return boundary.isBytedLen; } + void ClearGenericAttrsContentMap() { + genAttrs.ClearContentMap(); + } + protected: virtual MIRConst *Translate2MIRConstImpl() const { CHECK_FATAL(false, "Maybe implemented for other ASTDecls"); @@ -160,13 +183,14 @@ class ASTDecl { bool isGlobalDecl; bool isParam = false; uint32 align = 1; // in byte - const std::string srcFileName; - std::string name; - std::vector typeDesc; + const MapleString srcFileName; + + MapleString name; + MapleVector typeDesc; GenericAttrs genAttrs; - Pos pos = { 0, 0 }; - uint32 srcFileIdx = 0; - uint32 srcFileLineNum = 0; + Loc loc = { 0, 0, 0 }; + Pos pos = {0 , 0}; + uint32 isMacroID = false; DeclKind declKind = kASTDecl; BoundaryInfo boundary; std::string sectionAttr; @@ -174,7 +198,7 @@ class ASTDecl { class ASTField : public ASTDecl { public: - ASTField(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn, + ASTField(const MapleString &srcFile, const MapleString &nameIn, const MapleVector &typeDescIn, const GenericAttrs &genAttrsIn, bool isAnonymous = false) : ASTDecl(srcFile, nameIn, typeDescIn), isAnonymousField(isAnonymous) { genAttrs = genAttrsIn; @@ -191,8 +215,8 @@ class ASTField : public ASTDecl { class ASTFunc : public ASTDecl { public: - ASTFunc(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn, - const GenericAttrs &genAttrsIn, const std::vector ¶mDeclsIn) + ASTFunc(const MapleString &srcFile, const MapleString &nameIn, const MapleVector &typeDescIn, + const GenericAttrs &genAttrsIn, const MapleVector ¶mDeclsIn) : ASTDecl(srcFile, nameIn, typeDescIn), compound(nullptr), paramDecls(paramDeclsIn) { genAttrs = genAttrsIn; declKind = kASTFunc; @@ -203,7 +227,7 @@ class ASTFunc : public ASTDecl { void SetCompoundStmt(ASTStmt*); void InsertStmtsIntoCompoundStmtAtFront(const std::list &stmts); const ASTStmt *GetCompoundStmt() const; - const std::vector &GetParamDecls() const { + const MapleVector &GetParamDecls() const { return paramDecls; } std::vector> GenArgVarList() const; @@ -227,19 +251,27 @@ class ASTFunc : public ASTDecl { bodySize = size; } + bool HasCode() const { + if (compound == nullptr) { + return false; + } + return true; + } + private: // typeDesc format: [funcType, retType, arg0, arg1 ... argN] ASTStmt *compound = nullptr; // func body - std::vector paramDecls; + MapleVector paramDecls; std::pair weakrefAttr; uint32 bodySize = 0; }; class ASTStruct : public ASTDecl { public: - ASTStruct(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn, - const GenericAttrs &genAttrsIn) - : ASTDecl(srcFile, nameIn, typeDescIn), isUnion(false) { + ASTStruct(MapleAllocator &allocatorIn, const MapleString &srcFile, const MapleString &nameIn, + const MapleVector &typeDescIn, const GenericAttrs &genAttrsIn) + : ASTDecl(srcFile, nameIn, typeDescIn), + isUnion(false), fields(allocatorIn.Adapter()), methods(allocatorIn.Adapter()) { genAttrs = genAttrsIn; declKind = kASTStruct; } @@ -251,7 +283,7 @@ class ASTStruct : public ASTDecl { fields.emplace_back(f); } - const std::list &GetFields() const { + const MapleList &GetFields() const { return fields; } @@ -265,13 +297,13 @@ class ASTStruct : public ASTDecl { private: bool isUnion = false; - std::list fields; - std::list methods; + MapleList fields; + MapleList methods; }; class ASTVar : public ASTDecl { public: - ASTVar(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn, + ASTVar(const MapleString &srcFile, const MapleString &nameIn, const MapleVector &typeDescIn, const GenericAttrs &genAttrsIn) : ASTDecl(srcFile, nameIn, typeDescIn) { genAttrs = genAttrsIn; @@ -299,6 +331,14 @@ class ASTVar : public ASTDecl { variableArrayExpr = expr; } + void SetPromotedType(PrimType primType) { + promotedType = primType; + } + + PrimType GetPromotedType() const { + return promotedType; + } + std::unique_ptr Translate2FEIRVar() const; MIRSymbol *Translate2MIRSymbol() const; @@ -310,12 +350,14 @@ class ASTVar : public ASTDecl { ASTExpr *initExpr = nullptr; std::string asmAttr; ASTExpr *variableArrayExpr = nullptr; + PrimType promotedType = PTY_void; + bool hasAddedInMIRScope = false; }; class ASTFileScopeAsm : public ASTDecl { public: - ASTFileScopeAsm(const std::string &srcFile) - : ASTDecl(srcFile, "", std::vector{}) { + ASTFileScopeAsm(MapleAllocator &allocatorIn, const MapleString &srcFile) + : ASTDecl(srcFile, MapleString("", allocatorIn.GetMemPool()), MapleVector(allocatorIn.Adapter())) { declKind = kASTFileScopeAsm; } ~ASTFileScopeAsm() = default; @@ -334,8 +376,8 @@ class ASTFileScopeAsm : public ASTDecl { class ASTEnumConstant : public ASTDecl { public: - ASTEnumConstant(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn, - const GenericAttrs &genAttrsIn) + ASTEnumConstant(const MapleString &srcFile, const MapleString &nameIn, const MapleVector &typeDescIn, + const GenericAttrs &genAttrsIn) : ASTDecl(srcFile, nameIn, typeDescIn) { genAttrs = genAttrsIn; declKind = kASTEnumConstant; @@ -353,9 +395,9 @@ class ASTEnumConstant : public ASTDecl { // only process local `EnumDecl` here class ASTEnumDecl : public ASTDecl { public: - ASTEnumDecl(const std::string &srcFile, const std::string &nameIn, const std::vector &typeDescIn, - const GenericAttrs &genAttrsIn) - : ASTDecl(srcFile, nameIn, typeDescIn) { + ASTEnumDecl(MapleAllocator &allocatorIn, const MapleString &srcFile, const MapleString &nameIn, + const MapleVector &typeDescIn, const GenericAttrs &genAttrsIn) + : ASTDecl(srcFile, nameIn, typeDescIn), consts(allocatorIn.Adapter()) { genAttrs = genAttrsIn; declKind = kASTEnumDecl; } @@ -366,7 +408,7 @@ class ASTEnumDecl : public ASTDecl { } private: - std::list consts; + MapleList consts; }; } // namespace maple #endif // HIR2MPL_AST_INPUT_INCLUDE_AST_DECL_H diff --git a/src/hir2mpl/ast_input/common/include/ast_decl_builder.h b/src/hir2mpl/ast_input/common/include/ast_decl_builder.h index 45aaf4fdc795954cee5e8652e711f5f6e6fd054e..6ed5dd0a766a10d485abcb5e94783030a48eefc5 100644 --- a/src/hir2mpl/ast_input/common/include/ast_decl_builder.h +++ b/src/hir2mpl/ast_input/common/include/ast_decl_builder.h @@ -25,86 +25,102 @@ class ASTDeclsBuilder { return decl; } - static ASTDecl *ASTDeclBuilder(const MapleAllocator &allocator, const std::string &srcFile, - const std::string &nameIn, const std::vector &typeDescIn, int64 id = INT64_MAX) { + static void Clear() { + declesTable.clear(); + } + + static ASTDecl *ASTDeclBuilder(const MapleAllocator &allocator, const MapleString &srcFile, + const std::string &nameIn, const MapleVector &typeDescIn, int64 id = INT64_MAX) { + MapleString nameStr(nameIn, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, nameIn, typeDescIn); // for temp decl + return allocator.GetMemPool()->New(srcFile, nameStr, typeDescIn); // for temp decl } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, nameIn, typeDescIn); + declesTable[id] = allocator.GetMemPool()->New(srcFile, nameStr, typeDescIn); } return declesTable[id]; } - static ASTVar *ASTVarBuilder(const MapleAllocator &allocator, const std::string &srcFile, const std::string &varName, - const std::vector &desc, const GenericAttrs &genAttrsIn, int64 id = INT64_MAX) { + static ASTVar *ASTVarBuilder(const MapleAllocator &allocator, const MapleString &srcFile, const std::string &varName, + const MapleVector &desc, const GenericAttrs &genAttrsIn, int64 id = INT64_MAX) { + MapleString varNameStr(varName, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn); + return allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn); } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn); + declesTable[id] = allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn); } return static_cast(declesTable[id]); } - static ASTEnumConstant *ASTEnumConstBuilder(const MapleAllocator &allocator, const std::string &srcFile, - const std::string &varName, const std::vector &desc, + static ASTEnumConstant *ASTEnumConstBuilder(const MapleAllocator &allocator, const MapleString &srcFile, + const std::string &varName, const MapleVector &desc, const GenericAttrs &genAttrsIn, int64 id = INT64_MAX) { + MapleString varNameStr(varName, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn); + return allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn); } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn); + declesTable[id] = allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn); } return static_cast(declesTable[id]); } - static ASTEnumDecl *ASTLocalEnumDeclBuilder(const MapleAllocator &allocator, const std::string &srcFile, - const std::string &varName, const std::vector &desc, const GenericAttrs &genAttrsIn, + static ASTEnumDecl *ASTLocalEnumDeclBuilder(MapleAllocator &allocator, const MapleString &srcFile, + const std::string &varName, const MapleVector &desc, const GenericAttrs &genAttrsIn, int64 id = INT64_MAX) { + MapleString varNameStr(varName, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn); + return allocator.GetMemPool()->New(allocator, srcFile, varNameStr, desc, genAttrsIn); } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn); + declesTable[id] = allocator.GetMemPool()->New(allocator, srcFile, varNameStr, desc, genAttrsIn); } return static_cast(declesTable[id]); } - static ASTFunc *ASTFuncBuilder(const MapleAllocator &allocator, const std::string &srcFile, const std::string &nameIn, - const std::vector &typeDescIn, const GenericAttrs &genAttrsIn, - const std::vector ¶mDeclsIn, int64 id = INT64_MAX) { + static ASTFunc *ASTFuncBuilder(const MapleAllocator &allocator, const MapleString &srcFile, const std::string &nameIn, + const MapleVector &typeDescIn, const GenericAttrs &genAttrsIn, + MapleVector ¶mDeclsIn, int64 id = INT64_MAX) { + MapleString funcNameStr(nameIn, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, nameIn, typeDescIn, genAttrsIn, paramDeclsIn); + return allocator.GetMemPool()->New(srcFile, funcNameStr, typeDescIn, genAttrsIn, paramDeclsIn); } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, nameIn, typeDescIn, genAttrsIn, paramDeclsIn); + declesTable[id] = allocator.GetMemPool()->New(srcFile, funcNameStr, typeDescIn, genAttrsIn, + paramDeclsIn); } return static_cast(declesTable[id]); } template - static T *ASTStmtBuilder(const MapleAllocator &allocator) { - return allocator.GetMemPool()->New(); + static T *ASTStmtBuilder(MapleAllocator &allocator) { + return allocator.GetMemPool()->New(allocator); } template - static T *ASTExprBuilder(const MapleAllocator &allocator) { - return allocator.GetMemPool()->New(); + static T *ASTExprBuilder(MapleAllocator &allocator) { + return allocator.GetMemPool()->New(allocator); } - static ASTStruct *ASTStructBuilder(const MapleAllocator &allocator, const std::string &srcFile, const std::string &nameIn, - const std::vector &typeDescIn, const GenericAttrs &genAttrsIn, int64 id = INT64_MAX) { + static ASTStruct *ASTStructBuilder(MapleAllocator &allocator, const MapleString &srcFile, + const std::string &nameIn, const MapleVector &typeDescIn, + const GenericAttrs &genAttrsIn, int64 id = INT64_MAX) { + MapleString structNameStr(nameIn, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, nameIn, typeDescIn, genAttrsIn); + return allocator.GetMemPool()->New(allocator, srcFile, structNameStr, typeDescIn, genAttrsIn); } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, nameIn, typeDescIn, genAttrsIn); + declesTable[id] = allocator.GetMemPool()->New(allocator, srcFile, structNameStr, typeDescIn, + genAttrsIn); } return static_cast(declesTable[id]); } - static ASTField *ASTFieldBuilder(const MapleAllocator &allocator, const std::string &srcFile, const std::string &varName, - const std::vector &desc, const GenericAttrs &genAttrsIn, int64 id = INT64_MAX, - bool isAnonymous = false) { + static ASTField * ASTFieldBuilder(const MapleAllocator &allocator, const MapleString &srcFile, + const std::string &varName, const MapleVector &desc, + const GenericAttrs &genAttrsIn, int64 id = INT64_MAX, + bool isAnonymous = false) { + MapleString varNameStr(varName, allocator.GetMemPool()); if (id == INT64_MAX) { - return allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn, isAnonymous); + return allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn, isAnonymous); } else if (declesTable[id] == nullptr) { - declesTable[id] = allocator.GetMemPool()->New(srcFile, varName, desc, genAttrsIn, isAnonymous); + declesTable[id] = allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn, + isAnonymous); } return static_cast(declesTable[id]); } diff --git a/src/hir2mpl/ast_input/common/include/ast_input-inl.h b/src/hir2mpl/ast_input/common/include/ast_input-inl.h index ed577ba5862eaca799c6456b1dadd5ee8ca5607a..a0155a8ac374261f36b56d7773e33496233bf499 100644 --- a/src/hir2mpl/ast_input/common/include/ast_input-inl.h +++ b/src/hir2mpl/ast_input/common/include/ast_input-inl.h @@ -27,7 +27,7 @@ template bool ASTInput::ReadASTFile(MapleAllocator &allocatorIn, uint32 index, const std::string &fileName) { T *parser = allocator.GetMemPool()->New(allocator, index, fileName, astStructs, astFuncs, astVars, astFileScopeAsms); - TRY_DO(parser->OpenFile()); + TRY_DO(parser->OpenFile(allocatorIn)); TRY_DO(parser->Verify()); TRY_DO(parser->PreProcessAST()); // Some implicit record decl would be retrieved in func body at use, @@ -36,6 +36,7 @@ bool ASTInput::ReadASTFile(MapleAllocator &allocatorIn, uint32 index, const s TRY_DO(parser->RetrieveStructs(allocatorIn)); TRY_DO(parser->RetrieveGlobalVars(allocatorIn)); TRY_DO(parser->RetrieveFileScopeAsms(allocatorIn)); + TRY_DO(parser->Release()); parserMap.emplace(fileName, parser); return true; } diff --git a/src/hir2mpl/ast_input/common/src/ast_decl.cpp b/src/hir2mpl/ast_input/common/src/ast_decl.cpp index 56c9747695190252267d080b87c74acc1f9def70..95ec94111bac19853af5eb56c54fd40c38d2ee6f 100644 --- a/src/hir2mpl/ast_input/common/src/ast_decl.cpp +++ b/src/hir2mpl/ast_input/common/src/ast_decl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -24,19 +24,19 @@ namespace maple { // ---------- ASTDecl --------- -const std::string &ASTDecl::GetSrcFileName() const { - return srcFileName; +const std::string ASTDecl::GetSrcFileName() const { + return srcFileName.c_str() == nullptr ? "" : srcFileName.c_str(); } -const std::string &ASTDecl::GetName() const { - return name; +const std::string ASTDecl::GetName() const { + return name.c_str() == nullptr ? "" : name.c_str(); } -const std::vector &ASTDecl::GetTypeDesc() const { +const MapleVector &ASTDecl::GetTypeDesc() const { return typeDesc; } -void ASTDecl::SetTypeDesc(const std::vector &typeVecIn) { +void ASTDecl::SetTypeDesc(const MapleVector &typeVecIn) { typeDesc = typeVecIn; } @@ -47,9 +47,17 @@ MIRConst *ASTDecl::Translate2MIRConst() const { std::string ASTDecl::GenerateUniqueVarName() const { // add `_line_column` suffix for avoiding local var name conflict if (isGlobalDecl || isParam) { - return name; + return GetName(); } else { - return name + "_" + std::to_string(pos.first) + "_" + std::to_string(pos.second); + std::stringstream os; + os << GetName(); + if (isMacroID) { + // for macro expansion, variable names of same location need to be unique + os << "_" << std::to_string(isMacroID); + } else { + os << "_" << std::to_string(pos.first) << "_" << std::to_string(pos.second); + } + return os.str(); } } @@ -59,8 +67,8 @@ std::unique_ptr ASTVar::Translate2FEIRVar() const { auto feirVar = std::make_unique(GenerateUniqueVarName(), std::make_unique(*(typeDesc[0]))); feirVar->SetGlobal(isGlobalDecl); - feirVar->SetAttrs(const_cast(genAttrs)); - feirVar->SetSrcLOC(srcFileIdx, srcFileLineNum); + feirVar->SetAttrs(genAttrs); + feirVar->SetSrcLoc(loc); feirVar->SetSectionAttr(sectionAttr); if (boundary.lenExpr != nullptr) { std::list nullStmts; @@ -99,6 +107,7 @@ void ASTVar::GenerateInitStmt4StringLiteral(ASTExpr *initASTExpr, const UniqueFE argExprList->emplace_back(sizeExpr->Clone()); std::unique_ptr memcpyStmt = std::make_unique( INTRN_C_memcpy, nullptr, nullptr, std::move(argExprList)); + memcpyStmt->SetSrcLoc(initFeirExpr->GetLoc()); stmts.emplace_back(std::move(memcpyStmt)); if (mirArrayType->GetKind() != kTypeArray) { return; @@ -116,6 +125,7 @@ void ASTVar::GenerateInitStmt4StringLiteral(ASTExpr *initASTExpr, const UniqueFE argExprList->emplace_back(FEIRBuilder::CreateExprConstI32(needInitFurtherCnt * elemSize)); std::unique_ptr memsetStmt = std::make_unique( INTRN_C_memset, nullptr, nullptr, std::move(argExprList)); + memsetStmt->SetSrcLoc(initFeirExpr->GetLoc()); stmts.emplace_back(std::move(memsetStmt)); } return; @@ -126,16 +136,37 @@ void ASTVar::GenerateInitStmtImpl(std::list &stmts) { MIRSymbol *sym = Translate2MIRSymbol(); ENCChecker::CheckNonnullLocalVarInit(*sym, initExpr); UniqueFEIRVar feirVar = Translate2FEIRVar(); - if (variableArrayExpr != nullptr) { - // free, Currently, the back-end are not supported. + if (FEOptions::GetInstance().IsDbgFriendly() && !hasAddedInMIRScope) { + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + MIRScope *mirScope = feFunction.GetTopStmtMIRScope(); + feFunction.AddAliasInMIRScope(mirScope, GetName(), sym); + hasAddedInMIRScope = true; + } + if (variableArrayExpr != nullptr) { // vla declaration point + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + if (feFunction.GetTopStmtFEIRScopePtr() != nullptr && + feFunction.GetTopStmtFEIRScopePtr()->GetVLASavedStackVar() == nullptr) { + // stack save + MIRType *retType = GlobalTables::GetTypeTable().GetOrCreatePointerType( + *GlobalTables::GetTypeTable().GetPrimType(PTY_void)); + auto stackVar = FEIRBuilder::CreateVarNameForC(FEUtils::GetSequentialName("saved_stack."), *retType, false); + std::unique_ptr> argExprList = std::make_unique>(); + auto stackSaveStmt = std::make_unique(INTRN_C_stack_save, nullptr, stackVar->Clone(), + std::move(argExprList)); + stackSaveStmt->SetSrcLoc(feirVar->GetSrcLoc()); + stmts.emplace_back(std::move(stackSaveStmt)); + // push saved stack var into scope + feFunction.GetTopStmtFEIRScopePtr()->SetVLASavedStackVar(std::move(stackVar)); + } // alloca UniqueFEIRExpr variableArrayFEIRExpr = variableArrayExpr->Emit2FEExpr(stmts); MIRType *mirType = GlobalTables::GetTypeTable().GetPrimType(PTY_a64); UniqueFEIRType feType = std::make_unique(*mirType); UniqueFEIRExpr allocaExpr = std::make_unique(std::move(feType), OP_alloca, std::move(variableArrayFEIRExpr)); - UniqueFEIRStmt stmt = FEIRBuilder::CreateStmtDAssign(feirVar->Clone(), std::move(allocaExpr)); - stmts.emplace_back(std::move(stmt)); + UniqueFEIRStmt allocaStmt = FEIRBuilder::CreateStmtDAssign(feirVar->Clone(), std::move(allocaExpr)); + allocaStmt->SetSrcLoc(feirVar->GetSrcLoc()); + stmts.emplace_back(std::move(allocaStmt)); return; } if (initExpr == nullptr) { @@ -161,11 +192,11 @@ void ASTVar::GenerateInitStmtImpl(std::list &stmts) { UniqueFEIRStmt stmt; if (srcPrimType != feirVar->GetType()->GetPrimType() && srcPrimType != PTY_agg && srcPrimType != PTY_void) { auto castExpr = FEIRBuilder::CreateExprCastPrim(std::move(initFeirExpr), feirVar->GetType()->GetPrimType()); - stmt = FEIRBuilder::CreateStmtDAssign(std::move(feirVar), std::move(castExpr)); + stmt = FEIRBuilder::CreateStmtDAssign(feirVar->Clone(), std::move(castExpr)); } else { - stmt = FEIRBuilder::CreateStmtDAssign(std::move(feirVar), std::move(initFeirExpr)); + stmt = FEIRBuilder::CreateStmtDAssign(feirVar->Clone(), std::move(initFeirExpr)); } - stmt->SetSrcFileInfo(initExpr->GetSrcFileIdx(), initExpr->GetSrcFileLineNum()); + stmt->SetSrcLoc(feirVar->GetSrcLoc()); stmts.emplace_back(std::move(stmt)); } @@ -174,10 +205,8 @@ MIRSymbol *ASTVar::Translate2MIRSymbol() const { MIRSymbol *mirSymbol = feirVar->GenerateMIRSymbol(FEManager::GetMIRBuilder()); if (initExpr != nullptr && genAttrs.GetAttr(GENATTR_static)) { MIRConst *cst = initExpr->GenerateMIRConst(); - if (cst->GetKind() != kConstLblConst) { + if (cst != nullptr && cst->GetKind() != kConstInvalid) { mirSymbol->SetKonst(cst); - } else { - mirSymbol->SetKonst(nullptr); } } if (!sectionAttr.empty()) { @@ -228,7 +257,10 @@ std::list ASTFunc::EmitASTStmtToFEIR() const { return stmts; } const ASTCompoundStmt *astCpdStmt = static_cast(astStmt); - const std::list &astStmtList = astCpdStmt->GetASTStmtList(); + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + feFunction.PushFuncScope(astCpdStmt->GetSrcLoc().Emit2SourcePosition(), + astCpdStmt->GetEndLoc().Emit2SourcePosition()); + const MapleList &astStmtList = astCpdStmt->GetASTStmtList(); for (auto stmtNode : astStmtList) { std::list childStmts = stmtNode->Emit2FEStmt(); for (auto &stmt : childStmts) { @@ -236,6 +268,12 @@ std::list ASTFunc::EmitASTStmtToFEIR() const { stmts.emplace_back(std::move(stmt)); } } + UniqueFEIRScope scope = feFunction.PopTopStmtScope(); + if (scope->GetVLASavedStackVar() != nullptr) { + auto stackRestoreStmt = scope->GenVLAStackRestoreStmt(); + stackRestoreStmt->SetSrcLoc(astCpdStmt->GetEndLoc()); + stmts.emplace_back(std::move(stackRestoreStmt)); + } // fix int main() no return 0 and void func() no return. there are multiple branches, insert return at the end. if (stmts.size() == 0 || stmts.back()->GetKind() != kStmtReturn) { UniqueFEIRExpr retExpr = nullptr; @@ -255,6 +293,6 @@ std::list ASTFunc::EmitASTStmtToFEIR() const { // ---------- ASTStruct ---------- std::string ASTStruct::GetStructName(bool mapled) const { - return mapled ? namemangler::EncodeName(name) : name; + return mapled ? namemangler::EncodeName(GetName()) : GetName(); } } // namespace maple diff --git a/src/hir2mpl/ast_input/maple/src/maple_ast_parser.cpp b/src/hir2mpl/ast_input/maple/src/maple_ast_parser.cpp index 01765dc2d6ba18de8a7a18985e4ce35779c2773f..edbfc19b28aeadcacea583996cbc687b034f92b9 100644 --- a/src/hir2mpl/ast_input/maple/src/maple_ast_parser.cpp +++ b/src/hir2mpl/ast_input/maple/src/maple_ast_parser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2021-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -97,7 +97,7 @@ ASTDecl *MapleASTParser::ProcessDeclIdentifierNode(MapleAllocator &allocator, ma } GenericAttrs attrs; astVar = ASTDeclsBuilder::ASTVarBuilder( - allocator, fileName, varName, std::vector{varType}, attrs, identifierDecl->GetNodeId()); + allocator, fileName, varName, MapleVector{varType}, attrs, identifierDecl->GetNodeId()); if (identifierDecl->GetInit() != nullptr) { auto astInitExpr = ProcessExpr(allocator, identifierDecl->GetInit()); @@ -129,7 +129,7 @@ ASTDecl *MapleASTParser::ProcessDeclFunctionNode(MapleAllocator &allocator, mapl return nullptr; } - std::vector typeDescIn; + MapleVector typeDescIn; typeDescIn.push_back(nullptr); // mirFuncType MIRType *retType = astFile->MapType(funcDecl->GetType()); if (retType == nullptr) { @@ -137,7 +137,7 @@ ASTDecl *MapleASTParser::ProcessDeclFunctionNode(MapleAllocator &allocator, mapl } typeDescIn.push_back(retType); - std::vector paramDecls; + MapleVector paramDecls; uint32 numParam = funcDecl->GetParamsNum(); for (uint32 i = 0; i < numParam; ++i) { maplefe::TreeNode *param = funcDecl->GetParam(i); diff --git a/src/hir2mpl/bytecode_input/class/src/jbc_function.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_function.cpp index 63a92f0870acfb9196587a7c00f20b0fa4e8c63b..55b4bd740b80f87aa66d24c3929f9ea8dfc4f683 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_function.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_function.cpp @@ -36,8 +36,8 @@ JBCFunction::~JBCFunction() { void JBCFunction::InitImpl() { FEFunction::InitImpl(); - generalCFG = std::make_unique(genStmtHead, genStmtTail); - generalCFG->Init(); + feirCFG = std::make_unique(feirStmtHead, feirStmtHead); + feirCFG->Init(); pesudoBBCatchPred = RegisterFEIRBB(std::make_unique()); } @@ -80,11 +80,11 @@ void JBCFunction::FinishImpl() { if (FEOptions::GetInstance().IsDumpJBCStmt() && dumpFunc) { DumpGeneralStmts(); } - if (FEOptions::GetInstance().IsDumpJBCBB() && dumpFunc) { - DumpFEIRBBs(); + if (FEOptions::GetInstance().IsDumpFEIRBB() && dumpFunc) { + INFO(kLncInfo, "not implemented"); } - if (FEOptions::GetInstance().IsDumpFEIRCFGGraph() && dumpFunc) { - DumpFEIRCFGGraph(); + if (FEOptions::GetInstance().IsDumpFEIRCFGGraph(method.GetFullName())) { + (void)DumpFEIRCFGGraph("dump cfg graph"); } (void)UpdateFormal("finish/update formal"); // Not gen func body for abstract method @@ -367,7 +367,7 @@ FEIRStmt *JBCFunction::BuildStmtFromInstructionForBranch(const jbc::JBCOp &op) { FEIRStmt *stmt = uniStmt.get(); const jbc::JBCOpBranch &opBranch = static_cast(op); FEIRStmt *target = BuildAndUpdateLabel(opBranch.GetTarget(), uniStmt); - static_cast(stmt)->AddSucc(*target); + static_cast(stmt)->AddExtraSucc(*target); return stmt; } @@ -378,7 +378,7 @@ FEIRStmt *JBCFunction::BuildStmtFromInstructionForGoto(const jbc::JBCOp &op) { stmt->SetFallThru(false); const jbc::JBCOpGoto &opGoto = static_cast(op); FEIRStmt *target = BuildAndUpdateLabel(opGoto.GetTarget(), uniStmt); - static_cast(stmt)->AddSucc(*target); + static_cast(stmt)->AddExtraSucc(*target); return stmt; } @@ -390,10 +390,10 @@ FEIRStmt *JBCFunction::BuildStmtFromInstructionForSwitch(const jbc::JBCOp &op) { const jbc::JBCOpSwitch &opSwitch = static_cast(op); for (const std::pair &targetInfo : opSwitch.GetTargets()) { FEIRStmt *target = BuildAndUpdateLabel(targetInfo.second, uniStmt); - static_cast(stmt)->AddSucc(*target); + static_cast(stmt)->AddExtraSucc(*target); } FEIRStmt *target = BuildAndUpdateLabel(opSwitch.GetDefaultTarget(), uniStmt); - static_cast(stmt)->AddSucc(*target); + static_cast(stmt)->AddExtraSucc(*target); return stmt; } @@ -404,7 +404,7 @@ FEIRStmt *JBCFunction::BuildStmtFromInstructionForJsr(const jbc::JBCOp &op) { stmt->SetFallThru(false); const jbc::JBCOpJsr &opJsr = static_cast(op); FEIRStmt *target = BuildAndUpdateLabel(opJsr.GetTarget(), uniStmt); - static_cast(stmt)->AddSucc(*target); + static_cast(stmt)->AddExtraSucc(*target); return stmt; } @@ -423,7 +423,7 @@ FEIRStmt *JBCFunction::BuildStmtFromInstructionForRet(const jbc::JBCOp &op) { for (auto itTarget : itJsrInfo->second) { uint32 pc = itTarget.second; FEIRStmt *target = BuildAndUpdateLabel(pc, uniStmt); - static_cast(stmt)->AddSucc(*target); + static_cast(stmt)->AddExtraSucc(*target); } return stmt; } @@ -627,7 +627,7 @@ FEIRStmt *JBCFunction::BuildAndUpdateLabel(uint32 dstPC, const std::unique_ptrsecond; } ASSERT(stmtLabel != nullptr, "null ptr check"); - stmtLabel->AddPred(*srcStmt); + stmtLabel->AddExtraPred(*srcStmt); return stmtLabel; } diff --git a/src/hir2mpl/bytecode_input/class/src/jbc_stmt.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_stmt.cpp index ddfbd358c4a2e90d9b35f4b5ddf9963a2751e9fc..708395d4a5620ec2dc3be0a642ad5119b1276252 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_stmt.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_stmt.cpp @@ -1141,7 +1141,7 @@ void JBCStmtInstBranch::DumpImpl(const std::string &prefix) const { "kind=" << JBCStmtKindHelper::JBCStmtKindName(JBCkind) << ", " << "op=" << op.GetOpcodeName() << ", " << "targets={"; - for (FEIRStmt *stmt : predsOrSuccs) { + for (FEIRStmt *stmt : extraSuccs) { std::cout << stmt->GetID() << " "; } std::cout << "})" << std::endl; @@ -1416,7 +1416,7 @@ void JBCStmtPesudoLabel::DumpImpl(const std::string &prefix) const { std::cout << prefix << "JBCStmtPesudoLabel (id=" << id << "," << "kind=" << JBCStmtKindHelper::JBCStmtKindName(JBCkind) << ", " << "preds={"; - for (FEIRStmt *stmt : predsOrSuccs) { + for (FEIRStmt *stmt : extraPreds) { std::cout << stmt->GetID() << " "; } std::cout << "})" << std::endl; @@ -1442,7 +1442,7 @@ void JBCStmtPesudoCatch::DumpImpl(const std::string &prefix) const { std::cout << prefix << "JBCStmtPesudoCatch (id=" << id << "," << "kind=" << JBCStmtKindHelper::JBCStmtKindName(JBCkind) << ", " << "preds={"; - for (FEIRStmt *stmt : predsOrSuccs) { + for (FEIRStmt *stmt : extraPreds) { std::cout << stmt->GetID() << " "; } std::cout << "})" << std::endl; diff --git a/src/hir2mpl/bytecode_input/common/include/ark_annotation_map.h b/src/hir2mpl/bytecode_input/common/include/ark_annotation_map.h index 291b0d548ac44bcdd294c4ae8b726a6c44751a7a..c52e272deb996353866aab1577ddc32d5dec6a85 100644 --- a/src/hir2mpl/bytecode_input/common/include/ark_annotation_map.h +++ b/src/hir2mpl/bytecode_input/common/include/ark_annotation_map.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. @@ -12,33 +12,33 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#ifndef HIR2MPL_BC_INPUT_INCLUDE_ARK_ANNOTATION_MAP_H -#define HIR2MPL_BC_INPUT_INCLUDE_ARK_ANNOTATION_MAP_H -#include -#include "global_tables.h" - -namespace maple { -namespace bc { -class ArkAnnotationMap { - public: - inline static ArkAnnotationMap &GetArkAnnotationMap() { - return annotationMap; - } - - void Init(); - const std::string &GetAnnotationTypeName(const std::string &orinName); - const std::set &GetArkAnnotationTypeNames() const { - return arkAnnotationTypeNames; - } - - private: - ArkAnnotationMap() = default; - ~ArkAnnotationMap() = default; - - static ArkAnnotationMap annotationMap; - std::map pragmaTypeNameMap; - std::set arkAnnotationTypeNames; -}; -} // namespace bc -} // namespace maple +#ifndef HIR2MPL_BC_INPUT_INCLUDE_ARK_ANNOTATION_MAP_H +#define HIR2MPL_BC_INPUT_INCLUDE_ARK_ANNOTATION_MAP_H +#include +#include "global_tables.h" + +namespace maple { +namespace bc { +class ArkAnnotationMap { + public: + inline static ArkAnnotationMap &GetArkAnnotationMap() { + return annotationMap; + } + + void Init(); + const std::string &GetAnnotationTypeName(const std::string &orinName); + const std::set &GetArkAnnotationTypeNames() const { + return arkAnnotationTypeNames; + } + + private: + ArkAnnotationMap() = default; + ~ArkAnnotationMap() = default; + + static ArkAnnotationMap annotationMap; + std::map pragmaTypeNameMap; + std::set arkAnnotationTypeNames; +}; +} // namespace bc +} // namespace maple #endif // HIR2MPL_BC_INPUT_INCLUDE_ARK_ANNOTATION_MAP_H \ No newline at end of file diff --git a/src/hir2mpl/bytecode_input/common/include/bc_pragma.h b/src/hir2mpl/bytecode_input/common/include/bc_pragma.h index 28258bd93c246f40d46ae2a3ff611d5252e19004..0f26f90624ff259f846abaae3475b51e1e17ec5e 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_pragma.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_pragma.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. @@ -12,32 +12,32 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#ifndef HIR2MPL_BC_INPUT_INCLUDE_BC_PRAGMA_H -#define HIR2MPL_BC_INPUT_INCLUDE_BC_PRAGMA_H -#include -#include -#include -#include "mir_module.h" -#include "mir_pragma.h" -#include "mempool.h" - -namespace maple { -namespace bc { -class BCAnnotationsDirectory { - public: - BCAnnotationsDirectory(MIRModule &moduleArg, MemPool &mpArg) - : module(moduleArg), mp(mpArg) {} - virtual ~BCAnnotationsDirectory() = default; - std::vector &EmitPragmas() { - return EmitPragmasImpl(); - } - - protected: - virtual std::vector &EmitPragmasImpl() = 0; - MIRModule &module; - MemPool ∓ - std::vector pragmas; -}; -} // namespace bc -} // namespace maple +#ifndef HIR2MPL_BC_INPUT_INCLUDE_BC_PRAGMA_H +#define HIR2MPL_BC_INPUT_INCLUDE_BC_PRAGMA_H +#include +#include +#include +#include "mir_module.h" +#include "mir_pragma.h" +#include "mempool.h" + +namespace maple { +namespace bc { +class BCAnnotationsDirectory { + public: + BCAnnotationsDirectory(MIRModule &moduleArg, MemPool &mpArg) + : module(moduleArg), mp(mpArg) {} + virtual ~BCAnnotationsDirectory() = default; + std::vector &EmitPragmas() { + return EmitPragmasImpl(); + } + + protected: + virtual std::vector &EmitPragmasImpl() = 0; + MIRModule &module; + MemPool ∓ + std::vector pragmas; +}; +} // namespace bc +} // namespace maple #endif // HIR2MPL_BC_INPUT_INCLUDE_BC_PRAGMA_H \ No newline at end of file diff --git a/src/hir2mpl/bytecode_input/common/src/ark_annotation_map.cpp b/src/hir2mpl/bytecode_input/common/src/ark_annotation_map.cpp index d10ec2577cef7167d76e99e10cad722f5357c3a5..5a64cb4f3d5e791ab055a69d681d27e3cb9b6273 100644 --- a/src/hir2mpl/bytecode_input/common/src/ark_annotation_map.cpp +++ b/src/hir2mpl/bytecode_input/common/src/ark_annotation_map.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. @@ -12,76 +12,76 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#include "ark_annotation_map.h" - -namespace maple { -namespace bc { -ArkAnnotationMap ArkAnnotationMap::annotationMap; - -void ArkAnnotationMap::Init() { - // AnnotationDefault - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FAnnotationDefault_3B", - "Lark_2Fannotation_2FAnnotationDefault_3B")); - // EnclosingClass - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FEnclosingClass_3B", - "Lark_2Fannotation_2FEnclosingClass_3B")); - // EnclosingMethod - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FEnclosingMethod_3B", - "Lark_2Fannotation_2FEnclosingMethod_3B")); - // InnerClass - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FInnerClass_3B", - "Lark_2Fannotation_2FInnerClass_3B")); - // KnownFailure - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FKnownFailure_3B", - "Lark_2Fannotation_2FKnownFailure_3B")); - // MemberClasses - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FMemberClasses_3B", - "Lark_2Fannotation_2FMemberClasses_3B")); - // MethodParameters - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FMethodParameters_3B", - "Lark_2Fannotation_2FMethodParameters_3B")); - // Signature - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FSignature_3B", - "Lark_2Fannotation_2FSignature_3B")); - // SourceDebugExtension - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FSourceDebugExtension_3B", - "Lark_2Fannotation_2FSourceDebugExtension_3B")); - // TestTargetClass - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FTestTargetClass_3B", - "Lark_2Fannotation_2FTestTargetClass_3B")); - // TestTarget - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FTestTarget_3B", - "Lark_2Fannotation_2FTestTarget_3B")); - // Throws - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FThrows_3B", - "Lark_2Fannotation_2FThrows_3B")); - // compact - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Fcompat_2FUnsupportedAppUsage_3B", - "Lark_2Fannotation_2Fcompat_2FUnsupportedAppUsage_3B")); - // codegen - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Fcodegen_2FCovariantReturnType_3B", - "Lark_2Fannotation_2Fcodegen_2FCovariantReturnType_3B")); - // optimization - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FCriticalNative_3B", - "Lark_2Fannotation_2Foptimization_2FCriticalNative_3B")); - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FDeadReferenceSafe_3B", - "Lark_2Fannotation_2Foptimization_2FDeadReferenceSafe_3B")); - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FFastNative_3B", - "Lark_2Fannotation_2Foptimization_2FFastNative_3B")); - pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FReachabilitySensitive_3B", - "Lark_2Fannotation_2Foptimization_2FReachabilitySensitive_3B")); - for (auto &it : pragmaTypeNameMap) { - (void)arkAnnotationTypeNames.insert(it.second); - } -} - -const std::string &ArkAnnotationMap::GetAnnotationTypeName(const std::string &orinName) { - std::map::iterator it = pragmaTypeNameMap.find(orinName); - if (it == pragmaTypeNameMap.end()) { - return orinName; - } else { - return it->second; - } -} -} // namespace bc +#include "ark_annotation_map.h" + +namespace maple { +namespace bc { +ArkAnnotationMap ArkAnnotationMap::annotationMap; + +void ArkAnnotationMap::Init() { + // AnnotationDefault + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FAnnotationDefault_3B", + "Lark_2Fannotation_2FAnnotationDefault_3B")); + // EnclosingClass + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FEnclosingClass_3B", + "Lark_2Fannotation_2FEnclosingClass_3B")); + // EnclosingMethod + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FEnclosingMethod_3B", + "Lark_2Fannotation_2FEnclosingMethod_3B")); + // InnerClass + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FInnerClass_3B", + "Lark_2Fannotation_2FInnerClass_3B")); + // KnownFailure + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FKnownFailure_3B", + "Lark_2Fannotation_2FKnownFailure_3B")); + // MemberClasses + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FMemberClasses_3B", + "Lark_2Fannotation_2FMemberClasses_3B")); + // MethodParameters + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FMethodParameters_3B", + "Lark_2Fannotation_2FMethodParameters_3B")); + // Signature + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FSignature_3B", + "Lark_2Fannotation_2FSignature_3B")); + // SourceDebugExtension + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FSourceDebugExtension_3B", + "Lark_2Fannotation_2FSourceDebugExtension_3B")); + // TestTargetClass + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FTestTargetClass_3B", + "Lark_2Fannotation_2FTestTargetClass_3B")); + // TestTarget + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FTestTarget_3B", + "Lark_2Fannotation_2FTestTarget_3B")); + // Throws + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2FThrows_3B", + "Lark_2Fannotation_2FThrows_3B")); + // compact + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Fcompat_2FUnsupportedAppUsage_3B", + "Lark_2Fannotation_2Fcompat_2FUnsupportedAppUsage_3B")); + // codegen + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Fcodegen_2FCovariantReturnType_3B", + "Lark_2Fannotation_2Fcodegen_2FCovariantReturnType_3B")); + // optimization + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FCriticalNative_3B", + "Lark_2Fannotation_2Foptimization_2FCriticalNative_3B")); + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FDeadReferenceSafe_3B", + "Lark_2Fannotation_2Foptimization_2FDeadReferenceSafe_3B")); + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FFastNative_3B", + "Lark_2Fannotation_2Foptimization_2FFastNative_3B")); + pragmaTypeNameMap.insert(std::make_pair("Ldalvik_2Fannotation_2Foptimization_2FReachabilitySensitive_3B", + "Lark_2Fannotation_2Foptimization_2FReachabilitySensitive_3B")); + for (auto &it : pragmaTypeNameMap) { + (void)arkAnnotationTypeNames.insert(it.second); + } +} + +const std::string &ArkAnnotationMap::GetAnnotationTypeName(const std::string &orinName) { + std::map::iterator it = pragmaTypeNameMap.find(orinName); + if (it == pragmaTypeNameMap.end()) { + return orinName; + } else { + return it->second; + } +} +} // namespace bc } // namespace maple \ No newline at end of file diff --git a/src/hir2mpl/bytecode_input/common/src/bc_function.cpp b/src/hir2mpl/bytecode_input/common/src/bc_function.cpp index 4ef5f0159d10461cdcf43a6f49a4398dd39bac67..f316a33783bbcce49bbec4cfca2142f2757c4387 100644 --- a/src/hir2mpl/bytecode_input/common/src/bc_function.cpp +++ b/src/hir2mpl/bytecode_input/common/src/bc_function.cpp @@ -85,8 +85,9 @@ bool BCFunction::GenerateAliasVars(const std::string &phaseName) { GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName( namemangler::EncodeName(std::get<0>(item))); MIRAliasVars aliasVar; - aliasVar.memPoolStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(localVar->GetName(*mirType)); + aliasVar.mplStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(localVar->GetName(*mirType)); aliasVar.tyIdx = mirType->GetTypeIndex(); + aliasVar.isLocal = !localVar->IsGlobal(); if (!std::get<2>(item).empty()) { aliasVar.sigStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(std::get<2>(item)); } diff --git a/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp b/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp index c8ac5512389e0e1d30fb19b106f37a165e543279..c6fffb2da1c6e3ae37f4cbe278222e1a7ebe534e 100644 --- a/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp +++ b/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp @@ -104,7 +104,8 @@ std::list BCInstruction::EmitToFEIRStmts() { void BCInstruction::SetSrcFileInfo(std::list &stmts) const { #ifdef DEBUG if (FEOptions::GetInstance().IsDumpLOC() && !stmts.empty()) { - (*stmts.begin())->SetSrcFileInfo(srcFileIdx, srcFileLineNum); + Loc loc = {srcFileIdx, srcFileLineNum, 0}; + (*stmts.begin())->SetSrcLoc(loc); } #else (void) stmts; diff --git a/src/hir2mpl/bytecode_input/common/src/bc_pragma.cpp b/src/hir2mpl/bytecode_input/common/src/bc_pragma.cpp index d4f2bfb9ba77edbd3e46254ab98599db9f2ef053..8d432ec58cae12dba602a297b3afa69bd96c5cbd 100644 --- a/src/hir2mpl/bytecode_input/common/src/bc_pragma.cpp +++ b/src/hir2mpl/bytecode_input/common/src/bc_pragma.cpp @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. @@ -12,12 +12,12 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#include "bc_pragma.h" -namespace maple { -namespace bc { -std::vector &BCAnnotationsDirectory::EmitPragmasImpl() { - CHECK_FATAL(false, "this method must be overrided!!!"); - return pragmas; -} -} // namespace bc +#include "bc_pragma.h" +namespace maple { +namespace bc { +std::vector &BCAnnotationsDirectory::EmitPragmasImpl() { + CHECK_FATAL(false, "this method must be overrided!!!"); + return pragmas; +} +} // namespace bc } // namespace maple \ No newline at end of file diff --git a/src/hir2mpl/bytecode_input/common/src/rc_setter.cpp b/src/hir2mpl/bytecode_input/common/src/rc_setter.cpp index b7dfda5c4625c7bb49ac397b508d695f4767d836..526a82ab154937be12cc99fa4706de01416efa7c 100644 --- a/src/hir2mpl/bytecode_input/common/src/rc_setter.cpp +++ b/src/hir2mpl/bytecode_input/common/src/rc_setter.cpp @@ -326,7 +326,7 @@ void RCSetter::SetRCUnownedAttribute(const CallNode &callNode, MIRFunction &func const GStrIdx &strIdx = symbol->GetNameStrIdx(); // checking maple name in ALIAS for (auto als : func.GetAliasVarMap()) { - if (als.second.memPoolStrIdx != strIdx) { + if (als.second.mplStrIdx != strIdx) { continue; } for (auto sit : gStrIdx) { diff --git a/src/hir2mpl/common/include/basic_io.h b/src/hir2mpl/common/include/basic_io.h index 3fae06fedc9d39ca9cbc66dfefda22a096df8253..fd755bd4b6724b5583fd8ebb3ae212989d76201b 100644 --- a/src/hir2mpl/common/include/basic_io.h +++ b/src/hir2mpl/common/include/basic_io.h @@ -131,7 +131,7 @@ class BasicIOMapFile { class BasicIORead { public: - BasicIORead(BasicIOMapFile &f, bool bigEndian = false); + explicit BasicIORead(BasicIOMapFile &f, bool bigEndian = false); virtual ~BasicIORead() = default; uint8 ReadUInt8(); uint8 ReadUInt8(bool &success); diff --git a/src/hir2mpl/common/include/enhance_c_checker.h b/src/hir2mpl/common/include/enhance_c_checker.h index 66eb5b720c32e934e9824d586b699ee0310e292f..2eeba48312a7587088e50ad9d656101ecc9b565a 100644 --- a/src/hir2mpl/common/include/enhance_c_checker.h +++ b/src/hir2mpl/common/include/enhance_c_checker.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -29,19 +29,18 @@ class ENCChecker { static bool HasNonnullAttrInExpr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr, bool isNested = false); static bool HasNullExpr(const UniqueFEIRExpr &expr); static void CheckNonnullGlobalVarInit(const MIRSymbol &sym, const MIRConst *cst); - static void CheckNullFieldInGlobalStruct(MIRType &type, MIRAggConst &cst, const std::vector &initExprs); + static void CheckNullFieldInGlobalStruct(MIRType &type, MIRAggConst &cst, const MapleVector &initExprs); static void CheckNonnullLocalVarInit(const MIRSymbol &sym, const ASTExpr *initExpr); static void CheckNonnullLocalVarInit(const MIRSymbol &sym, const UniqueFEIRExpr &initFEExpr, std::list &stmts); static std::string GetNthStr(size_t index); static std::string PrintParamIdx(const std::list &idxs); - static void CheckNonnullArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, - uint32 fileNum, uint32 fileLine); + static void CheckNonnullArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, const Loc &loc); static bool HasNonnullFieldInStruct(const MIRType &mirType); static bool HasNonnullFieldInPtrStruct(const MIRType &mirType); + static void CheckNonnullFieldInStruct(const MIRType &src, const MIRType &dst, const Loc &loc); static bool IsSameBoundary(const AttrBoundary &arg1, const AttrBoundary &arg2); - static void CheckBoundaryArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, - uint32 fileNum, uint32 fileLine); + static void CheckBoundaryArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, const Loc &loc); static UniqueFEIRExpr FindBaseExprInPointerOperation(const UniqueFEIRExpr &expr, bool isIncludingAddrof = false); static MIRType *GetTypeFromAddrExpr(const UniqueFEIRExpr &expr); static MIRType *GetArrayTypeFromExpr(const UniqueFEIRExpr &expr); @@ -61,7 +60,7 @@ class ENCChecker { const ASTCallExpr &astCallExpr); static UniqueFEIRExpr GetRealBoundaryLenExprInField(const UniqueFEIRExpr &lenExpr, MIRStructType &baseType, const UniqueFEIRExpr &dstExpr); - static void InitBoundaryVarFromASTDecl(const MapleAllocator &allocator, ASTDecl *ptrDecl, + static void InitBoundaryVarFromASTDecl(MapleAllocator &allocator, ASTDecl *ptrDecl, ASTExpr *lenExpr, std::list &stmts); static void InitBoundaryVar(MIRFunction &curFunction, const ASTDecl &ptrDecl, UniqueFEIRExpr lenExpr, std::list &stmts); @@ -71,15 +70,14 @@ class ENCChecker { UniqueFEIRExpr lenExpr, std::list &stmts); static UniqueFEIRExpr GetGlobalOrFieldLenExprInExpr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr); static void InsertBoundaryAssignChecking(MIRBuilder &mirBuilder, std::list &ans, - const UniqueFEIRExpr &srcExpr, uint32 fileIdx, uint32 fileLine); + const UniqueFEIRExpr &srcExpr, const Loc &loc); static UniqueFEIRStmt InsertBoundaryLEChecking(UniqueFEIRExpr lenExpr, const UniqueFEIRExpr &srcExpr, const UniqueFEIRExpr &dstExpr); static void CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const UniqueFEIRVar &var, FieldID fieldID, - uint32 fileIdx, uint32 fileLine); + const Loc &loc); static void CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const UniqueFEIRType &addrType, FieldID fieldID, - uint32 fileIdx, uint32 fileLine); - static void CheckBoundaryLenFinalAddr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr, - uint32 fileIdx, uint32 fileLine); + const Loc &loc); + static void CheckBoundaryLenFinalAddr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr, const Loc &loc); static MapleVector ReplaceBoundaryChecking(MIRBuilder &mirBuilder, const FEIRStmtNary *stmt); static UniqueFEIRExpr GetBoundaryLenExprCache(uint32 hash); static UniqueFEIRExpr GetBoundaryLenExprCache(const TypeAttrs &attr); @@ -90,6 +88,7 @@ class ENCChecker { static void InsertBoundaryInAtts(FuncAttrs &attr, const BoundaryInfo &boundary); static bool IsSafeRegion(const MIRBuilder &mirBuilder); static bool IsUnsafeRegion(const MIRBuilder &mirBuilder); + static void CheckLenExpr(const ASTExpr &lenExpr, const std::list &nullstmts); }; // class ENCChecker } // namespace maple #endif // HIR2MPL_INCLUDE_COMMON_ENCCHECKER_H diff --git a/src/hir2mpl/common/include/fe_config_parallel.h b/src/hir2mpl/common/include/fe_config_parallel.h index 6ef8c11163d851a9e3e78a3128a286742c6ebabe..8d65a4d3aea91479480e0d3638ad7dcc06cbb1fa 100644 --- a/src/hir2mpl/common/include/fe_config_parallel.h +++ b/src/hir2mpl/common/include/fe_config_parallel.h @@ -47,7 +47,7 @@ class FEConfigParallel { void RegisterRunThreadID(const std::thread::id &tid) { mtx.lock(); - CHECK_FATAL(runThreadIDs.insert(tid).second == true, "failed to register thread id"); + CHECK_FATAL(runThreadIDs.insert(tid).second, "failed to register thread id"); mtx.unlock(); } diff --git a/src/hir2mpl/common/include/fe_file_type.h b/src/hir2mpl/common/include/fe_file_type.h index 65c3a3dbe09b19432567bb9e7d874cbb86543aab..b4e51d55513c211e7e942cb2fb2d8c70c2b0bb38 100644 --- a/src/hir2mpl/common/include/fe_file_type.h +++ b/src/hir2mpl/common/include/fe_file_type.h @@ -54,7 +54,7 @@ class FEFileType { static const uint32 kMagicZip = 0x04034B50; static const uint32 kMagicDex = 0x0A786564; static const uint32 kMagicAST = 0x48435043; - static const uint32 kMagicMAST = 0x854C504D; + static const uint32 kMagicMAST = 0xAB4C504D; std::map mapExtNameType; std::map mapTypeMagic; std::map mapMagicType; diff --git a/src/hir2mpl/common/include/fe_function.h b/src/hir2mpl/common/include/fe_function.h index cd953736117b490f56db172e7c479f5607716a5e..2152042eace7a45835538353a3f73b58ab5a05aa 100644 --- a/src/hir2mpl/common/include/fe_function.h +++ b/src/hir2mpl/common/include/fe_function.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -25,9 +25,11 @@ #include "feir_bb.h" #include "feir_stmt.h" #include "fe_timer_ns.h" +#include "feir_lower.h" #include "feir_cfg.h" #include "fe_function_phase_result.h" #include "feir_type_infer.h" +#include "feir_scope.h" namespace maple { #define SET_FUNC_INFO_PAIR(A, B, C, D) \ @@ -38,9 +40,6 @@ class FEFunction { public: FEFunction(MIRFunction &argMIRFunction, const std::unique_ptr &argPhaseResultTotal); virtual ~FEFunction(); - void LabelGenStmt(); - void LabelGenBB(); - bool HasDeadBB(); // element memory manage method FEIRStmt *RegisterGeneralStmt(std::unique_ptr stmt); @@ -50,11 +49,26 @@ class FEFunction { std::string GetDescription(); void OutputUseDefChain(); void OutputDefUseChain(); - + void PushFuncScope(const SrcPosition &startOfScope, const SrcPosition &endOfScope); + void PushStmtScope(const SrcPosition &startOfScope, const SrcPosition &endOfScope); + UniqueFEIRScope PopTopStmtScope(); + FEIRScope *GetTopStmtFEIRScopePtr() const; + MIRScope *GetTopStmtMIRScope() const; + void AddAliasInMIRScope(MIRScope *scope, const std::string &srcVarName, const MIRSymbol *symbol); void SetSrcFileName(const std::string &fileName) { srcFileName = fileName; } + const FEIRStmt *GetFEIRStmtHead() const { + ASSERT_NOT_NULL(feirStmtHead); + return feirStmtHead; + } + + const FEIRStmt *GetFEIRStmtTail() const { + ASSERT_NOT_NULL(feirStmtTail); + return feirStmtTail; + } + void Init() { InitImpl(); } @@ -112,6 +126,9 @@ class FEFunction { virtual bool SetupFEIRStmtJavaTry(const std::string &phaseName); virtual bool SetupFEIRStmtBranch(const std::string &phaseName); virtual bool UpdateRegNum2This(const std::string &phaseName); + bool LowerFunc(const std::string &phaseName); + bool DumpFEIRBBs(const std::string &phaseName); + bool DumpFEIRCFGGraph(const std::string &phaseName); bool BuildFEIRDFG(const std::string &phaseName); // process fe ir check point, build fe ir DFG bool BuildFEIRUDDU(const std::string &phaseName); // build fe ir UD DU chain bool TypeInfer(const std::string &phaseName); // feir based Type Infer @@ -135,15 +152,11 @@ class FEFunction { virtual bool VerifyGeneral() = 0; virtual void VerifyGeneralFailCallBack() = 0; virtual void DumpGeneralStmts(); - virtual void DumpFEIRBBs(); - virtual void DumpFEIRCFGGraph(); virtual std::string GetGeneralFuncName() const; void EmitToMIRStmt(); void PhaseTimerStart(FETimerNS &timer); void PhaseTimerStopAndDump(FETimerNS &timer, const std::string &label); - virtual void DumpFEIRCFGGraphForBB(std::ofstream &file, const FEIRBB &bb); - virtual void DumpFEIRCFGGraphForCFGEdge(std::ofstream &file); virtual void DumpFEIRCFGGraphForDFGEdge(std::ofstream &file); virtual bool HasThis() = 0; virtual bool IsNative() = 0; @@ -155,11 +168,11 @@ class FEFunction { std::list genStmtListRaw; FEIRBB *genBBHead; FEIRBB *genBBTail; - std::unique_ptr generalCFG; FEIRStmt *feirStmtHead; FEIRStmt *feirStmtTail; FEIRBB *feirBBHead; FEIRBB *feirBBTail; + std::unique_ptr feirLower; std::unique_ptr feirCFG; std::map genStmtBBMap; std::vector> argVarList; @@ -213,6 +226,8 @@ class FEFunction { std::list> genStmtList; std::list> genBBList; + // FeirStmts generated by feirLower are inserted after the kStmtPesudoFuncEnd and linked, + // Access sequential feirStmt instructions through a doubly linked FELinkListNode from feirStmtHead std::list feirStmtList; std::list> feirBBList; std::map feirStmtBBMap; @@ -223,6 +238,8 @@ class FEFunction { std::map defVarTypeScatterStmtMap; std::unordered_map> boundaryMap; // EnhanceC boundary var std::stack safeRegionFlag; // EnhanceC saferegion(true: safe, false: unsafe) + // an element of the stack represents the scope of one compoundstmt or forstmt + std::stack stmtsScopeStack; }; } // namespace maple #endif // HIR2MPL_INCLUDE_COMMON_FE_FUNCTION_H \ No newline at end of file diff --git a/src/hir2mpl/common/include/fe_input.h b/src/hir2mpl/common/include/fe_input.h index 369cdfe46bef2e1b82381337dbad4b45cd57704a..b9cdfd2d2ace67c6fce6270297a56baf618a7f53 100644 --- a/src/hir2mpl/common/include/fe_input.h +++ b/src/hir2mpl/common/include/fe_input.h @@ -14,7 +14,6 @@ */ #ifndef HIR2MPL_INCLUDE_FE_INPUT_H #define HIR2MPL_INCLUDE_FE_INPUT_H -#include #include "global_tables.h" #include "mir_module.h" #include "mpl_logging.h" @@ -52,7 +51,7 @@ enum FEInputSameNamePolicy { template class FEInputContent { public: - FEInputContent(MapleAllocator &alloc); + explicit FEInputContent(MapleAllocator &alloc); ~FEInputContent() = default; void RegisterItem(T &item); void CheckSameName(); @@ -75,7 +74,7 @@ class FEInputProgramUnit { class FEInputUnitMethod : public FEInputUnit { public: - FEInputUnitMethod(MapleAllocator &alloc); + explicit FEInputUnitMethod(MapleAllocator &alloc); ~FEInputUnitMethod() = default; protected: @@ -86,7 +85,7 @@ class FEInputUnitMethod : public FEInputUnit { class FEInputUnitVariable : public FEInputUnit { public: - FEInputUnitVariable(MapleAllocator &alloc); + explicit FEInputUnitVariable(MapleAllocator &alloc); ~FEInputUnitVariable() = default; protected: diff --git a/src/hir2mpl/common/include/fe_input_helper.h b/src/hir2mpl/common/include/fe_input_helper.h index 4faa813c13467fb15fbe8e3c594dcda065e8f48f..8500787c9d6ce93db186f19f309e15c372a4a5ba 100644 --- a/src/hir2mpl/common/include/fe_input_helper.h +++ b/src/hir2mpl/common/include/fe_input_helper.h @@ -22,12 +22,12 @@ #include "fe_function.h" namespace maple { -typedef struct { +struct ExtraField { std::string klass; std::string field; std::string type; std::string attr; -} ExtraField; +}; class FEInputContainer { public: @@ -57,7 +57,7 @@ class FEInputStructHelper; class FEInputGlobalVarHelper { public: - FEInputGlobalVarHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn) {} + explicit FEInputGlobalVarHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn) {} virtual ~FEInputGlobalVarHelper() = default; bool ProcessDecl() { @@ -75,7 +75,7 @@ class FEInputGlobalVarHelper { class FEInputFileScopeAsmHelper { public: - FEInputFileScopeAsmHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn) {} + explicit FEInputFileScopeAsmHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn) {} virtual ~FEInputFileScopeAsmHelper() = default; bool ProcessDecl() { @@ -93,7 +93,7 @@ class FEInputFileScopeAsmHelper { class FEInputFieldHelper { public: - FEInputFieldHelper(MapleAllocator &allocator) {} + explicit FEInputFieldHelper(MapleAllocator &allocator) {} virtual ~FEInputFieldHelper() = default; const FieldPair &GetMIRFieldPair() const { return mirFieldPair; @@ -131,7 +131,7 @@ class FEInputFieldHelper { class FEInputMethodHelper { public: - FEInputMethodHelper(MapleAllocator &allocatorIn) + explicit FEInputMethodHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn), srcLang(kSrcLangUnknown), feFunc(nullptr), diff --git a/src/hir2mpl/common/include/fe_macros.h b/src/hir2mpl/common/include/fe_macros.h index 37b0f9cb265a1131e9573ee50e23642090a569ff..80de014441308902f804030668dd920e72a77809 100644 --- a/src/hir2mpl/common/include/fe_macros.h +++ b/src/hir2mpl/common/include/fe_macros.h @@ -19,7 +19,6 @@ #include #include #include -#include #include "fe_options.h" #include "mpl_logging.h" diff --git a/src/hir2mpl/common/include/fe_manager.h b/src/hir2mpl/common/include/fe_manager.h index ba96fb4755a00d2949f734d22da117524c1aecd7..e3508189f12ea028cd3ceb5a64f430f5d1fc8ba5 100644 --- a/src/hir2mpl/common/include/fe_manager.h +++ b/src/hir2mpl/common/include/fe_manager.h @@ -113,7 +113,7 @@ class FEManager { } uint32 RegisterSourceFileIdx(const GStrIdx &strIdx) { - auto it = sourceFileIdxMap.find(strIdx); + const auto it = sourceFileIdxMap.find(strIdx); if (it != sourceFileIdxMap.end()) { return it->second; } else { diff --git a/src/hir2mpl/common/include/fe_options.h b/src/hir2mpl/common/include/fe_options.h index e00a26ba3251d267a2fd4050fbaac58ed3ef39cc..d7ec8672511bd6adc02d6405d3a988f21f8a33c6 100644 --- a/src/hir2mpl/common/include/fe_options.h +++ b/src/hir2mpl/common/include/fe_options.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -236,6 +236,16 @@ class FEOptions { return isDumpLOC; } + void SetDbgFriendly(bool flag) { + isDbgFriendly = flag; + // set isDumpLOC if flag is true + isDumpLOC = flag ? flag : isDumpLOC; + } + + bool IsDbgFriendly() const { + return isDbgFriendly; + } + void SetIsDumpPhaseTime(bool flag) { isDumpPhaseTime = flag; } @@ -285,28 +295,21 @@ class FEOptions { return isDumpJBCStmt; } - void SetIsDumpJBCBB(bool flag) { - isDumpJBCBB = flag; - } - - bool IsDumpJBCBB() const { - return isDumpJBCBB; + void SetIsDumpFEIRBB(bool flag) { + isDumpBB = flag; } - void SetIsDumpFEIRCFGGraph(bool flag) { - isDumpGenCFGGraph = flag; + bool IsDumpFEIRBB() const { + return isDumpBB; } - bool IsDumpFEIRCFGGraph() const { - return isDumpGenCFGGraph; + void AddFuncNameForDumpCFGGraph(const std::string &funcName) { + funcNamesForDumpCFGGraph.insert(funcName); } - void SetFEIRCFGGraphFileName(const std::string &fileName) { - genCFGGraphFileName = fileName; - } - - const std::string GetJBCCFGGraphFileName() const { - return genCFGGraphFileName; + bool IsDumpFEIRCFGGraph(const std::string &funcName) const { + return funcNamesForDumpCFGGraph.find(funcName) != + funcNamesForDumpCFGGraph.end(); } void SetIsDumpJBCAll(bool flag) { @@ -472,6 +475,14 @@ class FEOptions { return funcInlineSize; } + void SetWPAA(bool flag) { + wpaa = flag; + } + + bool GetWPAA() const { + return wpaa; + } + private: static FEOptions options; // input control options @@ -504,6 +515,7 @@ class FEOptions { bool isDumpTime; bool isDumpComment = false; bool isDumpLOC = true; + bool isDbgFriendly = false; bool isDumpPhaseTime = false; bool isDumpPhaseTimeDetail = false; @@ -512,7 +524,6 @@ class FEOptions { bool isJBCUseImpreciseType = false; bool isJBCInfoUsePathName = false; bool isDumpJBCStmt = false; - bool isDumpJBCBB = false; bool isDumpJBCAll = false; bool isDumpJBCErrorOnly = false; std::set dumpJBCFuncNames; @@ -530,8 +541,8 @@ class FEOptions { bool isBigEndian = false; // general stmt/bb/cfg debug options - bool isDumpGenCFGGraph = false; - std::string genCFGGraphFileName = ""; + bool isDumpBB = false; + std::set funcNamesForDumpCFGGraph; // parallel uint32 nthreads; @@ -549,6 +560,7 @@ class FEOptions { bool isEnableSafeRegion = false; uint32 funcInlineSize = 0; + bool wpaa = false; FEOptions(); ~FEOptions() = default; diff --git a/src/hir2mpl/common/include/fe_struct_elem_info.h b/src/hir2mpl/common/include/fe_struct_elem_info.h index b533e9c969cc4889679ac535905a4ab92f902c33..ac2933efc115e5444223a4415a31ec7733dce505 100644 --- a/src/hir2mpl/common/include/fe_struct_elem_info.h +++ b/src/hir2mpl/common/include/fe_struct_elem_info.h @@ -29,6 +29,7 @@ struct StructElemNameIdx { StructElemNameIdx(const GStrIdx &argKlass, const GStrIdx &argElem, const GStrIdx &argType, const GStrIdx &argFull) : klass(argKlass), elem(argElem), type(argType), full(argFull) {} + StructElemNameIdx(const std::string &klassStr, const std::string &elemStr, const std::string &typeStr) { const std::string &fullName = klassStr + "|" + elemStr + "|" + typeStr; klass = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(namemangler::EncodeName(klassStr)); @@ -36,7 +37,8 @@ struct StructElemNameIdx { type = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(namemangler::EncodeName(typeStr)); full = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(namemangler::EncodeName(fullName)); } - StructElemNameIdx(const std::string &funcStr) { + + explicit StructElemNameIdx(const std::string &funcStr) { klass = GStrIdx(0); elem = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(funcStr); type = GStrIdx(0); diff --git a/src/hir2mpl/common/include/fe_timer_ns.h b/src/hir2mpl/common/include/fe_timer_ns.h index 6ade65f5afe9c4d7c9b90b89cc701f6771c4f5aa..f8a73d19888eb7ad8de097a5b79b87ee7cf6d7c8 100644 --- a/src/hir2mpl/common/include/fe_timer_ns.h +++ b/src/hir2mpl/common/include/fe_timer_ns.h @@ -16,7 +16,6 @@ #define HIR2MPL_INCLUDE_COMMON_FE_TIMER_NS_H #include #include -#include namespace maple { class FETimerNS { diff --git a/src/hir2mpl/common/include/fe_utils.h b/src/hir2mpl/common/include/fe_utils.h index 92184fce85df2d9e457fc6b1668af32833ab43d4..8b4df709242f4110bed259ee174f7d506b379dcb 100644 --- a/src/hir2mpl/common/include/fe_utils.h +++ b/src/hir2mpl/common/include/fe_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -25,6 +25,20 @@ #include "mir_nodes.h" namespace maple { +struct Loc { + uint32 fileIdx; + uint32 line; + uint32 column; + + SrcPosition Emit2SourcePosition() const { + SrcPosition srcPos; + srcPos.SetFileNum(static_cast(fileIdx)); + srcPos.SetLineNum(line); + srcPos.SetColumn(static_cast(column)); + return srcPos; + } +}; + class FEUtils { public: FEUtils() = default; @@ -39,9 +53,10 @@ class FEUtils { static std::string GetBaseTypeName(const std::string &typeName); static PrimType GetPrimType(const GStrIdx &typeNameIdx); static uint32 GetSequentialNumber(); - static std::string GetFileNameHashStr(const std::string &fileName); + static std::string GetFileNameHashStr(const std::string &fileName, uint32 seed = 211); static std::string GetSequentialName0(const std::string &prefix, uint32_t num); static std::string GetSequentialName(const std::string &prefix); + static std::string CreateLabelName(); static FieldID GetStructFieldID(MIRStructType *base, const std::string &fieldName); static bool TraverseToNamedField(MIRStructType &structType, const GStrIdx &nameIdx, FieldID &fieldID, bool isTopLevel = true); @@ -262,6 +277,7 @@ class FELinkListNode { void InsertAfter(FELinkListNode *ins); static void InsertBefore(FELinkListNode *ins, FELinkListNode *pos); static void InsertAfter(FELinkListNode *ins, FELinkListNode *pos); + static void SpliceNodes(FELinkListNode *head, FELinkListNode *tail, FELinkListNode *newTail); FELinkListNode *GetPrev() const { return prev; } diff --git a/src/hir2mpl/common/include/fe_utils_ast.h b/src/hir2mpl/common/include/fe_utils_ast.h index 8591fb5a7a0317c3ae40cb8ed53480643106f2db..debf40a5916dc400b678f8752e26e3276166644d 100644 --- a/src/hir2mpl/common/include/fe_utils_ast.h +++ b/src/hir2mpl/common/include/fe_utils_ast.h @@ -15,7 +15,6 @@ #ifndef HIR2MPL_INCLUDE_FE_UTILS_AST_H #define HIR2MPL_INCLUDE_FE_UTILS_AST_H #include -#include #include "types_def.h" #include "cfg_primitive_types.h" #include "mempool.h" @@ -32,124 +31,5 @@ class FEUtilAST { FEUtilAST() = default; ~FEUtilAST() = default; }; - -template -std::function OpGenerator(Opcode op, T p0, T p1, bool isSigned) { - switch (op) { - case OP_add: { - return [p0, p1]() { return p0 + p1; }; - } - case OP_sub: { - return [p0, p1]() { return p0 - p1; }; - } - case OP_mul: { - return [p0, p1]() { return p0 * p1; }; - } - case OP_div: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) / static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) / static_cast(p1); }; - } - } - case OP_rem: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) % static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) % static_cast(p1); }; - } - } - case OP_shl: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) << static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) << static_cast(p1); }; - } - } - case OP_lshr: - case OP_ashr: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) >> static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) >> static_cast(p1); }; - } - } - case OP_bior: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) | static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) | static_cast(p1); }; - } - } - case OP_band: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) & static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) & static_cast(p1); }; - } - } - case OP_bxor: { - if (isSigned) { - return [p0, p1]() { return static_cast(p0) ^ static_cast(p1); }; - } else { - return [p0, p1]() { return static_cast(p0) ^ static_cast(p1); }; - } - } - case OP_land: { - return [p0, p1]() { - if (!p0) { - return static_cast(0); - } else if (!p1) { - return static_cast(0); - } else { - return static_cast(1); - } - }; - } - case OP_lior: { - return [p0, p1]() { - if (p0) { - return static_cast(1); - } else if (p1) { - return static_cast(1); - } else { - return static_cast(0); - } - }; - } - case OP_cand: { - return [p0, p1]() { - if (!p0) { - return static_cast(0); - } else if (!p1) { - return static_cast(0); - } else { - return static_cast(1); - } - }; - } - case OP_cior: { - return [p0, p1]() { - if (p0) { - return static_cast(1); - } else if (p1) { - return static_cast(1); - } else { - return static_cast(0); - } - }; - } - default: { - return nullptr; - } - } - return nullptr; -} - -template -T *MIRConstGenerator(MemPool *mp, T *konst0, T *konst1, Opcode op) { - bool isSigned = IsSignedInteger(konst0->GetType().GetPrimType()) && IsSignedInteger(konst1->GetType().GetPrimType()); - return mp->New(OpGenerator(op, konst0->GetValue(), konst1->GetValue(), isSigned)(), konst0->GetType()); -} } // namespace maple #endif // HIR2MPL_INCLUDE_FE_UTILS_AST_H diff --git a/src/hir2mpl/common/include/fe_utils_java.h b/src/hir2mpl/common/include/fe_utils_java.h index e914e6ff4c5a9e9bd739d798de1135d841599ffa..1f58dddd688b3a0a0627d33963af62b812f5b604 100644 --- a/src/hir2mpl/common/include/fe_utils_java.h +++ b/src/hir2mpl/common/include/fe_utils_java.h @@ -17,6 +17,8 @@ #include #include #include "feir_type.h" +#include "global_tables.h" +#include "types_def.h" namespace maple { class FEUtilJava { @@ -24,9 +26,39 @@ class FEUtilJava { static std::vector SolveMethodSignature(const std::string &signature); static std::string SolveParamNameInJavaFormat(const std::string &signature); + static GStrIdx &GetMultiANewArrayClassIdx() { + static GStrIdx multiANewArrayClassIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName( + namemangler::EncodeName("Ljava/lang/reflect/Array;")); + return multiANewArrayClassIdx; + } + + static GStrIdx &GetMultiANewArrayElemIdx() { + static GStrIdx multiANewArrayElemIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName( + namemangler::EncodeName("newInstance")); + return multiANewArrayElemIdx; + } + + static GStrIdx &GetMultiANewArrayTypeIdx() { + static GStrIdx multiANewArrayTypeIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName( + namemangler::EncodeName("(Ljava/lang/Class;[I)Ljava/lang/Object;")); + return multiANewArrayTypeIdx; + } + + static GStrIdx &GetMultiANewArrayFullIdx() { + static GStrIdx multiANewArrayFullIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName( + namemangler::EncodeName("Ljava/lang/reflect/Array;|newInstance|(Ljava/lang/Class;[I)Ljava/lang/Object;")); + return multiANewArrayFullIdx; + } + + static GStrIdx &GetJavaThrowableNameMplIdx() { + static GStrIdx javaThrowableNameMplIdx = + GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(namemangler::EncodeName( "Ljava/lang/Throwable;")); + return javaThrowableNameMplIdx; + } + private: FEUtilJava() = default; ~FEUtilJava() = default; }; } // namespace maple -#endif // HIR2MPL_INCLUDE_FE_UTILS_JAVA_H \ No newline at end of file +#endif // HIR2MPL_INCLUDE_FE_UTILS_JAVA_H diff --git a/src/hir2mpl/common/include/feir_node_kind.def b/src/hir2mpl/common/include/feir_node_kind.def index 8139d80342b420ae4afc9bb891e13e64eef9fb64..42d9797447be5639f57e569b28b2a089a4b39c9b 100644 --- a/src/hir2mpl/common/include/feir_node_kind.def +++ b/src/hir2mpl/common/include/feir_node_kind.def @@ -1,6 +1,6 @@ // FEIR_NODE_KIND (kind, description) FEIR_NODE_KIND(Stmt, "Stmt") -FEIR_NODE_KIND(FEIRStmtNary, "FEIRStmtNary") +FEIR_NODE_KIND(StmtNary, "StmtNary") FEIR_NODE_KIND(StmtAssign, "StmtAssign") FEIR_NODE_KIND(StmtNonAssign, "StmtNonAssign") FEIR_NODE_KIND(StmtPesudo, "StmtPesudo") @@ -83,3 +83,5 @@ FEIR_NODE_KIND(StmtContinue, "StmtContinue") FEIR_NODE_KIND(StmtLabel, "StmtLabel") FEIR_NODE_KIND(StmtAtomic, "StmtAtomic") FEIR_NODE_KIND(StmtGCCAsm, "StmtGCCAsm") +FEIR_NODE_KIND(StmtPesudoHead, "StmtPesudoHead") +FEIR_NODE_KIND(StmtPesudoTail, "StmtPesudoTail") diff --git a/src/hir2mpl/common/include/feir_scope.h b/src/hir2mpl/common/include/feir_scope.h new file mode 100644 index 0000000000000000000000000000000000000000..a8dd2dd9b8b86c716169aa45a96a854eef5f7fc0 --- /dev/null +++ b/src/hir2mpl/common/include/feir_scope.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) [2022] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "mir_scope.h" +#include "mpl_logging.h" +#include "src_position.h" +#include "feir_var.h" +#include "feir_stmt.h" + +#ifndef HIR2MPL_COMMON_INCLUDE_FEIR_SCOPE_H +#define HIR2MPL_COMMON_INCLUDE_FEIR_SCOPE_H +namespace maple { +class FEIRScope; +using UniqueFEIRScope = std::unique_ptr; + +class FEIRScope { + public: + FEIRScope() {}; + explicit FEIRScope(MIRScope *scope); + virtual ~FEIRScope() = default; + + void SetMIRScope(MIRScope *scope) { + mirScope = scope; + } + + MIRScope *GetMIRScope() const { + CHECK_NULL_FATAL(mirScope); + return mirScope; + } + + void SetVLASavedStackVar(UniqueFEIRVar var) { + vlaSavedStackVar = std::move(var); + } + + const UniqueFEIRVar &GetVLASavedStackVar() const { + return vlaSavedStackVar; + } + + UniqueFEIRStmt GenVLAStackRestoreStmt() const; + + private: + MIRScope *mirScope = nullptr; + UniqueFEIRVar vlaSavedStackVar = nullptr; +}; +} // namespace maple +#endif // HIR2MPL_AST_INPUT_INCLUDE_AST_VAR_SCOPE_H \ No newline at end of file diff --git a/src/hir2mpl/common/include/feir_stmt.h b/src/hir2mpl/common/include/feir_stmt.h old mode 100755 new mode 100644 index 4ffc046f50a57a3802f1718fd6593a50addaecc2..56165ac398ddeaa682eb62093270d02a5ffa083b --- a/src/hir2mpl/common/include/feir_stmt.h +++ b/src/hir2mpl/common/include/feir_stmt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -138,17 +138,13 @@ class FEIRStmt : public FELinkListNode { } bool IsFallThru() const { - return isFallThru; + return IsFallThroughImpl(); } void SetFallThru(bool arg) { isFallThru = arg; } - bool IsFallThrough() const { - return IsFallThroughImpl(); - } - bool IsBranch() const { return IsBranchImpl(); } @@ -189,28 +185,20 @@ class FEIRStmt : public FELinkListNode { return isAuxPre || isAuxPost; } - const std::vector &GetPredsOrSuccs() const { - return predsOrSuccs; - } - - void AddPredOrSucc(FEIRStmt &stmt) { - predsOrSuccs.push_back(&stmt); - } - - const std::vector &GetPreds() const { - return predsOrSuccs; + const std::vector &GetExtraPreds() const { + return extraPreds; } - const std::vector &GetSuccs() const { - return predsOrSuccs; + const std::vector &GetExtraSuccs() const { + return extraSuccs; } - void AddPred(FEIRStmt &stmt) { - predsOrSuccs.push_back(&stmt); + void AddExtraPred(FEIRStmt &stmt) { + extraPreds.push_back(&stmt); } - void AddSucc(FEIRStmt &stmt) { - predsOrSuccs.push_back(&stmt); + void AddExtraSucc(FEIRStmt &stmt) { + extraSuccs.push_back(&stmt); } bool HasDef() const { @@ -228,21 +216,24 @@ class FEIRStmt : public FELinkListNode { bool IsStmtInstComment() const; bool ShouldHaveLOC() const; BaseNode *ReplaceAddrOfNode(BaseNode *node) const; - void SetSrcFileInfo(uint32 srcFileIdxIn, uint32 srcFileLineNumIn) { - srcFileIndex = srcFileIdxIn; - srcFileLineNum = srcFileLineNumIn; + void SetSrcLoc(const Loc &l) { + loc = l; + } + + Loc GetSrcLoc() const { + return loc; } uint32 GetSrcFileIdx() const { - return srcFileIndex; + return loc.fileIdx; } uint32 GetSrcFileLineNum() const { - return srcFileLineNum; + return loc.line; } bool HasSetLOCInfo() const { - return (srcFileLineNum != 0 || srcFileIndex != 0); + return (loc.fileIdx != 0 || loc.line != 0); } bool IsDummy() const { @@ -277,7 +268,7 @@ class FEIRStmt : public FELinkListNode { virtual std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const; virtual bool IsStmtInstImpl() const; virtual bool IsFallThroughImpl() const { - return true; + return isFallThru; } virtual bool IsBranchImpl() const { @@ -302,22 +293,23 @@ class FEIRStmt : public FELinkListNode { void SetMIRStmtSrcPos(std::list &stmts) const { if (FEOptions::GetInstance().IsDumpLOC() && !stmts.empty()) { - (*stmts.begin())->GetSrcPos().SetFileNum(static_cast(srcFileIndex)); - (*stmts.begin())->GetSrcPos().SetLineNum(srcFileLineNum); + (*stmts.begin())->GetSrcPos().SetFileNum(static_cast(loc.fileIdx)); + (*stmts.begin())->GetSrcPos().SetLineNum(loc.line); + (*stmts.begin())->GetSrcPos().SetColumn(static_cast(loc.column)); } } FEIRNodeKind kind; uint32 id = 0; - uint32 srcFileIndex = 0; - uint32 srcFileLineNum = 0; + Loc loc = {0, 0, 0}; uint32 hexPC = UINT32_MAX; bool isDummy = false; - bool isFallThru = false; + bool isFallThru = true; bool isAuxPre = false; bool isAuxPost = false; bool isThrowable = false; - std::vector predsOrSuccs; + std::vector extraPreds; + std::vector extraSuccs; }; using UniqueFEIRStmt = std::unique_ptr; @@ -457,6 +449,18 @@ class FEIRExpr { return HashImpl(); } + void SetLoc(const Loc &locIn) { + loc = locIn; + } + + const Loc GetLoc() const { + return loc; + } + + std::string Dump() const { + return GetFEIRNodeKindDescription(kind); + } + protected: virtual std::unique_ptr CloneImpl() const = 0; virtual BaseNode *GenMIRNodeImpl(MIRBuilder &mirBuilder) const = 0; @@ -512,6 +516,7 @@ class FEIRExpr { bool hasException : 1; bool isBoundaryChecking : 1; std::unique_ptr type; + Loc loc = {0, 0, 0}; }; // class FEIRExpr using UniqueFEIRExpr = std::unique_ptr; @@ -668,12 +673,14 @@ class FEIRExprRegRead : public FEIRExpr { // ---------- FEIRExprAddrofConstArray ---------- class FEIRExprAddrofConstArray : public FEIRExpr { public: - FEIRExprAddrofConstArray(const std::vector &arrayIn, MIRType *typeIn); - FEIRExprAddrofConstArray(const std::string &arrayNameIn, const std::vector &arrayIn, MIRType *typeIn) + FEIRExprAddrofConstArray(const std::vector &arrayIn, MIRType *typeIn, const std::string &strIn); + FEIRExprAddrofConstArray(const std::string &arrayNameIn, const std::vector &arrayIn, MIRType *typeIn, + const std::string &strIn) : FEIRExpr(FEIRNodeKind::kExprAddrof, FEIRTypeHelper::CreateTypeNative(*GlobalTables::GetTypeTable().GetPtrType())), arrayName(arrayNameIn), - elemType(typeIn) { + elemType(typeIn), + str(strIn) { std::copy(arrayIn.begin(), arrayIn.end(), std::back_inserter(array)); } @@ -711,6 +718,7 @@ class FEIRExprAddrofConstArray : public FEIRExpr { std::string arrayName; std::vector array; MIRType *elemType = nullptr; + std::string str; }; // ---------- FEIRExprAddrOfLabel ---------- @@ -861,7 +869,7 @@ class FEIRExprAddrofArray : public FEIRExpr { void SetIndexsExprs(std::list &exprs) { exprIndexs.clear(); - for (auto &e : exprs) { + for (const auto &e : exprs) { auto ue = e->Clone(); exprIndexs.push_back(std::move(ue)); } @@ -894,7 +902,7 @@ class FEIRExprAddrofArray : public FEIRExpr { hash += exprArray->Hash(); } std::size_t seed = exprIndexs.size(); - for (auto &idx : exprIndexs) { + for (const auto &idx : exprIndexs) { if (idx != nullptr) { seed ^= idx->Hash() + kRandomNum + (seed << 6) + (seed >> 2); } @@ -1040,6 +1048,11 @@ class FEIRExprIRead : public FEIRExpr { return type->Clone(); } + void SetClonedOpnd(UniqueFEIRExpr argOpnd) { + CHECK_FATAL(argOpnd != nullptr, "opnd is nullptr"); + subExpr = std::move(argOpnd); + } + UniqueFEIRExpr GetClonedOpnd() const { return subExpr->Clone(); } @@ -1324,7 +1337,7 @@ class FEIRExprJavaNewArray : public FEIRExpr { // ---------- FEIRExprJavaArrayLength ---------- class FEIRExprJavaArrayLength : public FEIRExpr { public: - FEIRExprJavaArrayLength(UniqueFEIRExpr argExprArray); + explicit FEIRExprJavaArrayLength(UniqueFEIRExpr argExprArray); ~FEIRExprJavaArrayLength() = default; void SetExprArray(UniqueFEIRExpr argExprArray) { CHECK_NULL_FATAL(argExprArray); @@ -1855,7 +1868,7 @@ class FEIRStmtReturn : public FEIRStmtUseOnly { // ---------- FEIRStmtPesudoLabel ---------- class FEIRStmtPesudoLabel : public FEIRStmt { public: - FEIRStmtPesudoLabel(uint32 argLabelIdx); + explicit FEIRStmtPesudoLabel(uint32 argLabelIdx); ~FEIRStmtPesudoLabel() = default; void GenerateLabelIdx(MIRBuilder &mirBuilder); @@ -2023,7 +2036,7 @@ class FEIRStmtIGoto : public FEIRStmt { class FEIRStmtCondGotoForC : public FEIRStmt { public: explicit FEIRStmtCondGotoForC(UniqueFEIRExpr argExpr, Opcode op, const std::string &name) - : FEIRStmt(FEIRNodeKind::kStmtCondGoto), expr(std::move(argExpr)), opCode(op), labelName(std::move(name)) {} + : FEIRStmt(FEIRNodeKind::kStmtCondGoto), expr(std::move(argExpr)), opCode(op), labelName(name) {} virtual ~FEIRStmtCondGotoForC() = default; void SetLabelName(const std::string &name) { labelName = name; @@ -2034,10 +2047,6 @@ class FEIRStmtCondGotoForC : public FEIRStmt { } protected: - bool IsFallThroughImpl() const override { - return false; - } - bool IsBranchImpl() const override { return true; } @@ -2151,14 +2160,11 @@ class FEIRStmtSwitch : public FEIRStmt { } protected: - bool IsFallThroughImpl() const override { - return true; - } - bool IsBranchImpl() const override { return true; } + bool IsFallThroughImpl() const override; std::string DumpDotStringImpl() const override; void RegisterDFGNodes2CheckPointImpl(FEIRStmtCheckPoint &checkPoint) override; bool CalculateDefs4AllUsesImpl(FEIRStmtCheckPoint &checkPoint, FEIRUseDefChain &udChain) override; @@ -2215,14 +2221,11 @@ class FEIRStmtSwitch2 : public FEIRStmt { } protected: - bool IsFallThroughImpl() const override { - return true; - } - bool IsBranchImpl() const override { return true; } + bool IsFallThroughImpl() const override; std::string DumpDotStringImpl() const override; std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const override; @@ -2273,7 +2276,7 @@ class FEIRStmtSwitchForC : public FEIRStmt { // ---------- FEIRStmtCaseForC ---------- class FEIRStmtCaseForC : public FEIRStmt { public: - FEIRStmtCaseForC(int64 lCaseLabel); + explicit FEIRStmtCaseForC(int64 lCaseLabel); void AddCaseTag2CaseVec(int64 lCaseTag, int64 rCaseTag); ~FEIRStmtCaseForC() = default; void AddFeirStmt(UniqueFEIRStmt stmt) { @@ -2335,7 +2338,7 @@ class FEIRStmtArrayStore : public FEIRStmt { void SetIndexsExprs(std::list &exprs) { exprIndexs.clear(); - for (auto &e : exprs) { + for (const auto &e : exprs) { auto ue = e->Clone(); exprIndexs.push_back(std::move(ue)); } @@ -2386,7 +2389,7 @@ class FEIRStmtFieldStore : public FEIRStmt { bool CalculateDefs4AllUsesForStatic(FEIRStmtCheckPoint &checkPoint, FEIRUseDefChain &udChain); bool CalculateDefs4AllUsesForNonStatic(FEIRStmtCheckPoint &checkPoint, FEIRUseDefChain &udChain); bool NeedMCCForStatic(uint32 &typeID) const; - void InitPrimTypeFuncNameIdxMap (std::map &primTypeFuncNameIdxMap) const; + void InitPrimTypeFuncNameIdxMap(std::map &primTypeFuncNameIdxMap) const; std::list GenMIRStmtsImplForStatic(MIRBuilder &mirBuilder) const; std::list GenMIRStmtsImplForNonStatic(MIRBuilder &mirBuilder) const; @@ -2552,7 +2555,7 @@ class FEIRStmtPesudoJavaTry : public FEIRStmt { // ---------- FEIRStmtPesudoJavaTry2 ---------- class FEIRStmtPesudoJavaTry2 : public FEIRStmt { public: - FEIRStmtPesudoJavaTry2(uint32 outerIdxIn); + explicit FEIRStmtPesudoJavaTry2(uint32 outerIdxIn); ~FEIRStmtPesudoJavaTry2() = default; void AddCatchLabelIdx(uint32 labelIdx) { catchLabelIdxVec.push_back(labelIdx); @@ -2623,7 +2626,7 @@ class FEIRStmtPesudoCatch2 : public FEIRStmtPesudoLabel2 { class FEIRStmtPesudoSafe : public FEIRStmt { public: - FEIRStmtPesudoSafe(bool isEnd); + explicit FEIRStmtPesudoSafe(bool isEnd); ~FEIRStmtPesudoSafe() = default; protected: @@ -2634,7 +2637,7 @@ class FEIRStmtPesudoSafe : public FEIRStmt { class FEIRStmtPesudoUnsafe : public FEIRStmt { public: - FEIRStmtPesudoUnsafe(bool isEnd); + explicit FEIRStmtPesudoUnsafe(bool isEnd); ~FEIRStmtPesudoUnsafe() = default; protected: @@ -2702,6 +2705,10 @@ class FEIRStmtIf : public FEIRStmt { condExpr = std::move(argCondExpr); } + const UniqueFEIRExpr &GetCondExpr() const { + return condExpr; + } + void SetHasElse(bool argHasElse) { hasElse = argHasElse; } @@ -2725,10 +2732,7 @@ class FEIRStmtIf : public FEIRStmt { protected: std::string DumpDotStringImpl() const override; std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const override; - - bool IsFallThroughImpl() const override { - return true; - } + bool IsFallThroughImpl() const override; bool IsBranchImpl() const override { return true; @@ -2750,11 +2754,24 @@ class FEIRStmtDoWhile : public FEIRStmt { bodyStmts(std::move(argBodyStmts)) {} ~FEIRStmtDoWhile() = default; + const std::list &GetBodyStmts() const { + return bodyStmts; + } + + const UniqueFEIRExpr &GetCondExpr() const { + return condExpr; + } + + const Opcode GetOpcode() const { + return opcode; + } + protected: bool IsBranchImpl() const override { return true; } + bool IsFallThroughImpl() const override; std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const override; private: @@ -2807,6 +2824,10 @@ class FEIRStmtLabel : public FEIRStmt { explicit FEIRStmtLabel(const std::string &name) : FEIRStmt(FEIRNodeKind::kStmtLabel), labelName(name) {} ~FEIRStmtLabel() = default; + const std::string &GetLabelName() const { + return labelName; + } + protected: bool IsBranchImpl() const override { return true; @@ -2820,7 +2841,7 @@ class FEIRStmtLabel : public FEIRStmt { class FEIRStmtAtomic : public FEIRStmt { public: - FEIRStmtAtomic(UniqueFEIRExpr expr); + explicit FEIRStmtAtomic(UniqueFEIRExpr expr); ~FEIRStmtAtomic() = default; protected: @@ -2860,7 +2881,15 @@ class FEIRStmtGCCAsm : public FEIRStmt { protected: std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const override; - bool HandleConstraintPlusQm(MIRBuilder &mirBuilder, AsmNode *asmNode, uint32 index) const; + bool HandleConstraintPlusQm(MIRBuilder &mirBuilder, AsmNode *asmNode, uint32 index, + std::list &stmts, std::list &initStmts) const; + std::pair HandleGlobalAsmOutOperand(const UniqueFEIRVar &asmOut, + const FieldID fieldID, + std::list &stmts, + MIRBuilder &mirBuilder) const; + std::pair HandleAsmOutOperandWithPtrType(const FEIRExprIRead *ireadExpr, + std::list &stmts, + MIRBuilder &mirBuilder) const; private: std::vector> outputs; diff --git a/src/hir2mpl/common/include/feir_var.h b/src/hir2mpl/common/include/feir_var.h index 98322da484ba4986b15d0db8fbfbc530d03e3ad1..4e96977691b51064d0b781b8ebf980fe488ae42a 100644 --- a/src/hir2mpl/common/include/feir_var.h +++ b/src/hir2mpl/common/include/feir_var.h @@ -20,6 +20,7 @@ #include "mir_module.h" #include "mir_builder.h" #include "feir_type.h" +#include "fe_utils.h" #include "generic_attrs.h" namespace maple { @@ -71,7 +72,7 @@ enum FEIRVarKind : uint8 { class FEIRExpr; class FEIRVar { public: - FEIRVar(FEIRVarKind argKind); + explicit FEIRVar(FEIRVarKind argKind); FEIRVar(FEIRVarKind argKind, std::unique_ptr argType); virtual ~FEIRVar(); void SetType(std::unique_ptr argType); @@ -122,16 +123,18 @@ class FEIRVar { MIRSymbol *GenerateGlobalMIRSymbol(MIRBuilder &builder) const { MIRSymbol *mirSym = GenerateGlobalMIRSymbolImpl(builder); - mirSym->GetSrcPosition().SetFileNum(static_cast(srcFileIdx)); - mirSym->GetSrcPosition().SetLineNum(srcFileLineNum); + if (mirSym->GetSrcPosition().LineNum() == 0) { + mirSym->SetSrcPosition(loc.Emit2SourcePosition()); + } builder.GetMirModule().InsertInlineGlobal(mirSym->GetStIdx().Idx()); return mirSym; } MIRSymbol *GenerateLocalMIRSymbol(MIRBuilder &builder) const { MIRSymbol *mirSym = GenerateLocalMIRSymbolImpl(builder); - mirSym->GetSrcPosition().SetFileNum(static_cast(srcFileIdx)); - mirSym->GetSrcPosition().SetLineNum(srcFileLineNum); + if (mirSym->GetSrcPosition().LineNum() == 0) { + mirSym->SetSrcPosition(loc.Emit2SourcePosition()); + } return mirSym; } @@ -147,10 +150,6 @@ class FEIRVar { return GetNameRawImpl(); } - std::unique_ptr Clone() const { - return CloneImpl(); - } - bool EqualsTo(const std::unique_ptr &var) const { return EqualsToImpl(var); } @@ -167,19 +166,23 @@ class FEIRVar { sectionAttr = str; } - void SetSrcLOC(uint32 fileIdx, uint32 lineNum) { - srcFileIdx = fileIdx; - srcFileLineNum = lineNum; + void SetSrcLoc(const Loc &l) { + loc = l; + } + + Loc GetSrcLoc() const { + return loc; } uint32 GetSrcFileIdx() const { - return srcFileIdx; + return loc.fileIdx; } uint32 GetSrcFileLineNum() const { - return srcFileLineNum; + return loc.line; } + std::unique_ptr Clone() const; void SetBoundaryLenExpr(std::unique_ptr expr); const std::unique_ptr &GetBoundaryLenExpr() const; @@ -199,8 +202,7 @@ class FEIRVar { UniqueFEIRType type; UniqueFEIRVarTrans trans; GenericAttrs genAttrs; - uint32 srcFileIdx = 0; - uint32 srcFileLineNum = 0; + Loc loc = {0, 0, 0}; std::string sectionAttr; std::unique_ptr boundaryLenExpr; }; diff --git a/src/hir2mpl/common/include/feir_var_name.h b/src/hir2mpl/common/include/feir_var_name.h index b7c79a3042efec91894bf77d5fd778aee6001665..713ec5603470998548b51bc4611e33a2afd8f127 100644 --- a/src/hir2mpl/common/include/feir_var_name.h +++ b/src/hir2mpl/common/include/feir_var_name.h @@ -24,7 +24,7 @@ namespace maple { // ---------- FEIRVarName ---------- class FEIRVarName : public FEIRVar { public: - FEIRVarName(const GStrIdx &argNameIdx, bool argWithType = false) + explicit FEIRVarName(const GStrIdx &argNameIdx, bool argWithType = false) : FEIRVar(FEIRVarKind::kFEIRVarName), nameIdx(argNameIdx), withType(argWithType) {} diff --git a/src/hir2mpl/common/include/feir_var_reg.h b/src/hir2mpl/common/include/feir_var_reg.h index 55cbaec0bf3ca09b7468431c29792df14aaf230a..a37fdfbdc78a2dfe64c840ef1fe5eb229f9f41c5 100644 --- a/src/hir2mpl/common/include/feir_var_reg.h +++ b/src/hir2mpl/common/include/feir_var_reg.h @@ -20,7 +20,7 @@ namespace maple { class FEIRVarReg : public FEIRVar { public: - FEIRVarReg(uint32 argRegNum, FEIRVarKind kind = FEIRVarKind::kFEIRVarReg) + explicit FEIRVarReg(uint32 argRegNum, FEIRVarKind kind = FEIRVarKind::kFEIRVarReg) : FEIRVar(kind), regNum(argRegNum) {} @@ -50,7 +50,7 @@ class FEIRVarReg : public FEIRVar { class FEIRVarAccumulator : public FEIRVarReg { public: - FEIRVarAccumulator(uint32 argRegNum) + explicit FEIRVarAccumulator(uint32 argRegNum) : FEIRVarReg(argRegNum, FEIRVarKind::kFEIRVarAccumulator) {} FEIRVarAccumulator(uint32 argRegNum, PrimType argPrimType) diff --git a/src/hir2mpl/common/include/feir_var_type_scatter.h b/src/hir2mpl/common/include/feir_var_type_scatter.h index 10db374fc4a11d2f5e4832ebfb292f8870814ee4..d23a717015f7da2dd553f666fd5bc2490b938a6e 100644 --- a/src/hir2mpl/common/include/feir_var_type_scatter.h +++ b/src/hir2mpl/common/include/feir_var_type_scatter.h @@ -21,7 +21,7 @@ namespace maple { class FEIRVarTypeScatter : public FEIRVar { public: - FEIRVarTypeScatter(UniqueFEIRVar argVar); + explicit FEIRVarTypeScatter(UniqueFEIRVar argVar); ~FEIRVarTypeScatter() = default; void AddScatterType(const UniqueFEIRType &type); const std::unordered_set &GetScatterTypes() const { diff --git a/src/hir2mpl/common/include/generic_attrs.h b/src/hir2mpl/common/include/generic_attrs.h index 9f49d370c70c5e0ba8deb2d10487adf4d9acfc0c..6071ccc07466260d55d31b3ac25db4fbc3d48ca9 100644 --- a/src/hir2mpl/common/include/generic_attrs.h +++ b/src/hir2mpl/common/include/generic_attrs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -32,6 +32,7 @@ enum GenericAttrKind { #undef TYPE_ATTR #undef FIELD_ATTR }; +#define MAX_ATTR_NUM 128 class GenericAttrs { public: @@ -56,21 +57,49 @@ class GenericAttrs { return !(*this == tA); } + void InitContentMap() { + contentMap.resize(MAX_ATTR_NUM); + isInit = true; + } + + bool GetContentFlag(GenericAttrKind key) const { + return contentFlag[key]; + } + void InsertIntContentMap(GenericAttrKind key, int val) { - contentMap.insert(std::make_pair(key, val)); + if (!isInit) { + InitContentMap(); + } + if (!contentFlag[key]) { + contentMap[key] = val; + contentFlag.set(key); + } } void InsertStrIdxContentMap(GenericAttrKind key, GStrIdx nameIdx) { - contentMap.insert(std::make_pair(key, nameIdx)); + if (!isInit) { + InitContentMap(); + } + if (!contentFlag[key]) { + contentMap[key] = nameIdx; + contentFlag.set(key); + } + } + + void ClearContentMap() { + contentMap.clear(); + contentMap.shrink_to_fit(); } FieldAttrs ConvertToFieldAttrs(); - TypeAttrs ConvertToTypeAttrs(); + TypeAttrs ConvertToTypeAttrs() const; FuncAttrs ConvertToFuncAttrs(); private: - std::bitset<128> attrFlag = 0; - std::map contentMap; + std::bitset attrFlag = 0; + std::bitset contentFlag = 0; + std::vector contentMap; + bool isInit = false; }; } #endif // GENERIC_ATTRS_H \ No newline at end of file diff --git a/src/hir2mpl/common/include/hir2mpl_compiler.h b/src/hir2mpl/common/include/hir2mpl_compiler.h index f00e270545cc624dc236a881b4218f811fcc44d4..ac98ff9f5ad3fd8c918e52688c9ac61dea99c165 100644 --- a/src/hir2mpl/common/include/hir2mpl_compiler.h +++ b/src/hir2mpl/common/include/hir2mpl_compiler.h @@ -30,7 +30,6 @@ #ifdef ENABLE_MAST #include "maple_ast_parser.h" #endif -#include "mpl_timer.h" #include "hir2mpl_env.h" #include "fe_manager.h" #include "fe_type_hierarchy.h" @@ -70,7 +69,7 @@ class HIR2MPLCompiler { std::string firstInputName; std::string outputPath; std::string outputName; - std::string outputInlineName; + std::string outNameWithoutType; std::list> components; std::set compileFailedFEFunctions; }; diff --git a/src/hir2mpl/common/include/hir2mpl_compiler_component.h b/src/hir2mpl/common/include/hir2mpl_compiler_component.h index 5a9d4479be2a33ed78401f32ed41339789c356b3..558a4698d741452100f4598eb35adef34872efea 100644 --- a/src/hir2mpl/common/include/hir2mpl_compiler_component.h +++ b/src/hir2mpl/common/include/hir2mpl_compiler_component.h @@ -17,7 +17,6 @@ #include #include #include "mir_module.h" -#include "hir2mpl_options.h" #include "fe_function.h" #include "fe_input.h" #include "fe_input_helper.h" @@ -26,7 +25,7 @@ namespace maple { class FEFunctionProcessTask : public MplTask { public: - FEFunctionProcessTask(std::unique_ptr argFunction); + explicit FEFunctionProcessTask(std::unique_ptr argFunction); virtual ~FEFunctionProcessTask() = default; protected: @@ -39,7 +38,7 @@ class FEFunctionProcessTask : public MplTask { class FEFunctionProcessSchedular : public MplScheduler { public: - FEFunctionProcessSchedular(const std::string &name) + explicit FEFunctionProcessSchedular(const std::string &name) : MplScheduler(name) {} virtual ~FEFunctionProcessSchedular() = default; void AddFunctionProcessTask(std::unique_ptr function); diff --git a/src/hir2mpl/common/include/hir2mpl_option.h b/src/hir2mpl/common/include/hir2mpl_option.h new file mode 100644 index 0000000000000000000000000000000000000000..63c0351ec6a3b4397150c7dd4412e47981471d49 --- /dev/null +++ b/src/hir2mpl/common/include/hir2mpl_option.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) [2022] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#ifndef HIR2MPL_COMMON_INCLUDE_HIR2MPL_OPTION_H +#define HIR2MPL_COMMON_INCLUDE_HIR2MPL_OPTION_H + +#include "driver_options.h" + +namespace opts::hir2mpl { +extern maplecl::Option help; +extern maplecl::Option version; +extern maplecl::Option mpltSys; +extern maplecl::Option mpltApk; +extern maplecl::Option mplt; +extern maplecl::Option inClass; +extern maplecl::Option inJar; +extern maplecl::Option inDex; +extern maplecl::Option inAst; +extern maplecl::Option inMast; +extern maplecl::Option output; +extern maplecl::Option outputName; +extern maplecl::Option mpltOnly; +extern maplecl::Option asciimplt; +extern maplecl::Option dumpInstComment; +extern maplecl::Option noMplFile; +extern maplecl::Option dumpLevel; +extern maplecl::Option dumpTime; +extern maplecl::Option dumpComment; +extern maplecl::Option dumpLOC; +extern maplecl::Option dbgFriendly; +extern maplecl::Option dumpPhaseTime; +extern maplecl::Option dumpPhaseTimeDetail; +extern maplecl::Option rc; +extern maplecl::Option nobarrier; +extern maplecl::Option usesignedchar; +extern maplecl::Option o2; +extern maplecl::Option simplifyShortCircuit; +extern maplecl::Option enableVariableArray; +extern maplecl::Option funcInliceSize; +extern maplecl::Option np; +extern maplecl::Option dumpThreadTime; +extern maplecl::Option xbootclasspath; +extern maplecl::Option classloadercontext; +extern maplecl::Option dep; +extern maplecl::Option depsamename; +extern maplecl::Option npeCheckDynamic; +extern maplecl::Option boundaryCheckDynamic; +extern maplecl::Option safeRegion; +extern maplecl::Option dumpFEIRBB; +extern maplecl::Option dumpFEIRCFGGraph; +extern maplecl::Option wpaa; +extern maplecl::Option debug; + +} + +#endif /* HIR2MPL_COMMON_INCLUDE_HIR2MPL_OPTION_H */ diff --git a/src/hir2mpl/common/include/hir2mpl_options.h b/src/hir2mpl/common/include/hir2mpl_options.h index cb3d184ce6772bf8ab17e33c86b514995341662c..4b84aaf57e95be594387890b09dc2c3175b2ba43 100644 --- a/src/hir2mpl/common/include/hir2mpl_options.h +++ b/src/hir2mpl/common/include/hir2mpl_options.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -17,13 +17,12 @@ #include #include #include "factory.h" +#include "hir2mpl_option.h" #include "parser_opt.h" -#include "option_parser.h" #include "types_def.h" -#include "driver_option_common.h" namespace maple { -class HIR2MPLOptions : public maple::MapleDriverOptionBase { +class HIR2MPLOptions { public: static inline HIR2MPLOptions &GetInstance() { static HIR2MPLOptions options; @@ -31,7 +30,7 @@ class HIR2MPLOptions : public maple::MapleDriverOptionBase { } void Init(); static bool InitFactory(); - bool SolveOptions(const std::deque &opts, bool isDebug); + bool SolveOptions(bool isDebug); bool SolveArgs(int argc, char **argv); void DumpUsage() const; void DumpVersion() const; @@ -43,85 +42,87 @@ class HIR2MPLOptions : public maple::MapleDriverOptionBase { void ProcessInputFiles(const std::vector &inputs); private: - using OptionProcessFactory = FunctionFactory; + template + using OptionProcessFactory = FunctionFactory; + using OptionFactory = OptionProcessFactory; HIR2MPLOptions(); ~HIR2MPLOptions() = default; // option process - bool ProcessHelp(const mapleOption::Option &opt); - bool ProcessVersion(const mapleOption::Option &opt); + bool ProcessHelp(const maplecl::OptionInterface &opt); + bool ProcessVersion(const maplecl::OptionInterface &opt); // input control options - bool ProcessInClass(const mapleOption::Option &opt); - bool ProcessInJar(const mapleOption::Option &opt); - bool ProcessInDex(const mapleOption::Option &opt); - bool ProcessInAST(const mapleOption::Option &opt); - bool ProcessInMAST(const mapleOption::Option &opt); - bool ProcessInputMplt(const mapleOption::Option &opt); - bool ProcessInputMpltFromSys(const mapleOption::Option &opt); - bool ProcessInputMpltFromApk(const mapleOption::Option &opt); + bool ProcessInClass(const maplecl::OptionInterface &mpltSys); + bool ProcessInJar(const maplecl::OptionInterface &mpltApk); + bool ProcessInDex(const maplecl::OptionInterface &inDex); + bool ProcessInAST(const maplecl::OptionInterface &inAst); + bool ProcessInMAST(const maplecl::OptionInterface &inMast); + bool ProcessInputMplt(const maplecl::OptionInterface &mplt); + bool ProcessInputMpltFromSys(const maplecl::OptionInterface &mpltSys); + bool ProcessInputMpltFromApk(const maplecl::OptionInterface &mpltApk); // output control options - bool ProcessOutputPath(const mapleOption::Option &opt); - bool ProcessOutputName(const mapleOption::Option &opt); - bool ProcessGenMpltOnly(const mapleOption::Option &opt); - bool ProcessGenAsciiMplt(const mapleOption::Option &opt); - bool ProcessDumpInstComment(const mapleOption::Option &opt); - bool ProcessNoMplFile(const mapleOption::Option &opt); + bool ProcessOutputPath(const maplecl::OptionInterface &output); + bool ProcessOutputName(const maplecl::OptionInterface &outputName); + bool ProcessGenMpltOnly(const maplecl::OptionInterface &opt); + bool ProcessGenAsciiMplt(const maplecl::OptionInterface &opt); + bool ProcessDumpInstComment(const maplecl::OptionInterface &opt); + bool ProcessNoMplFile(const maplecl::OptionInterface &opt); // debug info control options - bool ProcessDumpLevel(const mapleOption::Option &opt); - bool ProcessDumpTime(const mapleOption::Option &opt); - bool ProcessDumpComment(const mapleOption::Option &opt); - bool ProcessDumpLOC(const mapleOption::Option &opt); - bool ProcessDumpPhaseTime(const mapleOption::Option &opt); - bool ProcessDumpPhaseTimeDetail(const mapleOption::Option &opt); + bool ProcessDumpLevel(const maplecl::OptionInterface &outputName); + bool ProcessDumpTime(const maplecl::OptionInterface &opt); + bool ProcessDumpComment(const maplecl::OptionInterface &opt); + bool ProcessDumpLOC(const maplecl::OptionInterface &opt); + bool ProcessDbgFriendly(const maplecl::OptionInterface &); + bool ProcessDumpPhaseTime(const maplecl::OptionInterface &opt); + bool ProcessDumpPhaseTimeDetail(const maplecl::OptionInterface &opt); // java compiler options - bool ProcessModeForJavaStaticFieldName(const mapleOption::Option &opt); - bool ProcessJBCInfoUsePathName(const mapleOption::Option &opt); - bool ProcessDumpJBCStmt(const mapleOption::Option &opt); - bool ProcessDumpJBCBB(const mapleOption::Option &opt); - bool ProcessDumpJBCAll(const mapleOption::Option &opt); - bool ProcessDumpJBCErrorOnly(const mapleOption::Option &opt); - bool ProcessDumpJBCFuncName(const mapleOption::Option &opt); - bool ProcessEmitJBCLocalVarInfo(const mapleOption::Option &opt); + bool ProcessModeForJavaStaticFieldName(const maplecl::OptionInterface &opt); + bool ProcessJBCInfoUsePathName(const maplecl::OptionInterface &opt); + bool ProcessDumpJBCStmt(const maplecl::OptionInterface &opt); + bool ProcessDumpJBCAll(const maplecl::OptionInterface &opt); + bool ProcessDumpJBCErrorOnly(const maplecl::OptionInterface &opt); + bool ProcessDumpJBCFuncName(const maplecl::OptionInterface &opt); + bool ProcessEmitJBCLocalVarInfo(const maplecl::OptionInterface &opt); // bc compiler options - bool ProcessRC(const mapleOption::Option &opt); - bool ProcessNoBarrier(const mapleOption::Option &opt); - bool ProcessO2(const mapleOption::Option &opt); - bool ProcessSimplifyShortCircuit(const mapleOption::Option &opt); - bool ProcessEnableVariableArray(const mapleOption::Option &opt); - bool ProcessFuncInlineSize(const mapleOption::Option &opt); + bool ProcessRC(const maplecl::OptionInterface &opt); + bool ProcessNoBarrier(const maplecl::OptionInterface &opt); + bool ProcessO2(const maplecl::OptionInterface &opt); + bool ProcessSimplifyShortCircuit(const maplecl::OptionInterface &opt); + bool ProcessEnableVariableArray(const maplecl::OptionInterface &opt); + bool ProcessFuncInlineSize(const maplecl::OptionInterface &funcInliceSize); + bool ProcessWPAA(const maplecl::OptionInterface &opt); // ast compiler options - bool ProcessUseSignedChar(const mapleOption::Option &opt); - bool ProcessBigEndian(const mapleOption::Option &opt); + bool ProcessUseSignedChar(const maplecl::OptionInterface &opt); + bool ProcessBigEndian(); - // general stmt/bb/cfg debug options - bool ProcessDumpFEIRCFGGraph(const mapleOption::Option &opt); + // general stmt/bb/cfg options + bool ProcessDumpFEIRBB(const maplecl::OptionInterface &opt); + bool ProcessDumpFEIRCFGGraph(const maplecl::OptionInterface &opt); // multi-thread control options - bool ProcessNThreads(const mapleOption::Option &opt); - bool ProcessDumpThreadTime(const mapleOption::Option &opt); - bool ProcessReleaseAfterEmit(const mapleOption::Option &opt); + bool ProcessNThreads(const maplecl::OptionInterface &numThreads); + bool ProcessDumpThreadTime(const maplecl::OptionInterface &opt); // On Demand Type Creation - bool ProcessXbootclasspath(const mapleOption::Option &opt); - bool ProcessClassLoaderContext(const mapleOption::Option &opt); - bool ProcessCompilefile(const mapleOption::Option &opt); - bool ProcessCollectDepTypes(const mapleOption::Option &opt); - bool ProcessDepSameNamePolicy(const mapleOption::Option &opt); + bool ProcessXbootclasspath(const maplecl::OptionInterface &xbootclasspath); + bool ProcessClassLoaderContext(const maplecl::OptionInterface &classloadercontext); + bool ProcessCollectDepTypes(const maplecl::OptionInterface &dep); + bool ProcessDepSameNamePolicy(const maplecl::OptionInterface &depsamename); // EnhanceC - bool ProcessNpeCheckDynamic(const mapleOption::Option &opt); - bool ProcessBoundaryCheckDynamic(const mapleOption::Option &opt); - bool ProcessSafeRegion(const mapleOption::Option &opt); + bool ProcessNpeCheckDynamic(const maplecl::OptionInterface &opt); + bool ProcessBoundaryCheckDynamic(const maplecl::OptionInterface &opt); + bool ProcessSafeRegion(const maplecl::OptionInterface &opt); // symbol resolve - bool ProcessAOT(const mapleOption::Option &opt); + bool ProcessAOT(const maplecl::OptionInterface &opt); }; // class HIR2MPLOptions } // namespace maple #endif // HIR2MPL_INCLUDE_COMMON_HIR2MPL_OPTIONS_H diff --git a/src/hir2mpl/common/include/simple_xml.h b/src/hir2mpl/common/include/simple_xml.h index 090dbd09d48fcf772b47087a40db6d2c5f6a2dff..3e07b9baf450d0c5c0879d9d706ce4048b3272d1 100644 --- a/src/hir2mpl/common/include/simple_xml.h +++ b/src/hir2mpl/common/include/simple_xml.h @@ -111,7 +111,7 @@ class SimpleXMLElemMultiLine : public SimpleXMLElem { class SimpleXML { public: - SimpleXML(MapleAllocator &alloc); + explicit SimpleXML(MapleAllocator &alloc); ~SimpleXML() = default; void AddRoot(SimpleXMLElem &elem); diff --git a/src/hir2mpl/common/include/simple_zip.h b/src/hir2mpl/common/include/simple_zip.h index 19efa5b4cebef98f5aebe3d7c54730d0f43b01c2..ba33fcbccd9007f8f9cd1a90cbcfd4a4c8a184be 100644 --- a/src/hir2mpl/common/include/simple_zip.h +++ b/src/hir2mpl/common/include/simple_zip.h @@ -115,7 +115,7 @@ class ZipLocalFile { class SimpleZip : public BasicIORead { public: - SimpleZip(BasicIOMapFile &file); + explicit SimpleZip(BasicIOMapFile &file); ~SimpleZip(); void ParseFile(); diff --git a/src/hir2mpl/common/src/base64.cpp b/src/hir2mpl/common/src/base64.cpp index c84a071692028eecac0e6f5bcc8f0ab3512a8edd..6afadbe9a2ade5e6f5fadb930eecc2415832af19 100644 --- a/src/hir2mpl/common/src/base64.cpp +++ b/src/hir2mpl/common/src/base64.cpp @@ -104,17 +104,16 @@ std::string Base64::Encode(const uint8 *input, size_t length) { size_t Base64::DecodeLength(const std::string &input) { // length calculation size_t length; - const char *inputBuf = input.c_str(); size_t inputLength = input.length(); if (inputLength == 0) { return 0; } CHECK_FATAL(inputLength % kBase64DecodeBaseLen == 0, "input.length must be factor of 4"); length = inputLength * kBase64EncodeBaseLen / kBase64DecodeBaseLen; - if (inputBuf[inputLength - 1] == '=') { + if (input[inputLength - 1] == '=') { length--; } - if (inputBuf[inputLength - 2] == '=') { + if (input[inputLength - 2] == '=') { length--; } return length; diff --git a/src/hir2mpl/common/src/basic_io.cpp b/src/hir2mpl/common/src/basic_io.cpp index c8849c7d5d93adeb36897149b8e7976983ad84e3..2844627dc14e983ae18c14f8475da258c567287a 100644 --- a/src/hir2mpl/common/src/basic_io.cpp +++ b/src/hir2mpl/common/src/basic_io.cpp @@ -14,7 +14,6 @@ */ #include "basic_io.h" #include -#include #include #include #include diff --git a/src/hir2mpl/common/src/enhance_c_checker.cpp b/src/hir2mpl/common/src/enhance_c_checker.cpp index beecaa10fabf90be7d88f71156771d3ce6e44eca..52664b183cf64a1c1690b3214556947e930c0673 100755 --- a/src/hir2mpl/common/src/enhance_c_checker.cpp +++ b/src/hir2mpl/common/src/enhance_c_checker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -22,7 +22,8 @@ #include "fe_macros.h" namespace maple { -void ASTParser::ProcessNonnullFuncPtrAttrs(const clang::ValueDecl &valueDecl, ASTDecl &astVar) { +void ASTParser::ProcessNonnullFuncPtrAttrs(MapleAllocator &allocator, const clang::ValueDecl &valueDecl, + ASTDecl &astVar) { const MIRFuncType *funcType = FEUtils::GetFuncPtrType(*astVar.GetTypeDesc().front()); if (funcType == nullptr) { return; @@ -48,8 +49,8 @@ void ASTParser::ProcessNonnullFuncPtrAttrs(const clang::ValueDecl &valueDecl, AS } MIRType *newFuncType = GlobalTables::GetTypeTable().GetOrCreateFunctionType( funcType->GetRetTyIdx(), funcType->GetParamTypeList(), attrsVec, funcType->IsVarargs(), retAttr); - astVar.SetTypeDesc(std::vector{GlobalTables::GetTypeTable().GetOrCreatePointerType( - *GlobalTables::GetTypeTable().GetOrCreatePointerType(*newFuncType))}); + astVar.SetTypeDesc(MapleVector({GlobalTables::GetTypeTable().GetOrCreatePointerType( + *GlobalTables::GetTypeTable().GetOrCreatePointerType(*newFuncType))}, allocator.Adapter())); } bool ENCChecker::HasNonnullAttrInExpr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr, bool isNested) { @@ -112,7 +113,7 @@ void ENCChecker::CheckNonnullGlobalVarInit(const MIRSymbol &sym, const MIRConst } } -void ENCChecker::CheckNullFieldInGlobalStruct(MIRType &type, MIRAggConst &cst, const std::vector &initExprs) { +void ENCChecker::CheckNullFieldInGlobalStruct(MIRType &type, MIRAggConst &cst, const MapleVector &initExprs) { if (!FEOptions::GetInstance().IsNpeCheckDynamic() || !ENCChecker::HasNonnullFieldInStruct(type)) { return; } @@ -156,7 +157,8 @@ void ENCChecker::CheckNonnullLocalVarInit(const MIRSymbol &sym, const UniqueFEIR } if (initFEExpr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique(OP_assignassertnonnull, initFEExpr->Clone()); - stmt->SetSrcFileInfo(sym.GetSrcPosition().FileNum(), sym.GetSrcPosition().LineNum()); + Loc loc = {sym.GetSrcPosition().FileNum(), sym.GetSrcPosition().LineNum(), sym.GetSrcPosition().Column()}; + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); } } @@ -189,7 +191,7 @@ std::string ENCChecker::PrintParamIdx(const std::list &idxs) { } void ENCChecker::CheckNonnullArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, - uint32 fileNum, uint32 fileLine) { + const Loc &loc) { if (!FEOptions::GetInstance().IsNpeCheckDynamic()) { return; } @@ -209,13 +211,14 @@ void ENCChecker::CheckNonnullArgsAndRetForFuncPtr(const MIRType &dstType, const } } if (!errIdxs.empty()) { - FE_ERR(kLncErr, "%s:%d error: function pointer and target function's nonnull attributes are mismatched " - "for the %s argument", FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine, - PrintParamIdx(errIdxs).c_str()); + FE_ERR(kLncErr, "%s:%d error: function pointer and assigned function %s are mismatched " + "for the %s argument of nonnull attributes", + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + srcFunc->GetName().c_str(), PrintParamIdx(errIdxs).c_str()); } if (srcFunc->GetFuncAttrs().GetAttr(FUNCATTR_nonnull) != funcType->GetRetAttrs().GetAttr(ATTR_nonnull)) { FE_ERR(kLncErr, "%s:%d error: function pointer and target function's nonnull attributes are mismatched for" - " the return value", FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine); + " the return value", FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } const MIRFuncType *srcFuncType = FEUtils::GetFuncPtrType(*srcExpr->GetType()->GenerateMIRTypeAuto()); @@ -229,11 +232,12 @@ void ENCChecker::CheckNonnullArgsAndRetForFuncPtr(const MIRType &dstType, const } if (!errIdxs.empty()) { FE_ERR(kLncErr, "%s:%d error: function pointer's nonnull attributes are mismatched for the %s argument", - FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine, PrintParamIdx(errIdxs).c_str()); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + PrintParamIdx(errIdxs).c_str()); } if (srcFuncType->GetRetAttrs().GetAttr(ATTR_nonnull) != funcType->GetRetAttrs().GetAttr(ATTR_nonnull)) { FE_ERR(kLncErr, "%s:%d error: function pointer's nonnull attributes are mismatched for the return value", - FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } } @@ -246,7 +250,7 @@ void FEIRStmtDAssign::CheckNonnullArgsAndRetForFuncPtr(const MIRBuilder &mirBuil if (fieldID != 0) { baseType = FEUtils::GetStructFieldType(static_cast(baseType), fieldID); } - ENCChecker::CheckNonnullArgsAndRetForFuncPtr(*baseType, expr, srcFileIndex, srcFileLineNum); + ENCChecker::CheckNonnullArgsAndRetForFuncPtr(*baseType, expr, loc); } void FEIRStmtIAssign::CheckNonnullArgsAndRetForFuncPtr(const MIRBuilder &mirBuilder, const MIRType &baseType) const { @@ -254,7 +258,7 @@ void FEIRStmtIAssign::CheckNonnullArgsAndRetForFuncPtr(const MIRBuilder &mirBuil return; } MIRType *fieldType = FEUtils::GetStructFieldType(static_cast(&baseType), fieldID); - ENCChecker::CheckNonnullArgsAndRetForFuncPtr(*fieldType, baseExpr, srcFileIndex, srcFileLineNum); + ENCChecker::CheckNonnullArgsAndRetForFuncPtr(*fieldType, baseExpr, loc); } bool ENCChecker::HasNonnullFieldInStruct(const MIRType &mirType) { @@ -280,29 +284,37 @@ void ASTCallExpr::CheckNonnullFieldInStruct() const { } std::list nullStmts; UniqueFEIRExpr baseExpr = nullptr; - if (funcName == "bzero" && args.size() == 2) { + if (GetFuncName() == "bzero" && args.size() == 2) { baseExpr = args[0]->Emit2FEExpr(nullStmts); - } else if (funcName == "memset" && args.size() == 3 && + } else if (GetFuncName() == "memset" && args.size() == 3 && FEIRBuilder::IsZeroConstExpr(args[1]->Emit2FEExpr(nullStmts))) { baseExpr = args[0]->Emit2FEExpr(nullStmts); } - if (baseExpr != nullptr && (baseExpr->GetKind() == kExprDRead || baseExpr->GetKind() == kExprIRead) && - baseExpr->GetType() != nullptr) { - MIRType *mirType = baseExpr->GetType()->GenerateMIRTypeAuto(); - if (ENCChecker::HasNonnullFieldInPtrStruct(*mirType)) { + if (baseExpr == nullptr) { + return; + } + MIRType *mirType = ENCChecker::GetTypeFromAddrExpr(baseExpr); // check addrof or iaddrof + if (mirType != nullptr) { + mirType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType); + } else if ((baseExpr->GetKind() == kExprDRead || baseExpr->GetKind() == kExprIRead) && + baseExpr->GetType() != nullptr) { + mirType = baseExpr->GetType()->GenerateMIRTypeAuto(); + } + if (mirType != nullptr && ENCChecker::HasNonnullFieldInPtrStruct(*mirType)) { FE_ERR(kLncErr, "%s:%d error: null assignment of nonnull structure field pointer in %s", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIdx).c_str(), srcFileLineNum, funcName.c_str()); - } + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, GetFuncName().c_str()); } } -void ASTCastExpr::CheckNonnullFieldInStruct() const { - if (!FEOptions::GetInstance().IsNpeCheckDynamic() || dst->GetTypeIndex() == src->GetTypeIndex()) { +void ENCChecker::CheckNonnullFieldInStruct(const MIRType &src, const MIRType &dst, const Loc &loc) { + if (!FEOptions::GetInstance().IsNpeCheckDynamic() || + !dst.IsMIRPtrType() || !src.IsMIRPtrType() || + dst.GetTypeIndex() == src.GetTypeIndex()) { return; } - if (ENCChecker::HasNonnullFieldInPtrStruct(*dst)) { + if (ENCChecker::HasNonnullFieldInPtrStruct(dst)) { FE_ERR(kLncErr, "%s:%d error: null assignment risk of nonnull field pointer", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIdx).c_str(), srcFileLineNum); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } @@ -552,10 +564,10 @@ void ASTParser::ProcessBoundaryFuncPtrAttrs(MapleAllocator &allocator, const cla if (isUpdated) { MIRType *newFuncType = GlobalTables::GetTypeTable().GetOrCreateFunctionType( funcType->GetRetTyIdx(), funcType->GetParamTypeList(), attrsVec, funcType->IsVarargs(), retAttr); - astDecl.SetTypeDesc(std::vector{GlobalTables::GetTypeTable().GetOrCreatePointerType( - *GlobalTables::GetTypeTable().GetOrCreatePointerType(*newFuncType))}); + astDecl.SetTypeDesc(MapleVector({GlobalTables::GetTypeTable().GetOrCreatePointerType( + *GlobalTables::GetTypeTable().GetOrCreatePointerType(*newFuncType))}, allocator.Adapter())); } - ProcessBoundaryFuncPtrAttrsByIndex(valueDecl, astDecl, *funcType); + ProcessBoundaryFuncPtrAttrsByIndex(allocator, valueDecl, astDecl, *funcType); } template @@ -575,8 +587,8 @@ bool ASTParser::ProcessBoundaryFuncPtrAttrsForParams(T *attr, MapleAllocator &al continue; } MIRType *ptrType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typesVec[idx]); - ASTVar *tmpDecl = ASTDeclsBuilder::ASTVarBuilder( - allocator, "", "tmpVar", std::vector{ptrType}, GenericAttrs()); + ASTVar *tmpDecl = ASTDeclsBuilder::ASTVarBuilder(allocator, MapleString("", allocator.GetMemPool()), "tmpVar", + MapleVector({ptrType}, allocator.Adapter()), GenericAttrs()); bool isByte = std::is_same::type, clang::ByteCountAttr>::value; ProcessBoundaryLenExprInVar(allocator, *tmpDecl, proto.getParamType(idx), lenExpr, !isByte); ENCChecker::InsertBoundaryInAtts(attrsVec[idx], tmpDecl->GetBoundaryInfo()); @@ -594,16 +606,16 @@ bool ASTParser::ProcessBoundaryFuncPtrAttrsForRet(T *attr, MapleAllocator &alloc return false; } MIRType *ptrType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType.GetRetTyIdx()); - ASTVar *tmpRetDecl = ASTDeclsBuilder::ASTVarBuilder( - allocator, "", "tmpRetVar", std::vector{ptrType}, GenericAttrs()); + ASTVar *tmpRetDecl = ASTDeclsBuilder::ASTVarBuilder(allocator, MapleString("", allocator.GetMemPool()), + "tmpRetVar", MapleVector({ptrType}, allocator.Adapter()), GenericAttrs()); bool isByte = std::is_same::type, clang::ReturnsByteCountAttr>::value; ProcessBoundaryLenExprInVar(allocator, *tmpRetDecl, clangFuncType.getReturnType(), lenExpr, !isByte); ENCChecker::InsertBoundaryInAtts(retAttr, tmpRetDecl->GetBoundaryInfo()); return true; } -void ASTParser::ProcessBoundaryFuncPtrAttrsByIndex(const clang::ValueDecl &valueDecl, ASTDecl &astDecl, - const MIRFuncType &funcType) { +void ASTParser::ProcessBoundaryFuncPtrAttrsByIndex(MapleAllocator &allocator, const clang::ValueDecl &valueDecl, + ASTDecl &astDecl, const MIRFuncType &funcType) { std::vector attrsVec = funcType.GetParamAttrsList(); TypeAttrs retAttr = funcType.GetRetAttrs(); bool isUpdated = false; @@ -631,14 +643,14 @@ void ASTParser::ProcessBoundaryFuncPtrAttrsByIndex(const clang::ValueDecl &value if (isUpdated) { MIRType *newFuncType = GlobalTables::GetTypeTable().GetOrCreateFunctionType( funcType.GetRetTyIdx(), funcType.GetParamTypeList(), attrsVec, funcType.IsVarargs(), retAttr); - astDecl.SetTypeDesc(std::vector{GlobalTables::GetTypeTable().GetOrCreatePointerType( - *GlobalTables::GetTypeTable().GetOrCreatePointerType(*newFuncType))}); + astDecl.SetTypeDesc(MapleVector({GlobalTables::GetTypeTable().GetOrCreatePointerType( + *GlobalTables::GetTypeTable().GetOrCreatePointerType(*newFuncType))}, allocator.Adapter())); } } template bool ASTParser::ProcessBoundaryFuncPtrAttrsByIndexForParams(T *attr, ASTDecl &astDecl, const MIRFuncType &funcType, - std::vector &attrsVec) { + std::vector &attrsVec) const { bool isUpdated = false; std::vector typesVec = funcType.GetParamTypeList(); unsigned int lenIdx = attr->getLenVarIndex().getASTIndex(); @@ -749,6 +761,24 @@ void ASTParser::ProcessBoundaryLenExpr(MapleAllocator &allocator, ASTDecl &ptrDe ptrDecl.SetIsBytedLen(!isSize); } +void ENCChecker::CheckLenExpr(const ASTExpr &lenExpr, const std::list &nullstmts) { + for (const auto &stmt : nullstmts) { + bool isAssertStmt = false; + if (stmt->GetKind() == kStmtNary) { + FEIRStmtNary *nary = static_cast(stmt.get()); + if (kOpcodeInfo.IsAssertBoundary(nary->GetOP()) || kOpcodeInfo.IsAssertNonnull(nary->GetOP())) { + isAssertStmt = true; + } + } + if (!isAssertStmt) { + FE_ERR(kLncErr, "%s:%d error: The boundary length expr containing statement is invalid", + FEManager::GetModule().GetFileNameFromFileNum(lenExpr.GetSrcFileIdx()).c_str(), + lenExpr.GetSrcFileLineNum()); + break; + } + } +} + void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, unsigned int idx, ASTFunc &astFunc, ASTExpr *lenExpr, bool isSize) { ASTDecl *ptrDecl = nullptr; @@ -953,7 +983,7 @@ MIRType *ENCChecker::GetArrayTypeFromExpr(const UniqueFEIRExpr &expr) { auto *constArr = static_cast(expr.get()); return GlobalTables::GetTypeTable().GetOrCreateArrayType( *constArr->GetElemType(), constArr->GetStringLiteralSize() + 1); // including the end character with string - } else if (expr->GetKind() == kExprDRead || expr->GetKind() == kExprIRead) { // global char* value size + } else if (expr->GetKind() == kExprDRead || expr->GetKind() == kExprIRead) { // global const char* value size MIRType *type = expr->GetType()->GenerateMIRTypeAuto(); if (type->IsMIRPtrType() && static_cast(type)->GetPointedType()->GetPrimType() == PTY_u8) { MIRConst *cst = GetMIRConstFromExpr(expr); @@ -974,7 +1004,7 @@ MIRConst *ENCChecker::GetMIRConstFromExpr(const UniqueFEIRExpr &expr) { return nullptr; } MIRSymbol *sym = expr->GetVarUses().front()->GenerateMIRSymbol(FEManager::GetMIRBuilder()); - if (!sym->IsGlobal() || sym->GetKonst() == nullptr) { + if (!sym->IsGlobal() || !sym->GetAttr(ATTR_const) || sym->GetKonst() == nullptr) { // const global return nullptr; } if (expr->GetKind() == kExprDRead || expr->GetKind() == kExprAddrofVar) { @@ -1000,7 +1030,7 @@ MIRConst *ENCChecker::GetMIRConstFromExpr(const UniqueFEIRExpr &expr) { FEIRExprAddrofArray *arrExpr = static_cast(expr.get()); MIRConst *cst = GetMIRConstFromExpr(arrExpr->GetExprArray()); if (cst != nullptr && cst->GetKind() == kConstAggConst) { - for (const auto & idxExpr : arrExpr->GetExprIndexs()) { + for (const auto &idxExpr : arrExpr->GetExprIndexs()) { MIRAggConst *aggConst = static_cast(cst); if (idxExpr->GetKind() != kExprConst) { return nullptr; @@ -1196,15 +1226,15 @@ void ENCChecker::AssignUndefVal(MIRBuilder &mirBuilder, MIRSymbol &sym) { } } -void ENCChecker::InitBoundaryVarFromASTDecl(const MapleAllocator &allocator, ASTDecl *ptrDecl, ASTExpr *lenExpr, +void ENCChecker::InitBoundaryVarFromASTDecl(MapleAllocator &allocator, ASTDecl *ptrDecl, ASTExpr *lenExpr, std::list &stmts) { MIRType *ptrType = ptrDecl->GetTypeDesc().front(); // insert lower boundary stmt ASTDeclRefExpr *lowerRefExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); lowerRefExpr->SetASTDecl(ptrDecl); std::string lowerVarName = "_boundary." + ptrDecl->GetName() + ".lower"; - ASTVar *lowerDecl = ASTDeclsBuilder::ASTVarBuilder( - allocator, "", lowerVarName, std::vector{ptrType}, GenericAttrs()); + ASTVar *lowerDecl = ASTDeclsBuilder::ASTVarBuilder(allocator, MapleString("", allocator.GetMemPool()), + lowerVarName, MapleVector({ptrType}, allocator.Adapter()), GenericAttrs()); lowerDecl->SetIsParam(true); lowerDecl->SetInitExpr(lowerRefExpr); ASTDeclStmt *lowerStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); @@ -1219,8 +1249,8 @@ void ENCChecker::InitBoundaryVarFromASTDecl(const MapleAllocator &allocator, AST upperBinExpr->SetRetType(ptrType); upperBinExpr->SetCvtNeeded(true); std::string upperVarName = "_boundary." + ptrDecl->GetName() + ".upper"; - ASTVar *upperDecl = ASTDeclsBuilder::ASTVarBuilder( - allocator, "", upperVarName, std::vector{ptrType}, GenericAttrs()); + ASTVar *upperDecl = ASTDeclsBuilder::ASTVarBuilder(allocator, MapleString("", allocator.GetMemPool()), + upperVarName, MapleVector({ptrType}, allocator.Adapter()), GenericAttrs()); upperDecl->SetIsParam(true); upperDecl->SetInitExpr(upperBinExpr); ASTDeclStmt *upperStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); @@ -1244,8 +1274,9 @@ void ENCChecker::InitBoundaryVar(MIRFunction &curFunction, const ASTDecl &ptrDec UniqueFEIRVar upperVar = FEIRBuilder::CreateVarNameForC(upperVarName, *ptrType); UniqueFEIRStmt upperStmt = FEIRBuilder::CreateStmtDAssign(std::move(upperVar), std::move(binExpr)); if (ptrDecl.GetSrcFileLineNum() != 0) { - lowerStmt->SetSrcFileInfo(ptrDecl.GetSrcFileIdx(), ptrDecl.GetSrcFileLineNum()); - upperStmt->SetSrcFileInfo(ptrDecl.GetSrcFileIdx(), ptrDecl.GetSrcFileLineNum()); + Loc loc = {ptrDecl.GetSrcFileIdx(), ptrDecl.GetSrcFileLineNum(), ptrDecl.GetSrcFileColumn()}; + lowerStmt->SetSrcLoc(loc); + upperStmt->SetSrcLoc(loc); } stmts.emplace_back(std::move(lowerStmt)); stmts.emplace_back(std::move(upperStmt)); @@ -1370,7 +1401,7 @@ bool ENCChecker::IsConstantIndex(const UniqueFEIRExpr &expr) { void ENCChecker::PeelNestedBoundaryChecking(std::list &stmts, const UniqueFEIRExpr &baseExpr) { std::list::iterator i = stmts.begin(); while (i != stmts.end()) { - bool flag = ((*i)->GetKind() == kFEIRStmtNary); + bool flag = ((*i)->GetKind() == kStmtNary); if (flag) { FEIRStmtNary *nary = static_cast((*i).get()); flag = kOpcodeInfo.IsAssertBoundary(nary->GetOP()) && @@ -1432,6 +1463,15 @@ UniqueFEIRExpr ENCChecker::GetRealBoundaryLenExprInFunc(const UniqueFEIRExpr &le return nullptr; } } + if (lenExpr->GetKind() == kExprIRead) { + FEIRExprIRead *ireadExpr = static_cast(lenExpr.get()); + UniqueFEIRExpr subExpr = GetRealBoundaryLenExprInFunc(ireadExpr->GetClonedOpnd(), astFunc, astCallExpr); + if (subExpr != nullptr) { + ireadExpr->SetClonedOpnd(std::move(subExpr)); + } else { + return nullptr; + } + } // formal parameter length expr -> actual parameter expr std::list nullStmts; if (lenExpr->GetKind() == kExprDRead) { @@ -1546,12 +1586,12 @@ void ASTFunc::InsertBoundaryCheckingInRet(std::list &stmts) cons exprs.emplace_back(std::move(lenExpr)); exprs.emplace_back(std::move(baseExpr)); UniqueFEIRStmt stmt = std::make_unique(OP_returnassertle, std::move(exprs)); - stmt->SetSrcFileInfo(stmts.back()->GetSrcFileIdx(), stmts.back()->GetSrcFileLineNum()); + stmt->SetSrcLoc(stmts.back()->GetSrcLoc()); stmts.insert(--stmts.end(), std::move(stmt)); } void ENCChecker::InsertBoundaryAssignChecking(MIRBuilder &mirBuilder, std::list &ans, - const UniqueFEIRExpr &srcExpr, uint32 fileIdx, uint32 fileLine) { + const UniqueFEIRExpr &srcExpr, const Loc &loc) { if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || srcExpr == nullptr || srcExpr->GetPrimType() != PTY_ptr || srcExpr->GetKind() != kExprBinary) { // pointer computed assignment return; @@ -1569,7 +1609,7 @@ void ENCChecker::InsertBoundaryAssignChecking(MIRBuilder &mirBuilder, std::list< lowerExprs.emplace_back(srcExpr->Clone()); lowerExprs.emplace_back(baseExpr->Clone()); UniqueFEIRStmt lowerStmt = std::make_unique(OP_calcassertge, std::move(lowerExprs)); - lowerStmt->SetSrcFileInfo(fileIdx, fileLine); + lowerStmt->SetSrcLoc(loc); std::list lowerStmts = lowerStmt->GenMIRStmts(mirBuilder); ans.splice(ans.end(), lowerStmts); // insert l-value upper boundary chencking @@ -1577,7 +1617,7 @@ void ENCChecker::InsertBoundaryAssignChecking(MIRBuilder &mirBuilder, std::list< upperExprs.emplace_back(srcExpr->Clone()); upperExprs.emplace_back(baseExpr->Clone()); UniqueFEIRStmt upperStmt = std::make_unique(OP_calcassertlt, std::move(upperExprs)); - upperStmt->SetSrcFileInfo(fileIdx, fileLine); + upperStmt->SetSrcLoc(loc); std::list upperStmts = upperStmt->GenMIRStmts(mirBuilder); ans.splice(ans.end(), upperStmts); } @@ -1625,6 +1665,7 @@ void ENCChecker::InsertBoundaryInAtts(TypeAttrs &attr, const BoundaryInfo &bound } std::list nullStmts; UniqueFEIRExpr lenExpr = boundary.lenExpr->Emit2FEExpr(nullStmts); + CheckLenExpr(*boundary.lenExpr, nullStmts); InsertBoundaryLenExprInAtts(attr, lenExpr); } @@ -1679,7 +1720,7 @@ void FEIRStmtDAssign::AssignBoundaryVarAndChecking(MIRBuilder &mirBuilder, std:: return; } // insert assign boundary checking for computed r-value - ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, expr, srcFileIndex, srcFileLineNum); + ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, expr, loc); UniqueFEIRExpr dstExpr = nullptr; UniqueFEIRExpr lenExpr = nullptr; @@ -1708,7 +1749,7 @@ void FEIRStmtDAssign::AssignBoundaryVarAndChecking(MIRBuilder &mirBuilder, std:: if (lenExpr != nullptr) { UniqueFEIRStmt stmt = ENCChecker::InsertBoundaryLEChecking(lenExpr->Clone(), expr, dstExpr); if (stmt != nullptr) { - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); std::list stmtnodes = stmt->GenMIRStmts(mirBuilder); ans.insert(ans.end(), stmtnodes.begin(), stmtnodes.end()); } @@ -1721,7 +1762,7 @@ void FEIRStmtIAssign::AssignBoundaryVarAndChecking(MIRBuilder &mirBuilder, std:: return; } // insert assign boundary checking for computed r-value - ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, baseExpr, srcFileIndex, srcFileLineNum); + ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, baseExpr, loc); MIRType *baseType = static_cast(addrType->GenerateMIRTypeAuto())->GetPointedType(); FieldID tmpID = fieldID; @@ -1739,7 +1780,7 @@ void FEIRStmtIAssign::AssignBoundaryVarAndChecking(MIRBuilder &mirBuilder, std:: } UniqueFEIRStmt stmt = ENCChecker::InsertBoundaryLEChecking(lenExpr->Clone(), baseExpr, dstExpr); if (stmt != nullptr) { - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); std::list stmtnodes = stmt->GenMIRStmts(mirBuilder); ans.insert(ans.end(), stmtnodes.begin(), stmtnodes.end()); } @@ -1748,7 +1789,7 @@ void FEIRStmtIAssign::AssignBoundaryVarAndChecking(MIRBuilder &mirBuilder, std:: } void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const UniqueFEIRVar &var, FieldID fieldID, - uint32 fileIdx, uint32 fileLine) { + const Loc &loc) { if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || !FEOptions::GetInstance().IsEnableSafeRegion()) { return; } @@ -1764,7 +1805,7 @@ void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const Uniqu if (dstSym->GetAttr(ATTR_final_boundary_size)) { WARN(kLncWarn, "%s:%d warning: this var specified as the global or field boundary length is " "assigned or token address. [Use __Unsafe__ to eliminate the warning]", - FEManager::GetModule().GetFileNameFromFileNum(fileIdx).c_str(), fileLine); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } else { FieldID tmpID = fieldID; @@ -1773,13 +1814,13 @@ void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const Uniqu if (fieldPair.second.second.GetAttr(FLDATTR_final_boundary_size)) { WARN(kLncWarn, "%s:%d warning: this field specified as the global or field boundary length is " "assigned or token address. [Use __Unsafe__ to eliminate the warning]", - FEManager::GetModule().GetFileNameFromFileNum(fileIdx).c_str(), fileLine); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } } void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const UniqueFEIRType &addrType, FieldID fieldID, - uint32 fileIdx, uint32 fileLine) { + const Loc &loc) { if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || !FEOptions::GetInstance().IsEnableSafeRegion() || fieldID == 0) { return; @@ -1797,21 +1838,20 @@ void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const Uniqu if (fieldPair.second.second.GetAttr(FLDATTR_final_boundary_size)) { WARN(kLncWarn, "%s:%d warning: this field specified as the global or field boundary length is " "assigned or token address. [Use __Unsafe__ to eliminate the warning]", - FEManager::GetModule().GetFileNameFromFileNum(fileIdx).c_str(), fileLine); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } -void ENCChecker::CheckBoundaryLenFinalAddr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr, - uint32 fileIdx, uint32 fileLine) { +void ENCChecker::CheckBoundaryLenFinalAddr(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr, const Loc &loc) { if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || !FEOptions::GetInstance().IsEnableSafeRegion()) { return; } if (expr->GetKind() == kExprAddrofVar) { UniqueFEIRVar var = expr->GetVarUses().front()->Clone(); - CheckBoundaryLenFinalAssign(mirBuilder, var, expr->GetFieldID(), fileIdx, fileLine); + CheckBoundaryLenFinalAssign(mirBuilder, var, expr->GetFieldID(), loc); } else if (expr->GetKind() == kExprIAddrof) { auto *iaddrof = static_cast(expr.get()); - CheckBoundaryLenFinalAssign(mirBuilder, iaddrof->GetClonedPtrType(), expr->GetFieldID(), fileIdx, fileLine); + CheckBoundaryLenFinalAssign(mirBuilder, iaddrof->GetClonedPtrType(), expr->GetFieldID(), loc); } } @@ -1898,9 +1938,7 @@ bool ASTArraySubscriptExpr::InsertBoundaryChecking(std::list &st return false; } if (arrayType->GetKind() == MIRTypeKind::kTypeArray) { - if (ENCChecker::IsConstantIndex(indexExpr)) { - return false; // skip checking when all indexes are constants - } + // checking all type of indexes, including constant indexes while (baseAddrFEExpr != nullptr && baseAddrFEExpr->GetKind() == kExprAddrofArray) { baseAddrFEExpr = static_cast(baseAddrFEExpr.get())->GetExprArray()->Clone(); } @@ -1918,7 +1956,7 @@ bool ASTArraySubscriptExpr::InsertBoundaryChecking(std::list &st lowerExprs.emplace_back(baseAddrFEExpr->Clone()); auto lowerStmt = std::make_unique(OP_assertge, std::move(lowerExprs)); lowerStmt->SetIsComputable(true); - lowerStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + lowerStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(lowerStmt)); // insert upper boundary chencking, baseExpr will be replace by upper boundary var when FEIRStmtNary GenMIRStmts std::list upperExprs; @@ -1926,7 +1964,7 @@ bool ASTArraySubscriptExpr::InsertBoundaryChecking(std::list &st upperExprs.emplace_back(std::move(baseAddrFEExpr)); auto upperStmt = std::make_unique(OP_assertlt, std::move(upperExprs)); upperStmt->SetIsComputable(true); - upperStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + upperStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(upperStmt)); return true; } @@ -1947,7 +1985,7 @@ bool ASTUODerefExpr::InsertBoundaryChecking(std::list &stmts, Un lowerExprs.emplace_back(baseExpr->Clone()); auto lowerStmt = std::make_unique(OP_assertge, std::move(lowerExprs)); lowerStmt->SetIsComputable(expr->GetKind() == kExprBinary); - lowerStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + lowerStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(lowerStmt)); // insert upper boundary chencking, baseExpr will be replace by upper boundary var when FEIRStmtNary GenMIRStmts std::list upperExprs; @@ -1955,7 +1993,7 @@ bool ASTUODerefExpr::InsertBoundaryChecking(std::list &stmts, Un upperExprs.emplace_back(std::move(baseExpr)); auto upperStmt = std::make_unique(OP_assertlt, std::move(upperExprs)); upperStmt->SetIsComputable(expr->GetKind() == kExprBinary); - upperStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + upperStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(upperStmt)); return true; } @@ -1967,7 +2005,7 @@ void ENCChecker::ReduceBoundaryChecking(std::list &stmts, const } std::list::iterator iter = stmts.begin(); for (; iter != stmts.end(); ++iter) { - if ((*iter)->GetKind() != kFEIRStmtNary) { + if ((*iter)->GetKind() != kStmtNary) { continue; } FEIRStmtNary *nary = static_cast((*iter).get()); @@ -1977,7 +2015,7 @@ void ENCChecker::ReduceBoundaryChecking(std::list &stmts, const } nary->SetOP(OP_calcassertge); std::list::iterator nextedIter = std::next(iter, 1); - if (nextedIter != stmts.end() && (*nextedIter)->GetKind() == kFEIRStmtNary) { + if (nextedIter != stmts.end() && (*nextedIter)->GetKind() == kStmtNary) { FEIRStmtNary *nextedNary = static_cast((*nextedIter).get()); if (nextedNary->GetOP() == OP_assertlt) { nextedNary->SetOP(OP_calcassertlt); @@ -2017,7 +2055,7 @@ void ASTCallExpr::InsertBoundaryCheckingInArgs(std::list &stmts) exprs.emplace_back(std::move(baseExpr)); UniqueFEIRStmt stmt = std::make_unique(OP_callassertle, std::move(exprs), GetFuncName(), i); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); } } @@ -2051,7 +2089,7 @@ void ASTCallExpr::InsertBoundaryCheckingInArgsForICall(std::list exprs.emplace_back(std::move(baseExpr)); UniqueFEIRStmt stmt = std::make_unique( OP_callassertle, std::move(exprs), "function_pointer", i); - stmt->SetSrcFileInfo(srcFileIdx, srcFileLineNum); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); } } @@ -2080,7 +2118,7 @@ void ASTCallExpr::InsertBoundaryVarInRet(std::list &stmts) const } // GetCurrentFunction need to be optimized when parallel features MIRFunction *curFunction = FEManager::GetMIRBuilder().GetCurrentFunctionNotNull(); - ENCChecker::InitBoundaryVar(*curFunction, varName, *retType, std::move(realLenExpr), stmts); + ENCChecker::InitBoundaryVar(*curFunction, GetRetVarName(), *retType, std::move(realLenExpr), stmts); } bool ENCChecker::IsSameBoundary(const AttrBoundary &arg1, const AttrBoundary &arg2) { @@ -2100,7 +2138,7 @@ bool ENCChecker::IsSameBoundary(const AttrBoundary &arg1, const AttrBoundary &ar } void ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, - uint32 fileNum, uint32 fileLine) { + const Loc &loc) { const MIRFuncType *funcType = FEUtils::GetFuncPtrType(dstType); if (funcType == nullptr) { return; @@ -2119,12 +2157,12 @@ void ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(const MIRType &dstType, const } if (!errIdxs.empty()) { FE_ERR(kLncErr, "%s:%d error: function pointer and target function's boundary attributes are mismatched " - "for the %s argument", FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine, + "for the %s argument", FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, PrintParamIdx(errIdxs).c_str()); } if (!IsSameBoundary(srcFunc->GetFuncAttrs().GetAttrBoundary(), funcType->GetRetAttrs().GetAttrBoundary())) { FE_ERR(kLncErr, "%s:%d error: function pointer and target function's boundary attributes are mismatched " - "for the return value", FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine); + "for the return value", FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } const MIRFuncType *srcFuncType = FEUtils::GetFuncPtrType(*srcExpr->GetType()->GenerateMIRTypeAuto()); @@ -2138,11 +2176,12 @@ void ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(const MIRType &dstType, const } if (!errIdxs.empty()) { FE_ERR(kLncErr, "%s:%d error: function pointer's boundary attributes are mismatched for the %s argument", - FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine, PrintParamIdx(errIdxs).c_str()); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + PrintParamIdx(errIdxs).c_str()); } if (!IsSameBoundary(srcFuncType->GetRetAttrs().GetAttrBoundary(), funcType->GetRetAttrs().GetAttrBoundary())) { FE_ERR(kLncErr, "%s:%d error: function pointer's boundary attributes are mismatched for the return value", - FEManager::GetModule().GetFileNameFromFileNum(fileNum).c_str(), fileLine); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); } } } @@ -2155,7 +2194,7 @@ void FEIRStmtDAssign::CheckBoundaryArgsAndRetForFuncPtr(const MIRBuilder &mirBui if (fieldID != 0) { baseType = FEUtils::GetStructFieldType(static_cast(baseType), fieldID); } - ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(*baseType, expr, srcFileIndex, srcFileLineNum); + ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(*baseType, expr, loc); } void FEIRStmtIAssign::CheckBoundaryArgsAndRetForFuncPtr(const MIRBuilder &mirBuilder, const MIRType &baseType) const { @@ -2163,7 +2202,7 @@ void FEIRStmtIAssign::CheckBoundaryArgsAndRetForFuncPtr(const MIRBuilder &mirBui return; } MIRType *fieldType = FEUtils::GetStructFieldType(static_cast(&baseType), fieldID); - ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(*fieldType, baseExpr, srcFileIndex, srcFileLineNum); + ENCChecker::CheckBoundaryArgsAndRetForFuncPtr(*fieldType, baseExpr, loc); } // --------------------------- diff --git a/src/hir2mpl/common/src/fe_diag_manager.cpp b/src/hir2mpl/common/src/fe_diag_manager.cpp index 4115610378a54d23681d2c3c738f03c9e2c386c8..16f0539ec5c604b5a30ed16f37416eb0837299a8 100644 --- a/src/hir2mpl/common/src/fe_diag_manager.cpp +++ b/src/hir2mpl/common/src/fe_diag_manager.cpp @@ -1,32 +1,32 @@ -/* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. - * - * OpenArkCompiler is licensed under Mulan PSL v2. - * You can use this software according to the terms and conditions of the Mulan PSL v2. - * You may obtain a copy of Mulan PSL v2 at: - * - * http://license.coscl.org.cn/MulanPSL2 - * - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR - * FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PSL v2 for more details. - */ -#include "fe_diag_manager.h" -#include "mpl_logging.h" - -namespace maple { -void FEDiagManager::IncErrNum() { - std::lock_guard lk(errNumMtx); - ++errNum; -} - -int FEDiagManager::GetDiagRes() const { - if (errNum > 0) { - INFO(kLncInfo, "%d error generated.", errNum); - return FEErrno::kFEError; - } - return FEErrno::kNoError; -} - +/* + * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "fe_diag_manager.h" +#include "mpl_logging.h" + +namespace maple { +void FEDiagManager::IncErrNum() { + std::lock_guard lk(errNumMtx); + ++errNum; +} + +int FEDiagManager::GetDiagRes() const { + if (errNum > 0) { + INFO(kLncInfo, "%d error generated.", errNum); + return FEErrno::kFEError; + } + return FEErrno::kNoError; +} + } // namespace maple \ No newline at end of file diff --git a/src/hir2mpl/common/src/fe_function.cpp b/src/hir2mpl/common/src/fe_function.cpp index 22e4a3a8921bc1fc7a13a17397e60d4ca40ec685..4bdc3002c469ff639463d32714883a7e40b00c9e 100644 --- a/src/hir2mpl/common/src/fe_function.cpp +++ b/src/hir2mpl/common/src/fe_function.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -38,8 +38,7 @@ FEFunction::FEFunction(MIRFunction &argMIRFunction, const std::unique_ptr bb) { return feirBBList.back().get(); } -void FEFunction::LabelGenStmt() { +void FEFunction::DumpGeneralStmts() { FELinkListNode *nodeStmt = genStmtHead; - uint32 idx = 0; while (nodeStmt != nullptr) { FEIRStmt *stmt = static_cast(nodeStmt); - stmt->SetID(idx); - idx++; + stmt->Dump(); nodeStmt = nodeStmt->GetNext(); } } -void FEFunction::LabelGenBB() { - FELinkListNode *nodeBB = genBBHead; - uint32 idx = 0; - while (nodeBB != nullptr) { - FEIRBB *bb = static_cast(nodeBB); - bb->SetID(idx); - idx++; - nodeBB = nodeBB->GetNext(); - } -} - -bool FEFunction::HasDeadBB() { - FELinkListNode *nodeBB = genBBHead->GetNext(); - while (nodeBB != nullptr && nodeBB != genBBTail) { - FEIRBB *bb = static_cast(nodeBB); - if (bb->IsDead()) { - return true; - } - nodeBB = nodeBB->GetNext(); - } - return false; -} - -void FEFunction::DumpGeneralStmts() { - FELinkListNode *nodeStmt = genStmtHead; - while (nodeStmt != nullptr) { - FEIRStmt *stmt = static_cast(nodeStmt); - stmt->Dump(); - nodeStmt = nodeStmt->GetNext(); +bool FEFunction::LowerFunc(const std::string &phaseName) { + phaseResult.RegisterPhaseNameAndStart(phaseName); + if (feirLower == nullptr) { + feirLower = std::make_unique(*this); + feirLower->LowerFunc(); + feirStmtHead = feirLower->GetlowerStmtHead(); + feirStmtTail = feirLower->GetlowerStmtTail(); } + return phaseResult.Finish(); } -void FEFunction::DumpFEIRBBs() { - FELinkListNode *nodeBB = genBBHead->GetNext(); - while (nodeBB != nullptr && nodeBB != genBBTail) { - FEIRBB *bb = static_cast(nodeBB); - bb->Dump(); - nodeBB = nodeBB->GetNext(); +bool FEFunction::DumpFEIRBBs(const std::string &phaseName) { + HIR2MPL_PARALLEL_FORBIDDEN(); + phaseResult.RegisterPhaseNameAndStart(phaseName); + if (feirCFG == nullptr) { + feirCFG = std::make_unique(feirStmtHead, feirStmtTail); + feirCFG->GenerateCFG(); } + std::cout << "****** CFG built by FEIR for " << GetGeneralFuncName() << " *******\n"; + feirCFG->DumpBBs(); + std::cout << "****** END CFG built for " << GetGeneralFuncName() << " *******\n\n"; + return phaseResult.Finish(); } -void FEFunction::DumpFEIRCFGGraph() { +bool FEFunction::DumpFEIRCFGGraph(const std::string &phaseName) { HIR2MPL_PARALLEL_FORBIDDEN(); - if (!FEOptions::GetInstance().IsDumpFEIRCFGGraph()) { - return; + phaseResult.RegisterPhaseNameAndStart(phaseName); + std::string outName = FEManager::GetModule().GetFileName(); + size_t lastDot = outName.find_last_of("."); + if (lastDot != std::string::npos) { + outName = outName.substr(0, lastDot); } - std::string fileName = FEOptions::GetInstance().GetJBCCFGGraphFileName(); - CHECK_FATAL(!fileName.empty(), "General CFG Graph FileName is empty"); + CHECK_FATAL(!outName.empty(), "General CFG Graph FileName is empty"); + std::string fileName = outName + "." + GetGeneralFuncName() + ".dot"; std::ofstream file(fileName); CHECK_FATAL(file.is_open(), "Failed to open General CFG Graph FileName: %s", fileName.c_str()); - file << "digraph {" << std::endl; - file << " # /* " << GetGeneralFuncName() << " */" << std::endl; - FELinkListNode *nodeBB = genBBHead->GetNext(); - while (nodeBB != nullptr && nodeBB != genBBTail) { - FEIRBB *bb = static_cast(nodeBB); - DumpFEIRCFGGraphForBB(file, *bb); - nodeBB = nodeBB->GetNext(); + if (feirCFG == nullptr) { + feirCFG = std::make_unique(feirStmtHead, feirStmtTail); + feirCFG->GenerateCFG(); } - DumpFEIRCFGGraphForCFGEdge(file); - DumpFEIRCFGGraphForDFGEdge(file); - file << "}" << std::endl; + file << "digraph {" << std::endl; + file << " label=\"" << GetGeneralFuncName() << "\"\n"; + file << " labelloc=t\n"; + feirCFG->DumpCFGGraph(file); file.close(); -} - -void FEFunction::DumpFEIRCFGGraphForBB(std::ofstream &file, const FEIRBB &bb) { - file << " BB" << bb.GetID() << " [shape=record,label=\"{" << std::endl; - const FELinkListNode *nodeStmt = bb.GetStmtHead(); - while (nodeStmt != nullptr) { - const FEIRStmt *stmt = static_cast(nodeStmt); - file << " " << stmt->DumpDotString(); - if (nodeStmt == bb.GetStmtTail()) { - file << std::endl; - break; - } else { - file << " |" << std::endl; - } - nodeStmt = nodeStmt->GetNext(); - } - file << " }\"];" << std::endl; -} - -void FEFunction::DumpFEIRCFGGraphForCFGEdge(std::ofstream &file) { - file << " subgraph cfg_edges {" << std::endl; - file << " edge [color=\"#000000\",weight=0.3,len=3];" << std::endl; - const FELinkListNode *nodeBB = genBBHead->GetNext(); - while (nodeBB != nullptr && nodeBB != genBBTail) { - const FEIRBB *bb = static_cast(nodeBB); - const FEIRStmt *stmtS = bb->GetStmtTail(); - for (FEIRBB *bbNext : bb->GetSuccBBs()) { - const FEIRStmt *stmtE = bbNext->GetStmtHead(); - file << " BB" << bb->GetID() << ":stmt" << stmtS->GetID() << " -> "; - file << "BB" << bbNext->GetID() << ":stmt" << stmtE->GetID() << std::endl; - } - nodeBB = nodeBB->GetNext(); - } - file << " }" << std::endl; + return phaseResult.Finish(); } void FEFunction::DumpFEIRCFGGraphForDFGEdge(std::ofstream &file) { @@ -538,7 +485,7 @@ bool FEFunction::IsBBEnd(const FEIRStmt &stmt) const { } bool FEFunction::MayBeBBEnd(const FEIRStmt &stmt) const { - return (stmt.IsBranch() || !stmt.IsFallThrough()); + return (stmt.IsBranch() || !stmt.IsFallThru()); } void FEFunction::LinkFallThroughBBAndItsNext(FEIRBB &bb) { @@ -566,8 +513,6 @@ void FEFunction::LinkBranchBBAndItsTargets(FEIRBB &bb) { FEIRNodeKind nodeKind = stmtTail->GetKind(); switch (nodeKind) { case FEIRNodeKind::kStmtCondGoto: - // should fallthrough - [[fallthrough]]; case FEIRNodeKind::kStmtGoto: { LinkGotoBBAndItsTarget(bb, *stmtTail); break; @@ -845,4 +790,65 @@ void FEFunction::AddLocForStmt(const FEIRStmt &stmt, std::list &mirSt mirStmts.front()->GetSrcPos().SetLineNum(pesudoLoc->GetSrcFileLineNum()); } } + +void FEFunction::PushFuncScope(const SrcPosition &startOfScope, const SrcPosition &endOfScope) { + UniqueFEIRScope feirScope = std::make_unique(); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRScope *mockedScope = mirFunction.GetScope(); + MIRScope *mirScope = mirFunction.GetModule()->GetMemPool()->New( + mirFunction.GetModule(), 1); // func scope start level is 1 + mirScope->SetRange(startOfScope, endOfScope); + mockedScope->AddScope(mirScope); + feirScope->SetMIRScope(mirScope); + } + stmtsScopeStack.push(std::move(feirScope)); +} + +void FEFunction::PushStmtScope(const SrcPosition &startOfScope, const SrcPosition &endOfScope) { + UniqueFEIRScope feirScope = std::make_unique(); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRScope *parentMIRScope = GetTopStmtMIRScope(); + MIRScope *mirScope = mirFunction.GetModule()->GetMemPool()->New( + mirFunction.GetModule(), parentMIRScope->GetLevel()); + mirScope->SetRange(startOfScope, endOfScope); + parentMIRScope->AddScope(mirScope); + feirScope->SetMIRScope(mirScope); + } + stmtsScopeStack.push(std::move(feirScope)); +} + +FEIRScope *FEFunction::GetTopStmtFEIRScopePtr() const { + if (!stmtsScopeStack.empty()) { + return stmtsScopeStack.top().get(); + } + CHECK_FATAL(false, "scope stack is empty"); + return nullptr; +} + +MIRScope *FEFunction::GetTopStmtMIRScope() const { + if (!stmtsScopeStack.empty()) { + return stmtsScopeStack.top().get()->GetMIRScope(); + } + CHECK_FATAL(false, "scope stack is empty"); + return nullptr; +} + +UniqueFEIRScope FEFunction::PopTopStmtScope() { + if (!stmtsScopeStack.empty()) { + UniqueFEIRScope scope = std::move(stmtsScopeStack.top()); + stmtsScopeStack.pop(); + return scope; + } + CHECK_FATAL(false, "scope stack is empty"); + return nullptr; +} + +void FEFunction::AddAliasInMIRScope(MIRScope *scope, const std::string &srcVarName, const MIRSymbol *symbol) { + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(srcVarName); + MIRAliasVars aliasVar; + aliasVar.tyIdx = symbol->GetTyIdx(); + aliasVar.mplStrIdx = symbol->GetNameStrIdx(); + aliasVar.isLocal = symbol->IsLocal(); + scope->SetAliasVarMap(nameIdx, aliasVar); +}; } // namespace maple diff --git a/src/hir2mpl/common/src/fe_input_helper.cpp b/src/hir2mpl/common/src/fe_input_helper.cpp index 71d21bb6534058abc0da97975d4d9508b31e2b4c..f6acd3e8f305640aff8feaa287a4a1c8537ad774 100644 --- a/src/hir2mpl/common/src/fe_input_helper.cpp +++ b/src/hir2mpl/common/src/fe_input_helper.cpp @@ -17,9 +17,11 @@ #include "fe_manager.h" namespace maple { -#define SET_CLASS_INFO_PAIR(A, B, C, D) \ - A->PushbackMIRInfo(MIRInfoPair(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(B), C)); \ - A->PushbackIsString(D) +#define SET_CLASS_INFO_PAIR(A, B, C, D) \ + do { \ + (A)->PushbackMIRInfo(MIRInfoPair(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(B), C)); \ + (A)->PushbackIsString(D); \ + } while (0); std::string FEInputStructHelper::GetSrcFileNameImpl() const { return "unknown"; diff --git a/src/hir2mpl/common/src/fe_struct_elem_info.cpp b/src/hir2mpl/common/src/fe_struct_elem_info.cpp index 82584923eb08608b000be43cebeea4b9c9fe758d..a20a5d6b143b65398ab6d72a45c89a14b666bcad 100644 --- a/src/hir2mpl/common/src/fe_struct_elem_info.cpp +++ b/src/hir2mpl/common/src/fe_struct_elem_info.cpp @@ -18,11 +18,11 @@ #include "namemangler.h" #include "feir_builder.h" #include "feir_var_name.h" +#include "fe_utils_java.h" #include "fe_utils.h" #include "fe_manager.h" -#include "jbc_util.h" #include "fe_options.h" -#include "bc_util.h" + namespace maple { // ---------- FEStructElemInfo ---------- @@ -219,6 +219,7 @@ FEStructMethodInfo::FEStructMethodInfo(MapleAllocator &allocatorIn, const Struct MIRSrcLang argSrcLang, bool argIsStatic) : FEStructElemInfo(allocatorIn, argStructElemNameIdx, argSrcLang, argIsStatic), isReturnVoid(false), + isConstructor(false), isJavaPolymorphicCall(false), isJavaDynamicCall(false), methodNameIdx(argStructElemNameIdx.full), @@ -300,7 +301,7 @@ void FEStructMethodInfo::LoadMethodType() { void FEStructMethodInfo::LoadMethodTypeJava() { std::string signatureJava = namemangler::DecodeName(GlobalTables::GetStrTable().GetStringFromStrIdx(structElemNameIdx.full)); - std::vector typeNames = jbc::JBCUtil::SolveMethodSignature(signatureJava); + std::vector typeNames = FEUtilJava::SolveMethodSignature(signatureJava); CHECK_FATAL(typeNames.size() > 0, "invalid method signature: %s", signatureJava.c_str()); // constructor check const std::string &funcName = GetElemName(); diff --git a/src/hir2mpl/common/src/fe_type_manager.cpp b/src/hir2mpl/common/src/fe_type_manager.cpp index 1ec9a40f6cbfd2f66ebb4ccf4e03e8125cd1aa60..52c55ab5fb3bb053f82781a11e03e2eb81f6f16e 100644 --- a/src/hir2mpl/common/src/fe_type_manager.cpp +++ b/src/hir2mpl/common/src/fe_type_manager.cpp @@ -124,7 +124,7 @@ void FETypeManager::UpdateStructNameTypeMapFromTypeTable(const std::string &mplt if ((type != nullptr) && IsStructType(*type)) { MIRStructType *structType = static_cast(type); auto it = structNameTypeMap.insert(std::make_pair(structType->GetNameStrIdx(), std::make_pair(structType, flag))); - if (it.second == false) { + if (!it.second) { // type is existed structSameNameSrcList.push_back(std::make_pair(structType->GetNameStrIdx(), structNameSrcMap[structType->GetNameStrIdx()])); @@ -444,7 +444,7 @@ FEStructElemInfo *FETypeManager::RegisterStructFieldInfo( return ptrInfo; } ptrInfo = allocator.GetMemPool()->New(allocator, structElemNameIdx, argSrcLang, isStatic); - CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(structElemNameIdx.full, ptrInfo)).second == true, + CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(structElemNameIdx.full, ptrInfo)).second, "register struct elem info failed"); return ptrInfo; } @@ -457,7 +457,7 @@ FEStructElemInfo *FETypeManager::RegisterStructMethodInfo( return ptrInfo; } ptrInfo = allocator.GetMemPool()->New(allocator, structElemNameIdx, argSrcLang, isStatic); - CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(structElemNameIdx.full, ptrInfo)).second == true, + CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(structElemNameIdx.full, ptrInfo)).second, "register struct elem info failed"); return ptrInfo; } @@ -470,7 +470,7 @@ FEStructElemInfo *FETypeManager::GetStructElemInfo(const GStrIdx &fullNameIdx) c return it->second; } -MIRFunction *FETypeManager::GetMIRFunction(const std::string &classMethodName, bool isStatic){ +MIRFunction *FETypeManager::GetMIRFunction(const std::string &classMethodName, bool isStatic) { GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(classMethodName); return GetMIRFunction(nameIdx, isStatic); } @@ -481,8 +481,8 @@ MIRFunction *FETypeManager::GetMIRFunction(const GStrIdx &nameIdx, bool isStatic if (it != funcMap.end()) { return it->second; } - const std::unordered_map &mpltFuncMap = isStatic ? mpltNameStaticFuncMap : - mpltNameFuncMap; + const std::unordered_map &mpltFuncMap = + isStatic ? mpltNameStaticFuncMap : mpltNameFuncMap; auto it2 = mpltFuncMap.find(nameIdx); if (it2 != mpltFuncMap.end()) { return it2->second; diff --git a/src/hir2mpl/common/src/fe_utils.cpp b/src/hir2mpl/common/src/fe_utils.cpp index 772620e1c45cc9108da4a73c7b5d1d9e9bf90172..7303e4f1f1182430f972eb527e44d23d7d618a2a 100644 --- a/src/hir2mpl/common/src/fe_utils.cpp +++ b/src/hir2mpl/common/src/fe_utils.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -105,14 +105,14 @@ PrimType FEUtils::MergePrimType(PrimType primType1, PrimType primType2) { return primType1; } // merge signed integer - CHECK_FATAL(LogicXOR(IsSignedInteger(primType1), IsSignedInteger(primType2)) == false, + CHECK_FATAL(!LogicXOR(IsSignedInteger(primType1), IsSignedInteger(primType2)), "can not merge type %s and %s", GetPrimTypeName(primType1), GetPrimTypeName(primType2)); if (IsSignedInteger(primType1)) { return GetPrimTypeSize(primType1) >= GetPrimTypeSize(primType2) ? primType1 : primType2; } // merge unsigned integer - CHECK_FATAL(LogicXOR(IsUnsignedInteger(primType1), IsUnsignedInteger(primType2)) == false, + CHECK_FATAL(!LogicXOR(IsUnsignedInteger(primType1), IsUnsignedInteger(primType2)), "can not merge type %s and %s", GetPrimTypeName(primType1), GetPrimTypeName(primType2)); if (IsUnsignedInteger(primType1)) { if (GetPrimTypeSize(primType1) == GetPrimTypeSize(primType2) && GetPrimTypeSize(primType1) == 1) { @@ -123,7 +123,7 @@ PrimType FEUtils::MergePrimType(PrimType primType1, PrimType primType2) { } // merge float - CHECK_FATAL(LogicXOR(IsPrimitiveFloat(primType1), IsPrimitiveFloat(primType2)) == false, + CHECK_FATAL(!LogicXOR(IsPrimitiveFloat(primType1), IsPrimitiveFloat(primType2)), "can not merge type %s and %s", GetPrimTypeName(primType1), GetPrimTypeName(primType2)); if (IsPrimitiveFloat(primType1)) { return GetPrimTypeSize(primType1) >= GetPrimTypeSize(primType2) ? primType1 : primType2; @@ -191,11 +191,14 @@ uint32 FEUtils::GetSequentialNumber() { return unnamedSymbolIdx++; } -std::string FEUtils::GetFileNameHashStr(const std::string &fileName) { - static const std::hash hasher; - auto tmp = static_cast(hasher(fileName)); - uint32 result = tmp & 0x7fffff; // The highest bit is always 0, so it can be converted to int32 safely - return "_" + std::to_string(static_cast(result)); +std::string FEUtils::GetFileNameHashStr(const std::string &fileName, uint32 seed) { + const char *name = fileName.c_str(); + uint32 hash = 0; + while (*name) { + uint8_t uName = *name++; + hash = hash * seed + uName; + } + return kRenameKeyWord + std::to_string(hash); } std::string FEUtils::GetSequentialName(const std::string &prefix) { @@ -203,6 +206,11 @@ std::string FEUtils::GetSequentialName(const std::string &prefix) { return name; } +std::string FEUtils::CreateLabelName() { + static uint32 unnamedSymbolIdx = 1; + return "L." + std::to_string(unnamedSymbolIdx++); +} + bool FEUtils::TraverseToNamedField(MIRStructType &structType, const GStrIdx &nameIdx, FieldID &fieldID, bool isTopLevel) { for (uint32 fieldIdx = 0; fieldIdx < structType.GetFieldsSize(); ++fieldIdx) { @@ -465,6 +473,16 @@ void FELinkListNode::InsertAfter(FELinkListNode *ins, FELinkListNode *pos) { ins->next = posNext; } +void FELinkListNode::SpliceNodes(FELinkListNode *head, FELinkListNode *tail, FELinkListNode *newTail) { + FELinkListNode *stmt = head->GetNext(); + FELinkListNode *nextStmt = stmt; + do { + stmt = nextStmt; + nextStmt = stmt->GetNext(); + newTail->InsertBefore(stmt); + } while (nextStmt != nullptr && nextStmt != tail); +} + uint32_t AstSwitchUtil::tempVarNo = 0; const char *AstSwitchUtil::cleanLabel = "clean"; const char *AstSwitchUtil::exitLabel = "exit"; diff --git a/src/hir2mpl/common/src/feir_builder.cpp b/src/hir2mpl/common/src/feir_builder.cpp index fc9890620a63a6c9641e646df55a117a4189c8e8..c791f1610e49bacf373b99ab75a905d226facd54 100644 --- a/src/hir2mpl/common/src/feir_builder.cpp +++ b/src/hir2mpl/common/src/feir_builder.cpp @@ -289,8 +289,8 @@ UniqueFEIRExpr FEIRBuilder::CreateExprZeroCompare(Opcode op, UniqueFEIRExpr expr } return std::make_unique(val, PTY_u1); } - UniqueFEIRExpr zeroExpr = (expr->GetPrimType() == PTY_ptr) ? CreateExprConstPtrNull() : - CreateExprConstAnyScalar(expr->GetPrimType(), 0); + UniqueFEIRExpr zeroExpr = + (expr->GetPrimType() == PTY_ptr) ? CreateExprConstPtrNull() : CreateExprConstAnyScalar(expr->GetPrimType(), 0); return CreateExprMathBinary(op, std::move(expr), std::move(zeroExpr)); } diff --git a/src/hir2mpl/common/src/feir_scope.cpp b/src/hir2mpl/common/src/feir_scope.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57b61d13325f0b60aaedeb13b5bd004dfc129dea --- /dev/null +++ b/src/hir2mpl/common/src/feir_scope.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) [2022] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +#include "feir_scope.h" +#include "feir_builder.h" + +namespace maple { +FEIRScope::FEIRScope(MIRScope *scope) : mirScope(scope) {} + +UniqueFEIRStmt FEIRScope::GenVLAStackRestoreStmt() const { + CHECK_NULL_FATAL(vlaSavedStackVar); + UniqueFEIRExpr dreadVar = FEIRBuilder::CreateExprDRead(vlaSavedStackVar->Clone()); + std::unique_ptr> argExprList = std::make_unique>(); + argExprList->emplace_back(std::move(dreadVar)); + return std::make_unique(INTRN_C_stack_restore, nullptr, nullptr, + std::move(argExprList)); +} +} diff --git a/src/hir2mpl/common/src/feir_stmt.cpp b/src/hir2mpl/common/src/feir_stmt.cpp old mode 100755 new mode 100644 index 9b6e73dc8eb44146cf8b7e85368335c1e44d28db..36bbbedce80082b4e111b3cac1d0ce50538c3218 --- a/src/hir2mpl/common/src/feir_stmt.cpp +++ b/src/hir2mpl/common/src/feir_stmt.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -24,11 +24,14 @@ #include "feir_var_type_scatter.h" #include "fe_options.h" #include "feir_type_helper.h" -#include "bc_util.h" -#include "rc_setter.h" #include "fe_utils.h" +#include "fe_utils_java.h" #include "enhance_c_checker.h" #include "fe_macros.h" +#ifndef ONLY_C +#include "rc_setter.h" +#endif +#include "ast_util.h" namespace maple { std::string GetFEIRNodeKindDescription(FEIRNodeKind kindArg) { @@ -108,7 +111,7 @@ std::string FEIRStmt::DumpDotStringImpl() const { } void FEIRStmt::DumpImpl(const std::string &prefix) const { - std::cout << prefix << "FEIRStmt" << id << "(kind=" << GetKind() << ")" << std::endl; + std::cout << prefix << "FEIRStmt" << id << "(kind=" << GetFEIRNodeKindDescription(kind) << ")\n"; } // ---------- FEIRStmtCheckPoint ---------- @@ -224,7 +227,7 @@ std::string FEIRStmtCheckPoint::DumpDotStringImpl() const { // ---------- FEIRStmtNary ---------- FEIRStmtNary::FEIRStmtNary(Opcode opIn, std::list> argExprsIn) - : FEIRStmt(kFEIRStmtNary), op(opIn), argExprs(std::move(argExprsIn)) {} + : FEIRStmt(kStmtNary), op(opIn), argExprs(std::move(argExprsIn)) {} std::list FEIRStmtNary::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list stmts; @@ -237,6 +240,14 @@ std::list FEIRStmtNary::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const } stmt = mirBuilder.CreateStmtNary(op, std::move(args)); } else if (argExprs.size() == 1) { + // ignore invalid syntax: access content pointed by void pointer + if (op == OP_eval && argExprs.front()->GetKind() == FEIRNodeKind::kExprIRead) { + FEIRExprIRead *ireadFeExpr = static_cast(argExprs.front().get()); + MIRType *mirType = ireadFeExpr->GetClonedPtrType()->GenerateMIRTypeAuto(); + if (ASTUtil::IsVoidPointerType(mirType->GetTypeIndex())) { + return stmts; + } + } BaseNode *node = argExprs.front()->GenMIRNode(mirBuilder); if (op == OP_eval && argExprs.front()->IsAddrof()) { node = ReplaceAddrOfNode(node); // addrof va_list @@ -325,8 +336,8 @@ std::list FEIRStmtDAssign::GenMIRStmtsImpl(MIRBuilder &mirBuilder) co CheckBoundaryArgsAndRetForFuncPtr(mirBuilder); StmtNode *mirStmt = mirBuilder.CreateStmtDassign(*dstSym, fieldID, srcNode); ans.push_back(mirStmt); - ENCChecker::CheckBoundaryLenFinalAssign(mirBuilder, var, fieldID, srcFileIndex, srcFileLineNum); - ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, expr, srcFileIndex, srcFileLineNum); + ENCChecker::CheckBoundaryLenFinalAssign(mirBuilder, var, fieldID, loc); + ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, expr, loc); return ans; } @@ -335,20 +346,24 @@ void FEIRStmtDAssign::InsertNonnullChecking(MIRBuilder &mirBuilder, const MIRSym if (!FEOptions::GetInstance().IsNpeCheckDynamic()) { return; } + MIRType *srcType = expr->GetType()->GenerateMIRTypeAuto(); if (fieldID == 0) { + ENCChecker::CheckNonnullFieldInStruct(*srcType, *dstSym.GetType(), loc); if (!dstSym.GetAttr(ATTR_nonnull)) { return; } } else { FieldID tmpID = fieldID; FieldPair fieldPair = static_cast(dstSym.GetType())->TraverseToFieldRef(tmpID); + MIRType *dstType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldPair.second.first); + ENCChecker::CheckNonnullFieldInStruct(*srcType, *dstType, loc); if (!fieldPair.second.second.GetAttr(FLDATTR_nonnull)) { return; } } if (ENCChecker::HasNullExpr(expr)) { FE_ERR(kLncErr, "%s:%d error: null assignment of nonnull pointer", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIndex).c_str(), srcFileLineNum); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); return; } UniqueFEIRStmt stmt = std::make_unique(OP_assignassertnonnull, expr->Clone()); @@ -706,10 +721,10 @@ FEStructMethodInfo &FEIRStmtJavaMultiANewArray::GetMethodInfoNewInstance() { if (methodInfoNewInstance != nullptr) { return *methodInfoNewInstance; } - StructElemNameIdx structElemNameIdx(bc::BCUtil::GetMultiANewArrayClassIdx(), - bc::BCUtil::GetMultiANewArrayElemIdx(), - bc::BCUtil::GetMultiANewArrayTypeIdx(), - bc::BCUtil::GetMultiANewArrayFullIdx()); + StructElemNameIdx structElemNameIdx(FEUtilJava::GetMultiANewArrayClassIdx(), + FEUtilJava::GetMultiANewArrayElemIdx(), + FEUtilJava::GetMultiANewArrayTypeIdx(), + FEUtilJava::GetMultiANewArrayFullIdx()); methodInfoNewInstance = static_cast(FEManager::GetTypeManager().RegisterStructMethodInfo( structElemNameIdx, kSrcLangJava, true)); return *methodInfoNewInstance; @@ -833,7 +848,9 @@ std::list FEIRStmtAssertBoundary::GenMIRStmtsImpl(MIRBuilder &mirBuil // ---------- FEIRStmtReturn ---------- FEIRStmtReturn::FEIRStmtReturn(std::unique_ptr argExpr) - : FEIRStmtUseOnly(FEIRNodeKind::kStmtReturn, OP_return, std::move(argExpr)) {} + : FEIRStmtUseOnly(FEIRNodeKind::kStmtReturn, OP_return, std::move(argExpr)) { + isFallThru = true; + } std::list FEIRStmtReturn::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list ans; @@ -850,8 +867,8 @@ std::list FEIRStmtReturn::GenMIRStmtsImpl(MIRBuilder &mirBuilder) con mirStmt = mirBuilder.CreateStmtReturn(nullptr); } else { InsertNonnullChecking(mirBuilder, ans); - ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, expr, srcFileIndex, srcFileLineNum); - ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, expr, srcFileIndex, srcFileLineNum); + ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, expr, loc); + ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, expr, loc); mirStmt = mirBuilder.CreateStmtReturn(srcNode); } } @@ -863,17 +880,21 @@ void FEIRStmtReturn::InsertNonnullChecking(MIRBuilder &mirBuilder, std::listGetType()->GenerateMIRTypeAuto(); + MIRType *dstType = mirBuilder.GetCurrentFunction()->GetReturnType(); + ENCChecker::CheckNonnullFieldInStruct(*srcType, *dstType, loc); if (!mirBuilder.GetCurrentFunction()->GetAttrs().GetAttr(FUNCATTR_nonnull)) { return; } if (ENCChecker::HasNullExpr(expr)) { FE_ERR(kLncErr, "%s:%d error: %s return nonnull but got null pointer", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIndex).c_str(), srcFileLineNum, + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, mirBuilder.GetCurrentFunction()->GetName().c_str()); return; } if (expr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique(OP_returnassertnonnull, expr->Clone()); + stmt->SetSrcLoc(expr->GetLoc()); std::list stmts = stmt->GenMIRStmts(mirBuilder); ans.splice(ans.end(), stmts); } @@ -1026,6 +1047,13 @@ bool FEIRStmtSwitch::CalculateDefs4AllUsesImpl(FEIRStmtCheckPoint &checkPoint, F return expr->CalculateDefs4AllUses(checkPoint, udChain); } +bool FEIRStmtSwitch::IsFallThroughImpl() const { + WARN(kLncWarn, "%s:%d stmt[%s] need to be lowed when building bb", + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + GetFEIRNodeKindDescription(kind).c_str()); + return false; +} + std::list FEIRStmtSwitch::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list ans; CaseVector switchTable(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); @@ -1059,6 +1087,13 @@ FEIRStmtSwitch2::~FEIRStmtSwitch2() { defaultTarget = nullptr; } +bool FEIRStmtSwitch2::IsFallThroughImpl() const { + WARN(kLncWarn, "%s:%d stmt[%s] need to be lowed when building bb", + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + GetFEIRNodeKindDescription(kind).c_str()); + return false; +} + std::list FEIRStmtSwitch2::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list ans; CaseVector switchTable(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); @@ -1101,6 +1136,13 @@ FEIRStmtIf::FEIRStmtIf(UniqueFEIRExpr argCondExpr, } } +bool FEIRStmtIf::IsFallThroughImpl() const { + WARN(kLncWarn, "%s:%d stmt[%s] need to be lowed when building bb", + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + GetFEIRNodeKindDescription(kind).c_str()); + return false; +} + std::list FEIRStmtIf::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { BaseNode *condBase = condExpr->GenMIRNode(mirBuilder); IfStmtNode *stmt = nullptr; @@ -1110,13 +1152,13 @@ std::list FEIRStmtIf::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { stmt = mirBuilder.CreateStmtIf(condBase); } for (const auto &thenStmt : thenStmts) { - for(auto thenNode : thenStmt->GenMIRStmts(mirBuilder)) { + for (auto thenNode : thenStmt->GenMIRStmts(mirBuilder)) { stmt->GetThenPart()->AddStatement(thenNode); } } if (hasElse) { for (const auto &elseStmt : elseStmts) { - for(auto elseNode : elseStmt->GenMIRStmts(mirBuilder)) { + for (auto elseNode : elseStmt->GenMIRStmts(mirBuilder)) { stmt->GetElsePart()->AddStatement(elseNode); } } @@ -1468,7 +1510,7 @@ bool FEIRStmtFieldStore::NeedMCCForStatic(uint32 &typeID) const { // check type first const std::string &actualContainerName = fieldInfo.GetActualContainerName(); typeID = FEManager::GetTypeManager().GetTypeIDFromMplClassName(actualContainerName, dexFileHashCode); - if(typeID == UINT32_MAX) { + if (typeID == UINT32_MAX) { return true; } @@ -1478,14 +1520,14 @@ bool FEIRStmtFieldStore::NeedMCCForStatic(uint32 &typeID) const { const auto &fields = currStructType->GetStaticFields(); for (auto f : fields) { const std::string &fieldNameIt = GlobalTables::GetStrTable().GetStringFromStrIdx(f.first); - if(fieldName.compare(fieldNameIt) == 0) { + if (fieldName.compare(fieldNameIt) == 0) { return false; } } return true; } -void FEIRStmtFieldStore::InitPrimTypeFuncNameIdxMap (std::map &primTypeFuncNameIdxMap) const { +void FEIRStmtFieldStore::InitPrimTypeFuncNameIdxMap(std::map &primTypeFuncNameIdxMap) const { primTypeFuncNameIdxMap = { { PTY_u1, FEUtils::GetMCCStaticFieldSetBoolIdx() }, { PTY_i8, FEUtils::GetMCCStaticFieldSetByteIdx() }, @@ -1564,9 +1606,11 @@ std::list FEIRStmtFieldStore::GenMIRStmtsImplForNonStatic(MIRBuilder BaseNode *nodeObj = exprDReadObj->GenMIRNode(mirBuilder); BaseNode *nodeField = exprDReadField->GenMIRNode(mirBuilder); StmtNode *stmt = mirBuilder.CreateStmtIassign(*ptrStructType, fieldID, nodeObj, nodeField); +#ifndef ONLY_C if (FEOptions::GetInstance().IsRC()) { bc::RCSetter::GetRCSetter().CollectInputStmtField(stmt, fieldInfo.GetElemNameIdx()); } +#endif ans.emplace_back(stmt); if (!FEOptions::GetInstance().IsNoBarrier() && fieldInfo.IsVolatile()) { StmtNode *barrier = mirBuilder.GetMirModule().CurFuncCodeMemPool()->New(OP_membarrelease); @@ -1644,7 +1688,7 @@ bool FEIRStmtFieldLoad::NeedMCCForStatic(uint32 &typeID) const { // check type first const std::string &actualContainerName = fieldInfo.GetActualContainerName(); typeID = FEManager::GetTypeManager().GetTypeIDFromMplClassName(actualContainerName, dexFileHashCode); - if(typeID == UINT32_MAX) { + if (typeID == UINT32_MAX) { return true; } @@ -1660,7 +1704,7 @@ bool FEIRStmtFieldLoad::NeedMCCForStatic(uint32 &typeID) const { } for (auto f : fields) { const std::string &fieldNameIt = GlobalTables::GetStrTable().GetStringFromStrIdx(f.first); - if(fieldName.compare(fieldNameIt) == 0) { + if (fieldName.compare(fieldNameIt) == 0) { return false; } } @@ -1820,8 +1864,8 @@ std::list FEIRStmtCallAssign::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const std::string funcName = methodInfo.GetMirFunc()->GetName(); for (const UniqueFEIRExpr &exprArg : exprArgs) { InsertNonnullCheckingInArgs(exprArg, index++, mirBuilder, ans, funcName); - ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, exprArg, srcFileIndex, srcFileLineNum); - ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, exprArg, srcFileIndex, srcFileLineNum); + ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, exprArg, loc); + ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, exprArg, loc); BaseNode *node = exprArg->GenMIRNode(mirBuilder); args.push_back(node); } @@ -1862,18 +1906,22 @@ void FEIRStmtCallAssign::InsertNonnullCheckingInArgs(const UniqueFEIRExpr &expr, if (index >= methodInfo.GetMirFunc()->GetParamSize()) { // Skip variable parameter return; } + MIRType *srcType = expr->GetType()->GenerateMIRTypeAuto(); + MIRType *dstType = methodInfo.GetMirFunc()->GetNthParamType(index); + ENCChecker::CheckNonnullFieldInStruct(*srcType, *dstType, loc); if (!methodInfo.GetMirFunc()->GetNthParamAttr(index).GetAttr(ATTR_nonnull)) { return; } if (ENCChecker::HasNullExpr(expr)) { FE_ERR(kLncErr, "%s:%d error: null passed to a callee that requires a nonnull argument[the %s argument]", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIndex).c_str(), srcFileLineNum, + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, ENCChecker::GetNthStr(index).c_str()); return; } if (expr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique(OP_callassertnonnull, expr->Clone(), funcName, index); + stmt->SetSrcLoc(expr->GetLoc()); std::list stmts = stmt->GenMIRStmts(mirBuilder); ans.splice(ans.end(), stmts); } @@ -1976,18 +2024,25 @@ void FEIRStmtICallAssign::InsertNonnullCheckingInArgs(MIRBuilder &mirBuilder, st size_t size = funcType->GetParamAttrsList().size(); for (const auto &expr : exprArgs) { ++idx; - if (idx < 0 || idx >= static_cast(size) || !funcType->GetNthParamAttrs(idx).GetAttr(ATTR_nonnull)) { + if (idx < 0 || idx >= static_cast(size)) { + continue; + } + MIRType *srcType = expr->GetType()->GenerateMIRTypeAuto(); + MIRType *dstType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(funcType->GetNthParamType(idx)); + ENCChecker::CheckNonnullFieldInStruct(*srcType, *dstType, loc); + if (!funcType->GetNthParamAttrs(idx).GetAttr(ATTR_nonnull)) { continue; } if (ENCChecker::HasNullExpr(expr)) { FE_ERR(kLncErr, "%s:%d error: null passed to a callee that requires a nonnull argument[the %s argument]", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIndex).c_str(), srcFileLineNum, + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, ENCChecker::GetNthStr(idx).c_str()); continue; } if (expr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique( OP_callassertnonnull, expr->Clone(), "function_pointer", idx); + stmt->SetSrcLoc(expr->GetLoc()); std::list stmts = stmt->GenMIRStmts(mirBuilder); ans.splice(ans.end(), stmts); } @@ -2016,8 +2071,8 @@ std::list FEIRStmtICallAssign::GenMIRStmtsImpl(MIRBuilder &mirBuilder args.reserve(exprArgs.size()); for (const UniqueFEIRExpr &exprArg : exprArgs) { BaseNode *node = exprArg->GenMIRNode(mirBuilder); - ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, exprArg, srcFileIndex, srcFileLineNum); - ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, exprArg, srcFileIndex, srcFileLineNum); + ENCChecker::InsertBoundaryAssignChecking(mirBuilder, ans, exprArg, loc); + ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, exprArg, loc); args.push_back(node); } InsertNonnullCheckingInArgs(mirBuilder, ans); @@ -2141,17 +2196,14 @@ std::list FEIRStmtIntrinsicCallAssign::GenMIRStmtsImpl(MIRBuilder &mi args.push_back(node); } } - stmtCall = mirBuilder.CreateStmtIntrinsicCall(intrinsicId, std::move(args), TyIdx(0)); - } else if (intrinsicId == INTRN_C_memset) { - MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); - if (exprList != nullptr) { - for (const auto &expr : *exprList) { - BaseNode *node = expr->GenMIRNode(mirBuilder); - args.push_back(node); - } + MIRSymbol *retVarSym = nullptr; + if (var != nullptr) { + retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicId, std::move(args), retVarSym); + } else { + stmtCall = mirBuilder.CreateStmtIntrinsicCall(intrinsicId, std::move(args), TyIdx(0)); } - stmtCall = mirBuilder.CreateStmtIntrinsicCall(INTRN_C_memset, std::move(args), TyIdx(0)); - } else if (intrinsicId >= INTRN_vector_zip_v2i32 && intrinsicId <= INTRN_vector_zip_v2f32) { + } else { MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); if (exprList != nullptr) { for (const auto &expr : *exprList) { @@ -2162,8 +2214,10 @@ std::list FEIRStmtIntrinsicCallAssign::GenMIRStmtsImpl(MIRBuilder &mi MIRSymbol *retVarSym = nullptr; if ((var != nullptr) && (var.get() != nullptr)) { retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicId, std::move(args), retVarSym); + } else { + stmtCall = mirBuilder.CreateStmtIntrinsicCall(intrinsicId, std::move(args), TyIdx(0)); } - stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicId, std::move(args), retVarSym); } // other intrinsic call should be implemented ans.emplace_back(stmtCall); @@ -2265,6 +2319,7 @@ std::unique_ptr FEIRExpr::Clone() { expr->isAddrof = IsAddrof(); expr->hasException = HasException(); expr->isBoundaryChecking = IsBoundaryChecking(); + expr->SetLoc(loc); return expr; } @@ -2368,6 +2423,8 @@ BaseNode *FEIRExprConst::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { case PTY_i16: case PTY_i32: case PTY_i64: + case PTY_i128: + case PTY_u128: case PTY_ref: case PTY_ptr: return mirBuilder.CreateIntConst(value.i64, primType); @@ -2516,23 +2573,30 @@ BaseNode *FEIRExprIRead::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { } // ---------- FEIRExprAddrofConstArray ---------- -FEIRExprAddrofConstArray::FEIRExprAddrofConstArray(const std::vector &arrayIn, MIRType *typeIn) +FEIRExprAddrofConstArray::FEIRExprAddrofConstArray(const std::vector &arrayIn, MIRType *typeIn, + const std::string &strIn) : FEIRExpr(FEIRNodeKind::kExprAddrof, FEIRTypeHelper::CreateTypeNative(*GlobalTables::GetTypeTable().GetPtrType())), arrayName(FEOptions::GetInstance().GetFuncInlineSize() != 0 ? FEUtils::GetSequentialName("const_array_") + FEUtils::GetFileNameHashStr(FEManager::GetModule().GetFileName()) : FEUtils::GetSequentialName("const_array_")), - elemType(typeIn) { + elemType(typeIn), + str(strIn) { std::copy(arrayIn.begin(), arrayIn.end(), std::back_inserter(array)); } std::unique_ptr FEIRExprAddrofConstArray::CloneImpl() const { - std::unique_ptr expr = std::make_unique(arrayName, array, elemType); + std::unique_ptr expr = std::make_unique(arrayName, array, elemType, str); return expr; } BaseNode *FEIRExprAddrofConstArray::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { + if (!str.empty()) { + MIRModule &module = mirBuilder.GetMirModule(); + UStrIdx StrIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str); + return module.GetMemPool()->New(PTY_ptr, StrIdx); + } MIRType *arrayTypeWithSize = GlobalTables::GetTypeTable().GetOrCreateArrayType( - *elemType,static_cast(array.size())); + *elemType, static_cast(array.size())); MIRSymbol *arrayVar = mirBuilder.GetOrCreateGlobalDecl(arrayName, *arrayTypeWithSize); arrayVar->SetAttr(ATTR_readonly); arrayVar->SetStorageClass(kScFstatic); @@ -3790,7 +3854,7 @@ BaseNode *FEIRExprAtomic::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { {kAtomicOpStoreN, INTRN_C___atomic_store_n}, {kAtomicOpStore, INTRN_C___atomic_store}, {kAtomicOpExchangeN, INTRN_C___atomic_exchange_n}, - {kAtomicOpExchange, INTRN_C___atomic_compare_exchange}, + {kAtomicOpExchange, INTRN_C___atomic_exchange}, {kAtomicOpAddFetch, INTRN_C___atomic_add_fetch}, {kAtomicOpSubFetch, INTRN_C___atomic_sub_fetch}, {kAtomicOpAndFetch, INTRN_C___atomic_and_fetch}, @@ -3863,7 +3927,8 @@ std::list FEIRStmtPesudoLabel2::GenMIRStmtsImpl(MIRBuilder &mirBuilde FEIRStmtPesudoLOC::FEIRStmtPesudoLOC(uint32 argSrcFileIdx, uint32 argLineNumber) : FEIRStmt(kStmtPesudoLOC) { isAuxPre = true; - SetSrcFileInfo(argSrcFileIdx, argLineNumber); + Loc loc = {argSrcFileIdx, argLineNumber, 0}; + SetSrcLoc(loc); } std::list FEIRStmtPesudoLOC::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { @@ -3990,7 +4055,7 @@ std::list FEIRStmtPesudoCatch2::GenMIRStmtsImpl(MIRBuilder &mirBuilde void FEIRStmtPesudoCatch2::AddCatchTypeNameIdx(GStrIdx typeNameIdx) { UniqueFEIRType type; if (typeNameIdx == FEUtils::GetVoidIdx()) { - type = std::make_unique(PTY_ref, bc::BCUtil::GetJavaThrowableNameMplIdx()); + type = std::make_unique(PTY_ref, FEUtilJava::GetJavaThrowableNameMplIdx()); } else { type = std::make_unique(PTY_ref, typeNameIdx); } @@ -4119,8 +4184,8 @@ std::list FEIRStmtIAssign::GenMIRStmtsImpl(MIRBuilder &mirBuilder) co AssignBoundaryVarAndChecking(mirBuilder, ans); IassignNode *iAssignNode = mirBuilder.CreateStmtIassign(*mirType, fieldID, addrNode, baseNode); ans.emplace_back(iAssignNode); - ENCChecker::CheckBoundaryLenFinalAssign(mirBuilder, addrType, fieldID, srcFileIndex, srcFileLineNum); - ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, addrExpr, srcFileIndex, srcFileLineNum); + ENCChecker::CheckBoundaryLenFinalAssign(mirBuilder, addrType, fieldID, loc); + ENCChecker::CheckBoundaryLenFinalAddr(mirBuilder, addrExpr, loc); return ans; } @@ -4131,10 +4196,13 @@ void FEIRStmtIAssign::InsertNonnullChecking(MIRBuilder &mirBuilder, const MIRTyp } FieldID tmpID = fieldID; FieldPair fieldPair = static_cast(baseType).TraverseToFieldRef(tmpID); + MIRType *srcType = baseExpr->GetType()->GenerateMIRTypeAuto(); + MIRType *dstType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fieldPair.second.first); + ENCChecker::CheckNonnullFieldInStruct(*srcType, *dstType, loc); if (fieldPair.second.second.GetAttr(FLDATTR_nonnull)) { if (ENCChecker::HasNullExpr(baseExpr)) { FE_ERR(kLncErr, "%s:%d error: null assignment of nonnull pointer", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIndex).c_str(), srcFileLineNum); + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line); return; } UniqueFEIRStmt stmt = std::make_unique(OP_assignassertnonnull, baseExpr->Clone()); @@ -4144,6 +4212,13 @@ void FEIRStmtIAssign::InsertNonnullChecking(MIRBuilder &mirBuilder, const MIRTyp } // ---------- FEIRStmtDoWhile ---------- +bool FEIRStmtDoWhile::IsFallThroughImpl() const { + WARN(kLncWarn, "%s:%d stmt[%s] need to be lowed when building bb", + FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx).c_str(), loc.line, + GetFEIRNodeKindDescription(kind).c_str()); + return false; +} + std::list FEIRStmtDoWhile::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list stmts; auto *whileStmtNode = mirBuilder.GetCurrentFuncCodeMp()->New(opcode); @@ -4194,21 +4269,29 @@ std::list FEIRStmtAtomic::GenMIRStmtsImpl(MIRBuilder &mirBuilder) con return stmts; } -bool FEIRStmtGCCAsm::HandleConstraintPlusQm(MIRBuilder &mirBuilder, AsmNode *asmNode, uint32 index) const { +bool FEIRStmtGCCAsm::HandleConstraintPlusQm(MIRBuilder &mirBuilder, AsmNode *asmNode, uint32 index, + std::list &stmts, std::list &initStmts) const { if (std::get<1>(outputs[index]) != "+Q" && std::get<1>(outputs[index]) != "+m") { return false; } FieldID fieldID = outputsExprs[index]->GetFieldID(); MIRSymbol *sym = outputsExprs[index]->GetVarUses().front()->GenerateMIRSymbol(mirBuilder); - - CallReturnPair retPair(sym->GetStIdx(), RegFieldPair(fieldID, 0)); - asmNode->asmOutputs.emplace_back(retPair); - UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(std::get<1>(outputs[index])); - asmNode->outputConstraints.emplace_back(strIdx); - + UniqueFEIRVar asmOut = outputsExprs[index]->GetVarUses().front()->Clone(); + MIRSymbol *localSym = nullptr; + UniqueFEIRVar localAsmOut = nullptr; BaseNode *node; if (outputsExprs[index]->GetKind() == kExprDRead) { - node = static_cast(mirBuilder.CreateExprAddrof(fieldID, *sym)); + if (asmOut->IsGlobal()) { + auto pair = HandleGlobalAsmOutOperand(asmOut, fieldID, stmts, mirBuilder); + localSym = pair.first; + localAsmOut = pair.second->Clone(); + // '+' means that asm out operand is both read and written, copy the initial value of global var into the + // local temp var and then add local temp var into the input list. + auto stmt = FEIRBuilder::CreateStmtDAssign(localAsmOut->Clone(), outputsExprs[index]->Clone()); + std::list node = stmt->GenMIRStmts(mirBuilder); + initStmts.splice(initStmts.end(), node); + } + node = static_cast(mirBuilder.CreateExprAddrof(fieldID, localSym != nullptr ? *localSym : *sym)); } else if (outputsExprs[index]->GetKind() == kExprIRead) { FEIRExprIRead *iread = static_cast(outputsExprs[index].get()); if (iread->GetFieldID() == 0) { @@ -4218,14 +4301,64 @@ bool FEIRStmtGCCAsm::HandleConstraintPlusQm(MIRBuilder &mirBuilder, AsmNode *asm iread->GetClonedOpnd()); node = addrOfExpr->GenMIRNode(mirBuilder); } + auto pair = HandleAsmOutOperandWithPtrType(iread, stmts, mirBuilder); + localSym = pair.first; + localAsmOut = pair.second->Clone(); + fieldID = 0; } else { CHECK_FATAL(false, "FEIRStmtGCCAsm NYI."); } + + UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(std::get<1>(outputs[index])); asmNode->PushOpnd(node); asmNode->inputConstraints.emplace_back(strIdx); + + CallReturnPair retPair(localSym != nullptr ? localSym->GetStIdx() : sym->GetStIdx(), RegFieldPair(fieldID, 0)); + asmNode->asmOutputs.emplace_back(retPair); + asmNode->outputConstraints.emplace_back(strIdx); return true; } +std::pair FEIRStmtGCCAsm::HandleAsmOutOperandWithPtrType(const FEIRExprIRead *ireadExpr, + std::list &stmts, + MIRBuilder &mirBuilder) const { + UniqueFEIRVar localAsmOut = FEIRBuilder::CreateVarNameForC(FEUtils::GetSequentialName("asm_out_"), + ireadExpr->GetClonedRetType()); + MIRSymbol *localSym = localAsmOut->GenerateLocalMIRSymbol(mirBuilder); + UniqueFEIRExpr srcExpr = FEIRBuilder::CreateExprDRead(localAsmOut->Clone()); + auto stmt = FEIRBuilder::CreateStmtIAssign(ireadExpr->GetClonedPtrType(), ireadExpr->GetClonedOpnd(), + std::move(srcExpr), ireadExpr->GetFieldID()); + std::list node = stmt->GenMIRStmts(mirBuilder); + stmts.splice(stmts.end(), node); + return std::make_pair(localSym, localAsmOut->Clone()); +} + +std::pair FEIRStmtGCCAsm::HandleGlobalAsmOutOperand(const UniqueFEIRVar &asmOut, + const FieldID fieldID, + std::list &stmts, + MIRBuilder &mirBuilder) const { + MIRSymbol *localSym = nullptr; + UniqueFEIRExpr srcExpr; + UniqueFEIRStmt stmt; + UniqueFEIRVar localAsmOut = FEIRBuilder::CreateVarNameForC(FEUtils::GetSequentialName("asm_out_"), + asmOut->GetType()->Clone(), false); + localSym = localAsmOut->GenerateLocalMIRSymbol(mirBuilder); + if (fieldID) { + MIRStructType *structType = static_cast(asmOut->GetType()->GenerateMIRTypeAuto()); + FieldPair fieldPair = structType->TraverseToField(fieldID); + UniqueFEIRType fieldType = FEIRTypeHelper::CreateTypeNative(*GlobalTables::GetTypeTable() + .GetTypeFromTyIdx(fieldPair.second.first)); + srcExpr = FEIRBuilder::CreateExprDReadAggField(localAsmOut->Clone(), fieldID, fieldType->Clone()); + stmt = FEIRBuilder::CreateStmtDAssignAggField(asmOut->Clone(), std::move(srcExpr), fieldID); + } else { + srcExpr = FEIRBuilder::CreateExprDRead(localAsmOut->Clone()); + stmt = FEIRBuilder::CreateStmtDAssign(asmOut->Clone(), std::move(srcExpr)); + } + std::list node = stmt->GenMIRStmts(mirBuilder); + stmts.splice(stmts.end(), node); + return std::make_pair(localSym, localAsmOut->Clone()); +} + std::list FEIRStmtGCCAsm::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list stmts; std::list initStmts; @@ -4239,48 +4372,48 @@ std::list FEIRStmtGCCAsm::GenMIRStmtsImpl(MIRBuilder &mirBuilder) con asmNode->inputConstraints.emplace_back(strIdx); } for (uint32 i = 0; i < outputs.size(); ++i) { - if (HandleConstraintPlusQm(mirBuilder, asmNode, i)) { + if (HandleConstraintPlusQm(mirBuilder, asmNode, i, stmts, initStmts)) { continue; } FieldID fieldID = 0; MIRSymbol *sym = nullptr; + MIRSymbol *localSym = nullptr; + UniqueFEIRVar localAsmOut = nullptr; UniqueFEIRVar asmOut; if (outputsExprs[i]->GetKind() == kExprDRead) { FEIRExprDRead *dread = static_cast(outputsExprs[i].get()); fieldID = dread->GetFieldID(); sym = dread->GetVarUses().front()->GenerateMIRSymbol(mirBuilder); asmOut = dread->GetVarUses().front()->Clone(); + if (asmOut->IsGlobal()) { + auto pair = HandleGlobalAsmOutOperand(asmOut, fieldID, stmts, mirBuilder); + localSym = pair.first; + localAsmOut = pair.second->Clone(); + } } else if (outputsExprs[i]->GetKind() == kExprIRead) { FEIRExprIRead *iread = static_cast(outputsExprs[i].get()); fieldID = iread->GetFieldID(); - asmOut = FEIRBuilder::CreateVarNameForC(FEUtils::GetSequentialName("asm_out_"), iread->GetClonedRetType()); - sym = asmOut->GenerateLocalMIRSymbol(mirBuilder); - UniqueFEIRExpr srcExpr = FEIRBuilder::CreateExprDRead(asmOut->Clone()); - auto stmt = FEIRBuilder::CreateStmtIAssign(iread->GetClonedPtrType(), iread->GetClonedOpnd(), - std::move(srcExpr), fieldID); - std::list node = stmt->GenMIRStmts(mirBuilder); - stmts.splice(stmts.end(), node); - - // The field ID is set to zero when a temporary variable is created for iread and sym is not a struct or union. - if (!sym->GetType()->IsStructType()) { - fieldID = 0; - } + auto pair = HandleAsmOutOperandWithPtrType(iread, stmts, mirBuilder); + localSym = pair.first; + localAsmOut = pair.second->Clone(); + fieldID = 0; } else { CHECK_FATAL(false, "FEIRStmtGCCAsm NYI."); } - CallReturnPair retPair(sym->GetStIdx(), RegFieldPair(fieldID, 0)); + CallReturnPair retPair(localSym != nullptr ? localSym->GetStIdx() : sym->GetStIdx(), RegFieldPair(fieldID, 0)); asmNode->asmOutputs.emplace_back(retPair); UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(std::get<1>(outputs[i])); asmNode->outputConstraints.emplace_back(strIdx); // If this is a read/write, copy the initial value into the temp before and added to the input list if (std::get<2>(outputs[i])) { - auto stmt = FEIRBuilder::CreateStmtDAssign(asmOut->Clone(), outputsExprs[i]->Clone()); + auto stmt = FEIRBuilder::CreateStmtDAssign(localAsmOut != nullptr ? localAsmOut->Clone() : asmOut->Clone(), + outputsExprs[i]->Clone()); std::list node = stmt->GenMIRStmts(mirBuilder); initStmts.splice(initStmts.end(), node); - AddrofNode *rNode = mirBuilder.CreateExprDread(*sym); + AddrofNode *rNode = mirBuilder.CreateExprDread(localSym != nullptr ? *localSym : *sym); asmNode->PushOpnd(static_cast(rNode)); asmNode->inputConstraints.emplace_back(strIdx); } diff --git a/src/hir2mpl/common/src/feir_var.cpp b/src/hir2mpl/common/src/feir_var.cpp index cd26cc9bd52a112f96ac39fcc2892fb79e830806..99ae56075d34835841eb2c0e4d659809752d18a5 100644 --- a/src/hir2mpl/common/src/feir_var.cpp +++ b/src/hir2mpl/common/src/feir_var.cpp @@ -99,6 +99,18 @@ FEIRVar::FEIRVar(FEIRVarKind argKind, std::unique_ptr argType) FEIRVar::~FEIRVar() {} +std::unique_ptr FEIRVar::Clone() const { + auto var = CloneImpl(); + var->SetGlobal(isGlobal); + var->SetAttrs(genAttrs); + var->SetSectionAttr(sectionAttr); + if (boundaryLenExpr != nullptr) { + var->SetBoundaryLenExpr(boundaryLenExpr->Clone()); + } + var->SetSrcLoc(loc); + return var; +} + void FEIRVar::SetBoundaryLenExpr(std::unique_ptr expr) { boundaryLenExpr = std::move(expr); } @@ -113,7 +125,7 @@ MIRSymbol *FEIRVar::GenerateGlobalMIRSymbolImpl(MIRBuilder &builder) const { std::string name = GetName(*mirType); GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); MIRSymbol *gSymbol = builder.GetOrCreateGlobalDecl(name, *mirType); - auto attrs = const_cast(genAttrs).ConvertToTypeAttrs(); + auto attrs = genAttrs.ConvertToTypeAttrs(); ENCChecker::InsertBoundaryLenExprInAtts(attrs, boundaryLenExpr); // do not allow extern var override global var if (gSymbol->GetAttrs().GetAttrFlag() != 0 && attrs.GetAttr(ATTR_extern)) { @@ -163,7 +175,7 @@ MIRSymbol *FEIRVar::GenerateLocalMIRSymbolImpl(MIRBuilder &builder) const { MIRType *mirType = type->GenerateMIRTypeAuto(); std::string name = GetName(*mirType); MIRSymbol *mirSymbol = builder.GetOrCreateLocalDecl(name, *mirType); - auto attrs = const_cast(genAttrs).ConvertToTypeAttrs(); + auto attrs = genAttrs.ConvertToTypeAttrs(); ENCChecker::InsertBoundaryLenExprInAtts(attrs, boundaryLenExpr); if (attrs.GetAttr(ATTR_static)) { attrs.ResetAttr(ATTR_static); diff --git a/src/hir2mpl/common/src/feir_var_name.cpp b/src/hir2mpl/common/src/feir_var_name.cpp index f6bbbef253e791e53512bcfeb02e8293a1055a39..8da2483cd47276ead9e44da78d0d2b0c8f1cb8fc 100644 --- a/src/hir2mpl/common/src/feir_var_name.cpp +++ b/src/hir2mpl/common/src/feir_var_name.cpp @@ -38,14 +38,7 @@ std::string FEIRVarName::GetNameRawImpl() const { } std::unique_ptr FEIRVarName::CloneImpl() const { - std::unique_ptr var = std::make_unique(nameIdx, type->Clone(), withType); - var->SetGlobal(isGlobal); - GenericAttrs attrs = genAttrs; - var->SetAttrs(attrs); - if (boundaryLenExpr != nullptr) { - var->SetBoundaryLenExpr(boundaryLenExpr->Clone()); - } - return var; + return std::make_unique(nameIdx, type->Clone(), withType); } bool FEIRVarName::EqualsToImpl(const std::unique_ptr &var) const { diff --git a/src/hir2mpl/common/src/generic_attrs.cpp b/src/hir2mpl/common/src/generic_attrs.cpp index 65a94a8f5a21e42c85d7148fb19e718415052c8e..2b382ef45df331a5fb110371585d538cbccc2360 100644 --- a/src/hir2mpl/common/src/generic_attrs.cpp +++ b/src/hir2mpl/common/src/generic_attrs.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -16,10 +16,9 @@ #include "global_tables.h" namespace maple { -TypeAttrs GenericAttrs::ConvertToTypeAttrs() { +TypeAttrs GenericAttrs::ConvertToTypeAttrs() const { TypeAttrs attr; - constexpr uint32 maxAttrNum = 128; - for (uint32 i = 0; i < maxAttrNum; ++i) { + for (uint32 i = 0; i < MAX_ATTR_NUM; ++i) { if (attrFlag[i] == 0) { continue; } @@ -38,13 +37,15 @@ TypeAttrs GenericAttrs::ConvertToTypeAttrs() { break; } } + if (GetContentFlag(GENATTR_pack)) { + attr.SetPack(static_cast(std::get(contentMap[GENATTR_pack]))); + } return attr; } FuncAttrs GenericAttrs::ConvertToFuncAttrs() { FuncAttrs attr; - constexpr uint32 maxAttrNum = 128; - for (uint32 i = 0; i < maxAttrNum; ++i) { + for (uint32 i = 0; i < MAX_ATTR_NUM; ++i) { if (attrFlag[i] == 0) { continue; } @@ -63,18 +64,16 @@ FuncAttrs GenericAttrs::ConvertToFuncAttrs() { break; } } - for(auto iter = contentMap.begin(); iter != contentMap.end(); ++iter) { - if (iter->first == GENATTR_alias) { - std::string name = GlobalTables::GetStrTable().GetStringFromStrIdx(std::get(iter->second)); + if (GetContentFlag(GENATTR_alias)) { + std::string name = GlobalTables::GetStrTable().GetStringFromStrIdx(std::get(contentMap[GENATTR_alias])); attr.SetAliasFuncName(name); } - if (iter->first == GENATTR_constructor_priority) { - attr.SetConstructorPriority(std::get(iter->second)); + if (GetContentFlag(GENATTR_constructor_priority)) { + attr.SetConstructorPriority(std::get(contentMap[GENATTR_constructor_priority])); } - if (iter->first == GENATTR_destructor_priority) { - attr.SetDestructorPriority(std::get(iter->second)); + if (GetContentFlag(GENATTR_destructor_priority)) { + attr.SetDestructorPriority(std::get(contentMap[GENATTR_destructor_priority])); } - } return attr; } @@ -102,4 +101,4 @@ FieldAttrs GenericAttrs::ConvertToFieldAttrs() { } return attr; } -} \ No newline at end of file +} diff --git a/src/hir2mpl/common/src/hir2mpl.cpp b/src/hir2mpl/common/src/hir2mpl.cpp index e72b42aff7d9c6405fee6861f32ddb1d8f10c979..acf5efe541402d5a8d34df6a9eec2f79a618ea07 100644 --- a/src/hir2mpl/common/src/hir2mpl.cpp +++ b/src/hir2mpl/common/src/hir2mpl.cpp @@ -20,16 +20,13 @@ int main(int argc, char **argv) { MPLTimer timer; timer.Start(); HIR2MPLOptions &options = HIR2MPLOptions::GetInstance(); - if (options.SolveArgs(argc, argv) == false) { + if (!options.SolveArgs(argc, argv)) { return static_cast(FEErrno::kCmdParseError); } HIR2MPLEnv::GetInstance().Init(); MIRModule module; HIR2MPLCompiler compiler(module); int res = compiler.Run(); - // The MIRModule destructor does not release the pragma memory, add releasing for front-end debugging. - MemPool *pragmaMemPoolPtr = module.GetPragmaMemPool(); - FEUtils::DeleteMempoolPtr(pragmaMemPoolPtr); timer.Stop(); if (FEOptions::GetInstance().IsDumpTime()) { INFO(kLncInfo, "hir2mpl time: %.2lfms", timer.ElapsedMilliseconds() / 1.0); diff --git a/src/hir2mpl/common/src/hir2mpl_compiler.cpp b/src/hir2mpl/common/src/hir2mpl_compiler.cpp index 04f1ca53034b0c24d95c24d423d9aee652e336ed..0a9f5d0a154514bad36e17b2a6e259dbe692127c 100644 --- a/src/hir2mpl/common/src/hir2mpl_compiler.cpp +++ b/src/hir2mpl/common/src/hir2mpl_compiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -17,7 +17,9 @@ #include "fe_manager.h" #include "fe_file_type.h" #include "fe_timer.h" +#ifndef ONLY_C #include "rc_setter.h" +#endif namespace maple { HIR2MPLCompiler::HIR2MPLCompiler(MIRModule &argModule) @@ -34,9 +36,11 @@ void HIR2MPLCompiler::Init() { FEManager::Init(module); module.SetFlavor(maple::kFeProduced); module.GetImportFiles().clear(); +#ifndef ONLY_C if (FEOptions::GetInstance().IsRC()) { bc::RCSetter::InitRCSetter(""); } +#endif } void HIR2MPLCompiler::Release() { @@ -61,11 +65,15 @@ int HIR2MPLCompiler::Run() { if (!FEOptions::GetInstance().IsGenMpltOnly()) { FETypeHierarchy::GetInstance().InitByGlobalTable(); ProcessFunctions(); +#ifndef ONLY_C if (FEOptions::GetInstance().IsRC()) { bc::RCSetter::GetRCSetter().MarkRCAttributes(); } } bc::RCSetter::ReleaseRCSetter(); +#else + } +#endif FEManager::GetManager().ReleaseStructElemMempool(); CHECK_FATAL(success, "Compile Error"); ExportMpltFile(); @@ -155,14 +163,12 @@ void HIR2MPLCompiler::SetupOutputPathAndName() { module.SetFileName(outName); // mapleall need outName with type, but mplt file no need size_t lastDot = outName.find_last_of("."); - std::string outNameWithoutType; if (lastDot == std::string::npos) { outNameWithoutType = outName; } else { outNameWithoutType = outName.substr(0, lastDot); } std::string mpltName = outNameWithoutType + ".mplt"; - outputInlineName = outNameWithoutType + ".mplt_inline"; if (srcLang != kSrcLangC) { GStrIdx strIdx = module.GetMIRBuilder()->GetOrCreateStringIndex(mpltName); module.GetImportFiles().push_back(strIdx); @@ -216,8 +222,8 @@ void HIR2MPLCompiler::ExportMplFile() { emitStructureType = true; } module.OutputAsciiMpl("", ".mpl", nullptr, emitStructureType, false); - if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - module.DumpInlineCandidateToFile(outputInlineName); + if (FEOptions::GetInstance().GetFuncInlineSize() != 0 && !FEOptions::GetInstance().GetWPAA()) { + module.DumpInlineCandidateToFile(outNameWithoutType + ".mplt_inline"); } timer.StopAndDumpTimeMS("Output mpl"); } @@ -308,6 +314,7 @@ void HIR2MPLCompiler::ProcessFunctions() { } void HIR2MPLCompiler::RegisterCompilerComponent() { +#ifndef ONLY_C if (FEOptions::GetInstance().HasJBC()) { FEOptions::GetInstance().SetTypeInferKind(FEOptions::TypeInferKind::kNo); std::unique_ptr jbcCompilerComp = std::make_unique(module); @@ -319,6 +326,7 @@ void HIR2MPLCompiler::RegisterCompilerComponent() { std::make_unique>(module); RegisterCompilerComponent(std::move(bcCompilerComp)); } +#endif if (FEOptions::GetInstance().GetInputASTFiles().size() != 0) { srcLang = kSrcLangC; std::unique_ptr astCompilerComp = diff --git a/src/hir2mpl/common/src/hir2mpl_option.cpp b/src/hir2mpl/common/src/hir2mpl_option.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7e42c57eb341a143c35445d503fce443a43f1480 --- /dev/null +++ b/src/hir2mpl/common/src/hir2mpl_option.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) [2022] Huawei Technologies Co.,Ltd.All rights reserved. + * + * OpenArkCompiler is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * + * http://license.coscl.org.cn/MulanPSL2 + * + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR + * FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +#include "driver_options.h" + +namespace opts::hir2mpl { + +maplecl::Option help({"--help", "-h"}, + " -h, -help : print usage and exit", + {hir2mplCategory}); + +maplecl::Option version({"--version", "-v"}, + " -v, -version : print version and exit", + {hir2mplCategory}); + +maplecl::Option mpltSys({"--mplt-sys", "-mplt-sys"}, + " -mplt-sys sys1.mplt,sys2.mplt\n" + " : input sys mplt files", + {hir2mplCategory}); + +maplecl::Option mpltApk({"--mplt-apk", "-mplt-apk"}, + " -mplt-apk apk1.mplt,apk2.mplt\n" + " : input apk mplt files", + {hir2mplCategory}); + +maplecl::Option mplt({"--mplt", "-mplt"}, + " -mplt lib1.mplt,lib2.mplt\n" + " : input mplt files", + {hir2mplCategory}); + +maplecl::Option inClass({"--in-class", "-in-class"}, + " -in-class file1.jar,file2.jar\n" + " : input class files", + {hir2mplCategory}); + +maplecl::Option inJar({"--in-jar", "-in-jar"}, + " -in-jar file1.jar,file2.jar\n" + " : input jar files", + {hir2mplCategory}); + +maplecl::Option inDex({"--in-dex", "-in-dex"}, + " -in-dex file1.dex,file2.dex\n" + " : input dex files", + {hir2mplCategory}); + +maplecl::Option inAst({"--in-ast", "-in-ast"}, + " -in-ast file1.ast,file2.ast\n" + " : input ast files", + {hir2mplCategory}); + +maplecl::Option inMast({"--in-mast", "-in-mast"}, + " -in-mast file1.mast,file2.mast\n" + " : input mast files", + {hir2mplCategory}); + +maplecl::Option output({"--output", "-p"}, + " -p, -output : output path", + {hir2mplCategory}); + +maplecl::Option outputName({"--output-name", "-o"}, + " -o, -output-name : output name", + {hir2mplCategory}); + +maplecl::Option mpltOnly({"--t", "-t"}, + " -t : generate mplt only", + {hir2mplCategory}); + +maplecl::Option asciimplt({"--asciimplt", "-asciimplt"}, + " -asciimplt : generate mplt in ascii format", + {hir2mplCategory}); + +maplecl::Option dumpInstComment({"--dump-inst-comment", "-dump-inst-comment"}, + " -dump-inst-comment : dump instruction comment", + {hir2mplCategory}); + +maplecl::Option noMplFile({"--no-mpl-file", "-no-mpl-file"}, + " -no-mpl-file : disable dump mpl file", + {hir2mplCategory}); + +maplecl::Option dumpLevel({"--dump-level", "-d"}, + " -d, -dump-level xx : debug info dump level\n" + " [0] disable\n" + " [1] dump simple info\n" + " [2] dump detail info\n" + " [3] dump debug info", + {hir2mplCategory}); + +maplecl::Option dumpTime({"--dump-time", "-dump-time"}, + " -dump-time : dump time", + {hir2mplCategory}); + +maplecl::Option dumpComment({"--dump-comment", "-dump-comment"}, + " -dump-comment : gen comment stmt", + {hir2mplCategory}); + +maplecl::Option dumpLOC({"--dump-LOC", "-dump-LOC"}, + " -dump-LOC : gen LOC", + {hir2mplCategory}); + +maplecl::Option dbgFriendly({"--g", "-g"}, + " -g : emit debug friendly mpl, including\n" + " no variable renaming\n" + " gen LOC", + {hir2mplCategory}); + +maplecl::Option dumpPhaseTime({"--dump-phase-time", "-dump-phase-time"}, + " -dump-phase-time : dump total phase time", + {hir2mplCategory}); + +maplecl::Option dumpPhaseTimeDetail({"-dump-phase-time-detail", "--dump-phase-time-detail"}, + " -dump-phase-time-detail\n" \ + " : dump phase time for each method", + {hir2mplCategory}); + +maplecl::Option rc({"-rc", "--rc"}, + " -rc : enable rc", + {hir2mplCategory}); + +maplecl::Option nobarrier({"-nobarrier", "--nobarrier"}, + " -nobarrier : no barrier", + {hir2mplCategory}); + +maplecl::Option usesignedchar({"-usesignedchar", "--usesignedchar"}, + " -usesignedchar : use signed char", + {hir2mplCategory}); + +maplecl::Option o2({"-O2", "--O2"}, + " -O2 : enable hir2mpl O2 optimize", + {hir2mplCategory}); + +maplecl::Option simplifyShortCircuit({"-simplify-short-circuit", "--simplify-short-circuit"}, + " -simplify-short-circuit\n" \ + " : enable simplify short circuit", + {hir2mplCategory}); + +maplecl::Option enableVariableArray({"-enable-variable-array", "--enable-variable-array"}, + " -enable-variable-array\n" \ + " : enable variable array", + {hir2mplCategory}); + +maplecl::Option funcInliceSize({"-func-inline-size", "--func-inline-size"}, + " -func-inline-size : set func inline size", + {hir2mplCategory}); + +maplecl::Option np({"-np", "--np"}, + " -np num : number of threads", + {hir2mplCategory}); + +maplecl::Option dumpThreadTime({"-dump-thread-time", "--dump-thread-time"}, + " -dump-thread-time : dump thread time in mpl schedular", + {hir2mplCategory}); + +maplecl::Option xbootclasspath({"-Xbootclasspath", "--Xbootclasspath"}, + " -Xbootclasspath=bootclasspath\n" \ + " : boot class path list", + {hir2mplCategory}); + +maplecl::Option classloadercontext({"-classloadercontext", "--classloadercontext"}, + " -classloadercontext=pcl\n" \ + " : class loader context \n" \ + " : path class loader", + {hir2mplCategory}); + +maplecl::Option dep({"-dep", "--dep"}, + " -dep=all or func\n" \ + " : [all] collect all dependent types\n" \ + " : [func] collect dependent types in function", + {hir2mplCategory}); + +maplecl::Option depsamename({"-depsamename", "--depsamename"}, + " -DepSameNamePolicy=sys or src\n" \ + " : [sys] load type from sys when on-demand load same name type\n" \ + " : [src] load type from src when on-demand load same name type", + {hir2mplCategory}); + +maplecl::Option npeCheckDynamic({"-npe-check-dynamic", "--npe-check-dynamic"}, + " -npe-check-dynamic : Nonnull pointr dynamic checking", + {hir2mplCategory}); + +maplecl::Option boundaryCheckDynamic({"-boundary-check-dynamic", "--boundary-check-dynamic"}, + " -boundary-check-dynamic\n" \ + " : Boundary dynamic checking", + {hir2mplCategory}); + +maplecl::Option safeRegion({"-safe-region", "--safe-region"}, + " -boundary-check-dynamic\n" \ + " -safe-region : Enable safe region", + {hir2mplCategory}); + +maplecl::Option dumpFEIRBB({"-dump-bb", "--dump-bb"}, + " -dump-bb : dump basic blocks info", + {hir2mplCategory}); + +maplecl::Option dumpFEIRCFGGraph({"-dump-cfg", "--dump-cfg"}, + " -dump-cfg funcname1,funcname2\n" \ + " : dump cfg graph to dot file", + {hir2mplCategory}); + +maplecl::Option wpaa({"-wpaa", "--wpaa"}, + " -dump-cfg funcname1,funcname2\n" \ + " -wpaa : enable whole program ailas analysis", + {hir2mplCategory}); + +maplecl::Option debug({"-debug", "--debug"}, + " -debug : dump enabled options", + {hir2mplCategory}); + +} diff --git a/src/hir2mpl/common/src/hir2mpl_options.cpp b/src/hir2mpl/common/src/hir2mpl_options.cpp index 3a18069b5b0bee9a51d022a9b66a8a40567b9c17..54e03331698e29d8e8ccfd4cc225cbd9a9b5fcf0 100644 --- a/src/hir2mpl/common/src/hir2mpl_options.cpp +++ b/src/hir2mpl/common/src/hir2mpl_options.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020-2021] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [2020-2022] Huawei Technologies Co.,Ltd.All rights reserved. * * OpenArkCompiler is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. @@ -12,273 +12,28 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#include "hir2mpl_options.h" -#include -#include +#include "driver_options.h" +#include "file_utils.h" #include "fe_options.h" #include "fe_macros.h" -#include "option_parser.h" -#include "parser_opt.h" #include "fe_file_type.h" +#include "hir2mpl_option.h" +#include "hir2mpl_options.h" +#include "parser_opt.h" +#include "triple.h" +#include "types_def.h" #include "version.h" -namespace maple { -using namespace mapleOption; - -enum OptionIndex : uint32 { - kHir2mplHelp = kCommonOptionEnd + 1, - // input control options - kMpltSys, - kMpltApk, - kInClass, - kInJar, - kInDex, - kInAST, - kInMAST, - // output control options - kOutputPath, - kOutputName, - kGenMpltOnly, - kGenAsciiMplt, - kDumpInstComment, - kNoMplFile, - // debug info control options - kDumpLevel, - kDumpTime, - kDumpComment, - kDumpLOC, - kDumpPhaseTime, - kDumpPhaseTimeDetail, - // bc bytecode compile options - kRC, - kNoBarrier, - // java bytecode compile options - kJavaStaticFieldName, - kJBCInfoUsePathName, - kDumpJBCStmt, - kDumpJBCBB, - kDumpJBCAll, - kDumpJBCErrorOnly, - kDumpJBCFuncName, - kEmitJBCLocalVarInfo, - // ast compiler options - kUseSignedChar, - kFEBigEndian, - // general stmt/bb/cfg debug options - kDumpGenCFGGraph, - // multi-thread control options - kNThreads, - kDumpThreadTime, - // type-infer - kTypeInfer, - // On Demand Type Creation - kXBootClassPath, - kClassLoaderContext, - kInputFile, - kCollectDepTypes, - kDepSameNamePolicy, - // EnhanceC - kNpeCheckDynamic, - kBoundaryCheckDynamic, - kSafeRegion, - kO2, - kSimplifyShortCircuit, - kEnableVariableArray, - kFuncInlineSize, -}; - -const Descriptor kUsage[] = { - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== Usage: hir2mpl [options] input1 input2 input3 ======\n" - " options:", "hir2mpl", {} }, - { kHir2mplHelp, 0, "h", "help", - kBuildTypeAll, kArgCheckPolicyNone, - " -h, -help : print usage and exit", "hir2mpl", {} }, - { kVersion, 0, "v", "version", - kBuildTypeAll, kArgCheckPolicyNone, - " -v, -version : print version and exit", "hir2mpl", {} }, - - // input control options - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== Input Control Options ======", "hir2mpl", {} }, - { kMpltSys, 0, "", "mplt-sys", - kBuildTypeAll, kArgCheckPolicyRequired, - " -mplt-sys sys1.mplt,sys2.mplt\n" - " : input sys mplt files", "hir2mpl", {} }, - { kMpltApk, 0, "", "mplt-apk", - kBuildTypeAll, kArgCheckPolicyRequired, - " -mplt-apk apk1.mplt,apk2.mplt\n" - " : input apk mplt files", "hir2mpl", {} }, - { kInMplt, 0, "", "mplt", - kBuildTypeAll, kArgCheckPolicyRequired, - " -mplt lib1.mplt,lib2.mplt\n" - " : input mplt files", "hir2mpl", {} }, - { kInClass, 0, "", "in-class", - kBuildTypeAll, kArgCheckPolicyRequired, - " -in-class file1.jar,file2.jar\n" - " : input class files", "hir2mpl", {} }, - { kInJar, 0, "", "in-jar", - kBuildTypeAll, kArgCheckPolicyRequired, - " -in-jar file1.jar,file2.jar\n" - " : input jar files", "hir2mpl", {} }, - { kInDex, 0, "", "in-dex", - kBuildTypeAll, kArgCheckPolicyRequired, - " -in-dex file1.dex,file2.dex\n" - " : input dex files", "hir2mpl", {} }, - { kInAST, 0, "", "in-ast", - kBuildTypeAll, kArgCheckPolicyRequired, - " -in-ast file1.ast,file2.ast\n" - " : input ast files", "hir2mpl", {} }, - { kInMAST, 0, "", "in-mast", - kBuildTypeAll, kArgCheckPolicyRequired, - " -in-mast file1.mast,file2.mast\n" - " : input mast files", "hir2mpl", {} }, - - // output control options - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== Output Control Options ======", "hir2mpl", {} }, - { kOutputPath, 0, "p", "output", - kBuildTypeAll, kArgCheckPolicyRequired, - " -p, -output : output path", "hir2mpl", {} }, - { kOutputName, 0, "o", "output-name", - kBuildTypeAll, kArgCheckPolicyRequired, - " -o, -output-name : output name", "hir2mpl", {} }, - { kGenMpltOnly, 0, "t", "", - kBuildTypeAll, kArgCheckPolicyNone, - " -t : generate mplt only", "hir2mpl", {} }, - { kGenAsciiMplt, 0, "", "asciimplt", - kBuildTypeAll, kArgCheckPolicyNone, - " -asciimplt : generate mplt in ascii format", "hir2mpl", {} }, - { kDumpInstComment, 0, "", "dump-inst-comment", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-inst-comment : dump instruction comment", "hir2mpl", {} }, - { kNoMplFile, 0, "", "no-mpl-file", - kBuildTypeAll, kArgCheckPolicyNone, - " -no-mpl-file : disable dump mpl file", "hir2mpl", {} }, - - // debug info control options - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== Debug Info Control Options ======", "hir2mpl", {} }, - { kDumpLevel, 0, "d", "dump-level", - kBuildTypeAll, kArgCheckPolicyNumeric, - " -d, -dump-level xx : debug info dump level\n" - " [0] disable\n" - " [1] dump simple info\n" - " [2] dump detail info\n" - " [3] dump debug info", "hir2mpl", {} }, - { kDumpTime, 0, "", "dump-time", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-time : dump time", "hir2mpl", {} }, - { kDumpComment, 0, "", "dump-comment", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-comment : gen comment stmt", "hir2mpl", {} }, - { kDumpLOC, 0, "", "dump-LOC", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-LOC : gen LOC", "hir2mpl", {} }, - { kDumpPhaseTime, 0, "", "dump-phase-time", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-phase-time : dump total phase time", "hir2mpl", {} }, - { kDumpPhaseTimeDetail, 0, "", "dump-phase-time-detail", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-phase-time-detail\n" \ - " : dump phase time for each method", "hir2mpl", {} }, - - // bc bytecode compile options - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== BC Bytecode Compile Options ======", "hir2mpl", {} }, - { kRC, 0, "", "rc", - kBuildTypeAll, kArgCheckPolicyNone, - " -rc : enable rc", "hir2mpl", {} }, - { kNoBarrier, 0, "", "nobarrier", - kBuildTypeAll, kArgCheckPolicyNone, - " -nobarrier : no barrier", "hir2mpl", {} }, - - // ast compiler options - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== ast Compile Options ======", "hir2mpl", {} }, - { kUseSignedChar, 0, "", "usesignedchar", - kBuildTypeAll, kArgCheckPolicyNone, - " -usesignedchar : use signed char", "hir2mpl", {} }, - { kFEBigEndian, 0, "", "be", - kBuildTypeAll, kArgCheckPolicyNone, - " -be : enable big endian", "hir2mpl", {} }, - { kO2, 0, "O2", "", - kBuildTypeAll, kArgCheckPolicyNone, - " -O2 : enable hir2mpl O2 optimize", "hir2mpl", {} }, - { kSimplifyShortCircuit, 0, "", "simplify-short-circuit", - kBuildTypeAll, kArgCheckPolicyNone, - " -simplify-short-circuit\n" \ - " : enable simplify short circuit", "hir2mpl", {} }, - { kEnableVariableArray, 0, "", "enable-variable-array", - kBuildTypeAll, kArgCheckPolicyNone, - " -enable-variable-array\n" \ - " : enable variable array", "hir2mpl", {} }, - { kFuncInlineSize, 0, "", "func-inline-size", - kBuildTypeAll, kArgCheckPolicyRequired, - " -func-inline-size : set func inline size", "hir2mpl", {} }, - - // multi-thread control - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== Multi-Thread Control Options ======", "hir2mpl", {} }, - { kNThreads, 0, "", "np", - kBuildTypeAll, kArgCheckPolicyRequired, - " -np num : number of threads", "hir2mpl", {} }, - { kDumpThreadTime, 0, "", "dump-thread-time", - kBuildTypeAll, kArgCheckPolicyNone, - " -dump-thread-time : dump thread time in mpl schedular", "hir2mpl", {} }, +#include +#include +#include +#include +#include +#include - // On Demand Type Creation - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== On Demand Type Creation ======", "hir2mpl", {} }, - { kXBootClassPath, 0, "", "Xbootclasspath", - kBuildTypeAll, kArgCheckPolicyRequired, - " -Xbootclasspath=bootclasspath\n"\ - " : boot class path list", "hir2mpl", {} }, - { kClassLoaderContext, 0, "", "classloadercontext", - kBuildTypeAll, kArgCheckPolicyRequired, - " -classloadercontext=pcl\n"\ - " : class loader context \n"\ - " : path class loader", "hir2mpl", {} }, - { kCollectDepTypes, 0, "", "dep", - kBuildTypeAll, kArgCheckPolicyRequired, - " -dep=all or func\n"\ - " : [all] collect all dependent types\n"\ - " : [func] collect dependent types in function", "hir2mpl", {} }, - { kDepSameNamePolicy, 0, "", "depsamename", - kBuildTypeAll, kArgCheckPolicyRequired, - " -DepSameNamePolicy=sys or src\n"\ - " : [sys] load type from sys when on-demand load same name type\n"\ - " : [src] load type from src when on-demand load same name type", "hir2mpl", {} }, - - // security check - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyUnknown, - "\n====== Security Check ======", "hir2mpl", {} }, - { kNpeCheckDynamic, 0, "", "npe-check-dynamic", - kBuildTypeAll, kArgCheckPolicyNone, - " -npe-check-dynamic : Nonnull pointr dynamic checking", "hir2mpl", {} }, - { kBoundaryCheckDynamic, 0, "", "boundary-check-dynamic", - kBuildTypeAll, kArgCheckPolicyNone, - " -boundary-check-dynamic\n" \ - " : Boundary dynamic checking", "hir2mpl", {} }, - { kSafeRegion, 0, "", "safe-region", - kBuildTypeAll, kArgCheckPolicyNone, - " -safe-region : Enable safe region", "hir2mpl", {} }, - { kUnknown, 0, "", "", - kBuildTypeAll, kArgCheckPolicyNone, - "\n", "hir2mpl", {} } -}; +namespace maple { HIR2MPLOptions::HIR2MPLOptions() { - CreateUsages(kUsage); Init(); } @@ -289,313 +44,337 @@ void HIR2MPLOptions::Init() { } bool HIR2MPLOptions::InitFactory() { - RegisterFactoryFunction(kHir2mplHelp, - &HIR2MPLOptions::ProcessHelp); - RegisterFactoryFunction(kVersion, - &HIR2MPLOptions::ProcessVersion); + RegisterFactoryFunction(&opts::hir2mpl::help, + &HIR2MPLOptions::ProcessHelp); + RegisterFactoryFunction(&opts::hir2mpl::version, + &HIR2MPLOptions::ProcessVersion); // input control options - RegisterFactoryFunction(kMpltSys, - &HIR2MPLOptions::ProcessInputMpltFromSys); - RegisterFactoryFunction(kMpltApk, - &HIR2MPLOptions::ProcessInputMpltFromApk); - RegisterFactoryFunction(kInMplt, - &HIR2MPLOptions::ProcessInputMplt); - RegisterFactoryFunction(kInClass, - &HIR2MPLOptions::ProcessInClass); - RegisterFactoryFunction(kInJar, - &HIR2MPLOptions::ProcessInJar); - RegisterFactoryFunction(kInDex, - &HIR2MPLOptions::ProcessInDex); - RegisterFactoryFunction(kInAST, - &HIR2MPLOptions::ProcessInAST); - RegisterFactoryFunction(kInMAST, - &HIR2MPLOptions::ProcessInMAST); + RegisterFactoryFunction(&opts::hir2mpl::mpltSys, + &HIR2MPLOptions::ProcessInputMpltFromSys); + RegisterFactoryFunction(&opts::hir2mpl::mpltApk, + &HIR2MPLOptions::ProcessInputMpltFromApk); + RegisterFactoryFunction(&opts::hir2mpl::mplt, + &HIR2MPLOptions::ProcessInputMplt); + RegisterFactoryFunction(&opts::hir2mpl::inClass, + &HIR2MPLOptions::ProcessInClass); + RegisterFactoryFunction(&opts::hir2mpl::inJar, + &HIR2MPLOptions::ProcessInJar); + RegisterFactoryFunction(&opts::hir2mpl::inDex, + &HIR2MPLOptions::ProcessInDex); + RegisterFactoryFunction(&opts::hir2mpl::inAst, + &HIR2MPLOptions::ProcessInAST); + RegisterFactoryFunction(&opts::hir2mpl::inMast, + &HIR2MPLOptions::ProcessInMAST); // output control options - RegisterFactoryFunction(kOutputPath, - &HIR2MPLOptions::ProcessOutputPath); - RegisterFactoryFunction(kOutputName, - &HIR2MPLOptions::ProcessOutputName); - RegisterFactoryFunction(kGenMpltOnly, - &HIR2MPLOptions::ProcessGenMpltOnly); - RegisterFactoryFunction(kGenAsciiMplt, - &HIR2MPLOptions::ProcessGenAsciiMplt); - RegisterFactoryFunction(kDumpInstComment, - &HIR2MPLOptions::ProcessDumpInstComment); - RegisterFactoryFunction(kNoMplFile, - &HIR2MPLOptions::ProcessNoMplFile); + RegisterFactoryFunction(&opts::hir2mpl::output, + &HIR2MPLOptions::ProcessOutputPath); + RegisterFactoryFunction(&opts::hir2mpl::outputName, + &HIR2MPLOptions::ProcessOutputName); + RegisterFactoryFunction(&opts::hir2mpl::mpltOnly, + &HIR2MPLOptions::ProcessGenMpltOnly); + RegisterFactoryFunction(&opts::hir2mpl::asciimplt, + &HIR2MPLOptions::ProcessGenAsciiMplt); + RegisterFactoryFunction(&opts::hir2mpl::dumpInstComment, + &HIR2MPLOptions::ProcessDumpInstComment); + RegisterFactoryFunction(&opts::hir2mpl::noMplFile, + &HIR2MPLOptions::ProcessNoMplFile); // debug info control options - RegisterFactoryFunction(kDumpLevel, - &HIR2MPLOptions::ProcessDumpLevel); - RegisterFactoryFunction(kDumpTime, - &HIR2MPLOptions::ProcessDumpTime); - RegisterFactoryFunction(kDumpComment, - &HIR2MPLOptions::ProcessDumpComment); - RegisterFactoryFunction(kDumpLOC, - &HIR2MPLOptions::ProcessDumpLOC); - RegisterFactoryFunction(kDumpPhaseTime, - &HIR2MPLOptions::ProcessDumpPhaseTime); - RegisterFactoryFunction(kDumpPhaseTimeDetail, - &HIR2MPLOptions::ProcessDumpPhaseTimeDetail); - - // java bytecode compile options - RegisterFactoryFunction(kJavaStaticFieldName, - &HIR2MPLOptions::ProcessModeForJavaStaticFieldName); - RegisterFactoryFunction(kJBCInfoUsePathName, - &HIR2MPLOptions::ProcessJBCInfoUsePathName); - RegisterFactoryFunction(kDumpJBCStmt, - &HIR2MPLOptions::ProcessDumpJBCStmt); - RegisterFactoryFunction(kDumpJBCBB, - &HIR2MPLOptions::ProcessDumpJBCBB); - RegisterFactoryFunction(kDumpJBCErrorOnly, - &HIR2MPLOptions::ProcessDumpJBCErrorOnly); - RegisterFactoryFunction(kDumpJBCFuncName, - &HIR2MPLOptions::ProcessDumpJBCFuncName); - RegisterFactoryFunction(kEmitJBCLocalVarInfo, - &HIR2MPLOptions::ProcessEmitJBCLocalVarInfo); + RegisterFactoryFunction(&opts::hir2mpl::dumpLevel, + &HIR2MPLOptions::ProcessDumpLevel); + RegisterFactoryFunction(&opts::hir2mpl::dumpTime, + &HIR2MPLOptions::ProcessDumpTime); + RegisterFactoryFunction(&opts::hir2mpl::dumpComment, + &HIR2MPLOptions::ProcessDumpComment); + RegisterFactoryFunction(&opts::hir2mpl::dumpLOC, + &HIR2MPLOptions::ProcessDumpLOC); + RegisterFactoryFunction(&opts::hir2mpl::dbgFriendly, + &HIR2MPLOptions::ProcessDbgFriendly); + RegisterFactoryFunction(&opts::hir2mpl::dumpPhaseTime, + &HIR2MPLOptions::ProcessDumpPhaseTime); + RegisterFactoryFunction(&opts::hir2mpl::dumpPhaseTimeDetail, + &HIR2MPLOptions::ProcessDumpPhaseTimeDetail); // general stmt/bb/cfg debug options - RegisterFactoryFunction(kDumpGenCFGGraph, - &HIR2MPLOptions::ProcessDumpFEIRCFGGraph); + RegisterFactoryFunction(&opts::hir2mpl::dumpFEIRBB, + &HIR2MPLOptions::ProcessDumpFEIRBB); + RegisterFactoryFunction(&opts::hir2mpl::dumpFEIRCFGGraph, + &HIR2MPLOptions::ProcessDumpFEIRCFGGraph); // multi-thread control options - RegisterFactoryFunction(kNThreads, - &HIR2MPLOptions::ProcessNThreads); - RegisterFactoryFunction(kDumpThreadTime, - &HIR2MPLOptions::ProcessDumpThreadTime); + RegisterFactoryFunction(&opts::hir2mpl::np, + &HIR2MPLOptions::ProcessNThreads); + RegisterFactoryFunction(&opts::hir2mpl::dumpThreadTime, + &HIR2MPLOptions::ProcessDumpThreadTime); - RegisterFactoryFunction(kRC, - &HIR2MPLOptions::ProcessRC); - RegisterFactoryFunction(kNoBarrier, - &HIR2MPLOptions::ProcessNoBarrier); + RegisterFactoryFunction(&opts::hir2mpl::rc, + &HIR2MPLOptions::ProcessRC); + RegisterFactoryFunction(&opts::hir2mpl::nobarrier, + &HIR2MPLOptions::ProcessNoBarrier); // ast compiler options - RegisterFactoryFunction(kUseSignedChar, - &HIR2MPLOptions::ProcessUseSignedChar); - RegisterFactoryFunction(kFEBigEndian, - &HIR2MPLOptions::ProcessBigEndian); + RegisterFactoryFunction(&opts::hir2mpl::usesignedchar, + &HIR2MPLOptions::ProcessUseSignedChar); + // On Demand Type Creation - RegisterFactoryFunction(kXBootClassPath, - &HIR2MPLOptions::ProcessXbootclasspath); - RegisterFactoryFunction(kClassLoaderContext, - &HIR2MPLOptions::ProcessClassLoaderContext); - RegisterFactoryFunction(kInputFile, - &HIR2MPLOptions::ProcessCompilefile); - RegisterFactoryFunction(kCollectDepTypes, - &HIR2MPLOptions::ProcessCollectDepTypes); - RegisterFactoryFunction(kDepSameNamePolicy, - &HIR2MPLOptions::ProcessDepSameNamePolicy); + RegisterFactoryFunction(&opts::hir2mpl::xbootclasspath, + &HIR2MPLOptions::ProcessXbootclasspath); + RegisterFactoryFunction(&opts::hir2mpl::classloadercontext, + &HIR2MPLOptions::ProcessClassLoaderContext); + RegisterFactoryFunction(&opts::hir2mpl::dep, + &HIR2MPLOptions::ProcessCollectDepTypes); + RegisterFactoryFunction(&opts::hir2mpl::depsamename, + &HIR2MPLOptions::ProcessDepSameNamePolicy); // EnhanceC - RegisterFactoryFunction(kNpeCheckDynamic, - &HIR2MPLOptions::ProcessNpeCheckDynamic); - RegisterFactoryFunction(kBoundaryCheckDynamic, - &HIR2MPLOptions::ProcessBoundaryCheckDynamic); - RegisterFactoryFunction(kSafeRegion, - &HIR2MPLOptions::ProcessSafeRegion); - - RegisterFactoryFunction(kO2, - &HIR2MPLOptions::ProcessO2); - RegisterFactoryFunction(kSimplifyShortCircuit, - &HIR2MPLOptions::ProcessSimplifyShortCircuit); - RegisterFactoryFunction(kEnableVariableArray, - &HIR2MPLOptions::ProcessEnableVariableArray); - RegisterFactoryFunction(kFuncInlineSize, - &HIR2MPLOptions::ProcessFuncInlineSize); - return true; -} - -bool HIR2MPLOptions::SolveOptions(const std::deque