diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000000000000000000000000000000000000..28771e1ae591700be3fe27c3acd668ef8cee77ad --- /dev/null +++ b/.clang-format @@ -0,0 +1,195 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Empty +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +StatementAttributeLikeMacros: + - Q_EMIT +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: false +SortIncludes: true +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 2 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/.gitignore b/.gitignore index f71bf2703f6ebf9a684037b3df228a6082d56a73..25a4d8c9ee9366594bb507bf22d0f4a6918455fc 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,13 @@ 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* tools/clang* +tools/cmake* tools/gcc* tools/gn* tools/icu* diff --git a/BUILD.gn b/BUILD.gn index 6801cf5b4813146f60163e5bf837271829983af0..df4b0a16c39b0414392b6f9e4cfeffaf56f9f04f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -13,52 +13,66 @@ # 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("mplverf") { + deps = [ "${MAPLEALL_ROOT}:mplverf" ] } 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 + ]) + } +} + +group("mplsh-lmbc") { + deps = [ "${MAPLEENG_ROOT}/lmbc:mplsh-lmbc" ] } + + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..84ccf6d05418c9bbc891df6fab6101c08775840a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,216 @@ +# This file is the master GN build configuration, all variables +# declare here will be implicitly global. +# +# 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. +# + +# List all the input args + +# project +cmake_minimum_required(VERSION 3.10) +project(maple) +set(CMAKE_STATIC_LIBRARY_PREFIX "") +set(CMAKE_SHARED_LIBRARY_PREFIX "") +set(EXECUTABLE_OUTPUT_PATH ${MAPLE_BUILD_OUTPUT}/bin) + +set(COV_CHECK "1") +# env args +set(MAPLE_ROOT $ENV{MAPLE_ROOT}) +set(ANDROID_ROOT ${MAPLE_ROOT}/android) +set(AOSP_ROOT ${MAPLE_ROOT}/third_party/aosp_modified) +set(MAPLE_BUILD_TYPE $ENV{MAPLE_BUILD_TYPE}) +set(MAPLE_BUILD_OUTPUT $ENV{MAPLE_BUILD_OUTPUT}) +set(TOOL_BIN_PATH $ENV{TOOL_BIN_PATH}) +set(QEMU_PATH $ENV{TOOL_BIN_PATH}) +set(OLD_OS $ENV{OLD_OS}) +set(IS_AST2MPL_EXISTS $ENV{IS_AST2MPL_EXISTS}) + + +# global args +set(DYNAMICLANG true) +set(RC_V2 true) +set(TEST_BENCHMARK false) +set(MEMORY_LEAK_CHECK false) +set(MARK_CYCLE_ROOTS false) +if(${OLD_OS} STREQUAL "1") + set(DESIGNATOR "-Wno-gnu-designator") +else() + set(DESIGNATOR "-Wno-c99-designator") +endif() +set(OPENSOURCE_DEPS ${MAPLE_ROOT}/src/mapleall/deplibs) +set(OPENSOURCE_OUTPUT ${MAPLE_BUILD_OUTPUT}) +set(AST2MPL_ROOT ${MAPLE_ROOT}/src/ast2mpl) +set(MAPLEALL_ROOT ${MAPLE_ROOT}/src/mapleall) +set(HIR2MPL_ROOT ${MAPLE_ROOT}/src/hir2mpl) +set(MAPLE_MRT_ROOT ${MAPLE_ROOT}/src/mrt) +set(THIRD_PARTY_ROOT ${MAPLE_ROOT}/third_party) +set(LIB_HW_SECURE_C ${MAPLE_ROOT}/third_party/bounds_checking_function) + + +# dir +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${MAPLE_BUILD_OUTPUT}/ar/host-x86_64-${OPT}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${MAPLE_BUILD_OUTPUT}/lib) +set(PROJECT_BINARY_DIR ${MAPLE_BUILD_OUTPUT}/lib) + + +#--------------------------------- toolchain ------------------------------------- +set(CLANG_PATH ${MAPLE_ROOT}/tools/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-18.04) +set(LLVMINC ${CLANG_PATH}/include) +set(LLVMLIBDIR ${CLANG_PATH}/lib) +set(CFE_SRC_DIR ${MAPLE_ROOT}/../third_party/clang-10.0.0.src) +set(CFE_SRC_PATH ${MAPLE_ROOT}/third_party/llvm-12.0.0.src/clang) +set(MAPLE_PARSER_PATH ${MAPLE_ROOT}/src/MapleFE) +set(GCC_LINARO_PATH ${MAPLE_ROOT}/tools/gcc-linaro-7.5.0) +set(NDK_PATH ${MAPLE_ROOT}/tools/android-ndk-r21) +set(target_toolchain "//build/toolchain:clang") + +set(CMAKE_C_COMPILER ${TOOL_BIN_PATH}/clang) +set(CMAKE_CXX_COMPILER ${TOOL_BIN_PATH}/clang++) +set(CMAKE_AR ${TOOL_BIN_PATH}/llvm-ar) +set(CMAKE_RANLIB ${TOOL_BIN_PATH}/llvm-ranlib) + +set(CMAKE_C_CROSS_COMPILER ${GCC_LINARO_PATH}/bin/aarch64-linux-gnu-gcc) +set(CMAKE_CXX_CROSS_COMPILER ${GCC_LINARO_PATH}/bin/aarch64-linux-gnu-g++) +set(CMAKE_AR_CROSS_COMPILER ${GCC_LINARO_PATH}/bin/aarch64-linux-gnu-ar) +set(CMAKE_RANLIB_CROSS_COMPILER ${GCC_LINARO_PATH}/bin/aarch64-linux-gnu-ranlib) + +# toolchain:clang +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld ") +if(${CMAKE_BUILD_TYPE} STREQUAL "RELEASE" AND ${GPROF} STREQUAL 0) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s") +endif() + +# -----------------------CMAKE FLAGS--------------------------------- +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fno-common") +if(${CMAKE_BUILD_TYPE} STREQUAL "RELEASE") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -O2 -fno-strict-aliasing -D_FORTIFY_SOURCE=2") + set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -O2 -fno-strict-aliasing -D_FORTIFY_SOURCE=2") +elseif(${CMAKE_BUILD_TYPE} STREQUAL "DEBUG") + add_definitions("-DDEBUG") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -O0 -g3 -ftrapv -fstack-check") + set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -O0 -g3 -ftrapv -fstack-check") + if(${target_toolchain} STREQUAL "//build/toolchain:clang") + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -fno-limit-debug-info") + set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -fno-limit-debug-info") + endif() +else() + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -O2 -fno-strict-aliasing -g") + set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -O2 -fno-strict-aliasing -g") +endif() + +set(CMAKE_C_FLAGS + "${CMAKE_C_FLAGS} -Wall -fstack-protector-strong -fPIC -fPIE -pipe -Werror -Wdate-time -Wfloat-equal ${DESIGNATOR}") +set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -Wall -fstack-protector-strong -fPIC -fPIE -pipe -Wno-c99-designator -Wno-range-loop-construct -Werror -Wdate-time -Wfloat-equal ${DESIGNATOR} -DMIR_FEATURE_FULL=1") + +if(HOST_ARCH STREQUAL 64) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m64") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIC -rdynamic -lpthread -ldl -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -pie -Wl,--start-group ") +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32") +endif() + +if(DYNAMICLANG STREQUAL true) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DDYNAMICLANG") +endif() + +if(RC_V2 STREQUAL true) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRC_NO_MMAP") +endif() + +if(TEST_BENCHMARK STREQUAL true) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DTEST_BENCHMARK") +endif() + +if(MEMORY_LEAK_CHECK STREQUAL true) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMEMORY_LEAK_CHECK") +endif() + +if(MARK_CYCLE_ROOTS STREQUAL true) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMARK_CYCLE_ROOTS") +endif() + +if(MIR_JAVA STREQUAL 1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMIR_JAVA=1") +else() + set(TARGET vm) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMIR_JAVA=0") +endif() + +if(${ASAN} STREQUAL 1) + add_definitions(" -fsanitize=address ") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ldl ${LLVMLIBDIR}/libclang_rt.asan-x86_64.a") +endif() + +if(${COV} STREQUAL 1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") +endif() + +if(${GPROF} STREQUAL 1) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") +endif() + +if(${TARGET} STREQUAL aarch64) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -DTARGAARCH64 -DMAPLE_ROOT=\"${MAPLE_ROOT}\"") +endif() + +if(${TARGET} STREQUAL aarch64_ilp32) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -DTARGAARCH64 -DILP32 -DMAPLE_ROOT=\"${MAPLE_ROOT}\"") +endif() + +if(${TARGET} STREQUAL x86_64) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -DTARGX86_64 -DMAPLE_ROOT=\"${MAPLE_ROOT}\"") +endif() + +if(${TARGET} STREQUAL riscv64) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -DTARGRISCV64 -DMAPLE_ROOT=\"${MAPLE_ROOT}\"") +endif() + +if(${TARGET} STREQUAL ark) + set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} -DTARGARK -DMAPLE_ROOT=\"${MAPLE_ROOT}\"") +endif() + + +# -----------------------CMAKE FLAGS END--------------------------------- + + +#subdirectory +add_subdirectory(src/hir2mpl) +add_subdirectory(src/hir2mpl/test) +add_subdirectory(src/mapleall) +add_subdirectory(third_party/bounds_checking_function) +add_subdirectory(src/mapleall/test) +add_subdirectory(src/mrt) +if (NOT ${ONLY_C} STREQUAL "1") + add_subdirectory(third_party/aosp_modified/art/libdexfile) + add_subdirectory(third_party/aosp_modified/system/core/libziparchive) + add_subdirectory(third_party/aosp_modified/system/core/base) +endif() diff --git a/Dockerfile b/Dockerfile index f1e5b20f8152395af6c06f294c0275611b1abc89..0b250bd5a390e983cf94de42719c36b193b9a0d8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,51 +1,30 @@ -FROM ubuntu:16.04 AS build-env +FROM ubuntu:18.04 AS build-env MAINTAINER https://www.openarkcompiler.cn # Setting up the build environment -RUN sed -i 's/archive.ubuntu.com/mirrors.163.com/g' /etc/apt/sources.list && \ - dpkg --add-architecture i386 && \ - apt-get -y update && \ - apt-get -y dist-upgrade && \ - apt-get -y install openjdk-8-jdk git-core build-essential zlib1g-dev libc6-dev-i386 g++-multilib gcc-multilib linux-libc-dev:i386 && \ - apt-get -y install gcc-5-aarch64-linux-gnu g++-5-aarch64-linux-gnu unzip tar curl && \ - apt-get -y install python3-paramiko python-paramiko python-requests && \ - mkdir -p /tools/ninja /tools/gn - -# 在国内请反注释下行, 因为容器也是个单独的系统,所以别用127.0.0.1 -#ENV http_proxy=http://192.168.3.81:1081 \ -# https_proxy=http://192.168.3.81:1081 - -RUN cd /tools && \ - curl -C - -LO http://releases.llvm.org/8.0.0/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz && \ - curl -LO https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip && \ - curl -LO http://tools.harmonyos.com/mirrors/gn/1523/linux/gn.1523.tar && \ - tar Jvxf /tools/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz -C /tools/ && \ - unzip /tools/ninja-linux.zip -d /tools/ninja/ && \ - tar xvf /tools/gn.1523.tar && \ - chmod a+x /tools/gn/gn && \ - rm /tools/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04.tar.xz /tools/ninja-linux.zip && \ - rm -rf /var/cache/apt/archives +RUN apt-get -y update +RUN apt-get -y install clang llvm lld libelf-dev libssl-dev python \ + qemu openjdk-8-jre-headless openjdk-8-jdk-headless git build-essential \ + zlib1g-dev libc6-dev-i386 gcc-7-aarch64-linux-gnu g++-7-aarch64-linux-gnu \ + lsb-core wget zip curl # copy source COPY . /OpenArkCompiler WORKDIR /OpenArkCompiler -# create symbolic link -RUN mkdir -p /OpenArkCompiler/tools /OpenArkCompiler/tools/gn && \ - ln -s /tools/ninja /OpenArkCompiler/tools/ninja_1.9.0 && \ - ln -s /tools/gn/gn /OpenArkCompiler/tools/gn/gn && \ - ln -s /tools/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04 /OpenArkCompiler/tools/clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-16.04 +# use the latest cmake +WORKDIR /OpenArkCompiler/tools +# change the version as you need +RUN wget https://github.com/Kitware/CMake/releases/download/v3.24.3/cmake-3.24.3-linux-x86_64.tar.gz && \ + tar -xf cmake-3.24.3-linux-x86_64.tar.gz && ln -s cmake-3.24.3-linux-x86_64 cmake +ENV PATH="/OpenArkCompiler/tools/cmake/bin:/$PATH" + +# build env +# this will take a long time. +WORKDIR /OpenArkCompiler +RUN ["/bin/bash", "-c", "source build/envsetup.sh arm release && make setup"] # compile -RUN ["/bin/bash", "-c", "source build/envsetup.sh && make && ls -al "] +ENV PATH="/OpenArkCompiler/tools/cmake/bin:/OpenArkCompiler/tools/ninja:/$PATH" +RUN ["/bin/bash", "-c", "source build/envsetup.sh arm release && make setup && make"] -# build final docker image -FROM ubuntu:16.04 -RUN sed -i 's/archive.ubuntu.com/mirrors.163.com/g' /etc/apt/sources.list && \ - apt-get -y update && \ - apt-get install -y openjdk-8-jdk curl vim && \ - rm -rf /var/cache/apt/archives -COPY --from=build-env /OpenArkCompiler/output /OpenArkCompiler -VOLUME /OpenArkCompiler -ENV PATH=/OpenArkCompiler/bin:$PATH -CMD maple -h diff --git a/Makefile b/Makefile index 250f27b5c0b3e6adb5888bb50a361d67a321f1e7..cde93a55ae6fbc3b49a78ce7572d5095f95a2259 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,10 @@ 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 +GPROF := 0 ifeq ($(DEBUG),0) BUILD_TYPE := RELEASE else @@ -35,6 +38,7 @@ endif HOST_ARCH := 64 MIR_JAVA := 1 GN := $(MAPLE_ROOT)/tools/gn/gn +CMAKE := $(shell ls $(MAPLE_ROOT)/tools/cmake*/bin/cmake | tail -1) NINJA := $(shell ls $(MAPLE_ROOT)/tools/ninja*/ninja | tail -1) ifneq ($(findstring GC,$(OPT)),) GCONLY := 1 @@ -55,7 +59,39 @@ 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) \ + GPROF=$(GPROF) + +CMAKE_OPTIONS := \ + -DCMAKE_INSTALL_PREFIX="$(MAPLE_ROOT)" \ + -DCMAKE_BUILD_TYPE="$(BUILD_TYPE)" \ + -DHOST_ARCH=$(HOST_ARCH) \ + -DMIR_JAVA=$(MIR_JAVA) \ + -DOPT="$(OPT)" \ + -DGCONLY=$(GCONLY) \ + -DTARGET="$(TARGET_PROCESSOR)" \ + -DMAJOR_VERSION="$(MAJOR_VERSION)" \ + -DMINOR_VERSION="$(MINOR_VERSION)" \ + -DRELEASE_VERSION="$(RELEASE_VERSION)" \ + -DBUILD_VERSION="$(BUILD_VERSION)" \ + -DGIT_REVISION="$(GIT_REVISION)" \ + -DMAST=$(MAST) \ + -DASAN=$(ASAN) \ + -DONLY_C=$(ONLY_C) \ + -DCOV=$(COV) \ + -DGPROF=$(GPROF) + + +TOOLS := cmake +BUILD := build_cmake +OPTIONS := $(CMAKE_OPTIONS) +ifeq ($(TOOLS),gn) + BUILD := build_gn + OPTIONS := $(GN_OPTIONS) +endif .PHONY: default default: install @@ -74,39 +110,47 @@ uninstall_patch: .PHONY: maplegen maplegen:install_patch - $(call build_gn, $(GN_OPTIONS), maplegen) + $(call $(BUILD), $(OPTIONS), maplegen) .PHONY: maplegendef maplegendef: maplegen +ifeq ($(TOOLS),gn) $(call build_gn, $(GN_OPTIONS), maplegendef) +else + @python3 src/mapleall/maple_be/mdgen/gendef.py -e ${MAPLE_BUILD_OUTPUT}/bin/maplegen -m ${MAPLE_ROOT}/src/mapleall/maple_be/include/ad/cortex_a55 -o ${MAPLE_BUILD_OUTPUT}/common/target +endif .PHONY: maple maple: maplegendef - $(call build_gn, $(GN_OPTIONS), maple) + $(call $(BUILD), $(OPTIONS), maple) .PHONY: irbuild irbuild: install_patch - $(call build_gn, $(GN_OPTIONS), irbuild) + $(call $(BUILD), $(OPTIONS), irbuild) .PHONY: mpldbg mpldbg: - $(call build_gn, $(GN_OPTIONS), mpldbg) + $(call $(BUILD), $(OPTIONS), mpldbg) + +.PHONY: mplverf +mplverf: install_patch + $(call $(BUILD), $(GN_OPTIONS), mplverf) .PHONY: ast2mpl ast2mpl: - $(call build_gn, $(GN_OPTIONS), ast2mpl) + $(call $(BUILD), $(OPTIONS), ast2mpl) .PHONY: hir2mpl hir2mpl: install_patch - $(call build_gn, $(GN_OPTIONS), hir2mpl) + $(call $(BUILD), $(OPTIONS), hir2mpl) .PHONY: clang2mpl clang2mpl: maple (cd tools/clang2mpl; make setup; make; make install) .PHONY: hir2mplUT -hir2mplUT: - $(call build_gn, $(GN_OPTIONS) COV_CHECK=1, hir2mplUT) +hir2mplUT:install_patch + $(call $(BUILD), $(OPTIONS) COV_CHECK=1, hir2mplUT) .PHONY: libcore libcore: maple-rt @@ -115,7 +159,18 @@ libcore: maple-rt .PHONY: maple-rt maple-rt: java-core-def +ifeq ($(TOOLS),gn) $(call build_gn, $(GN_OPTIONS), maple-rt) +else + $(call build_cmake, $(CMAKE_OPTIONS), libmplcompiler-rt) + $(call build_cmake, $(CMAKE_OPTIONS), libcore-static-binding-jni) + $(call build_cmake, $(CMAKE_OPTIONS), libmaplert) + $(call build_cmake, $(CMAKE_OPTIONS), libhuawei_secure_c) +endif + +.PHONY: mapleallUT +mapleallUT: install_patch + $(call $(BUILD), $(OPTIONS), mapleallUT) .PHONY: java-core-def java-core-def: install @@ -123,15 +178,16 @@ java-core-def: install 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 +install: maple dex2mpl_install irbuild hir2mpl mplverf $(shell mkdir -p $(INSTALL_DIR)/ops/linker/; \ rsync -a -L $(MRT_ROOT)/maplert/linker/maplelld.so.lds $(INSTALL_DIR)/ops/linker/; \ rsync -a -L $(MAPLE_ROOT)/build/java2d8 $(INSTALL_DIR)/bin; \ rsync -a -L $(MAPLE_BIN_DIR)/java2jar $(INSTALL_DIR)/bin/; \ cp -rf $(MAPLE_ROOT)/tools $(INSTALL_DIR)/../; \ + rsync -a -L $(MAPLE_ROOT)/libc_enhanced/include/ $(INSTALL_DIR)/lib/include/; \ rsync -a -L $(MAPLE_ROOT)/src/hir2mpl/ast_input/clang/lib/sys/ $(INSTALL_DIR)/lib/include/;) .PHONY: all @@ -158,6 +214,15 @@ 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) + +.PHONY: mplsh-lmbc +mplsh-lmbc: + $(call build_gn, $(GN_OPTIONS), mplsh-lmbc) + + THREADS := 50 ifneq ($(findstring test,$(MAKECMDGOALS)),) TESTTARGET := $(MAKECMDGOALS) @@ -184,9 +249,26 @@ clean: cleanrsd clobber: cleanrsd @rm -rf output +# ----------------------debug--------------------- +DEBUG_TARGET := libhuawei_secure_c +.PHONY: cmk +cmk:install_patch + $(call build_cmake, $(CMAKE_OPTIONS), ${DEBUG_TARGET}) +.PHONY: gn +gn:install_patch + $(call build_gn, $(GN_OPTIONS), ${DEBUG_TARGET}) +# ----------------------debug--------------------- define build_gn mkdir -p $(INSTALL_DIR); \ $(GN) gen $(INSTALL_DIR) --args='$(1)' --export-compile-commands; \ cd $(INSTALL_DIR); \ $(NINJA) -v $(2); endef + +define build_cmake + mkdir -p $(INSTALL_DIR); \ + $(CMAKE) -B $(INSTALL_DIR) $(CMAKE_OPTIONS) -G Ninja; \ + cd $(INSTALL_DIR); \ + $(NINJA) -v $(2); +endef + 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..9de64def59a5c3867a735c2bd09ecebe63e14218 100755 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn @@ -31,6 +31,10 @@ declare_args() { BUILD_VERSION = "" GIT_REVISION = "" MAST = 0 + ASAN = 0 + ONLY_C = 0 + COV = 0 + GPROF = 0 } # Define global args @@ -63,6 +67,7 @@ MAPLEALL_ROOT = "${MAPLE_ROOT}/src/mapleall" HIR2MPL_ROOT = "${MAPLE_ROOT}/src/hir2mpl" MAPLE_MRT_ROOT = "${MAPLE_ROOT}/src/mrt" THIRD_PARTY_ROOT = "${MAPLE_ROOT}/third_party" +MAPLEENG_ROOT = "${MAPLE_ROOT}/src/MapleEng" # Put all built library files under lib GN_ARCHIVE_OUTPUT_DIRECTORY = "${MAPLE_BUILD_OUTPUT}/ar/host-x86_64-${OPT}" @@ -81,11 +86,13 @@ if (GN_BUILD_TYPE == "RELEASE") { cflags_cc += [ "-O2", "-fno-strict-aliasing", + "-fvisibility=hidden", "-D_FORTIFY_SOURCE=2", ] cflags_c += [ "-O2", "-fno-strict-aliasing", + "-fvisibility=hidden", "-D_FORTIFY_SOURCE=2", ] } else if (GN_BUILD_TYPE == "DEBUG") { @@ -123,7 +130,6 @@ cflags_c += [ "-fstack-protector-strong", "-fPIC", "-fPIE", - "-fvisibility=hidden", "-pipe", "-Werror", "-Wdate-time", @@ -136,7 +142,6 @@ cflags_cc += [ "-fstack-protector-strong", "-fPIC", "-fPIE", - "-fvisibility=hidden", "-pipe", "-Wno-c99-designator", "-Wno-range-loop-construct", diff --git a/build/envsetup.sh b/build/envsetup.sh index 70e5e2f32172b23a4ca3aada4fc4a9a9ddebf204..eba899daa049e931443120fdc5ce7c65f41a51ec 100644 --- a/build/envsetup.sh +++ b/build/envsetup.sh @@ -16,7 +16,7 @@ function print_usage { echo " " - echo "usage: source envsetup.sh arm/ark/engine/riscv release/debug" + echo "usage: source envsetup.sh arm/ark/engine/riscv/x86_64 release/debug" echo " " } @@ -26,6 +26,9 @@ if [ "$#" -lt 2 ]; then fi curdir=$(pwd) +# force to use local cmake and ninja +export PATH=${curdir}/tools/cmake/bin:${curdir}/tools/ninja:$PATH + export MAPLE_ROOT=${curdir} export SPEC=${MAPLE_ROOT}/testsuite/c_test/spec_test export LD_LIBRARY_PATH=${MAPLE_ROOT}/tools/gcc-linaro-7.5.0/aarch64-linux-gnu/libc/lib:${MAPLE_ROOT}/tools/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-18.04/lib:${LD_LIBRARY_PATH} @@ -74,6 +77,9 @@ if [ $1 = "arm" ]; then elif [ $1 = "riscv" ]; then PLATFORM=riscv64 USEOJ=0 +elif [ $1 = "x86_64" ] ; then + PLATFORM=x86_64 + USEOJ=0 elif [ $1 = "engine" ]; then PLATFORM=ark USEOJ=1 diff --git a/build/third_party/aosp_gn/art/libdexfile/CMakeLists.txt b/build/third_party/aosp_gn/art/libdexfile/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba8c19d639ea97dff4342b838c671a97615daa17 --- /dev/null +++ b/build/third_party/aosp_gn/art/libdexfile/CMakeLists.txt @@ -0,0 +1,54 @@ +# +# 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. +# +set(include_directories + ${AOSP_ROOT}/system/core/base/include + ${AOSP_ROOT}/system/core/libziparchive/include + ${AOSP_ROOT}/system/core/liblog/include + ${AOSP_ROOT}/system/core/libutils/include + ${AOSP_ROOT}/art/libartpalette/include + ${AOSP_ROOT}/art/libartbase + ${AOSP_ROOT}/art/libdexfile + ${AOSP_ROOT}/include + ${AOSP_ROOT}/libnativehelper/include_jni +) + +set(sources_files + dex/art_dex_file_loader.cc + dex/compact_dex_file.cc + dex/compact_offset_table.cc + dex/descriptors_names.cc + dex/dex_file.cc + dex/dex_file_exception_helpers.cc + dex/dex_file_layout.cc + dex/dex_file_loader.cc + dex/dex_file_tracking_registrar.cc + dex/dex_file_verifier.cc + dex/dex_instruction.cc + dex/modifiers.cc + dex/primitive.cc + dex/signature.cc + dex/standard_dex_file.cc + dex/type_lookup_table.cc + dex/utf.cc +) + +# libdexfile +add_library(libdexfile STATIC ${sources_files}) +set_target_properties(libdexfile PROPERTIES + COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -Wno-defaulted-function-deleted -std=gnu++17 -fPIC" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + RUNTIME_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/lib/${HOST_ARCH}" +) diff --git a/build/third_party/aosp_gn/system/core/base/CMakeLists.txt b/build/third_party/aosp_gn/system/core/base/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..6e0583580c0082ab77c609f31ce6c6bde6c1b687 --- /dev/null +++ b/build/third_party/aosp_gn/system/core/base/CMakeLists.txt @@ -0,0 +1,42 @@ +# +# 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. +# +set(include_directories + ${AOSP_ROOT}/system/core/base/include + ${AOSP_ROOT}/include +) + +set(sources_files + chrono_utils.cpp + cmsg.cpp + file.cpp + logging.cpp + mapped_file.cpp + parsenetaddress.cpp + properties.cpp + quick_exit.cpp + stringprintf.cpp + strings.cpp + test_utils.cpp + threads.cpp +) + +# libbase +add_library(libbase STATIC ${sources_files}) +set_target_properties(libbase PROPERTIES + COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -fPIC" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + RUNTIME_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/lib/${HOST_ARCH}" +) diff --git a/build/third_party/aosp_gn/system/core/libziparchive/CMakeLists.txt b/build/third_party/aosp_gn/system/core/libziparchive/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3e606765e2d97132eb615e8b394e2eb605ab8aa0 --- /dev/null +++ b/build/third_party/aosp_gn/system/core/libziparchive/CMakeLists.txt @@ -0,0 +1,38 @@ +# +# 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. +# +set(include_directories + ${AOSP_ROOT}/system/core/include + ${AOSP_ROOT}/system/core/base/include + ${AOSP_ROOT}/system/core/libziparchive/include + ${AOSP_ROOT}/system/core/libziparchive + ${AOSP_ROOT}/system/core/liblog/include + ${AOSP_ROOT}/system/core/libutils/include + ${AOSP_ROOT}/include +) + +set(sources_files + zip_archive.cc + zip_archive_stream_entry.cc + zip_writer.cc +) + +# libziparchive +add_library(libziparchive STATIC ${sources_files}) +set_target_properties(libziparchive PROPERTIES + COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++17 -fPIC" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + RUNTIME_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/lib/${HOST_ARCH}" +) diff --git a/build/third_party/patch.sh b/build/third_party/patch.sh index 647ba0f34807bfaa40c99d440c44170c4f04cb95..171152b4f700bf4115c87b89904199a96738cb5d 100644 --- a/build/third_party/patch.sh +++ b/build/third_party/patch.sh @@ -42,13 +42,13 @@ function install_patch { mkdir -p include/ cp -r ${MAPLE_ROOT}/src/hir2mpl/bytecode_input/dex/include/string_view_format.h include/ - cd $MODIFIED_LLVM_PATH - patch -p0 < $TOOLS_PATH/llvm_001.patch - #add third_party gn cp -f $AOSP_GN_PATH/art/libdexfile/BUILD.gn $MODIFIED_AOSP_PATH/art/libdexfile/ cp -f $AOSP_GN_PATH/system/core/libziparchive/BUILD.gn $MODIFIED_AOSP_PATH/system/core/libziparchive/ cp -f $AOSP_GN_PATH/system/core/base/BUILD.gn $MODIFIED_AOSP_PATH/system/core/base/ + cp -f $AOSP_GN_PATH/art/libdexfile/CMakeLists.txt $MODIFIED_AOSP_PATH/art/libdexfile/ + cp -f $AOSP_GN_PATH/system/core/libziparchive/CMakeLists.txt $MODIFIED_AOSP_PATH/system/core/libziparchive/ + cp -f $AOSP_GN_PATH/system/core/base/CMakeLists.txt $MODIFIED_AOSP_PATH/system/core/base/ } diff --git a/build/toolchain/BUILD.gn b/build/toolchain/BUILD.gn index 00a3f708a9f91ea0f1dbf3e8d212fa55154be348..d45cde7be74dbf4cc33faff3ebd9af95e833d9f0 100755 --- a/build/toolchain/BUILD.gn +++ b/build/toolchain/BUILD.gn @@ -86,11 +86,14 @@ toolchain("clang") { outfile = "${GN_BINARY_OUTPUT_DIRECTORY}/{{target_output_name}}{{output_extension}}" rspfile = "$outfile.rsp" rspfile_content = "{{inputs}}" - if (GN_BUILD_TYPE == "RELEASE") { - command = "${GN_CXX_COMPILER} -s -fuse-ld=lld {{ldflags}} -o $outfile -Wl,--start-group ${rspfile_content} {{libs}} -Wl,--end-group {{solibs}}" - } else { - command = "${GN_CXX_COMPILER} -fuse-ld=lld {{ldflags}} -o $outfile -Wl,--start-group ${rspfile_content} {{libs}} -Wl,--end-group {{solibs}}" + + strip_flag = "" + if (GN_BUILD_TYPE == "RELEASE" && GPROF == 0) { + strip_flag = "-s" } + + command = "${GN_CXX_COMPILER} ${strip_flag} -fuse-ld=lld {{ldflags}} -o $outfile -Wl,--start-group ${rspfile_content} {{libs}} -Wl,--end-group {{solibs}}" + description = "LINK $outfile" rspfile_content = "{{inputs}}" outputs = [ 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/format.sh b/format.sh new file mode 100755 index 0000000000000000000000000000000000000000..1189a7868479d16a67d2db24b67a054fca1fdaba --- /dev/null +++ b/format.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# usage: in OpenArkCompiler dir, ./format.sh xxx.cpp +CLANG_FORMAT=$MAPLE_ROOT/tools/clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-18.04/bin/clang-format + +$CLANG_FORMAT -style=file -i $1 +sed -i -e 's/ \*,/\*,/g' -e 's/ \*>/\*>/g' -e 's/ \*)/\*)/g' -e 's/ \&,/\&,/g' -e 's/ \&>/\&>/g' -e 's/ \&)/\&)/g' $1 +sed -i ":a;$!N;s/enum\(.*\)\n{/enum\1 {/g;ba" $1 diff --git a/libc_enhanced/include/c_enhanced.h b/libc_enhanced/include/c_enhanced.h new file mode 100644 index 0000000000000000000000000000000000000000..be560b3dec884f29f00f7cf0180f4ae2a647b885 --- /dev/null +++ b/libc_enhanced/include/c_enhanced.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) [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. + */ +#ifndef __C_ENHANCED_H +#define __C_ENHANCED_H +#ifdef C_ENHANCED +#define VNON __attribute__((nonnull)) +#define NON(...) __attribute__((nonnull(__VA_ARGS__))) +#define RNON __attribute__((returns_nonnull)) + +#define VCNT(N) __attribute__((count(N))) +#define CNT(N, ...) __attribute__((count(N, __VA_ARGS__))) +#define CNTI(I, ...) __attribute__((count_index(I, __VA_ARGS__))) +#define RCNT(N) __attribute__((returns_count(N))) +#define RCNTI(I) __attribute__((returns_count_index(I))) + +#define BVCNT(N) __attribute__((byte_count(N))) +#define BCNT(N, ...) __attribute__((byte_count(N, __VA_ARGS__))) +#define BCNTI(I, ...) __attribute__((byte_count_index(I, __VA_ARGS__))) +#define BRCNT(N) __attribute__((returns_byte_count(N))) +#define BRCNTI(I) __attribute__((returns_byte_count_index(I))) + +#define SAFE __Safe__ +#define UNSAFE __Unsafe__ +#else +#define VNON +#define NON(...) +#define RNON +#define VCNT(N) +#define CNT(N, ...) +#define CNTI(I, ...) +#define RCNT(N) +#define RCNTI(I) +#define BVCNT(N) +#define BCNT(N, ...) +#define BCNTI(I, ...) +#define BRCNT(N) +#define BRCNTI(I) +#define SAFE +#define UNSAFE +#endif // C_ENHANCED + +#ifndef size_t +#include +#endif + +BRCNTI(2) +static __inline__ void* __builtin_dynamic_bounds_cast(void* p, size_t size) { + return p; +} + +#ifdef C_ENHANCED +#define BOUNDS_CAST(p, size) __builtin_dynamic_bounds_cast((p), (size)) +#else +#define BOUNDS_CAST(p, size) (p) +#endif + +#endif // __C_ENHANCED_H diff --git a/src/mapleall/maple_be/include/cg/aarch64/aarch64_immediate.h b/libc_enhanced/include/stdio.h similarity index 44% rename from src/mapleall/maple_be/include/cg/aarch64/aarch64_immediate.h rename to libc_enhanced/include/stdio.h index 82ffafdfe1ea49f0981aa8bfbdd7615def54d805..936863e7f0fc3c5f5e9ad61a09be96d1bd68e100 100644 --- a/src/mapleall/maple_be/include/cg/aarch64/aarch64_immediate.h +++ b/libc_enhanced/include/stdio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) [2020] Huawei Technologies Co.,Ltd.All rights reserved. + * Copyright (c) [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. @@ -12,17 +12,28 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#ifndef MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_IMMEDIATE_H -#define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_IMMEDIATE_H +#include_next +#ifndef __STDIO_C_ENHANCED_H +#if !defined __need_FILE && !defined __need___FILE +#define __STDIO_C_ENHANCED_H +#include "c_enhanced.h" +#include -#include "types_def.h" /* maple_ir/include/typedef.h */ -#include +// Fix EOF not defined error +#ifndef EOF +# define EOF (-1) +#endif -namespace maplebe { -bool IsBitSizeImmediate(maple::uint64 val, maple::uint32 bitLen, maple::uint32 nLowerZeroBits); -bool IsBitmaskImmediate(maple::uint64 val, maple::uint32 bitLen); -bool IsMoveWidableImmediate(maple::uint64 val, maple::uint32 bitLen); -bool BetterUseMOVZ(maple::uint64 val); -} /* namespace maplebe */ +CNTI(2, 1) +SAFE int snprintf(char *__restrict str, size_t, const char *__restrict, ...); -#endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_IMMEDIATE_H */ +CNTI(2, 1) +SAFE int vsnprintf(char *__restrict str, size_t, const char *__restrict, va_list); + +#ifdef __FILE_defined +CNTI(2, 1) +SAFE char *fgets(char *__restrict str, int, FILE *__restrict); +#endif + +#endif +#endif // __STDIO_C_ENHANCED_H diff --git a/libc_enhanced/include/stdlib.h b/libc_enhanced/include/stdlib.h new file mode 100644 index 0000000000000000000000000000000000000000..cfeb7517c1523c07269246d12586561e2fd2b521 --- /dev/null +++ b/libc_enhanced/include/stdlib.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) [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. + */ +#ifndef __STDLIB_C_ENHANCED_H +#define __STDLIB_C_ENHANCED_H +#include_next +#include "c_enhanced.h" + +BRCNTI(1) +SAFE void *malloc(size_t); + +SAFE void *calloc(size_t n_elements, size_t element_size) BRCNT(n_elements * element_size); + +BRCNTI(2) +SAFE void *realloc(void *, size_t); + +#endif // __STDLIB_C_ENHANCED_H diff --git a/libc_enhanced/include/string.h b/libc_enhanced/include/string.h new file mode 100644 index 0000000000000000000000000000000000000000..ecba51d7cbaa0958a8795a91b03ecf9d8b94344e --- /dev/null +++ b/libc_enhanced/include/string.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) [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. + */ +#ifndef __STRING_C_ENHANCED_H +#define __STRING_C_ENHANCED_H +#include_next +#include "c_enhanced.h" +BCNTI(3, 1, 2) +SAFE void *memcpy(void *__restrict __dest, const void *__restrict __src, size_t count); + +BCNTI(3, 1, 2) +SAFE void *memmove(void *__dest, const void *__src, size_t count); + +BCNTI(3, 1) +SAFE void *memset(void *__s, int __c, size_t count); + +BCNTI(3, 1, 2) +SAFE int memcmp (const void *__s1, const void *__s2, size_t __n); + +#endif // __STRING_C_ENHANCED_H diff --git a/src/MapleEng/BUILD.gn b/src/MapleEng/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..9ec5543293ca8ba346c786429408048f37b1fbb3 --- /dev/null +++ b/src/MapleEng/BUILD.gn @@ -0,0 +1,19 @@ +# +# Copyright (c) [2022] Futurewei Technologies, Inc. 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. +# +configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] + +group("mplsh-lmbc") { + deps = [ "${MAPLEENG_ROOT}/lmbc:lmbc_mplsh" ] +} diff --git a/src/MapleEng/Readme.md b/src/MapleEng/Readme.md new file mode 100644 index 0000000000000000000000000000000000000000..5604ff83b7b0c81c66edb2bb9058833f2afad646 --- /dev/null +++ b/src/MapleEng/Readme.md @@ -0,0 +1,45 @@ +``` +# +# Copyright (C) [2022] Futurewei Technologies, Inc. All rights reserved. +# +# OpenArkCompiler is licensed underthe Mulan Permissive Software License v2. +# You can use this software according to the terms and conditions of the MulanPSL - 2.0. +# You may obtain a copy of MulanPSL - 2.0 at: +# +# https://opensource.org/licenses/MulanPSL-2.0 +# +# 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 MulanPSL - 2.0 for more details. +# +``` +## Maple Engine for Lmbc + Maple Engine for Lmbc is an interpreter that executes Lmbc files (.lmbc) that the + OpenArkCompiler generates. C source code is first parsed by C to Maple frontends, which + can be either hir2mpl or clang2mpl, and the output is then compiled by OpernArkCompiler + into .lmbc (lowered Maple bytecode format) format to be executed by Maple Engine for Lmbc. + +## Build OpernArkCompiler and engine + The following build example assumes OpenArkCompiler root directory at ~/OpenArkCompiler: +``` + cd ~/OpenArkCompiler + source build/envsetup.sh arm release + make + make clang2mpl + make mplsh_lmbc +``` +## Build and run a C app + The following example compiles a C demo program at ~/OpenArkCompiler/test/c_demo/ to lmbc + and runs it with Maple Engine for Lmbc. +``` + cd $MAPLE_ROOT/test/c_demo + $MAPLE_ROOT/src/MapleEng/lmbc/test/c2lmbc.sh printHuawei.c + $MAPLE_EXECUTE_BIN/mplsh-lmbc printHuawei.lmbc +``` +## Running ctorture with Maple Engine for Lmbc +``` + git clone https://gitee.com/hu-_-wen/ctorture + cd ctorture + ./mpleng.sh mpleng.list +``` diff --git a/src/MapleEng/lmbc/BUILD.gn b/src/MapleEng/lmbc/BUILD.gn new file mode 100755 index 0000000000000000000000000000000000000000..4f1012ff5e065a4b4e54149365b2ae42cb5aada8 --- /dev/null +++ b/src/MapleEng/lmbc/BUILD.gn @@ -0,0 +1,55 @@ +# +# Copyright (c) [2022] Futurewei Technologies, Inc. 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. +# +configs = [ "${MAPLEALL_ROOT}:mapleallcompilecfg" ] + +include_directories = [ + "${MAPLEALL_ROOT}/maple_ir/include", + "${MAPLEALL_ROOT}/mpl2mpl/include", + "${MAPLEALL_ROOT}/maple_util/include", + "${MAPLEALL_ROOT}/maple_driver/include", + "${MAPLEALL_ROOT}/mempool/include", + "${THIRD_PARTY_ROOT}/bounds_checking_function/include", + "${MAPLEALL_ROOT}/maple_ipa/include", + "${MAPLEALL_ROOT}/maple_ipa/include/old", + "${MAPLEALL_ROOT}/maple_me/include", + "${MAPLEALL_ROOT}/maple_phase/include", + "${MAPLEALL_ROOT}/maple_be/include/be", + "${MAPLEENG_ROOT}/lmbc/include" +] + +src_mplsh_lmbc = [ + "src/mplsh.cpp", + "src/init.cpp", + "src/mfunction.cpp", + "src/eng_shim.cpp", + "src/load_store.cpp", + "src/invoke_method.cpp", +] + +executable("mplsh-lmbc") { + sources = src_mplsh_lmbc + include_dirs = include_directories + deps = [ + "${MAPLEALL_ROOT}/maple_ir:libmplir", + "${MAPLEALL_ROOT}/mempool:libmempool", + "${MAPLEALL_ROOT}/mpl2mpl:libmpl2mpl", + "${THIRD_PARTY_ROOT}/bounds_checking_function:libHWSecureC", + ] + + libs = [ + "ffi", + "dl", + ] +} diff --git a/src/MapleEng/lmbc/include/eng_shim.h b/src/MapleEng/lmbc/include/eng_shim.h new file mode 100644 index 0000000000000000000000000000000000000000..8e67057c16545ccbdbe23098e79c1ebf37d7bd7a --- /dev/null +++ b/src/MapleEng/lmbc/include/eng_shim.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_SHIM_H_ +#define MPLENG_SHIM_H_ + +#include +#include "lmbc_eng.h" + +namespace maple { + +extern "C" int64_t MplEngShim(LmbcFunc*, ...); + +} + +#endif // MPLENG_SHIM_H_ diff --git a/src/MapleEng/lmbc/include/lmbc_eng.h b/src/MapleEng/lmbc/include/lmbc_eng.h new file mode 100644 index 0000000000000000000000000000000000000000..2fb0a21eae78f538bf7da4056022ea09cd2d3ead --- /dev/null +++ b/src/MapleEng/lmbc/include/lmbc_eng.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_LMBC_H_ +#define MPLENG_LMBC_H_ + +#include +#include +#include +#include +#include "mir_parser.h" +#include "bin_mplt.h" +#include "opcode_info.h" +#include "mir_function.h" +#include "constantfold.h" +#include "mir_type.h" +#include "mvalue.h" +#include "global_tables.h" +#include "mfunction.h" +#include "common_utils.h" + +namespace maple { +class LmbcMod; + +// Parameter and variable info +struct ParmInf { + PrimType ptyp; + size_t size; + bool isPreg; + bool isVararg; + // use scenarios for storeIdx field: + // ParmInf - idx into pReg array if isPreg (formal is preg) + // ParmInf - idx into formalvar array if formal is var symbol + // ParmInf - offset into func formalagg mem block if PTY_agg formal arg + // ParmInf - offset into func varagg mem blk if PTY_agg var-arg + // VarInf - offset into module globals mem blk if global or PUStatic var + int32 storeIdx; + MIRSymbol *sym; // VarInf only - for global and PUStatic var + PUIdx puIdx; // VarInf only - for PUStatic var + ParmInf(PrimType type, size_t sz, bool ispreg, int32_t storageIdx) : ptyp(type), + size(sz), isPreg(ispreg), storeIdx(storageIdx) {} + ParmInf(PrimType type, size_t sz, bool ispreg, int32_t storageIdx, MIRSymbol *psym) : ptyp(type), + size(sz), isPreg(ispreg), storeIdx(storageIdx), sym(psym) {} + ParmInf(PrimType type, size_t sz, bool ispreg, int32_t storageIdx, MIRSymbol *psym, PUIdx puidx) : ptyp(type), + size(sz), isPreg(ispreg), storeIdx(storageIdx), sym(psym), puIdx(puidx) {} +}; + +using LabelMap = std::unordered_map; + +class LmbcFunc { + public: + LmbcMod *lmbcMod; + MIRFunction *mirFunc; + uint32 retSize; + uint32 frameSize; // auto var size in bytes + uint16 formalsNum; // num formals: vars+pregs + uint32 formalsNumVars; // num formals: vars only + uint32 formalsAggSize; // total struct size of all formal args of type agg + uint32 formalsSize; // total size of all formal args + LabelMap labelMap; // map labelIdx to Stmt address + size_t numPregs; + bool isVarArgs; + std::vector pos2Parm; // formals info lkup by pos order + std::unordered_map stidx2Parm; // formals info lkup by formals stidx + LmbcFunc(LmbcMod *mod, MIRFunction *func); + void ScanFormals(void); + void ScanLabels(StmtNode* stmt); +}; + +class FuncAddr { + public: + union { + LmbcFunc *lmbcFunc; + void *nativeFunc; + } funcPtr; + bool isLmbcFunc; + uint32 formalsAggSize; // native func only + std::string funcName; + FuncAddr(bool lmbcFunc, void *func, std::string funcName, uint32 formalsAggSz = 0); +}; + +using VarInf = struct ParmInf; +using FuncMap = std::unordered_map; + +class LmbcMod { + public: + std::string lmbcPath; + MIRModule* mirMod {nullptr}; + FuncMap funcMap; + LmbcFunc* mainFn {nullptr}; + std::unordered_map globalAndStaticVars; + std::unordered_map globalStrTbl; + int unInitPUStaticsSize {0}; // uninitalized PUStatic vars + uint8* unInitPUStatics{nullptr}; + int globalsSize {0}; // global vars and initialized PUStatic + uint8* globals {nullptr}; + uint32 aggrInitOffset {0}; + + void InitGlobalVars(void); + void InitGlobalVariable(VarInf *pInf); + void InitIntConst(VarInf *pInf, MIRIntConst &intConst, uint8 *dst); + void InitStrConst(VarInf* pInf, MIRStrConst &mirStrConst, uint8 *dst); + void InitAddrofConst(VarInf *pInf, MIRAddrofConst &addrofConst, uint8 *dst); + void InitFloatConst(VarInf *pInf, MIRFloatConst &f32Const, uint8 *dst); + void InitDoubleConst(VarInf *Inf, MIRDoubleConst &f64Const, uint8 *dst); + void InitLblConst(VarInf *pInf, MIRLblConst &labelConst, uint8 *dst); + void InitBitFieldConst(VarInf *pInf, MIRConst &mirConst, int32_t &allocdBits, bool &forceAlign); + uint8_t* GetGlobalVarInitAddr(VarInf* pInf, uint32 align); + void UpdateGlobalVarInitAddr(VarInf* pInf, uint32 size); + void CheckUnamedBitField(MIRStructType &stType, uint32 &prevInitFd, uint32 curFd, int32 &allocdBits); + + LmbcMod(std::string path); + MIRModule* Import(std::string path); + void InitModule(void); + void CalcGlobalAndStaticVarSize(void); + void ScanPUStatic(MIRFunction *func); + LmbcFunc* LkupLmbcFunc(PUIdx puIdx); + + std::vector libHandles; + std::unordered_mapextFuncMap; // PUIdx to ext func addr map + std::unordered_mapextSymMap; // StIdx.FullIdx() to ext sym addr map + void LoadDefLibs(void); + void* FindExtFunc(PUIdx puidx); + void* FindExtSym(StIdx stidx); + void AddGlobalVar(MIRSymbol &sym, VarInf *pInf); + void AddPUStaticVar(PUIdx puIdx, MIRSymbol &sym, VarInf *pInf); + uint8 *GetVarAddr(StIdx stidx); // globa var + uint8 *GetVarAddr(PUIdx puidx, StIdx stidx); // PUStatic var + + void InitAggConst(VarInf *pInf, MIRConst &mirConst); + void InitArrayConst(VarInf *pInf, MIRConst &mirConst); + void InitScalarConst(VarInf *pInf, MIRConst &mirConst); + void InitPointerConst(VarInf *pInf, MIRConst &mirConst); + std::unordered_map PUIdx2FuncAddr; + FuncAddr* GetFuncAddr(PUIdx puIdx); +}; + +} // namespace maple + +#endif // MPLENG_LMBC_H_ diff --git a/src/MapleEng/lmbc/include/massert.h b/src/MapleEng/lmbc/include/massert.h new file mode 100644 index 0000000000000000000000000000000000000000..2030082a9a4c2c54057719bc45a4f942c6bff6a7 --- /dev/null +++ b/src/MapleEng/lmbc/include/massert.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_MASSERT_H_ +#define MPLENG_MASSERT_H_ + +#include +#include + +#define MASSERT(cond, fmt, ...) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, __FILE__ ":%d: Assert failed: " fmt "\n", __LINE__, ##__VA_ARGS__); \ + abort(); \ + } \ + } while (0) + +#endif // MPLENG_MASSERT_H_ + diff --git a/src/MapleEng/lmbc/include/mexpression.h b/src/MapleEng/lmbc/include/mexpression.h new file mode 100644 index 0000000000000000000000000000000000000000..306ac1bf8ec019c582b0158febe91d3707bd5a56 --- /dev/null +++ b/src/MapleEng/lmbc/include/mexpression.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_MEXPRESSION_H_ +#define MPLENG_MEXPRESSION_H_ + +#include +#include "massert.h" // for MASSERT + +#define EXPRBINOP(exprop, res, op0, op1, exprPtyp) \ + do { \ + switch (exprPtyp) { \ + case PTY_i8: res.x.i8 = op0.x.i8 exprop op1.x.i8; break; \ + case PTY_i16: res.x.i16 = op0.x.i16 exprop op1.x.i16; break; \ + case PTY_i32: res.x.i32 = (int64)op0.x.i32 exprop (int64)op1.x.i32; break; \ + case PTY_i64: res.x.i64 = op0.x.i64 exprop op1.x.i64; break; \ + case PTY_u8: res.x.u8 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_u16: res.x.u16 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_u32: res.x.u32 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_u64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_a64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_f32: res.x.f32 = op0.x.f32 exprop op1.x.f32; break; \ + case PTY_f64: res.x.f64 = op0.x.f64 exprop op1.x.f64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for binary operator %s", exprPtyp, #exprop); \ + } \ + res.ptyp = expr->ptyp; \ + } while (0) + +#define EXPRCOMPOP(exprop, res, op0, op1, optyp, exprptyp) \ + do { \ + switch (optyp) { \ + case PTY_i8: res.x.i64 = op0.x.i8 exprop op1.x.i8; break; \ + case PTY_i16: res.x.i64 = op0.x.i16 exprop op1.x.i16; break; \ + case PTY_i32: res.x.i64 = op0.x.i32 exprop op1.x.i32; break; \ + case PTY_i64: res.x.i64 = op0.x.i64 exprop op1.x.i64; break; \ + case PTY_u8: res.x.i64 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_u16: res.x.i64 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_u32: res.x.i64 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_u64: res.x.i64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_a64: res.x.i64 = op0.x.a64 exprop op1.x.a64; break; \ + case PTY_f32: res.x.i64 = op0.x.f32 exprop op1.x.f32; break; \ + case PTY_f64: res.x.i64 = op0.x.f64 exprop op1.x.f64; break; \ + default: MIR_FATAL("Unsupported operand PrimType %d for comparison operator %s", op0.ptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +// EXPRCOMPOP with f32 amd f64 comparison cases taken out because of +// -Wfloat-equal compile flag warnings with != and == on float types. +// The float cases for != and == are special case handled in op handlers. +#define EXPRCOMPOPNOFLOAT(exprop,res, op0, op1, optyp, exprptyp) \ + do { \ + switch (optyp) { \ + case PTY_i8: res.x.i64 = op0.x.i8 exprop op1.x.i8; break; \ + case PTY_i16: res.x.i64 = op0.x.i16 exprop op1.x.i16; break; \ + case PTY_i32: res.x.i64 = op0.x.i32 exprop op1.x.i32; break; \ + case PTY_i64: res.x.i64 = op0.x.i64 exprop op1.x.i64; break; \ + case PTY_u8: res.x.i64 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_u16: res.x.i64 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_u32: res.x.i64 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_u64: res.x.i64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_a64: res.x.i64 = op0.x.a64 exprop op1.x.a64; break; \ + default: MIR_FATAL("Unsupported operand PrimType %d for comparison operator %s", op0.ptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +#define EXPRSELECTOP(res, op0, sel1, sel2, exprptyp) \ + do { \ + MValue op1, op2; \ + op1 = CvtType(sel1, exprptyp, sel1.ptyp); \ + op2 = CvtType(sel2, exprptyp, sel2.ptyp); \ + switch (exprptyp) { \ + case PTY_i8: res.x.i8 = op0.x.i64? op1.x.i8 : op2.x.i8; break; \ + case PTY_i16: res.x.i16 = op0.x.i64? op1.x.i16 : op2.x.i16; break; \ + case PTY_i32: res.x.i32 = op0.x.i64? op1.x.i32 : op2.x.i32; break; \ + case PTY_i64: res.x.i64 = op0.x.i64? op1.x.i64 : op2.x.i64; break; \ + case PTY_u8: res.x.u8 = op0.x.i64? op1.x.u8 : op2.x.u8; break; \ + case PTY_u16: res.x.u16 = op0.x.i64? op1.x.u16 : op2.x.u16; break; \ + case PTY_u32: res.x.u32 = op0.x.i64? op1.x.u32 : op2.x.u32; break; \ + case PTY_u64: res.x.u64 = op0.x.i64? op1.x.u64 : op2.x.u64; break; \ + case PTY_a64: res.x.a64 = op0.x.i64? op1.x.a64 : op2.x.a64; break; \ + case PTY_f32: res.x.f32 = op0.x.i64? op1.x.f32 : op2.x.f32; break; \ + case PTY_f64: res.x.f64 = op0.x.i64? op1.x.f64 : op2.x.f64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for select operator", exprptyp); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +#define EXPRBININTOP(exprop, res, op, op1, exprptyp) \ + do { \ + MValue op0 = CvtType(op, exprptyp, op.ptyp); \ + switch (exprptyp) { \ + case PTY_i8: res.x.i8 = op0.x.i8 exprop op1.x.i8; break; \ + case PTY_i16: res.x.i16 = op0.x.i16 exprop op1.x.i16; break; \ + case PTY_i32: res.x.i32 = op0.x.i32 exprop op1.x.i32; break; \ + case PTY_i64: res.x.i64 = op0.x.i64 exprop op1.x.i64; break; \ + case PTY_u8: res.x.u8 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_u16: res.x.u16 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_u32: res.x.u32 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_u64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_a64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for integer binary operator %s", exprptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +// Used by OP_lshr only +#define EXPRBININTOPUNSIGNED(exprop, res, op0, op1, exprptyp) \ + do { \ + MASSERT((op0.ptyp == exprptyp) || \ + (op0.ptyp == PTY_u32 && exprptyp == PTY_i32) || \ + (op0.ptyp == PTY_i32 && exprptyp == PTY_u32), \ + "BINUINTOP Type mismatch: 0x%02x and 0x%02x", op0.ptyp, exprptyp); \ + switch (op1.ptyp) { \ + case PTY_i8: \ + case PTY_u8: \ + MASSERT(op1.x.u8 <= 64, "OP_lshr shifting more than 64 bites"); \ + break; \ + case PTY_i16: \ + case PTY_u16: \ + MASSERT(op1.x.u16 <= 64, "OP_lshr shifting more than 64 bites"); \ + break; \ + case PTY_i32: \ + case PTY_u32: \ + MASSERT(op1.x.u32 <= 64, "OP_lshr shifting more than 64 bites"); \ + break; \ + case PTY_i64: \ + case PTY_u64: \ + case PTY_a64: \ + MASSERT(op1.x.u64 <= 64, "OP_lshr shifting more than 64 bites"); \ + break; \ + default: \ + MIR_FATAL("Unsupported PrimType %d for unsigned integer binary operator %s", exprptyp, #exprop); \ + break; \ + } \ + switch (exprptyp) { \ + case PTY_i8: res.x.u8 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_i16: res.x.u16 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_i32: res.x.u32 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_i64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_a64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + case PTY_u8: res.x.u8 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_u16: res.x.u16 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_u32: res.x.u32 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_u64: res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for unsigned integer binary operator %s", exprptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +#define EXPRMAXMINOP(exprop, res, op0, op1, exprptyp) \ + do { \ + MASSERT(op0.ptyp == op1.ptyp, "MAXMINOP Type mismatch: 0x%02x and 0x%02x", op0.ptyp, op1.ptyp); \ + MASSERT(op0.ptyp == exprptyp, "MAXMINOP Type mismatch: 0x%02x and 0x%02x", op0.ptyp, exprptyp); \ + switch (exprptyp) { \ + case PTY_i8: res.x.i8 = op0.x.i8 exprop op1.x.i8? op0.x.i8 : op1.x.i8; break; \ + case PTY_i16: res.x.i16 = op0.x.i16 exprop op1.x.i16? op0.x.i16 : op1.x.i16; break; \ + case PTY_i32: res.x.i32 = op0.x.i32 exprop op1.x.i32? op0.x.i32 : op1.x.i32; break; \ + case PTY_i64: res.x.i64 = op0.x.i64 exprop op1.x.i64? op0.x.i64 : op1.x.i64; break; \ + case PTY_u8: res.x.u8 = op0.x.u8 exprop op1.x.u8 ? op0.x.u8 : op1.x.u8; break; \ + case PTY_u16: res.x.u16 = op0.x.u16 exprop op1.x.u16? op0.x.u16 : op1.x.u16; break; \ + case PTY_u32: res.x.u32 = op0.x.u32 exprop op1.x.u32? op0.x.u32 : op1.x.u32; break; \ + case PTY_u64: res.x.u64 = op0.x.u64 exprop op1.x.u64? op0.x.u64 : op1.x.u64; break; \ + case PTY_a64: res.x.a64 = op0.x.a64 exprop op1.x.a64? op0.x.a64 : op1.x.a64; break; \ + case PTY_f32: res.x.f32 = op0.x.f32 exprop op1.x.f32? op0.x.f32 : op1.x.f32; break; \ + case PTY_f64: res.x.f64 = op0.x.f64 exprop op1.x.f64? op0.x.f64 : op1.x.f64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for binary max/min operator %s", exprptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +#define EXPRREMOP(exprop, res, op0, op1, exprptyp) \ + do { \ + switch (exprptyp) { \ + case PTY_i8: if (op1.x.i8 == 0) res.x.i8 = 0; \ + else if (op1.x.i8 == -1 && op0.x.i8 == INT8_MIN) op0.x.i8 = 0; \ + else res.x.i8 = op0.x.i8 exprop op1.x.i8; break; \ + case PTY_i16: if (op1.x.i16 == 0) res.x.i16 = 0; \ + else if (op1.x.i16 == -1 && op0.x.i16 == INT16_MIN) op0.x.i16 = 0; \ + else res.x.i16 = op0.x.i16 exprop op1.x.i16; break; \ + case PTY_i32: if (op1.x.i32 == 0) res.x.i32 = 0; \ + else if (op1.x.i32 == -1 && op0.x.i32 == INT32_MIN) op0.x.i32 = 0; \ + else res.x.i32 = op0.x.i32 exprop op1.x.i32; break; \ + case PTY_i64: if (op1.x.i64 == 0) res.x.i64 = 0; \ + else if (op1.x.i64 == -1 && op0.x.i64 == INT64_MIN) op0.x.i64 = 0; \ + else res.x.i64 = op0.x.i64 exprop op1.x.i64; break; \ + case PTY_u8: if (op1.x.u8 == 0) res.x.u8 = 0; \ + else res.x.u8 = op0.x.u8 exprop op1.x.u8; break; \ + case PTY_u16: if (op1.x.u16 == 0) res.x.u16 = 0; \ + else res.x.u16 = op0.x.u16 exprop op1.x.u16; break; \ + case PTY_u32: if (op1.x.u32 == 0) res.x.u32 = 0; \ + else res.x.u32 = op0.x.u32 exprop op1.x.u32; break; \ + case PTY_u64: if (op1.x.u64 == 0) res.x.u64 = 0; \ + else res.x.u64 = op0.x.u64 exprop op1.x.u64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for rem operator %s", exprptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +#define EXPRUNROP(exprop, res, op0, exprptyp) \ + do { \ + MASSERT(op0.ptyp == exprptyp || \ + ((op0.ptyp == PTY_i32 || op0.ptyp == PTY_u32) && \ + (exprptyp == PTY_i32 || exprptyp == PTY_u32)), \ + "UNROP Type mismatch: 0x%02x and 0x%02x", op0.ptyp, exprptyp); \ + switch (exprptyp) { \ + case PTY_i8: res.x.i8 = exprop op0.x.i8; break; \ + case PTY_i16: res.x.i16 = exprop op0.x.i16; break; \ + case PTY_i32: res.x.i32 = exprop op0.x.i32; break; \ + case PTY_i64: res.x.i64 = exprop op0.x.i64; break; \ + case PTY_u8: res.x.u8 = exprop op0.x.u8; break; \ + case PTY_u16: res.x.u16 = exprop op0.x.u16; break; \ + case PTY_u32: res.x.u32 = exprop op0.x.u32; break; \ + case PTY_u64: res.x.u64 = exprop op0.x.u64; break; \ + default: MIR_FATAL("Unsupported PrimType %d for unary operator %s", exprptyp, #exprop); \ + } \ + res.ptyp = exprptyp; \ + } while (0) + +#endif // MPLENG_MEXPRESSION_H_ diff --git a/src/MapleEng/lmbc/include/mfunction.h b/src/MapleEng/lmbc/include/mfunction.h new file mode 100644 index 0000000000000000000000000000000000000000..b56e9fc34ba6b64fe295c465b7b21d7332a801d7 --- /dev/null +++ b/src/MapleEng/lmbc/include/mfunction.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_MFUNCTION_H_ +#define MPLENG_MFUNCTION_H_ + +#include +#include + +#include +#include + +#include "mir_nodes.h" +#include "mvalue.h" +#include "lmbc_eng.h" + +#define VARNAMELENGTH 16 +#define ALLOCA_MEMMAX 0x4000 + +namespace maple { + +class LmbcMod; +class LmbcFunc; +struct ParmInf; + +using ffi_fp_t = void(*)(); + +// For x86 valist setup, to force va arg acess from stack pointed to +// by overflow_arg_area, set gp_offset to 48, fp_offset to 304, +// reg_save_rea to null, and overflow_arg_arg to location for vaArgs. +typedef struct { + uint gp_offset; + uint fp_offset; + void *overflow_arg_area; + void *reg_save_area; +} VaListX86_64[1]; + +typedef struct { + void *stack; + void *gr_top; + void *vr_top; + int gr_offs; + int vr_offs; +} VaListAarch64; + +using VaList = VaListAarch64; + +// State of executing Maple function +class MFunction { + public: + // state of an executing function + LmbcFunc* info; // current func + MFunction* caller; // caller of current func + StmtNode* nextStmt; // next maple IR statement to execute + uint8* frame; // stack frame (auto var only) + uint8* fp; // point to bottom of frame + uint8* allocaMem; // point to reserved stack memory for Maple IR OP_alloca + uint32 allocaOffset; // next avail offset in allocaMem + MValue* pRegs; // array of pseudo regs used in function + MValue* formalVars; // array of var/non-preg args passed in + + // for function calls made from this function + uint16 numCallArgs; // number of call args to pass to callee + MValue* callArgs; // array of call args to pass to callee + uint8* aggrArgsBuf; // buffer for PTY_agg call formal args, which offsets into it + uint8* varArgsBuf; // buffer for PTY_agg call var-args, which offsets into it + MValue retVal0; // %retVal0 return from callee + MValue retVal1; // %retval1 return from callee + uint8* vaArgs; // AARCH64 ABI vararg stack for calling va-arg funcs + uint32 vaArgsSize; + + explicit MFunction(LmbcFunc *funcInfo, + MFunction *funcCaller, + uint8 *autoVars, + MValue *pRegs, + MValue *formalVars); + ~MFunction(); + uint8 *Alloca(uint32 size); + uint8 *GetFormalVarAddr(StIdx stidx); + void CallMapleFuncDirect(CallNode *call); + void CallMapleFuncIndirect(IcallNode *icall, LmbcFunc *callInfo); + void CallExtFuncDirect(CallNode* call); + void CallExtFuncIndirect(IcallNode *icallproto, void* fp); + void CallVaArgFunc(int numArgs, LmbcFunc *callInfo); + void CallWithFFI(PrimType ret_ptyp, ffi_fp_t fp); + void CallIntrinsic(IntrinsiccallNode &intrn); +}; + +bool IsExtFunc(PUIdx puIdx, LmbcMod &module); +MValue InvokeFunc(LmbcFunc* fn, MFunction *caller); +MValue EvalExpr(MFunction &func, BaseNode* expr, ParmInf *parm = nullptr); +void mload(uint8* addr, PrimType ptyp, MValue& res, size_t aggSizea = 0); +void mstore(uint8* addr, PrimType ptyp, MValue& val, bool toVarArgStack = false); + +} +#endif // MPLENG_MFUNCTION_H_ diff --git a/src/MapleEng/lmbc/include/mprimtype.h b/src/MapleEng/lmbc/include/mprimtype.h new file mode 100644 index 0000000000000000000000000000000000000000..68b42041c485594df8f720386eec3c24b5b4d939 --- /dev/null +++ b/src/MapleEng/lmbc/include/mprimtype.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_MPRIMTYPE_H_ +#define MPLENG_MPRIMTYPE_H_ + +// Define size info of primtypes, some of them are undefined for now(set to 0) +// 1 - 1 byte +// 2 - 2 bytes +// 3 - 4 bytes +// 4 - 8 bytes +// 5 - 16 bytes +// 6 - 32 bytes +#define PTYSIZE_Invalid 0 +#define PTYSIZE_void 0 +#define PTYSIZE_i8 1 +#define PTYSIZE_i16 2 +#define PTYSIZE_i32 3 +#define PTYSIZE_i64 4 +#define PTYSIZE_u8 1 +#define PTYSIZE_u16 2 +#define PTYSIZE_u32 3 +#define PTYSIZE_u64 4 +#define PTYSIZE_u1 1 +#define PTYSIZE_ptr 3 +#define PTYSIZE_ref 3 +#define PTYSIZE_a32 3 +#define PTYSIZE_a64 4 +#define PTYSIZE_f32 3 +#define PTYSIZE_f64 4 +#define PTYSIZE_f128 5 +#define PTYSIZE_c64 5 +#define PTYSIZE_c128 6 +#define PTYSIZE_simplestr 3 +#define PTYSIZE_simpleobj 3 +#define PTYSIZE_dynany 4 +#define PTYSIZE_dynundef 4 +#define PTYSIZE_dynnull 4 +#define PTYSIZE_dynbool 4 +#define PTYSIZE_dyni32 4 +#define PTYSIZE_dynstr 4 +#define PTYSIZE_dynobj 4 +#define PTYSIZE_dynf64 4 +#define PTYSIZE_dynf32 4 +#define PTYSIZE_dynnone 4 +#define PTYSIZE_constStr 0 +#define PTYSIZE_gen 0 +#define PTYSIZE_agg 0 +#define PTYSIZE_v2i64 0 +#define PTYSIZE_v4i32 0 +#define PTYSIZE_v8i16 0 +#define PTYSIZE_v16i8 0 +#define PTYSIZE_v2f64 0 +#define PTYSIZE_v4f32 0 +#define PTYSIZE_unknown 0 +#define PTYSIZE_Derived 0 + +// Define ffi types for each primtype, some of them are unsupported(set to ffi_type_void) +#define FFITYPE_Invalid ffi_type_void +#define FFITYPE_void ffi_type_void +#define FFITYPE_i8 ffi_type_sint8 +#define FFITYPE_i16 ffi_type_sint16 +#define FFITYPE_i32 ffi_type_sint32 +#define FFITYPE_i64 ffi_type_sint64 +#define FFITYPE_u8 ffi_type_uint8 +#define FFITYPE_u16 ffi_type_uint16 +#define FFITYPE_u32 ffi_type_uint32 +#define FFITYPE_u64 ffi_type_uint64 +#define FFITYPE_u1 ffi_type_uint8 +#define FFITYPE_ptr ffi_type_pointer +#define FFITYPE_ref ffi_type_pointer +#define FFITYPE_a32 ffi_type_pointer +#define FFITYPE_a64 ffi_type_pointer +#define FFITYPE_f32 ffi_type_float +#define FFITYPE_f64 ffi_type_double +#define FFITYPE_f128 ffi_type_void +#define FFITYPE_c64 ffi_type_void +#define FFITYPE_c128 ffi_type_void +#define FFITYPE_simplestr ffi_type_void +#define FFITYPE_simpleobj ffi_type_void +#define FFITYPE_dynany ffi_type_void +#define FFITYPE_dynundef ffi_type_void +#define FFITYPE_dynnull ffi_type_void +#define FFITYPE_dynbool ffi_type_void +#define FFITYPE_dyni32 ffi_type_void +#define FFITYPE_dynstr ffi_type_void +#define FFITYPE_dynobj ffi_type_void +#define FFITYPE_dynf64 ffi_type_void +#define FFITYPE_dynf32 ffi_type_void +#define FFITYPE_dynnone ffi_type_void +#define FFITYPE_constStr ffi_type_void +#define FFITYPE_gen ffi_type_void +#define FFITYPE_agg ffi_type_void +#define FFITYPE_v2i64 ffi_type_void +#define FFITYPE_v4i32 ffi_type_void +#define FFITYPE_v8i16 ffi_type_void +#define FFITYPE_v16i8 ffi_type_void +#define FFITYPE_v2f64 ffi_type_void +#define FFITYPE_v4f32 ffi_type_void +#define FFITYPE_unknown ffi_type_void +#define FFITYPE_Derived ffi_type_void +#define FFITYPE_i128 ffi_type_void +#define FFITYPE_u128 ffi_type_void +#define FFITYPE_v2u64 ffi_type_void +#define FFITYPE_v4u32 ffi_type_void +#define FFITYPE_v8u16 ffi_type_void +#define FFITYPE_v16u8 ffi_type_void +#define FFITYPE_v2i32 ffi_type_void +#define FFITYPE_v4i16 ffi_type_void +#define FFITYPE_v8i8 ffi_type_void +#define FFITYPE_v2u32 ffi_type_void +#define FFITYPE_v4u16 ffi_type_void +#define FFITYPE_v8u8 ffi_type_void +#define FFITYPE_v2f32 ffi_type_void +#define FFITYPE_reservedpty1 ffi_type_void +#define FFITYPE_reservedpty2 ffi_type_void +#define FFITYPE_reservedpty3 ffi_type_void +#define FFITYPE_reservedpty4 ffi_type_void +#define FFITYPE_reservedpty5 ffi_type_void +#define FFITYPE_reservedpty6 ffi_type_void +#define FFITYPE_reservedpty7 ffi_type_void +#define FFITYPE_reservedpty8 ffi_type_void +#define FFITYPE_reservedpty9 ffi_type_void +#define FFITYPE_reservedpty10 ffi_type_void +#endif // MPLENG_MPRIMTYPE_H_ diff --git a/src/MapleEng/lmbc/include/mvalue.h b/src/MapleEng/lmbc/include/mvalue.h new file mode 100644 index 0000000000000000000000000000000000000000..f7bb933d8a665155b94b461c6ca2049f99788d34 --- /dev/null +++ b/src/MapleEng/lmbc/include/mvalue.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 MPLENG_MVALUE_H_ +#define MPLENG_MVALUE_H_ + +#include +#include "prim_types.h" + +namespace maple { + struct MValue { + union { + int8 i8; + int16 i16; + int32 i32; + int64 i64; + uint8 u8; + uint16 u16; + uint32 u32; + uint64 u64; + float f32; + double f64; + uint8 *a64; // object ref (use uint8_t* instead of void* for reference) + void *ptr; + void *str; + } x; + PrimType ptyp:8; + size_t aggSize; // for PTY_agg only + }; +} + +#endif // MPLENG_MVALUE_H_ + diff --git a/src/MapleEng/lmbc/src/eng_shim.cpp b/src/MapleEng/lmbc/src/eng_shim.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3323aaf9f4d6b1fe529999653085b7a3cb0cfaf2 --- /dev/null +++ b/src/MapleEng/lmbc/src/eng_shim.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 "mfunction.h" +#include "massert.h" +#include "lmbc_eng.h" + +namespace maple { + +extern "C" int64 MplEngShim(LmbcFunc* fn, ...) { + uint8 frame[fn->frameSize]; + MValue pregs[fn->numPregs]; + MValue formalVars[fn->formalsNumVars+1]; + MFunction shim_caller(fn, nullptr, frame, pregs, formalVars); // create local Mfunction obj for shim + + MValue val; + if (fn->formalsNum > 0) { + MValue callArgs[fn->formalsNum]; + va_list args; + va_start (args, fn); + + int argIdx = 0; + while (argIdx < fn->formalsNum) { + // convert argv args to interpreter types and push on operand stack + val.ptyp = fn->pos2Parm[argIdx]->ptyp; + switch (val.ptyp) { + case PTY_i8: + val.x.i8 = va_arg(args, int); + break; + case PTY_i16: + val.x.i16 = va_arg(args, int); + break; + case PTY_i32: + val.x.i32 = va_arg(args, int); + break; + case PTY_i64: + val.x.i64 = va_arg(args, long long); + break; + case PTY_u16: + val.x.u16 = va_arg(args, int); + break; + case PTY_a64: + val.x.a64 = va_arg(args, uint8*); + break; + case PTY_f32: + // Variadic function expects that float arg is promoted to double + case PTY_f64: + val.x.f64 = va_arg(args, double); + break; + default: + MIR_FATAL("Unsupported PrimType %d", val.ptyp); + } + callArgs[argIdx] = val; + ++argIdx; + } + shim_caller.numCallArgs = fn->formalsNum; + shim_caller.callArgs = callArgs; + } + val = InvokeFunc(fn, &shim_caller); + return 0; +} + +} diff --git a/src/MapleEng/lmbc/src/init.cpp b/src/MapleEng/lmbc/src/init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..eccab17f79a4a71a6c1be589d2d178a2b96b32c1 --- /dev/null +++ b/src/MapleEng/lmbc/src/init.cpp @@ -0,0 +1,598 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 "massert.h" +#include "lmbc_eng.h" +#include "eng_shim.h" + +namespace maple { + +// Align offset to required alignment +inline void AlignOffset(uint32 &offset, uint32 align) { + offset = (offset + align-1) & ~(align-1); +} + +LmbcFunc::LmbcFunc(LmbcMod *mod, MIRFunction *func) : lmbcMod(mod), mirFunc(func) { + frameSize = ((func->GetFrameSize()+maplebe::k8ByteSize-1) >> maplebe::k8BitShift) << maplebe::k8BitShift; // round up to nearest 8 + isVarArgs = func->GetMIRFuncType()->IsVarargs(); + numPregs = func->GetPregTab()->Size(); +} + +void LmbcMod::InitModule(void) { + CalcGlobalAndStaticVarSize(); + for (MIRFunction *mirFunc : mirMod->GetFunctionList()) { + if (auto node = mirFunc->GetBody()) { + LmbcFunc* fn = new LmbcFunc(this, mirFunc); + MASSERT(fn, "Create Lmbc function failed"); + fn->ScanFormals(); + fn->ScanLabels(node); + funcMap[mirFunc->GetPuidx()] = fn; + if (mirFunc->GetName().compare("main") == 0) { + mainFn = fn; + } + } + } + InitGlobalVars(); +} + +void LmbcFunc::ScanFormals(void) { + MapleVector formalDefVec = mirFunc->GetFormalDefVec(); + formalsNum = formalDefVec.size(); + formalsSize = 0; + formalsNumVars = 0; + formalsAggSize = 0; + MASSERT(mirFunc->GetReturnType() != nullptr, "mirFunc return type is null"); + retSize = mirFunc->GetReturnType()->GetSize(); + for (uint32 i = 0; i < formalDefVec.size(); i++) { + MIRSymbol* symbol = formalDefVec[i].formalSym; + MIRType* ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDefVec[i].formalTyIdx); + bool isPreg = (symbol->GetSKind() == kStPreg); + int32 storageIdx; + if (ty->GetPrimType() == PTY_agg) { + storageIdx = formalsAggSize; + formalsAggSize += ty->GetSize(); + } else { + storageIdx = isPreg? symbol->GetPreg()->GetPregNo(): ++formalsNumVars; + } + // collect formal params info + ParmInf* pInf = new ParmInf(ty->GetPrimType(), ty->GetSize(), isPreg, storageIdx); + stidx2Parm[symbol->GetStIdx().FullIdx()] = pInf; // formals info map keyed on formals stidx + pos2Parm.push_back(pInf); // vector of formals info in formalDefVec order + formalsSize += ty->GetSize(); + } +} + +void LmbcFunc::ScanLabels(StmtNode* stmt) { + while (stmt != nullptr) { + switch (stmt->op) { + case OP_block: + stmt = static_cast(stmt)->GetFirst(); + ScanLabels(stmt); + break; + case OP_label: + labelMap[static_cast(stmt)->GetLabelIdx()] = stmt; + break; + default: + break; + } + stmt= stmt->GetNext(); + } +} + +// Check for initialized flex array struct member and return size. The number +// of elements is not specified in the array type declaration but determined +// by array initializer. +// - Flex array must be last field of a top level struct +// - Only 1st dim of multi-dim array can be unspecified. Other dims must have bounds. +// - In Maple AST, array with unspecified num elements is defined with 1 element in +// 1st array dim, and is the storage for 1st initialiazed array element. +// The interpreter identifies such arrays by a dim of 1 in the array's 1st dim +// together with an array const initializer with > 1 element (should identify using +// kTypeFArray return from GetKind() but it's returning kTypeArray now ). +uint32 CheckFlexArrayMember(MIRSymbol &sym, MIRType &ty) { + auto &stType = static_cast(ty); + auto &stConst = static_cast(*sym.GetKonst()); + TyIdxFieldAttrPair tfap = stType.GetTyidxFieldAttrPair(stType.GetFieldsSize()-1); // last struct fd + MIRType *lastFdType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first); + if (lastFdType->GetKind() == kTypeArray && // last struct field is array + static_cast(lastFdType)->GetSizeArrayItem(0) == 1 && // 1st dim of array is 1 + stConst.GetConstVec().size() == stType.GetFieldsSize()) { // there is an initializer for the array + MIRConst &elemConst = *stConst.GetConstVecItem(stConst.GetConstVec().size()-1); // get array initializer + MASSERT(elemConst.GetType().GetKind() == kTypeArray, "array initializer expected"); + auto &arrCt = static_cast(elemConst); + if (arrCt.GetConstVec().size() > 1) { + return (arrCt.GetConstVec().size()-1) * elemConst.GetType().GetSize(); // 1st elem already in arr type def + } + } + return 0; +} + +// Calcluate total memory needed for global vars, Fstatic vars and initialized PUstatic vars. +// Walks global sym table and local sym table of all funcs to gather size info and adds +// var to table for looking up its size, type and offset within the storage segment. +void LmbcMod::CalcGlobalAndStaticVarSize() { + uint32 offset = 0; + for (size_t i = 0; i < GlobalTables::GetGsymTable().GetSymbolTableSize(); ++i) { + MIRSymbol *sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(i); + if (!sym || + !(sym->GetSKind() == kStVar) || + !(sym->GetStorageClass() == kScGlobal || sym->GetStorageClass() == kScFstatic)) { + continue; + } + if (MIRType *ty = sym->GetType()) { + AlignOffset(offset, ty->GetAlign()); // check and align var + VarInf* pInf = new VarInf(ty->GetPrimType(), ty->GetSize(), false, offset, sym); + AddGlobalVar(*sym, pInf); // add var to lookup table + offset += ty->GetSize(); + if (ty->GetKind() == kTypeStruct) { // check and account for flex array member + offset += CheckFlexArrayMember(*sym, *ty); + } + } + } + globalsSize = offset; + // get total size of nitialized function static vars + for (MIRFunction *func : mirMod->GetFunctionList()) { + if (auto node = func->GetBody()) { + ScanPUStatic(func); + } + } +} + +void LmbcMod::ScanPUStatic(MIRFunction *func) { + size_t size = func->GetSymbolTabSize(); + for (size_t i = 0; i < size; ++i) { + MIRSymbol *sym = func->GetSymbolTabItem(i); + if (!sym || !sym->IsPUStatic() || !sym->IsConst()) { // exclude un-init PUStatic + continue; + } + if (MIRType *ty = sym->GetType()) { + VarInf* pInf = new VarInf(ty->GetPrimType(), ty->GetSize(), false, globalsSize, sym, func->GetPuidx()); + AddPUStaticVar(func->GetPuidx(), *sym, pInf); // add var to lookup table + globalsSize += ty->GetSize(); + } + } +} + +// Get the address of a non-agg global var or next field within a global var to init. +// If a PTY_agg var, align offset to next init addr (aggrInitOffset) for ptyp. +// Otherwise, storeIdx should be aligned properly already in CalcGlobalVarsSize. +// - storeIdx: offset of the global var in global var segment +// - aggrInitOffset: offset of the field to init within global var of type PTY_agg +uint8 *LmbcMod::GetGlobalVarInitAddr(VarInf* pInf, uint32 align) { + if (pInf->ptyp != PTY_agg) { // init non-aggr global var + return globals + pInf->storeIdx; + } + AlignOffset(aggrInitOffset, align); + return globals + pInf->storeIdx + aggrInitOffset; +} + +inline void LmbcMod::UpdateGlobalVarInitAddr(VarInf* pInf, uint32 size) { + if (pInf->ptyp == PTY_agg) { + aggrInitOffset += size; + } +} + +// Check for un-named bitfields in initialized global struct vars and +// include in global var memory sizing and field offset calcuations. Un-named +// bit fields appears as gaps in field id between initialized struct fields +// of a global var. +void LmbcMod::CheckUnamedBitField(MIRStructType &stType, uint32 &prevInitFd, uint32 curFd, int32 &allocdBits) { + if (curFd - 1 == prevInitFd) { + prevInitFd = curFd; + return; + } + for (auto i = prevInitFd; i < curFd -1; ++i) { // struct fd idx 0 based; agg const fd 1 based + TyIdxFieldAttrPair tfap = stType.GetTyidxFieldAttrPair(i); + MIRType *ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tfap.first); // type of struct fd + // Gaps in struct fields with initializer are either un-named bit fields or empty struct fields + // Account for bits in un-named bit fields. Skip over emtpy struct fields. + if (ty->GetKind() != kTypeBitField) { + continue; + } + MASSERT(ty->GetKind()==kTypeBitField, "Un-named bitfield expected"); + uint8 bitFdWidth = static_cast(ty)->GetFieldSize(); + uint32 baseFdSz = GetPrimTypeSize(ty->GetPrimType()); + + uint32 align = allocdBits ? 1 : baseFdSz; // align with base fd if no bits have been allocated + AlignOffset(aggrInitOffset, align); + + if (allocdBits + bitFdWidth > (baseFdSz * maplebe::k8BitSize)) { // alloc bits will cross align boundary of base type + aggrInitOffset+= baseFdSz; + allocdBits = bitFdWidth; // alloc bits at new boundary + } else { + allocdBits += bitFdWidth; + } + } + prevInitFd = curFd; +} + +void LmbcMod::InitStrConst(VarInf* pInf, MIRStrConst &mirStrConst, uint8* dst) { + UStrIdx ustrIdx = mirStrConst.GetValue(); + auto it = globalStrTbl.insert( + std::pair(ustrIdx, GlobalTables::GetUStrTable().GetStringFromStrIdx(ustrIdx))); + *(const char **)dst = it.first->second.c_str(); +} + +inline void LmbcMod::InitFloatConst(VarInf *pInf, MIRFloatConst &f32Const, uint8* dst) { + *(float*)dst = f32Const.GetValue(); +} + +inline void LmbcMod::InitDoubleConst(VarInf *pInf, MIRDoubleConst &f64Const, uint8* dst) { + *(double*)dst = f64Const.GetValue(); +} + +void LmbcMod::InitLblConst(VarInf *pInf, MIRLblConst &labelConst, uint8 *dst) { + LabelIdx labelIdx = labelConst.GetValue(); + LmbcFunc *fn = LkupLmbcFunc(labelConst.GetPUIdx()); + StmtNode* label = fn->labelMap[labelIdx]; + MASSERT(label, "InitLblConst label not foound"); + *(StmtNode **)dst = label; +} + +void LmbcMod::InitIntConst(VarInf* pInf, MIRIntConst &intConst, uint8* dst) { + int64 val = intConst.GetExtValue(); + switch (intConst.GetType().GetPrimType()) { + case PTY_i64: + *(int64*)dst = (int64)val; + break; + case PTY_i32: + *(int32*)dst = (int32)val; + break; + case PTY_i16: + *(int16*)dst = (int16)val; + break; + case PTY_i8: + *(int8*)dst = (int8)val; + break; + case PTY_u64: + *(uint64*)dst = (uint64)val; + break; + case PTY_u32: + *(uint32*)dst = (uint32)val; + break; + case PTY_u16: + *(uint16*)dst = (uint16)val; + break; + case PTY_u8: + *(uint8*)dst = (uint8)val; + break; + default: + break; + } +} + +void LmbcMod::InitPointerConst(VarInf *pInf, MIRConst &mirConst) { + uint8 *dst = GetGlobalVarInitAddr(pInf, mirConst.GetType().GetAlign()); + switch (mirConst.GetKind()) { + case kConstAddrof: + InitAddrofConst(pInf, static_cast(mirConst), dst); + break; + case kConstStrConst: + InitStrConst(pInf, static_cast(mirConst), dst); + break; + case kConstInt: { + InitIntConst(pInf, static_cast(mirConst), dst); + break; + } + case kConstAddrofFunc: + default: + MASSERT(false, "InitPointerConst %d kind NYI", mirConst.GetKind()); + break; + } + UpdateGlobalVarInitAddr(pInf, mirConst.GetType().GetSize()); +} + +void SetBitFieldConst(uint8* baseFdAddr, uint32 baseFdSz, uint32 bitsOffset, uint8 bitsSize, MIRConst &elemConst) { + MIRIntConst &intConst = static_cast(elemConst); + int64 val = intConst.GetExtValue(); + uint64 mask = ~(0xffffffffffffffff << bitsSize); + uint64 from = (val & mask) << bitsOffset; + mask = mask << bitsOffset; + switch (elemConst.GetType().GetPrimType()) { + case PTY_i64: + *(int64*)baseFdAddr = ((*(int64*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_i32: + *(int32*)baseFdAddr = ((*(int32*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_i16: + *(int16*)baseFdAddr = ((*(int16*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_i8: + *(int8*)baseFdAddr = ((*(int8*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_u64: + *(uint64*)baseFdAddr = ((*(uint64*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_u32: + *(uint32*)baseFdAddr = ((*(uint32*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_u16: + *(uint16*)baseFdAddr = ((*(uint16*)baseFdAddr) & ~(mask)) | from; + break; + case PTY_u8: + *(uint8*)baseFdAddr = ((*(uint8*)baseFdAddr) & ~(mask)) | from; + break; + default: + MASSERT(false, "Unexpected primary type"); + break; + } +} + +void LmbcMod::InitBitFieldConst(VarInf *pInf, MIRConst &elemConst, int32 &allocdBits, bool &forceAlign) { + uint8 bitFdWidth = static_cast(elemConst.GetType()).GetFieldSize(); + if (!bitFdWidth) { // flag to force align immediate following bit field + forceAlign = true; + return; + } + if (forceAlign) { // align to next boundary + aggrInitOffset += (allocdBits + maplebe::k8ByteSize-1) >> maplebe::k8BitShift; + forceAlign = false; + } + uint32 baseFdSz = GetPrimTypeSize(elemConst.GetType().GetPrimType()); + uint32 align = allocdBits ? 1 : baseFdSz; // align with base fd if no bits have been allocated + uint8* baseFdAddr = GetGlobalVarInitAddr(pInf, align); + + if (allocdBits + bitFdWidth > (baseFdSz * maplebe::k8BitSize)) { // alloc bits will cross align boundary of base type + baseFdAddr = baseFdAddr + baseFdSz; // inc addr & offset by size of base type + SetBitFieldConst(baseFdAddr, baseFdSz, 0, bitFdWidth, elemConst); + aggrInitOffset+= baseFdSz; + allocdBits = bitFdWidth; // alloc bits at new boundary + } else { + SetBitFieldConst(baseFdAddr, baseFdSz, allocdBits, bitFdWidth, elemConst); + allocdBits += bitFdWidth; + } +} + +void LmbcMod::InitAggConst(VarInf *pInf, MIRConst &mirConst) { + auto &stType = static_cast(mirConst.GetType()); + auto &aggConst = static_cast(mirConst); + bool forceAlign = false; + int32 allocdBits = 0; + + AlignOffset(aggrInitOffset, aggConst.GetType().GetAlign()); // next init offset in global var mem + MIRTypeKind prevElemKind = kTypeUnknown; + for (uint32 i = 0, prevInitFd = 0; i < aggConst.GetConstVec().size(); ++i) { + MIRConst &elemConst = *aggConst.GetConstVecItem(i); + MIRType &elemType = elemConst.GetType(); + + // if non bit fd preceded by bit fd, round bit fd to byte boundary + // so next bit fd will start on new boundary + if (prevElemKind == kTypeBitField && elemType.GetKind() != kTypeBitField) { + forceAlign = false; + if (allocdBits) { + aggrInitOffset += (allocdBits + maplebe::k8ByteSize-1) >> maplebe::k8BitShift; // pad preceding bit fd to byte boundary + allocdBits = 0; + } + } + + // No need to check for un-named bit fd if aggr is an array + if (stType.GetKind() != kTypeArray) { + CheckUnamedBitField(stType, prevInitFd, aggConst.GetFieldIdItem(i), allocdBits); + } + switch (elemType.GetKind()) { + case kTypeScalar: + InitScalarConst(pInf, elemConst); + break; + case kTypeStruct: + case kTypeUnion: + InitAggConst(pInf, elemConst); + break; + case kTypeArray: + InitArrayConst(pInf, elemConst); + break; + case kTypePointer: + InitPointerConst(pInf, elemConst); + break; + case kTypeBitField: { + InitBitFieldConst(pInf, elemConst, allocdBits, forceAlign); + break; + } + default: { + MASSERT(false, "init struct type %d NYI", elemType.GetKind()); + break; + } + } + prevElemKind = elemType.GetKind(); + } +} + +void LmbcMod::InitScalarConst(VarInf *pInf, MIRConst &mirConst) { + uint8 *dst = GetGlobalVarInitAddr(pInf, mirConst.GetType().GetAlign()); + switch (mirConst.GetKind()) { + case kConstInt: + InitIntConst(pInf, static_cast(mirConst), dst); + break; + case kConstFloatConst: + InitFloatConst(pInf, static_cast(mirConst), dst); + break; + case kConstDoubleConst: + InitDoubleConst(pInf, static_cast(mirConst), dst); + break; + case kConstStrConst: + InitStrConst(pInf, static_cast(mirConst), dst); + break; + case kConstLblConst: + InitLblConst(pInf, static_cast(mirConst), dst); + break; + case kConstStr16Const: + case kConstAddrof: + case kConstAddrofFunc: + default: + MASSERT(false, "Scalar Const Type %d NYI", mirConst.GetKind()); + break; + } + UpdateGlobalVarInitAddr(pInf, mirConst.GetType().GetSize()); +} + +void LmbcMod::InitArrayConst(VarInf *pInf, MIRConst &mirConst) { + MIRArrayType &arrayType = static_cast(mirConst.GetType()); + MIRAggConst &arrayCt = static_cast(mirConst); + AlignOffset(aggrInitOffset, arrayType.GetAlign()); + + size_t uNum = arrayCt.GetConstVec().size(); + uint32 dim = arrayType.GetSizeArrayItem(0); + TyIdx scalarIdx = arrayType.GetElemTyIdx(); + MIRType *subTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(scalarIdx); + if (uNum == 0 && dim != 0) { + while (subTy->GetKind() == kTypeArray) { + MIRArrayType *aSubTy = static_cast(subTy); + if (aSubTy->GetSizeArrayItem(0) > 0) { + dim *= (aSubTy->GetSizeArrayItem(0)); + } + scalarIdx = aSubTy->GetElemTyIdx(); + subTy = GlobalTables::GetTypeTable().GetTypeFromTyIdx(scalarIdx); + } + } + for (size_t i = 0; i < uNum; ++i) { + MIRConst *elemConst = arrayCt.GetConstVecItem(i); + if (IsPrimitiveVector(subTy->GetPrimType())) { + MASSERT(false, "Unexpected primitive vector"); + } else if (IsPrimitiveScalar(elemConst->GetType().GetPrimType())) { + InitScalarConst(pInf, *elemConst); + } else if (elemConst->GetType().GetKind() == kTypeArray) { + InitArrayConst(pInf, *elemConst); + } else if (elemConst->GetType().GetKind() == kTypeStruct || + elemConst->GetType().GetKind() == kTypeClass || + elemConst->GetType().GetKind() == kTypeUnion) { + InitAggConst(pInf, *elemConst); + } else { + MASSERT(false, "InitArrayConst unexpected error"); + } + } +} + +void LmbcMod::InitAddrofConst(VarInf *pInf, MIRAddrofConst &addrofConst, uint8* dst) { + StIdx stIdx = addrofConst.GetSymbolIndex(); + int32 offset = addrofConst.GetOffset(); + uint8 *addr = pInf->sym->IsPUStatic() ? GetVarAddr(pInf->puIdx, stIdx) : GetVarAddr(stIdx); + *(uint8**)dst = addr + offset; +} + +void LmbcMod::InitGlobalVariable(VarInf *pInf) { + MIRConst *mirConst = pInf->sym->GetKonst(); + uint8 *dst = GetGlobalVarInitAddr(pInf, mirConst->GetType().GetAlign()); + + switch (mirConst->GetKind()) { + case kConstAggConst: + aggrInitOffset = 0; + InitAggConst(pInf, *mirConst); + return; + case kConstInt: + InitIntConst(pInf, *static_cast(mirConst), dst); + break; + case kConstFloatConst: + InitFloatConst(pInf, *static_cast(mirConst), dst); + break; + case kConstDoubleConst: + InitDoubleConst(pInf, *static_cast(mirConst), dst); + break; + case kConstAddrof: + InitAddrofConst(pInf, *static_cast(mirConst), dst); + break; + case kConstStrConst: + InitStrConst(pInf, *static_cast(mirConst), dst); + break; + default: + MASSERT(false, "Init MIRConst type %d NYI", mirConst->GetKind()); + break; + } + UpdateGlobalVarInitAddr(pInf, mirConst->GetType().GetSize()); +} + +void LmbcMod::InitGlobalVars(void) { + // alloc mem for global vars + this->globals = (uint8*)malloc(this->globalsSize); + this->unInitPUStatics = (uint8*)malloc(this->unInitPUStaticsSize); + memset_s(this->globals, this->globalsSize, 0, this->globalsSize); + memset_s(this->unInitPUStatics, this->unInitPUStaticsSize, 0, this->unInitPUStaticsSize); + + // init global vars and static vars + for (const auto it : globalAndStaticVars) { + VarInf *pInf = it.second; + if (pInf->sym->IsConst()) { + InitGlobalVariable(pInf); + } + } +} + +inline void LmbcMod::AddGlobalVar(MIRSymbol &sym, VarInf *pInf) { + globalAndStaticVars[sym.GetStIdx().FullIdx()] = pInf; +} + +inline void LmbcMod::AddPUStaticVar(PUIdx puIdx, MIRSymbol &sym, VarInf *pInf) { + globalAndStaticVars[((uint64)puIdx << maplebe::k32BitSize) | sym.GetStIdx().FullIdx()] = pInf; +} + +// global var +uint8 *LmbcMod::GetVarAddr(StIdx stIdx) { + auto it = globalAndStaticVars.find(stIdx.FullIdx()); + MASSERT(it != globalAndStaticVars.end(), "global var not found"); + return globals + it->second->storeIdx; +} + +// PUStatic var +uint8 *LmbcMod::GetVarAddr(PUIdx puIdx, StIdx stIdx) { + auto it = globalAndStaticVars.find(((long)puIdx << maplebe::k32BitSize) | stIdx.FullIdx()); + MASSERT(it != globalAndStaticVars.end(), "PUStatic var not found"); + return globals + it->second->storeIdx; +} + +LmbcFunc *LmbcMod::LkupLmbcFunc(PUIdx puIdx) { + auto it = funcMap.find(puIdx); + return it == funcMap.end()? nullptr: it->second; +} + +FuncAddr::FuncAddr(bool lmbcFunc, void *func, std::string name, uint32 formalsAggSz) { + funcName = name; + isLmbcFunc = lmbcFunc; + formalsAggSize = formalsAggSz; + if (isLmbcFunc) { + funcPtr.lmbcFunc = (LmbcFunc*)func; + } else { + funcPtr.nativeFunc = func; + } +} + +// Get size total of all func parameters of type TY_agg. +uint32 GetAggFormalsSize(MIRFunction *func) { + uint32 totalSize = 0; + MapleVector &formalDefVec = func->GetFormalDefVec(); + for (int i = 0; i < formalDefVec.size(); i++) { + MIRType* ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDefVec[i].formalTyIdx); + if (ty->GetPrimType() == PTY_agg) { + totalSize += ty->GetSize(); + } + } + return totalSize; +} + +FuncAddr* LmbcMod::GetFuncAddr(PUIdx idx) { + FuncAddr *faddr; + if (PUIdx2FuncAddr[idx]) { + return PUIdx2FuncAddr[idx]; + } + MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(idx); + MASSERT(func, "Function not found in global table"); + if (IsExtFunc(idx, *this)) { + faddr = new FuncAddr(false, FindExtFunc(idx), func->GetName(), GetAggFormalsSize(func)); + } else { + faddr = new FuncAddr(true, LkupLmbcFunc(idx), func->GetName()); + } + PUIdx2FuncAddr[idx] = faddr; + return faddr; +} + + +} // namespace maple diff --git a/src/MapleEng/lmbc/src/invoke_method.cpp b/src/MapleEng/lmbc/src/invoke_method.cpp new file mode 100644 index 0000000000000000000000000000000000000000..162fda67b061e5db494cd36e5eb9adae39f368f7 --- /dev/null +++ b/src/MapleEng/lmbc/src/invoke_method.cpp @@ -0,0 +1,1322 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 +#include +#include +#include +#include +#include "mvalue.h" +#include "mprimtype.h" +#include "mfunction.h" +#include "mexpression.h" +#include "opcodes.h" +#include "massert.h" + +namespace maple { + +int64 MVal2Int64(MValue &val) { + switch (val.ptyp) { + case PTY_i64: + return val.x.i64; + case PTY_i32: + return (int64)val.x.i32; + case PTY_i16: + return (int64)val.x.i16; + case PTY_i8: + return (int64)val.x.i8; + case PTY_u32: + return (int64)val.x.u32; + default: + MASSERT(false, "MValue type %d for int64 conversion NYI", val.ptyp); + } +} + +bool IsZero(MValue& cond) { + switch (cond.ptyp) { + case PTY_u8: return cond.x.u8 == 0; + case PTY_u16: return cond.x.u16 == 0; + case PTY_u32: return cond.x.u32 == 0; + case PTY_u64: return cond.x.u64 == 0; + case PTY_i8: return cond.x.i8 == 0; + case PTY_i16: return cond.x.i16 == 0; + case PTY_i32: return cond.x.i32 == 0; + case PTY_i64: return cond.x.i64 == 0; + default: MASSERT(false, "IsZero type %d NYI", cond.ptyp); + } +} + +bool RegAssignZextOrSext(MValue& from, PrimType toTyp, MValue& to) { + switch (toTyp) { + case PTY_u8: + switch (from.ptyp) { + case PTY_u32: to.x.u8 = from.x.u32; break; // special case as needed + default: return false; + } + break; + case PTY_u32: + switch (from.ptyp) { + case PTY_u8: to.x.u64 = from.x.u8; break; + case PTY_u16: to.x.u64 = from.x.u16; break; + case PTY_i32: to.x.u64 = from.x.i32; break; + default: return false; + } + break; + case PTY_i32: + switch (from.ptyp) { + case PTY_i8: to.x.i64 = from.x.i8; break; + case PTY_i16: to.x.i64 = from.x.i16; break; + case PTY_u32: to.x.i64 = from.x.u32; break; + default: return false; + } + break; + case PTY_u64: + switch (from.ptyp) { + case PTY_u8: to.x.u64 = from.x.u8; break; + case PTY_u16: to.x.u64 = from.x.u16; break; + case PTY_u32: to.x.u64 = from.x.u32; break; + case PTY_i64: to.x.u64 = from.x.i64; break; // for large_stack.c + default: return false; + } + break; + case PTY_i64: + switch (from.ptyp) { + case PTY_i8: to.x.i64 = from.x.i8; break; + case PTY_i16: to.x.i64 = from.x.i16; break; + case PTY_i32: to.x.i64 = from.x.i32; break; + default: return false; + } + break; + case PTY_i16: + switch (from.ptyp) { + case PTY_i32: to.x.i16 = from.x.i32; break; + case PTY_u16: to.x.i16 = from.x.u16; break; + default: return false; + } + break; + case PTY_u16: + switch (from.ptyp) { + case PTY_u32: to.x.u16 = from.x.i32; break; + default: return false; + } + break; + default: + return false; + break; + } + to.ptyp = toTyp; + return true; +} + +#define CASE_TOPTYP(toPtyp, toCtyp) \ + case PTY_##toPtyp: \ + if (cvtInt) res.x.toPtyp = (toCtyp)fromInt; else \ + if (cvtUint) res.x.toPtyp = (toCtyp)fromUint; else \ + if (cvtf32) res.x.toPtyp = (toCtyp)fromFloat; else \ + if (cvtf64) res.x.toPtyp = (toCtyp)fromDouble; \ + break; + +MValue CvtType(MValue &opnd, PrimType toPtyp, PrimType fromPtyp) { + MValue res; + intptr_t fromInt; + uintptr_t fromUint; + float fromFloat; + double fromDouble; + bool cvtInt = false; + bool cvtUint = false; + bool cvtf32 = false; + bool cvtf64 = false; + + if (opnd.ptyp == toPtyp) { + return opnd; + } + switch (fromPtyp) { + case PTY_i8: fromInt = opnd.x.i8; cvtInt = true; break; + case PTY_i16: fromInt = opnd.x.i16; cvtInt = true; break; + case PTY_i32: fromInt = opnd.x.i32; cvtInt = true; break; + case PTY_i64: fromInt = opnd.x.i64; cvtInt = true; break; + case PTY_u8: fromUint = opnd.x.u8; cvtUint= true; break; + case PTY_u16: fromUint = opnd.x.u16; cvtUint= true; break; + case PTY_u32: fromUint = opnd.x.u32; cvtUint= true; break; + case PTY_u64: fromUint = opnd.x.u64; cvtUint= true; break; + case PTY_a64: fromUint = opnd.x.u64; cvtUint= true; break; + case PTY_ptr: fromUint = opnd.x.u64; cvtUint= true; break; + case PTY_f32: fromFloat = opnd.x.f32; cvtf32 = true; break; + case PTY_f64: fromDouble= opnd.x.f64; cvtf64 = true; break; + default: MASSERT(false, "OP_cvt from ptyp %d NYI", fromPtyp); break; + } + switch (toPtyp) { + CASE_TOPTYP(i8, int8) + CASE_TOPTYP(i16, int16) + CASE_TOPTYP(i32, int32) + CASE_TOPTYP(i64, int64) + CASE_TOPTYP(u8, uint8) + CASE_TOPTYP(u16, uint16) + CASE_TOPTYP(u32, uint32) + CASE_TOPTYP(u64, uint64) + CASE_TOPTYP(f32, float) + CASE_TOPTYP(f64, double) + case PTY_a64: + if (cvtInt) + res.x.a64 = (uint8*)fromInt; + else if (cvtUint) + res.x.a64 = (uint8*)fromUint; + else + MASSERT(false, "OP_cvt: type %d to %d not supported", fromPtyp, toPtyp); + break; + default: MASSERT(false, "OP_cvt: type %d to %d NYI", fromPtyp, toPtyp); + } + res.ptyp = toPtyp; + return res; +} + + +inline bool CompareFloat(float x, float y, float epsilon = 0.00000001f) { + if (isinf(x) && isinf(y)) { + return true; + } + return (fabs(x - y) < epsilon) ? true : false; +} + +inline bool CompareDouble(double x, double y, double epsilon = 0.0000000000000001f) { + if (isinf(x) && isinf(y)) { + return true; + } + return (fabs(x - y) < epsilon) ? true : false; +} + +void HandleFloatEq(Opcode op, PrimType opndType, MValue &res, MValue &op1, MValue &op2) { + MASSERT(opndType == op1.ptyp && op1.ptyp == op2.ptyp, "Operand type mismatch %d %d", op1.ptyp, op2.ptyp); + switch (op) { + case OP_ne: + if (opndType == PTY_f32) { + res.x.i64 = !CompareFloat(op1.x.f32, op2.x.f32); + } else if (opndType == PTY_f64) { + res.x.i64 = !CompareDouble(op1.x.f64, op2.x.f64); + } else { + MASSERT(false, "Unexpected type"); + } + break; + case OP_eq: + if (opndType == PTY_f32) { + res.x.i64 = CompareFloat(op1.x.f32, op2.x.f32); + } else if (opndType == PTY_f64) { + res.x.i64 = CompareDouble(op1.x.f64, op2.x.f64); + } else { + MASSERT(false, "Unexpected type"); + } + break; + default: + break; + } +} + +void LoadArgs(MFunction& func) { + for (int i=0; i < func.info->formalsNum; ++i) { + if (func.info->pos2Parm[i]->isPreg) { + func.pRegs[func.info->pos2Parm[i]->storeIdx] = func.caller->callArgs[i]; + } else { + func.formalVars[func.info->pos2Parm[i]->storeIdx] = func.caller->callArgs[i]; + } + } +} + +// Handle regassign agg %%retval0 +// Return agg <= 16 bytes in %%retval0 and %%retval1 +void HandleAggrRetval(MValue &rhs, MFunction *caller) { + MASSERT(rhs.aggSize <= 16, "regassign of agg >16 bytes to %%retval0"); + uint64 retval[2] = {0, 0}; + memcpy_s(retval, sizeof(retval), rhs.x.a64, rhs.aggSize); + caller->retVal0.x.u64 = retval[0]; + caller->retVal0.ptyp = PTY_agg; // treat as PTY_u64 if aggSize <= 16 + caller->retVal0.aggSize = rhs.aggSize; + if (rhs.aggSize > maplebe::k8ByteSize) { + caller->retVal1.x.u64 = retval[1]; + caller->retVal1.ptyp = PTY_agg; + caller->retVal1.aggSize= rhs.aggSize; + } +} + +// Walk the Maple LMBC IR tree of a function and execute its statements. +MValue InvokeFunc(LmbcFunc* fn, MFunction *caller) { + MValue retVal; + MValue pregs[fn->numPregs]; // func pregs (incl. func formals that are pregs) + MValue formalVars[fn->formalsNumVars+1]; // func formals that are named vars + alignas(maplebe::k8ByteSize) uint8 frame[fn->frameSize]; // func autovars + MFunction mfunc(fn, caller, frame, pregs, formalVars); // init func execution state + + static void* const labels[] = { + &&label_OP_Undef, +#define OPCODE(base_node,dummy1,dummy2,dummy3) &&label_OP_##base_node, +#include "opcodes.def" +#undef OPCODE + &&label_OP_Undef + }; + + LoadArgs(mfunc); + uint8 buf[ALLOCA_MEMMAX]; + mfunc.allocaMem = buf; +// mfunc.allocaMem = static_cast(alloca(ALLOCA_MEMMAX)); + StmtNode *stmt = mfunc.nextStmt; + goto *(labels[stmt->op]); + +label_OP_Undef: + { + MASSERT(false, "Hit OP_undef"); + } +label_OP_block: + { + stmt = static_cast(stmt)->GetFirst(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); + } +label_OP_iassignfpoff: + { + IassignFPoffNode* node = static_cast(stmt); + int32 offset= node->GetOffset(); + BaseNode* rhs = node->GetRHS(); + MValue val = EvalExpr(mfunc, rhs); + PrimType ptyp = node->ptyp; + mstore(mfunc.fp+offset, ptyp, val); + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_call: + { + CallNode *call = static_cast(stmt); + MValue callArgs[call->NumOpnds()]; // stack for callArgs + mfunc.callArgs = callArgs; + mfunc.numCallArgs = call->NumOpnds(); + if (IsExtFunc(call->GetPUIdx(), *mfunc.info->lmbcMod)) { + mfunc.CallExtFuncDirect(call); + } else { + mfunc.CallMapleFuncDirect(call); + } + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_regassign: + { + RegassignNode* node = static_cast(stmt); + PregIdx regIdx = node->GetRegIdx(); + MValue rhs = EvalExpr(mfunc, node->GetRHS()); + if (node->ptyp == rhs.ptyp) { + MASSERT(regIdx != -kSregRetval1, "regassign to %%%%retval1"); + if (regIdx == -kSregRetval0) { + if (node->ptyp != PTY_agg) { + caller->retVal0 = rhs; + } else { + HandleAggrRetval(rhs, caller); + } + } else { + MASSERT(regIdx < fn->numPregs, "regassign regIdx %d out of bound", regIdx); + mfunc.pRegs[regIdx] = rhs; + } + } else { + bool extended = false; + if (regIdx == -kSregRetval0) { + extended = RegAssignZextOrSext(rhs, node->ptyp, caller->retVal0); + } else if (regIdx == -kSregRetval1) { + extended = RegAssignZextOrSext(rhs, node->ptyp, caller->retVal1); + } else { + MASSERT(regIdx < fn->numPregs, "regassign regIdx %d out of bound", regIdx); + extended = RegAssignZextOrSext(rhs, node->ptyp, mfunc.pRegs[regIdx]); + } + if (!extended) { + if ((node->ptyp == PTY_a64 || node->ptyp == PTY_u64) && + (rhs.ptyp == PTY_a64 || rhs.ptyp == PTY_u64)) { + mfunc.pRegs[regIdx] = rhs; + mfunc.pRegs[regIdx].ptyp = node->ptyp; + } else { + mfunc.pRegs[regIdx] = CvtType(rhs, node->ptyp, rhs.ptyp); + } + } + } + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_brfalse: +label_OP_brtrue: + { + CondGotoNode* node = static_cast(stmt); + uint32 labelIdx = node->GetOffset(); (void)labelIdx; + MValue cond = EvalExpr(mfunc, node->GetRHS()); + StmtNode* label = fn->labelMap[labelIdx]; + if (stmt->op == OP_brfalse && IsZero(cond)) stmt = label; + if (stmt->op == OP_brtrue && !IsZero(cond)) stmt = label; + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_label: + // no-op + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_goto: + { + uint32 labelIdx = static_cast(stmt)->GetOffset(); + StmtNode* label = fn->labelMap[labelIdx]; + stmt = label; + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_return: + return caller->retVal0; +label_OP_iassignoff: + { + IassignoffNode* node = static_cast(stmt); + int32 offset = node->GetOffset(); + MValue addr = EvalExpr(mfunc, node->Opnd(0)); + MValue rhs = EvalExpr(mfunc, node->Opnd(1)); + mstore(addr.x.a64 + offset, stmt->ptyp, rhs); + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_blkassignoff: + { + BlkassignoffNode* node = static_cast(stmt); + int32 dstOffset = node->offset; + int32 blkSize = node->blockSize; + MValue dstAddr = EvalExpr(mfunc, node->Opnd(0)); + MValue srcAddr = EvalExpr(mfunc, node->Opnd(1)); + memcpy_s(dstAddr.x.a64 + dstOffset, blkSize, srcAddr.x.a64, blkSize); + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_icallproto: + { + IcallNode *icallproto = static_cast(stmt); + MASSERT(icallproto->NumOpnds() > 0, "icallproto num operands is %ld", icallproto->NumOpnds()); + // alloc stack space for call args + MValue callArgs[icallproto->NumOpnds()-1]; + mfunc.callArgs = callArgs; + mfunc.numCallArgs = icallproto->NumOpnds()-1; + // assume func addr in opnd 0 is from addroffunc + MValue fnAddr = EvalExpr(mfunc, icallproto->Opnd(0)); + FuncAddr *faddr = reinterpret_cast(fnAddr.x.a64); + if (faddr->isLmbcFunc) { + mfunc.CallMapleFuncIndirect(icallproto, faddr->funcPtr.lmbcFunc); + } else { + mfunc.CallExtFuncIndirect(icallproto, faddr->funcPtr.nativeFunc); + } + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_rangegoto: + { + RangeGotoNode *rgoto = static_cast(stmt); + int32 tagOffset = rgoto->GetTagOffset(); + MValue opnd = EvalExpr(mfunc, rgoto->Opnd(0)); + int64 tag = MVal2Int64(opnd); + uint32 labelIdx = rgoto->GetRangeGotoTableItem(tag - tagOffset).second; + StmtNode *label = fn->labelMap[labelIdx]; + stmt = label; + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_igoto: + { + MValue opnd = EvalExpr(mfunc, stmt->Opnd(0)); + StmtNode *label = (StmtNode*)opnd.x.a64; + stmt = label; + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); +label_OP_intrinsiccall: + { + mfunc.CallIntrinsic(*static_cast(stmt)); + } + stmt = stmt->GetNext(); + mfunc.nextStmt = stmt; + goto *(labels[stmt->op]); + +label_OP_dassign: +label_OP_piassign: +label_OP_maydassign: +label_OP_iassign: +label_OP_doloop: +label_OP_dowhile: +label_OP_if: +label_OP_while: +label_OP_switch: +label_OP_multiway: +label_OP_foreachelem: +label_OP_comment: +label_OP_eval: +label_OP_free: +label_OP_calcassertge: +label_OP_calcassertlt: +label_OP_assertge: +label_OP_assertlt: +label_OP_callassertle: +label_OP_returnassertle: +label_OP_assignassertle: +label_OP_abort: +label_OP_assertnonnull: +label_OP_assignassertnonnull: +label_OP_callassertnonnull: +label_OP_returnassertnonnull: +label_OP_dread: +label_OP_iread: +label_OP_addrof: +label_OP_iaddrof: +label_OP_sizeoftype: +label_OP_fieldsdist: +label_OP_array: +label_OP_virtualcall: +label_OP_superclasscall: +label_OP_interfacecall: +label_OP_customcall: +label_OP_polymorphiccall: +label_OP_icall: +label_OP_interfaceicall: +label_OP_virtualicall: +label_OP_intrinsiccallwithtype: +label_OP_xintrinsiccall: +label_OP_callassigned: +label_OP_virtualcallassigned: +label_OP_superclasscallassigned: +label_OP_interfacecallassigned: +label_OP_customcallassigned: +label_OP_polymorphiccallassigned: +label_OP_icallassigned: +label_OP_interfaceicallassigned: +label_OP_virtualicallassigned: +label_OP_intrinsiccallassigned: +label_OP_intrinsiccallwithtypeassigned: +label_OP_xintrinsiccallassigned: +label_OP_callinstant: +label_OP_callinstantassigned: +label_OP_virtualcallinstant: +label_OP_virtualcallinstantassigned: +label_OP_superclasscallinstant: +label_OP_superclasscallinstantassigned: +label_OP_interfacecallinstant: +label_OP_interfacecallinstantassigned: +label_OP_jstry: +label_OP_try: +label_OP_cpptry: +label_OP_throw: +label_OP_jscatch: +label_OP_catch: +label_OP_cppcatch: +label_OP_finally: +label_OP_cleanuptry: +label_OP_endtry: +label_OP_safe: +label_OP_endsafe: +label_OP_unsafe: +label_OP_endunsafe: +label_OP_gosub: +label_OP_retsub: +label_OP_syncenter: +label_OP_syncexit: +label_OP_decref: +label_OP_incref: +label_OP_decrefreset: +label_OP_membaracquire: +label_OP_membarrelease: +label_OP_membarstoreload: +label_OP_membarstorestore: +label_OP_ireadoff: +label_OP_ireadfpoff: +label_OP_regread: +label_OP_addroffunc: +label_OP_addroflabel: +label_OP_constval: +label_OP_conststr: +label_OP_conststr16: +label_OP_ceil: +label_OP_cvt: +label_OP_floor: +label_OP_retype: +label_OP_round: +label_OP_trunc: +label_OP_abs: +label_OP_bnot: +label_OP_lnot: +label_OP_neg: +label_OP_recip: +label_OP_sqrt: +label_OP_sext: +label_OP_zext: +label_OP_alloca: +label_OP_malloc: +label_OP_gcmalloc: +label_OP_gcpermalloc: +label_OP_stackmalloc: +label_OP_gcmallocjarray: +label_OP_gcpermallocjarray: +label_OP_stackmallocjarray: +label_OP_resolveinterfacefunc: +label_OP_resolvevirtualfunc: +label_OP_add: +label_OP_sub: +label_OP_mul: +label_OP_div: +label_OP_rem: +label_OP_ashr: +label_OP_lshr: +label_OP_shl: +label_OP_ror: +label_OP_max: +label_OP_min: +label_OP_band: +label_OP_bior: +label_OP_bxor: +label_OP_CG_array_elem_add: +label_OP_eq: +label_OP_ge: +label_OP_gt: +label_OP_le: +label_OP_lt: +label_OP_ne: +label_OP_cmp: +label_OP_cmpl: +label_OP_cmpg: +label_OP_land: +label_OP_lior: +label_OP_cand: +label_OP_cior: +label_OP_select: +label_OP_intrinsicop: +label_OP_intrinsicopwithtype: +label_OP_extractbits: +label_OP_depositbits: +label_OP_iassignpcoff: +label_OP_ireadpcoff: +label_OP_checkpoint: +label_OP_addroffpc: +label_OP_asm: +label_OP_dreadoff: +label_OP_addrofoff: +label_OP_dassignoff: +label_OP_iassignspoff: +label_OP_icallprotoassigned: + { + MASSERT(false, "NIY"); + for(;;); + } + return retVal; +} + +MValue EvalExpr(MFunction& func, BaseNode* expr, ParmInf *parm) { + MValue res; + + static void* const labels[] = { + &&label_OP_Undef, +#define OPCODE(base_node,dummy1,dummy2,dummy3) &&label_OP_##base_node, +#include "opcodes.def" +#undef OPCODE + &&label_OP_Undef + }; + + goto *(labels[expr->op]); +label_OP_Undef: + { + MASSERT(false, "Hit OP_undef"); + } +label_OP_constval: + { + MIRConst* constval = static_cast(expr)->GetConstVal(); + int64 constInt = 0; + float constFloat = 0; + double constDouble = 0; + switch (constval->GetKind()) { + case kConstInt: + constInt = static_cast(constval)->GetExtValue(); + break; + case kConstDoubleConst: + constDouble = static_cast(constval)->GetValue(); + break; + case kConstFloatConst: + constFloat = static_cast(constval)->GetValue(); + break; + default: + MASSERT(false, "constval kind %d NYI", constval->GetKind()); + break; + } + PrimType ptyp = expr->ptyp; + switch (ptyp) { + case PTY_i8: + case PTY_i16: + case PTY_i32: + case PTY_i64: + MASSERT(constval->GetKind() == kConstInt, "ptyp and constval kind mismatch"); + res.x.i64 = constInt; + res.ptyp = ptyp; + break; + case PTY_u8: + case PTY_u16: + case PTY_u32: + case PTY_u64: + case PTY_a64: + MASSERT(constval->GetKind() == kConstInt, "ptyp and constval kind mismatch"); + res.x.u64 = constInt; + res.ptyp = ptyp; + break; + case PTY_f32: + MASSERT(constval->GetKind() == kConstFloatConst, "ptyp and constval kind mismatch"); + res.x.f32 = constFloat; + res.ptyp = ptyp; + break; + case PTY_f64: + MASSERT(constval->GetKind() == kConstDoubleConst, "constval ptyp and kind mismatch"); + res.x.f64 = constDouble; + res.ptyp = ptyp; + break; + default: + MASSERT(false, "ptype %d for constval NYI", ptyp); + break; + } + } + goto _exit; + +label_OP_add: + { + MValue op0 = EvalExpr(func, expr->Opnd(0)); + MValue op1 = EvalExpr(func, expr->Opnd(1)); + switch (expr->ptyp) { + case PTY_i8: res.x.i8 = op0.x.i8 + op1.x.i8; break; + case PTY_i16: res.x.i16 = op0.x.i16 + op1.x.i16; break; + case PTY_i32: res.x.i32 = (int64)op0.x.i32 + (int64)op1.x.i32; break; + case PTY_i64: res.x.i64 = (uint64)op0.x.i64 + (uint64)op1.x.i64; break; + case PTY_u8: res.x.u8 = op0.x.u8 + op1.x.u8; break; + case PTY_u16: res.x.u16 = op0.x.u16 + op1.x.u16; break; + case PTY_u32: res.x.u32 = op0.x.u32 + op1.x.u32; break; + case PTY_u64: res.x.u64 = op0.x.u64 + op1.x.u64; break; + case PTY_a64: res.x.u64 = op0.x.u64 + op1.x.u64; break; + case PTY_f32: res.x.f32 = op0.x.f32 + op1.x.f32; break; + case PTY_f64: res.x.f64 = op0.x.f64 + op1.x.f64; break; + default: MIR_FATAL("Unsupported PrimType %d for binary operator %s", expr->ptyp, "+"); + } + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_sub: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRBINOP(-, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_mul: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRBINOP(*, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_div: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRBINOP(/, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_regread: + { + PregIdx regIdx = static_cast(expr)->GetRegIdx(); + switch (regIdx) { + case -(kSregFp): + MASSERT(expr->ptyp == PTY_a64, "regread %%FP with wrong ptyp %d", expr->ptyp); + res.x.a64 = func.fp; + break; + case -(kSregRetval0): + if (expr->ptyp == func.retVal0.ptyp) { + res = func.retVal0; + } else if (expr->ptyp == PTY_agg || expr->ptyp == PTY_u64) { + res = func.retVal0; + } else { + res = CvtType(func.retVal0, expr->ptyp, func.retVal0.ptyp); + } + break; + case -(kSregRetval1): + MASSERT(expr->ptyp == func.retVal1.ptyp || + (expr->ptyp == PTY_agg || expr->ptyp == PTY_u64), + "regread %%retVal0 type mismatch: %d %d", expr->ptyp, func.retVal1.ptyp); + res = func.retVal1; + break; + case -(kSregGp): + MASSERT(expr->ptyp == PTY_a64, "regread %%GP with wrong ptyp %d", expr->ptyp); + res.x.a64 = func.info->lmbcMod->unInitPUStatics; + break; + default: + MASSERT(regIdx < func.info->numPregs, "regread regIdx %d out of bound", regIdx); + res = func.pRegs[regIdx]; + break; + } + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_conststr: + { + UStrIdx ustrIdx = static_cast(expr)->GetStrIdx(); + auto it = func.info->lmbcMod->globalStrTbl.insert( + std::pair(ustrIdx, GlobalTables::GetUStrTable().GetStringFromStrIdx(ustrIdx))); + res.x.ptr = const_cast(it.first->second.c_str()); + res.ptyp = PTY_a64; + goto _exit; + } +label_OP_ireadfpoff: + { + IreadFPoffNode* node = static_cast(expr); + int32 offset = node->GetOffset(); + if (node->ptyp != PTY_agg) { + mload(func.fp+offset, expr->ptyp, res); + goto _exit; + } + // handle PTY_agg + // ireadfpoff agg should be opnd from either call or return, i.e. either + // - caller: call &foo (ireadfpoff agg -16, ireadfpoff agg -28) + // - callee: regassign agg %%retval0 (ireadfpoff agg -12) + // so set agg size in mvalue result with agg size from corresponding func formal or func return, and + // - if from caller, read agg into caller allocated buffer for agg and return the pointer in an mvalue to be passed to callee + // - if from callee, just pass fp offset ptr in an mvalue and regassign will copy it to caller's retval0/1 area + if (func.nextStmt->op == OP_call) { // caller + // check if calling external func: + MASSERT(func.aggrArgsBuf != nullptr, "aggrArgsBuf is null"); + memcpy_s(func.aggrArgsBuf+parm->storeIdx, parm->size, func.fp+offset, parm->size); + mload(func.aggrArgsBuf+parm->storeIdx, expr->ptyp, res, parm->size); + } else { // callee + mload(func.fp+offset, expr->ptyp, res, func.info->retSize); + } + goto _exit; + } +label_OP_ireadoff: + { + int32 offset = static_cast(expr)->GetOffset(); + MValue rhs = EvalExpr(func, static_cast(expr)->Opnd(0)); + if (expr->ptyp == PTY_agg) { + // ireadoff agg should be operand for either call or return (like ireadfpoff) + // - caller: call &f (ireadoff agg 0 (regread a64 %1)) + // - callee: regassign agg %%retval0 (ireadoff agg 0 (addrofoff a64 $x 0)) + MASSERT(rhs.ptyp == PTY_a64, "ireadoff agg RHS not PTY_agg"); + if (func.nextStmt->op == OP_call) { + MASSERT(func.aggrArgsBuf != nullptr, "aggrArgsBuf is null"); + memcpy_s(func.aggrArgsBuf+parm->storeIdx, parm->size, rhs.x.a64 + offset, parm->size); + mload(func.aggrArgsBuf+parm->storeIdx, expr->ptyp, res, parm->size); + } else { + MASSERT(func.nextStmt->op == OP_regassign, "ireadoff agg not used as regassign agg opnd"); + mload(rhs.x.a64 + offset, expr->ptyp, res, func.info->retSize); + } + goto _exit; + } + MASSERT(rhs.ptyp == PTY_a64 || rhs.ptyp == PTY_u64 || rhs.ptyp == PTY_i64, + "ireadoff rhs ptyp %d not PTY_a64 or PTY_u64", rhs.ptyp); + mload(rhs.x.a64+offset, expr->ptyp, res); + goto _exit; + } +label_OP_iread: + { + MASSERT(func.nextStmt->op == OP_call && expr->ptyp == PTY_agg, "iread unexpected outside call"); + MValue addr = EvalExpr(func, expr->Opnd(0)); + MASSERT(func.aggrArgsBuf != nullptr, "aggrArgsBuf is null"); + memcpy_s(func.aggrArgsBuf+parm->storeIdx, parm->size, addr.x.a64, parm->size); + mload(func.aggrArgsBuf+parm->storeIdx, expr->ptyp, res, parm->size); + goto _exit; + } +label_OP_eq: + { + PrimType opndType = static_cast(expr)->GetOpndType(); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + if (opndType == PTY_f32 || opndType == PTY_f64) { + res.ptyp = expr->ptyp; + HandleFloatEq(expr->op, opndType, res, opnd0, opnd1); + } else { + EXPRCOMPOPNOFLOAT(==, res, opnd0, opnd1, opndType, expr->ptyp); + } + goto _exit; + } +label_OP_ne: + { + PrimType opndType = static_cast(expr)->GetOpndType(); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + if (opndType == PTY_f32 || opndType == PTY_f64) { + res.ptyp = expr->ptyp; + HandleFloatEq(expr->op, opndType, res, opnd0, opnd1); + } else { + EXPRCOMPOPNOFLOAT(!=, res, opnd0, opnd1, opndType, expr->ptyp); + } + goto _exit; + } +label_OP_gt: + { + PrimType opndTyp= static_cast(expr)->GetOpndType(); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRCOMPOP(>, res, opnd0, opnd1, opndTyp, expr->ptyp); + goto _exit; + } +label_OP_ge: + { + PrimType opndTyp= static_cast(expr)->GetOpndType(); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRCOMPOP(>=, res, opnd0, opnd1, opndTyp, expr->ptyp); + goto _exit; + } +label_OP_lt: + { + PrimType opndTyp= static_cast(expr)->GetOpndType(); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRCOMPOP(<, res, opnd0, opnd1, opndTyp, expr->ptyp); + goto _exit; + } +label_OP_le: + { + PrimType opndTyp= static_cast(expr)->GetOpndType(); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRCOMPOP(<=, res, opnd0, opnd1, opndTyp, expr->ptyp); + goto _exit; + } +label_OP_select: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + MValue opnd2 = EvalExpr(func, expr->Opnd(2)); + EXPRSELECTOP(res, opnd0, opnd1, opnd2, expr->ptyp); + goto _exit; + } +label_OP_band: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRBININTOP(&, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_bior: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRBININTOP(|, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_bxor: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRBININTOP(^, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_lshr: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue numBits = EvalExpr(func, expr->Opnd(1)); + EXPRBININTOPUNSIGNED(>>, res, opnd0, numBits, expr->ptyp); + goto _exit; + } +label_OP_ashr: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue numBits = EvalExpr(func, expr->Opnd(1)); + EXPRBININTOP(>>, res, opnd0, numBits, expr->ptyp); + goto _exit; + } +label_OP_shl: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue numBits = EvalExpr(func, expr->Opnd(1)); + EXPRBININTOP(<<, res, opnd0, numBits, expr->ptyp); + goto _exit; + } +label_OP_bnot: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + EXPRUNROP(~, res, opnd0, expr->ptyp); + goto _exit; + } +label_OP_lnot: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + EXPRUNROP(!, res, opnd0, expr->ptyp); + goto _exit; + } +label_OP_neg: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + switch (expr->ptyp) { + case PTY_i8: res.x.i8 = -opnd0.x.i8; break; + case PTY_i16: res.x.i16 = -opnd0.x.i16; break; + case PTY_i32: res.x.i32 = ~(uint32)opnd0.x.i32+1; break; + case PTY_i64: res.x.i64 = -opnd0.x.i64; break; + case PTY_u8: res.x.u8 = -opnd0.x.u8; break; + case PTY_u16: res.x.u16 = -opnd0.x.u16; break; + case PTY_u32: res.x.u32 = -opnd0.x.u32; break; + case PTY_u64: res.x.u64 = -opnd0.x.u64; break; + case PTY_f32: res.x.f32 = -opnd0.x.f32; break; + case PTY_f64: res.x.f64 = -opnd0.x.f64; break; + default: MIR_FATAL("Unsupported PrimType %d for unary operator %s", expr->ptyp, "OP_neg"); + } + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_abs: + { + MValue op0 = EvalExpr(func, expr->Opnd(0)); + switch (expr->ptyp) { + // abs operand must be signed + case PTY_i8: res.x.i8 = abs(op0.x.i8); break; + case PTY_i16: res.x.i16 = abs(op0.x.i16); break; + case PTY_i32: res.x.i32 = abs(op0.x.i32); break; + case PTY_i64: res.x.i64 = abs(op0.x.i64); break; + case PTY_f32: res.x.f32 = fabsf(op0.x.f32); break; + case PTY_f64: res.x.f64 = fabs(op0.x.f64); break; + default: MASSERT(false, "op_abs unsupported type %d", expr->ptyp); + } + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_min: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRMAXMINOP(<, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_max: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRMAXMINOP(>, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_rem: + { + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + EXPRREMOP(%, res, opnd0, opnd1, expr->ptyp); + goto _exit; + } +label_OP_cvt: + { + PrimType toPtyp = expr->ptyp; + PrimType fromPtyp = static_cast(expr)->FromType(); + MValue opnd = EvalExpr(func, expr->Opnd(0)); + res = CvtType(opnd, toPtyp, fromPtyp); + goto _exit; + } +label_OP_addrofoff: + { + // get addr of var symbol which can be formal/global/extern/PUStatic + int32 offset = static_cast(expr)->offset; + StIdx stidx = static_cast(expr)->stIdx; + uint8 *addr; + + if (stidx.Islocal()) { // local sym can only be formals or PUstatic + addr = func.GetFormalVarAddr(stidx); + if (!addr) { + addr = func.info->lmbcMod->GetVarAddr(func.info->mirFunc->GetPuidx(), stidx); + } + MASSERT(addr, "addrofoff can not find local var"); + } else { + MASSERT(stidx.IsGlobal(), "addrofoff: symbol neither local nor global"); + MIRSymbol* var = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); + switch (var->GetStorageClass()) { + case kScExtern: + addr = (uint8 *)(func.info->lmbcMod->FindExtSym(stidx)); + break; + case kScGlobal: + case kScFstatic: + addr = func.info->lmbcMod->GetVarAddr(var->GetStIdx()); + break; + default: + MASSERT(false, "addrofoff: storage class %d NYI", var->GetStorageClass()); + break; + } + } + res.x.a64 = addr + offset; + res.ptyp = PTY_a64; + goto _exit; + } +label_OP_alloca: + { + MValue opnd = EvalExpr(func, expr->Opnd(0)); + res.ptyp = PTY_a64; + res.x.a64 = func.Alloca(opnd.x.u64); + goto _exit; + } +label_OP_addroffunc: + { + FuncAddr *faddr = func.info->lmbcMod->GetFuncAddr(static_cast(expr)->GetPUIdx()); + res.x.a64 = (uint8*)faddr; + res.ptyp = PTY_a64; + goto _exit; + } +label_OP_addroflabel: + { + AddroflabelNode *node = static_cast(expr); + LabelIdx labelIdx = node->GetOffset(); + StmtNode *label = func.info->labelMap[labelIdx]; + res.x.a64 = reinterpret_cast(label); + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_retype: + { + res = EvalExpr(func, expr->Opnd(0)); + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_sext: + { + ExtractbitsNode *ext = static_cast(expr); + uint8 bOffset = ext->GetBitsOffset(); + uint8 bSize = ext->GetBitsSize(); + MASSERT(bOffset == 0, "sext unexpected offset"); + uint64 mask = bSize < k64BitSize ? (1ull << bSize) - 1 : ~0ull; + res = EvalExpr(func, expr->Opnd(0)); + res.x.i64 = (((uint64)res.x.i64 >> (bSize - 1)) & 1ull) ? res.x.i64 | ~mask : res.x.i64 & mask; + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_zext: + { + ExtractbitsNode *ext = static_cast(expr); + uint8 bOffset = ext->GetBitsOffset(); + uint8 bSize = ext->GetBitsSize(); + MASSERT(bOffset == 0, "zext unexpected offset"); + uint64 mask = bSize < k64BitSize ? (1ull << bSize) - 1 : ~0ull; + res = EvalExpr(func, expr->Opnd(0)); + res.x.i64 &= mask; + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_extractbits: + { + ExtractbitsNode *ebits = static_cast(expr); + uint8 bOffset = ebits->GetBitsOffset(); + uint8 bSize = ebits->GetBitsSize(); + uint64 mask = ((1ull << bSize) - 1) << bOffset; + res = EvalExpr(func, expr->Opnd(0)); + res.x.i64 = (uint64)(res.x.i64 & mask) >> bOffset; + if (IsSignedInteger(expr->ptyp)) { + mask = (1ull << bSize) - 1; + res.x.i64 = (((uint64)res.x.i64 >> (bSize - 1)) & 1ull) ? res.x.i64 | ~mask : res.x.i64 & mask; + } + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_depositbits: + { + DepositbitsNode *dbits = static_cast(expr); + MValue opnd0 = EvalExpr(func, expr->Opnd(0)); + MValue opnd1 = EvalExpr(func, expr->Opnd(1)); + uint64 mask = ~(0xffffffffffffffff << dbits->GetBitsSize()); + uint64 from = (opnd1.x.u64 & mask) << dbits->GetBitsOffset(); + mask = mask << dbits->GetBitsOffset(); + res.x.u64 = (opnd0.x.u64 & ~(mask)) | from; + res.ptyp = expr->ptyp; + goto _exit; + } +label_OP_intrinsicop: + { + auto *intrnop = static_cast(expr); + MValue op0 = EvalExpr(func, expr->Opnd(0)); + res.ptyp = expr->ptyp; + switch (intrnop->GetIntrinsic()) { + case INTRN_C_sin: + if (expr->ptyp == PTY_f32) { + res.x.f32 = sin(op0.x.f32); + } else if (expr->ptyp == PTY_f64) { + res.x.f64 = sin(op0.x.f64); + } + break; + case INTRN_C_ctz32: + if (expr->ptyp == PTY_u32 || expr->ptyp == PTY_i32) { + res.x.u32 = __builtin_ctz(op0.x.u32); + } + break; + case INTRN_C_clz32: + if (expr->ptyp == PTY_u32 || expr->ptyp == PTY_i32) { + res.x.u32 = __builtin_clz(op0.x.u32); + } + break; + case INTRN_C_ffs: + if (expr->ptyp == PTY_u32 || expr->ptyp == PTY_i32) { + res.x.u32 = __builtin_ffs(op0.x.u32); + } + break; + case INTRN_C_rev_4: + if (expr->ptyp == PTY_u32 || expr->ptyp == PTY_i32) { + res.x.u32 = __builtin_bitreverse32(op0.x.u32); + } + break; + default: + break; + } + goto _exit; + } + + // unsupported opcodes +label_OP_dassign: +label_OP_piassign: +label_OP_maydassign: +label_OP_iassign: +label_OP_block: +label_OP_doloop: +label_OP_dowhile: +label_OP_if: +label_OP_while: +label_OP_switch: +label_OP_multiway: +label_OP_foreachelem: +label_OP_comment: +label_OP_eval: +label_OP_free: +label_OP_calcassertge: +label_OP_calcassertlt: +label_OP_assertge: +label_OP_assertlt: +label_OP_callassertle: +label_OP_returnassertle: +label_OP_assignassertle: +label_OP_abort: +label_OP_assertnonnull: +label_OP_assignassertnonnull: +label_OP_callassertnonnull: +label_OP_returnassertnonnull: +label_OP_dread: +label_OP_addrof: +label_OP_iaddrof: +label_OP_sizeoftype: +label_OP_fieldsdist: +label_OP_array: +label_OP_iassignoff: +label_OP_iassignfpoff: +label_OP_regassign: +label_OP_goto: +label_OP_brfalse: +label_OP_brtrue: +label_OP_return: +label_OP_rangegoto: +label_OP_call: +label_OP_virtualcall: +label_OP_superclasscall: +label_OP_interfacecall: +label_OP_customcall: +label_OP_polymorphiccall: +label_OP_icall: +label_OP_interfaceicall: +label_OP_virtualicall: +label_OP_intrinsiccall: +label_OP_intrinsiccallwithtype: +label_OP_xintrinsiccall: +label_OP_callassigned: +label_OP_virtualcallassigned: +label_OP_superclasscallassigned: +label_OP_interfacecallassigned: +label_OP_customcallassigned: +label_OP_polymorphiccallassigned: +label_OP_icallassigned: +label_OP_interfaceicallassigned: +label_OP_virtualicallassigned: +label_OP_intrinsiccallassigned: +label_OP_intrinsiccallwithtypeassigned: +label_OP_xintrinsiccallassigned: +label_OP_callinstant: +label_OP_callinstantassigned: +label_OP_virtualcallinstant: +label_OP_virtualcallinstantassigned: +label_OP_superclasscallinstant: +label_OP_superclasscallinstantassigned: +label_OP_interfacecallinstant: +label_OP_interfacecallinstantassigned: +label_OP_jstry: +label_OP_try: +label_OP_cpptry: +label_OP_throw: +label_OP_jscatch: +label_OP_catch: +label_OP_cppcatch: +label_OP_finally: +label_OP_cleanuptry: +label_OP_endtry: +label_OP_safe: +label_OP_endsafe: +label_OP_unsafe: +label_OP_endunsafe: +label_OP_gosub: +label_OP_retsub: +label_OP_syncenter: +label_OP_syncexit: +label_OP_decref: +label_OP_incref: +label_OP_decrefreset: +label_OP_membaracquire: +label_OP_membarrelease: +label_OP_membarstoreload: +label_OP_membarstorestore: +label_OP_label: +label_OP_conststr16: +label_OP_ceil: +label_OP_floor: +label_OP_round: +label_OP_trunc: +label_OP_recip: +label_OP_sqrt: +label_OP_malloc: +label_OP_gcmalloc: +label_OP_gcpermalloc: +label_OP_stackmalloc: +label_OP_gcmallocjarray: +label_OP_gcpermallocjarray: +label_OP_stackmallocjarray: +label_OP_resolveinterfacefunc: +label_OP_resolvevirtualfunc: +label_OP_ror: +label_OP_CG_array_elem_add: +label_OP_cmp: +label_OP_cmpl: +label_OP_cmpg: +label_OP_land: +label_OP_lior: +label_OP_cand: +label_OP_cior: +label_OP_intrinsicopwithtype: +label_OP_iassignpcoff: +label_OP_ireadpcoff: +label_OP_checkpoint: +label_OP_addroffpc: +label_OP_igoto: +label_OP_asm: +label_OP_dreadoff: +label_OP_dassignoff: +label_OP_iassignspoff: +label_OP_blkassignoff: +label_OP_icallproto: +label_OP_icallprotoassigned: + { + MASSERT(false, "NIY"); + } + +_exit: + return res; +} + +} // namespace maple diff --git a/src/MapleEng/lmbc/src/load_store.cpp b/src/MapleEng/lmbc/src/load_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d5ccd611e2f43be429c121d0013fd3f6b598082a --- /dev/null +++ b/src/MapleEng/lmbc/src/load_store.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 "mvalue.h" +#include "mfunction.h" +#include "massert.h" + +namespace maple { + +void mload(uint8* addr, PrimType ptyp, MValue& res, size_t aggSize) { + res.ptyp = ptyp; + switch (ptyp) { + case PTY_i8: + res.x.i64 = *(int8 *)addr; + return; + case PTY_i16: + res.x.i64 = *(int16 *)addr; + return; + case PTY_i32: + res.x.i64 = *(int32 *)addr; + return; + case PTY_i64: + res.x.i64 = *(int64 *)addr; + return; + case PTY_u8: + res.x.u64 = *(uint8 *)addr; + return; + case PTY_u16: + res.x.u64 = *(uint16 *)addr; + return; + case PTY_u32: + res.x.u64 = *(uint32 *)addr; + return; + case PTY_u64: + res.x.u64 = *(uint64 *)addr; + return; + case PTY_f32: + res.x.f32 = *(float *)addr; + return; + case PTY_f64: + res.x.f64 = *(double *)addr; + return; + case PTY_a64: + res.x.a64 = *(uint8 **)addr; + return; + case PTY_agg: + res.x.a64 = addr; + res.aggSize = aggSize; // agg size + return; + default: + MASSERT(false, "mload ptyp %d NYI", ptyp); + break; + } +} + +void mstore(uint8* addr, PrimType ptyp, MValue& val, bool toVarArgStack) { + if (!IsPrimitiveInteger(ptyp) || !IsPrimitiveInteger(val.ptyp)) { + MASSERT(ptyp == val.ptyp || + ptyp == PTY_a64 && val.ptyp == PTY_u64 || + ptyp == PTY_u64 && val.ptyp == PTY_a64, + "mstore type mismatch: %d and %d", ptyp, val.ptyp); + } + switch (ptyp) { + case PTY_i8: + *(int8 *)addr = val.x.i8; + return; + case PTY_i16: + *(int16 *)addr = val.x.i16; + return; + case PTY_i32: + *(int32 *)addr = val.x.i32; + return; + case PTY_i64: + *(int64 *)addr = val.x.i64; + return; + case PTY_u8: + *(uint8 *)addr = val.x.u8; + return; + case PTY_u16: + *(uint16 *)addr = val.x.u16; + return; + case PTY_u32: + *(uint32 *)addr = val.x.u32; + return; + case PTY_u64: + *(uint64 *)addr = val.x.u64; + return; + case PTY_f32: + *(float *)addr = val.x.f32; + return; + case PTY_f64: + *(double *)addr = val.x.f64; + return; + case PTY_a64: + *(uint8 **)addr = val.x.a64; + return; + case PTY_agg: + if (toVarArgStack) { + if (val.aggSize > maplebe::k16ByteSize) { + *(uint8 **)addr = val.x.a64; + } else { + memcpy_s(addr, val.aggSize, val.x.a64, val.aggSize); + } + } else { + // val holds aggr data (regassign agg of <= 16 bytes to %%retval0) instead of ptr to aggr data + MASSERT(val.aggSize <= 16, "mstore agg > 16"); + memcpy_s(addr, val.aggSize, &(val.x.u64), val.aggSize); + } + return; + default: + MASSERT(false, "mstore ptyp %d NYI", ptyp); + break; + } +} + +} // namespace maple diff --git a/src/MapleEng/lmbc/src/mfunction.cpp b/src/MapleEng/lmbc/src/mfunction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9d274c2b3d4da923d27ede78a4bee84ef5fc4044 --- /dev/null +++ b/src/MapleEng/lmbc/src/mfunction.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 +#include "mfunction.h" +#include "mprimtype.h" +#include "massert.h" + +namespace maple { + +MFunction::MFunction(LmbcFunc *funcInfo, + MFunction *funcCaller, + uint8 *autoVars, + MValue *pregs, + MValue *formalvars) : info(funcInfo), + caller(funcCaller), + frame(autoVars), + pRegs(pregs), + formalVars(formalvars), + callArgs(nullptr), + aggrArgsBuf(nullptr) { + numCallArgs = 0; + nextStmt = info->mirFunc->GetBody(); + fp = (uint8*)frame + info->frameSize; + allocaOffset = 0; + allocaMem = nullptr; +} + +MFunction::~MFunction() { } + +uint8 *MFunction::Alloca(uint32 sz) { + if (allocaOffset + sz > ALLOCA_MEMMAX) { + return nullptr; + } + uint8 *ptr = allocaMem + allocaOffset; + allocaOffset += sz; + return ptr; +} + +uint8 *MFunction::GetFormalVarAddr(StIdx stidx) { + auto it = info->stidx2Parm.find(stidx.FullIdx()); + if (it == info->stidx2Parm.end()) { + return nullptr; + } + if (it->second->ptyp == PTY_agg) { + MASSERT(caller->aggrArgsBuf, "aggrArgsBuf not init"); + return caller->aggrArgsBuf + it->second->storeIdx; + } + return((uint8*)&formalVars[it->second->storeIdx].x); +} + +bool IsExtFunc(PUIdx puIdx, LmbcMod& module) { + MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puIdx); + if (func->IsExtern() || // ext func with proto + func->GetAttr(FUNCATTR_implicit) || // ext func with no proto + !func->GetBody() || // func with no body + (func->IsWeak() && module.FindExtFunc(puIdx))) { + return true; + } + return false; +} + +// Return size (roundup to 8 byte multiples) of aggregate returned by an iread. +size_t GetIReadAggrSize(BaseNode* expr) { + MASSERT(expr->op == OP_iread && expr->ptyp == PTY_agg, "iread on non PTY_agg type"); + IreadNode *iread = static_cast(expr); + TyIdx ptrTyIdx = iread->GetTyIdx(); + MIRPtrType *ptrType = + static_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrTyIdx)); + MIRType *aggType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(ptrType->GetPointedTyIdx()); + FieldID fd = iread->GetFieldID(); + size_t sz = aggType->GetSize(); + if (fd != 0) { + MIRStructType *structType = static_cast(aggType); + MIRType *fdType = structType->GetFieldType(fd); + uint32 fdOffset = structType->GetBitOffsetFromBaseAddr(fd); + sz = fdType->GetSize(); + (void)fdOffset; + } + return ((sz + maplebe::k8ByteSize-1) >> maplebe::k8BitShift) << maplebe::k8BitShift; +} + +// Get total buffer size needed for all arguments of type PTY_agg in a call. +// This includes all type PTY_agg formal args and va-args (if any). +size_t GetAggCallArgsSize(LmbcFunc *callee, CallNode *call) { + size_t totalAggCallArgsSize = callee->formalsAggSize; + if (callee->isVarArgs) { + for (int i = callee->formalsNum; i < call->NumOpnds(); i++) { // PTY_agg va-args + if (call->Opnd(i)->ptyp == PTY_agg) { + MASSERT(call->Opnd(i)->op == OP_iread, "agg var arg unexpected op"); + totalAggCallArgsSize += GetIReadAggrSize(call->Opnd(i)); + } + } + } + return totalAggCallArgsSize; +} + +// Caller passes arguments to callees using MValues which is a union of Maple +// prim types. For PTY_agg, MValue holds ptr to the aggregate data. +// Memory allocation scenarios for call arguments: +// 1. Non-varidiac callee +// - Caller alloca array of MValue to pass call operands to callee +// - If any call arg is PTY_agg +// - Caller alloca agg buffer to hold data for all args of type PTY_agg +// - MValues for all args of type PTY_agg points to offsets in agg buffer +// 2. Varidiac callee +// - Caller alloca array of MValue to pass call operands including va-arg ones to callee +// - If any call arg is PTY_agg +// - Caller alloca agg buffer to hold data for all args (formals+va_args) of type PTY_agg +// - MValues of all args of type PTY_agg points to offsets in agg buffer +// - Caller alloca arg stack per AARCH64 ABI for va-args and copy va-args to this arg stack +void MFunction::CallMapleFuncDirect(CallNode *call) { + LmbcFunc *callee = info->lmbcMod->LkupLmbcFunc(call->GetPUIdx()); + if (!callee->formalsNum) { // ignore args if callee takes no params + InvokeFunc(callee, this); + return; + } + // alloca stack space for aggr args before evaluating operands + size_t totalAggCallArgsSize = GetAggCallArgsSize(callee, call); + uint8 buf[totalAggCallArgsSize]; + aggrArgsBuf = buf; // stack alloc for aggr args + for (int i = 0, sz = 0, offset = callee->formalsAggSize; i < call->NumOpnds(); i++) { + // a non-aggregate arg + if (call->Opnd(i)->ptyp != PTY_agg) { + callArgs[i] = EvalExpr(*this, call->Opnd(i)); + continue; + } + // an aggregate formal arg + if (i < callee->formalsNum) { + callArgs[i] = EvalExpr(*this, call->Opnd(i), callee->pos2Parm[i]); + continue; + } + // an aggregate var-arg + sz = GetIReadAggrSize(call->Opnd(i)); + ParmInf parmInf(PTY_agg, sz, false, offset); + offset += sz; + callArgs[i] = EvalExpr(*this, call->Opnd(i), &parmInf); + } + if (callee->isVarArgs) { + CallVaArgFunc(call->NumOpnds(), callee); + } else { + InvokeFunc(callee, this); + } +} + +void MFunction::CallMapleFuncIndirect(IcallNode *icall, LmbcFunc *callInfo) { + if (!callInfo->formalsNum) { // ignore caller args if callee has no formals + InvokeFunc(callInfo, this); + return; + } + + // Set up call args - skip over 1st arg, which is addr of func to call + uint8 buf[callInfo->formalsAggSize]; + aggrArgsBuf = buf; + for (int i = 0; i < icall->NumOpnds() - 1; i++) { + callArgs[i] = (icall->Opnd(i+1)->ptyp == PTY_agg) ? + EvalExpr(*this, icall->Opnd(i+1), callInfo->pos2Parm[i]) : + EvalExpr(*this, icall->Opnd(i+1)); + } + if (callInfo->isVarArgs) { + CallVaArgFunc(icall->NumOpnds()-1, callInfo); + } else { + InvokeFunc(callInfo, this); + } +} + +// Maple front end generates Maple IR in varidiac functions to +// use target ABI va_list to access va-args. For the caller, this +// function sets up va-args in a stack buffer which is passed to +// the variadic callee in va_list fields (stack field in aarch64 +// valist, or overflow_arg_area field in x86_64 valist): +// - Calc size of stack to emulate va-args stack in ABI +// - Alloca va-args stack and copy args to the stack +// - For vaArg up to 16 bytes, copy data directly to vaArg stack +// - For vaArg larger than 16 bytes, put pointer to data in vaArg stack +// - On a va_start intrinsic, the va-args stack addr in caller.vaArgs +// is saved in corresponding vaList field for va-arg access by callee. +void MFunction::CallVaArgFunc(int numArgs, LmbcFunc *callInfo) { + uint32 vArgsSz = 0; + for (int i = callInfo->formalsNum; i < numArgs; ++i) { + if (callArgs[i].ptyp != PTY_agg || callArgs[i].aggSize > maplebe::k16ByteSize) { + vArgsSz += maplebe::k8ByteSize; + } else { + vArgsSz += callArgs[i].aggSize; + } + } + vaArgsSize = vArgsSz; + uint8 buf[vaArgsSize]; + vaArgs = buf; + for (int i = callInfo->formalsNum, offset = 0; i < numArgs; ++i) { + mstore(vaArgs + offset, callArgs[i].ptyp, callArgs[i], true); + if (callArgs[i].ptyp != PTY_agg || callArgs[i].aggSize > maplebe::k16ByteSize) { + offset += maplebe::k8ByteSize; + } else { + offset += callArgs[i].aggSize; + } + } + InvokeFunc(callInfo, this); +} + +void MFunction::CallExtFuncDirect(CallNode* call) { + MIRFunction *func = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(call->GetPUIdx()); + MapleVector &formalDefVec = func->GetFormalDefVec(); + FuncAddr& faddr = *info->lmbcMod->GetFuncAddr(call->GetPUIdx()); + ffi_fp_t fp = (ffi_fp_t)(faddr.funcPtr.nativeFunc); + MASSERT(fp, "External function not found"); + + for (int i = formalDefVec.size(); i < call->NumOpnds(); i++) { + if (call->Opnd(i)->ptyp == PTY_agg) { + MASSERT(false, "extern func: va-arg of agg type NYI"); + } + } + // alloca stack space for aggr args before evaluating operands + uint8 buf[faddr.formalsAggSize]; + aggrArgsBuf = buf; + for (int i = 0, offset = 0; i < call->NumOpnds(); i++) { + // a non-aggregate arg + if (call->Opnd(i)->ptyp != PTY_agg) { + callArgs[i] = EvalExpr(*this, call->Opnd(i)); + continue; + } + // an aggregate formal arg + if (i < formalDefVec.size()) { + MIRType* ty = GlobalTables::GetTypeTable().GetTypeFromTyIdx(formalDefVec[i].formalTyIdx); + MASSERT(ty->GetPrimType() == PTY_agg, "expects formal arg of agg type"); + ParmInf parmInf(PTY_agg, ty->GetSize(), false, offset); + offset += ty->GetSize(); + callArgs[i] = EvalExpr(*this, call->Opnd(i), &parmInf); + continue; + } + } + CallWithFFI(func->GetReturnType()->GetPrimType(), fp); +} + +void MFunction::CallExtFuncIndirect(IcallNode *icallproto, void* fp) { + for (int i = 0; i < icallproto->NumOpnds() - 1; i++) { + callArgs[i]= EvalExpr(*this, icallproto->Opnd(i+1)); + } + MIRType *type = GlobalTables::GetTypeTable().GetTypeFromTyIdx(icallproto->GetRetTyIdx()); + MIRFuncType *fProto = static_cast(type); + MIRType *fRetType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(fProto->GetRetTyIdx()); + CallWithFFI(fRetType->GetPrimType(), (ffi_fp_t)fp); +} + +void MFunction::CallIntrinsic(IntrinsiccallNode &intrn) { + MIRIntrinsicID callId = intrn.GetIntrinsic(); + switch (callId) { + case INTRN_C_va_start: { + MValue addrofAP = EvalExpr(*this, intrn.Opnd(0)); + // setup VaList for Aarch64 + VaList *vaList = (maple::VaList*)addrofAP.x.a64; + vaList->gr_offs = 0; // indicate args are on vaList stack + vaList->stack = caller->vaArgs; + break; + } + default: + MASSERT(false, "CallIntrinsic %d\n NYI", callId); + break; + } +} + +// Maple PrimType to libffi type conversion table +static ffi_type ffi_type_table[] = { + ffi_type_void, // kPtyInvalid +#define EXPANDFFI1(x) x, +#define EXPANDFFI2(x) EXPANDFFI1(x) +#define PRIMTYPE(P) EXPANDFFI2(FFITYPE_##P) +#define LOAD_ALGO_PRIMARY_TYPE +#include "prim_types.def" +#undef PRIMTYPE + ffi_type_void // kPtyDerived +}; + +// FFI type def for Arm64 VaList struct fields +ffi_type *vaListObjAarch64 [] = { + ffi_type_table + PTY_ptr, + ffi_type_table + PTY_ptr, + ffi_type_table + PTY_ptr, + ffi_type_table + PTY_i32, + ffi_type_table + PTY_i32, + nullptr +}; + +// FFI type def for X86_64 VaList struct fields +ffi_type *vaListObjX86_64 [] = { + ffi_type_table + PTY_u32, + ffi_type_table + PTY_u32, + ffi_type_table + PTY_ptr, + ffi_type_table + PTY_ptr, + nullptr +}; + +// currently only support ARM64 va_list +ffi_type vaList_ffi_type = { 0, 0, FFI_TYPE_STRUCT, vaListObjAarch64 }; + +// Setup array of call args and their types then call libffi interface +// to invoked external function. Note that for varidiac external funcs, +// PTY_agg type is used to detect a pass by value va_list arg, and used +// to setup its type for ffi call - this works for now because pass by +// value struct args (except va_list) is not supported yet when calling +// external varidiac functions - a different way to detect pass by value +// va_list arg will be needed when pass by value struct for external +// varidiac funcs is supported. +void MFunction::CallWithFFI(PrimType ret_ptyp, ffi_fp_t fp) { + ffi_cif cif; + ffi_type ffi_ret_type = ffi_type_table[ret_ptyp]; + ffi_type* arg_types[numCallArgs]; + void* args[numCallArgs]; + + // gather args and arg types + for (int i = 0; i < numCallArgs; ++i) { + args[i] = &callArgs[i].x; + if (callArgs[i].ptyp == PTY_agg) { + arg_types[i] = &vaList_ffi_type; + } else { + arg_types[i] = ffi_type_table + callArgs[i].ptyp; + } + } + + ffi_status status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, numCallArgs, &ffi_ret_type, arg_types); + if (status == FFI_OK) { + ffi_call(&cif, fp, &retVal0.x, args); + retVal0.ptyp = ret_ptyp; + } else { + MIR_FATAL("Failed to call method at %p", (void *)fp); + } +} + +} // namespace maple diff --git a/src/MapleEng/lmbc/src/mplsh.cpp b/src/MapleEng/lmbc/src/mplsh.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9cbf9812dc8b61872a5caee845fc0347c9d08f42 --- /dev/null +++ b/src/MapleEng/lmbc/src/mplsh.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) [2022] Futurewei Technologies, Inc. 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 +#include "massert.h" +#include "lmbc_eng.h" +#include "eng_shim.h" + +namespace maple { + +void *LmbcMod::FindExtFunc(PUIdx puidx) { + void* fp = extFuncMap[puidx]; + if (fp) { + return fp; + } + std::string fname = GlobalTables::GetFunctionTable().GetFunctionFromPuidx(puidx)->GetName(); + for (auto it : libHandles) { + fp = dlsym(it, fname.c_str()); + if (fp) { + break; + } + } + MASSERT(fp, "dlsym symbol not found: %s", fname.c_str()); + extFuncMap[puidx] = fp; + return(fp); +} + +void *LmbcMod::FindExtSym(StIdx stidx) { + void* var = extSymMap[stidx.FullIdx()]; + if (var) { + return var; + } + MIRSymbol* sym = GlobalTables::GetGsymTable().GetSymbolFromStidx(stidx.Idx()); + if (sym) { + for (auto it : libHandles) { + var = dlsym(it, sym->GetName().c_str()); + if (var) { + break; + } + } + MASSERT(var, "dlsym ExtSym not found: %s", sym->GetName().c_str()); + extSymMap[stidx.FullIdx()] = var; + } + MASSERT(sym, "Unable to find symbol"); + return(var); +} + +maple::MIRModule *LmbcMod::Import(std::string path) { + maple::MIRModule* mod = new maple::MIRModule(path.c_str()); + mod->SetSrcLang(kSrcLangC); + std::string::size_type lastdot = mod->GetFileName().find_last_of("."); + bool islmbc = lastdot != std::string::npos && mod->GetFileName().compare(lastdot, 5, ".lmbc\0") == 0; + if (!islmbc) { + ERR(kLncErr, "Input must be .lmbc file: %s", path.c_str()); + delete mod; + return nullptr; + } + + BinaryMplImport binMplt(*mod); + binMplt.SetImported(false); + std::string modid = mod->GetFileName(); + if (!binMplt.Import(modid, true)) { + ERR(kLncErr, "mplsh-lmbc: cannot open .lmbc file: %s", modid.c_str()); + delete mod; + return nullptr; + } + return mod; +} + +// C runtime libs to preload. +// Add to list as needed or change to read list dynamically at runtime. +std::vector preLoadLibs = { + LIBC_SO, + LIBM_SO +}; + +void LmbcMod::LoadDefLibs() { + for (auto it : preLoadLibs) { + void *handle = dlopen(it.c_str(), RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE); + MASSERT(handle, "dlopen %s failed", it.c_str()); + libHandles.push_back(handle); + } +} + +LmbcMod::LmbcMod(std::string path) : lmbcPath(path) { + LoadDefLibs(); + mirMod = Import(path); + // In Lmbc GlobalMemSize is the mem segment size for un-init + // PU static variables, and is referenced through %%GP register. + unInitPUStaticsSize = mirMod->GetGlobalMemSize(); +} + +int RunLmbc(int argc, char** argv) { + int rc = 1; + const int skipArgsNum = 1; + LmbcMod* mod = new LmbcMod(argv[skipArgsNum]); + MASSERT(mod, "Create Lmbc module failed"); + MASSERT(mod->mirMod, "Import Lmbc module failed"); + mod->InitModule(); + if (mod->mainFn) { + rc = MplEngShim(mod->mainFn, argc-skipArgsNum, argv+skipArgsNum); + } + return rc; +} + +} // namespace maple + +int main(int argc, char **argv) { + if (argc == 1) { + std::string path(argv[0]); + (void)MIR_PRINTF("usage: %s .lmbc\n", path.substr(path.find_last_of("/\\") + 1).c_str()); + exit(1); + } + return maple::RunLmbc(argc, argv); +} diff --git a/src/MapleEng/lmbc/test/c2lmbc.sh b/src/MapleEng/lmbc/test/c2lmbc.sh new file mode 100755 index 0000000000000000000000000000000000000000..5c0e8d9ffe888085b450f70265b435f0a6630086 --- /dev/null +++ b/src/MapleEng/lmbc/test/c2lmbc.sh @@ -0,0 +1,58 @@ +#!/bin/bash +# Copyright (C) [2022] Futurewei Technologies, Inc. All rights reverved. +# +# Licensed under the Mulan Permissive Software License v2 +# You can use this software according to the terms and conditions of the MulanPSL - 2.0. +# You may obtain a copy of MulanPSL - 2.0 at: +# +# https://opensource.org/licenses/MulanPSL-2.0 +# +# 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 MulanPSL - 2.0 for more details. +# +set -x +[[ -z "${MAPLE_ROOT}" ]] && { echo "Please source OpenArkCompiler environment"; exit 1; } + +if [ ! $# -le 2 ] || [ $# -eq 0 ]; then + echo "usage: ./c2lmbc.sh .c [clang2mpl|hir2mpl]" + exit +fi + +if [ $# -le 1 ]; then + FE=clang2mpl +else + FE=$2 +fi + +# hir2mpl flags +CLANGBIN=$MAPLE_ROOT/output/tools/bin +LINARO=$MAPLE_ROOT/output/tools/gcc-linaro-7.5.0 +ISYSTEM_FLAGS="-isystem $MAPLE_ROOT/output/aarch64-clang-release/lib/include -isystem $LINARO/aarch64-linux-gnu/libc/usr/include -isystem $LINARO/lib/gcc/aarch64-linux-gnu/7.5.0/include" +CLANGFE_FLAGS="-emit-ast --target=aarch64 -U __SIZEOF_INT128__ $ISYSTEM_FLAGS" +CLANGFE_FLAGS="$CLANGFE_FLAGS -o ${file%.c}.ast" +# clang2mpl flags +FE_FLAG="--ascii --simple-short-circuit --improved-issimple" +CLANG_FLAGS="--target=aarch64-linux-elf -Wno-return-type -U__SIZEOF_INT128__ -O3 -Wno-implicit -save-temps -fno-builtin-printf -fno-common -falign-functions=4" +# executables +CLANG=$CLANGBIN/clang +HIR2MPL=$MAPLE_EXECUTE_BIN/hir2mpl +CLANG2MPL=$MAPLE_EXECUTE_BIN/clang2mpl +MAPLE=$MAPLE_EXECUTE_BIN/maple +IRBUILD=$MAPLE_EXECUTE_BIN/irbuild +MPLSH=$MAPLE_EXECUTE_BIN/mplsh-lmbc + +file=$(basename -- "$1") +file="${file%.*}" + +if [[ $FE == "hir2mpl" ]]; then + $CLANG $CLANGFE_FLAGS -o ${file%.c}.ast $file.c || exit 1 + $HIR2MPL ${file%.c}.ast -enable-variable-array -o ${file%.c}.mpl || exit 1 +else + $CLANG2MPL $FE_FLAG $file.c -- $CLANG_FLAGS || exit 1 +fi + +$MAPLE --run=me --option="-O2 --no-lfo --no-mergestmts --skip-phases=slp" --genmempl --genlmbc $file.mpl +$IRBUILD $file.lmbc +mv comb.me.mpl $file.me.mpl 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..6da530248e4d0641553fb8c77b4b667b12589016 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)) @@ -24,7 +24,7 @@ ifeq ($(SRCLANG),java) else ifeq ($(SRCLANG),typescript) TARGET := ts2ast ast2cpp else ifeq ($(SRCLANG),c) - TARGET := c2ast + TARGET := c2ast ast2mpl endif all: $(TARGET) @@ -44,7 +44,7 @@ recdetect: autogen shared ladetect ladetect: autogen shared $(MAKE) LANG=$(SRCLANG) -C ladetect -ast2mpl: astopt java2ast +ast2mpl: astopt $(MAKE) -C ast2mpl astopt: shared recdetect ladetect @@ -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/Makefile.in b/src/MapleFE/Makefile.in index 9ec2c1ca5240a2d01be9d271ec8a04b1c6abbcb3..53a98c559cac2fad3849e6998261bb4af412255f 100644 --- a/src/MapleFE/Makefile.in +++ b/src/MapleFE/Makefile.in @@ -10,11 +10,19 @@ LANG=java MKDIR_P = mkdir -p -MAPLELIBPATH:=$(MAPLE_ROOT)/OpenArkCompiler/output/aarch64-clang-debug/lib/64 -MAPLELIBS := -L $(MAPLELIBPATH) -lmplir -loption_parser -lmplphase -lmplutil -lmempool -lmpl2mpl -lHWSecureC -ldriver_option -lmplir -loption_parser -ldriver_option +MAPLELIBPATH:=$(MAPLE_ROOT)/output/aarch64-clang-debug/lib/64 +MAPLELIBS := -L $(MAPLELIBPATH) -lmplir -lmplphase -lmplutil -lcommandline -lmempool -lmpl2mpl -lHWSecureC -ldriver_option MAPLEALL_INC = -I $(MAPLEALL_SRC)/maple_ir/include \ -I $(MAPLEALL_SRC)/mempool/include \ -I $(MAPLEALL_SRC)/maple_util/include \ -I $(MAPLEALL_SRC)/maple_driver/include \ - -I $(MAPLEALL_ROOT)/third_party/bounds_checking_function/include + -I $(MAPLE_ROOT)/third_party/bounds_checking_function/include + +BUILDBIN=$(BUILDDIR)/bin +BUILDGEN=$(BUILDDIR)/gen +BUILDLIB=$(BUILDDIR)/lib +BUILDASTGEN=$(BUILDDIR)/ast_gen/shared + +LANGSPEC=$(BUILDDIR)/$(SRCLANG)/lang_spec.o + diff --git a/src/MapleFE/README b/src/MapleFE/README index 9446b57ff2979767e8ab7b069dae94f732af269f..0d57667771c3609c0a64c8d403304bcb88e8405f 100644 --- a/src/MapleFE/README +++ b/src/MapleFE/README @@ -40,23 +40,30 @@ sudo npm install -g typescript@latest [How to build] -1. source envsetup.sh [java|typescript] +typescript +1. source envsetup.sh typescript +2. make +3. outputs: + output/typescript/bin/ts2ast - executable frontend + output/typescript/bin/ast2cpp - translate AST to cpp source code. + +java +1. source envsetup.sh java 2. make mapleall This step is to build mapleall (Maple IR related libraries). If you have done it once, you dont need do it again unless you changed the code in mapleall. 3. make -4. If you are working at Java frontend, you will see output/java/java/java2mpl. This is the executable - frontend. -4. If you are working at Typescript frontend, you will see output/typescript/bin/ts2ast. This is the executable - frontend. You can also see output/typescript/bin/ast2cpp, which translate AST to cpp source code. +4. outputs: + output/java/bin/java2ast - executable frontend + output/java/bin/ast2mpl - translate AST to mpl [How to test] 1. make test -run a single test, say t1.java: +run a single test, say add.ts: 1. cd test -2. make t1 +2. make add You can find all Java test cases in test/java. You can find all Typescript test cases in test/typescript. diff --git a/src/MapleFE/README.SPEC b/src/MapleFE/README.SPEC index 9706682d2e21333d8e4d1c0e35dde31a76534cdf..5ca0bb84580c102f525ccef1ce767b8fd0f3aef6 100644 --- a/src/MapleFE/README.SPEC +++ b/src/MapleFE/README.SPEC @@ -162,7 +162,7 @@ _____________________ attr.validity : IsUnsigned(%1) attr.action.%1,%2 : GenerateBinaryExpr(%1, %2, %3) attr.action : GenerateUnaryExpr(%1), BuildXXXExpr(%1) - attr.property,%1,%2 : Single, Top + attr.property.%1,%2 : Single, Top 1. attr.xxx must follow the rule which it attaches to. 2. attr.type tells the data type of the generated IR component of this rule. 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..12b9832370c6fbe843d609b786f64e7e202611e2 100644 --- a/src/MapleFE/ast2cpp/src/Makefile +++ b/src/MapleFE/ast2cpp/src/Makefile @@ -13,11 +13,8 @@ # include ../../Makefile.in -BUILDBIN=$(BUILDDIR)/bin BUILD=$(BUILDDIR)/ast2cpp -BUILDGEN=$(BUILDDIR)/gen -BUILDASTGEN=$(BUILDDIR)/ast_gen/shared -$(shell $(MKDIR_P) $(BUILD)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB)) SRC=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) @@ -32,21 +29,21 @@ DEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) $(DEPG) LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(OBJS)) -GENDIR:=${BUILDDIR}/ast_gen/shared - INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ -I $(MAPLEFE_ROOT)/astopt/include \ -I $(MAPLEFE_ROOT)/ast2cpp/include \ -I $(MAPLEFE_ROOT)/autogen/include \ -I $(MAPLEFE_ROOT)/shared/include \ - -I $(MAPLEFE_ROOT)/typescript/include \ - $(MAPLEALL_INC) -I ${GENDIR} + -I $(MAPLEFE_ROOT)/$(SRCLANG)/include \ + -I ${BUILDASTGEN} \ + $(MAPLEALL_INC) INCLUDEGEN := -I $(MAPLEFE_ROOT)/shared/include -I $(BUILDDIR)/gen -I $(BUILDASTGEN) TARGET=ast2cpp -SHAREDLIB = $(BUILDDIR)/astopt/astopt.a $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a -LANGSPEC=$(BUILDDIR)/typescript/lang_spec.o +TARGET_A=libast2cpp.a + +SHAREDLIB = -L $(BUILDLIB) -lastopt -lshared -lgenast .PHONY: all all: $(BUILDBIN)/$(TARGET) @@ -78,9 +75,12 @@ $(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) +$(BUILDLIB)/$(TARGET_A): $(LIBOBJS) + /usr/bin/ar rcs $(BUILDLIB)/$(TARGET_A) $(LIBOBJS) + +$(BUILDBIN)/$(TARGET): $(BUILDLIB)/$(TARGET_A) $(OBJS) @mkdir -p $(BUILDBIN) - $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(LANGSPEC) $(SHAREDLIB) + $(LD) -o $(BUILDBIN)/$(TARGET) $(BUILD)/main.o $(BUILDLIB)/$(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/include/generic_attrs.h b/src/MapleFE/ast2mpl/include/generic_attrs.h index ecab7c62d180bec7218941b55af3167d9d8eefcf..6b7406d30dd1516e305de461292c3369d429bb86 100644 --- a/src/MapleFE/ast2mpl/include/generic_attrs.h +++ b/src/MapleFE/ast2mpl/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. @@ -15,9 +15,11 @@ #ifndef GENERIC_ATTRS_H #define GENERIC_ATTRS_H #include +#include #include "mir_type.h" namespace maple { +using AttrContent = std::variant; // only for internal use, not emitted enum GenericAttrKind { #define FUNC_ATTR @@ -30,6 +32,7 @@ enum GenericAttrKind { #undef TYPE_ATTR #undef FIELD_ATTR }; +constexpr uint32 kMaxATTRNum = 128; class GenericAttrs { public: @@ -42,6 +45,10 @@ class GenericAttrs { attrFlag.set(x); } + void ResetAttr(GenericAttrKind x) { + attrFlag.reset(x); + } + bool GetAttr(GenericAttrKind x) const { return attrFlag[x]; } @@ -54,12 +61,49 @@ class GenericAttrs { return !(*this == tA); } + void InitContentMap() { + contentMap.resize(kMaxATTRNum); + isInit = true; + } + + bool GetContentFlag(GenericAttrKind key) const { + return contentFlag[key]; + } + + void InsertIntContentMap(GenericAttrKind key, int val) { + if (!isInit) { + InitContentMap(); + } + if (!contentFlag[key]) { + contentMap[key] = val; + contentFlag.set(key); + } + } + + void InsertStrIdxContentMap(GenericAttrKind key, GStrIdx 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::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/MapleFE/ast2mpl/src/Makefile b/src/MapleFE/ast2mpl/src/Makefile index 51ab1dcd3e1b7c95dcda06ba6a8a02e8df10d433..bb197d2748bdc6d7970f15003e95327add2658e0 100644 --- a/src/MapleFE/ast2mpl/src/Makefile +++ b/src/MapleFE/ast2mpl/src/Makefile @@ -13,11 +13,8 @@ # include ../../Makefile.in -BUILDBIN=$(BUILDDIR)/bin BUILD=$(BUILDDIR)/ast2mpl -BUILDGEN=$(BUILDDIR)/gen -BUILDASTGEN=$(BUILDDIR)/ast_gen/shared -$(shell $(MKDIR_P) $(BUILD)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB)) SRC=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) @@ -32,23 +29,21 @@ DEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) $(DEPG) LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(OBJS)) -GENDIR:=${BUILDDIR}/ast_gen/shared - INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ -I $(MAPLEFE_ROOT)/astopt/include \ -I $(MAPLEFE_ROOT)/ast2mpl/include \ -I $(MAPLEFE_ROOT)/autogen/include \ -I $(MAPLEFE_ROOT)/shared/include \ - -I $(MAPLEFE_ROOT)/java/include \ - $(MAPLEALL_INC) -I ${GENDIR} - -AST2MPLLIB = ast2mpl.a + -I $(MAPLEFE_ROOT)/$(SRCLANG)/include \ + -I ${BUILDASTGEN} \ + $(MAPLEALL_INC) INCLUDEGEN := -I $(MAPLEFE_ROOT)/shared/include -I $(BUILDDIR)/gen -I $(BUILDASTGEN) TARGET=ast2mpl -SHAREDLIB = $(BUILDDIR)/astopt/astopt.a $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a -LANGSPEC=$(BUILDDIR)/java/lang_spec.o +TARGET_A=libast2mpl.a + +SHAREDLIB = -L $(BUILDLIB) -lastopt -lshared -lgenast .PHONY: all all: $(BUILDBIN)/$(TARGET) @@ -80,9 +75,12 @@ $(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) +$(BUILDLIB)/$(TARGET_A): $(LIBOBJS) + /usr/bin/ar rcs $(BUILDLIB)/$(TARGET_A) $(LIBOBJS) + +$(BUILDBIN)/$(TARGET): $(BUILDLIB)/$(TARGET_A) $(OBJS) @mkdir -p $(BUILDBIN) - $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(LANGSPEC) $(SHAREDLIB) $(MAPLELIBS) + $(LD) -o $(BUILDBIN)/$(TARGET) $(BUILD)/main.o $(BUILDLIB)/$(TARGET_A) $(OBJG) $(LANGSPEC) $(SHAREDLIB) $(MAPLELIBS) clean: rm -rf $(BUILD) diff --git a/src/MapleFE/ast2mpl/src/ast2mpl_builder.cpp b/src/MapleFE/ast2mpl/src/ast2mpl_builder.cpp index 2c8c3546f32498b5d14b0b4639585a97e747164d..d5779c8a936579badf18d1d88fe6be35cbf69560 100644 --- a/src/MapleFE/ast2mpl/src/ast2mpl_builder.cpp +++ b/src/MapleFE/ast2mpl/src/ast2mpl_builder.cpp @@ -13,12 +13,12 @@ * See the Mulan PSL v2 for more details. */ +#include "generic_attrs.h" #include "ast2mpl_builder.h" #include "gen_astdump.h" #include "mir_module.h" #include "mir_function.h" #include "maplefe_mir_builder.h" -#include "cvt_block.h" namespace maplefe { @@ -41,12 +41,23 @@ Ast2MplBuilder::~Ast2MplBuilder() { void Ast2MplBuilder::Init() { // create mDefaultType maple::MIRType *type = maple::GlobalTables::GetTypeTable().GetOrCreateClassType("DEFAULT_TYPE", *mMirModule); - type->SetMIRTypeKind(maple::kTypeClass); - mDefaultType = mMirBuilder->GetOrCreatePointerType(type); + mDefaultType = type; // setup flavor and srclang - mMirModule->SetFlavor(maple::kFeProduced); - mMirModule->SetSrcLang(maple::kSrcLangJava); + mMirModule->SetFlavor(maple::kFlavorMapleFE); + SrcLang lang = mASTHandler->GetModuleHandler((unsigned)0)->GetASTModule()->GetSrcLang(); + switch (lang) { + case SrcLangJava: + mMirModule->SetSrcLang(maple::kSrcLangJava); + mDefaultType = mMirBuilder->GetOrCreatePointerType(type); + break; + case SrcLangC: + mMirModule->SetSrcLang(maple::kSrcLangC); + break; + default: + mMirModule->SetSrcLang(maple::kSrcLangUnknown); + break; + } // setup INFO_filename maple::GStrIdx idx = maple::GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(mFilename); @@ -77,10 +88,6 @@ void Ast2MplBuilder::Build() { std::cout << "============= in ProcessAST ===========" << std::endl; std::cout << "srcLang : " << module->GetSrcLangString() << std::endl; } - // pass 0: convert to use BlockNode for if-then-else and loop bodies - CvtToBlockVisitor visitor(module); - visitor.CvtToBlock(); - // pass 1: collect class/interface/function decl for (unsigned i = 0; i < module->GetTreesNum(); i++) { TreeNode *tnode = module->GetTree(i); @@ -109,13 +116,14 @@ maple::PrimType Ast2MplBuilder::MapPrim(TypeId id) { case TY_Double: prim = maple::PTY_f64; break; case TY_Void: prim = maple::PTY_void; break; case TY_Null: prim = maple::PTY_void; break; - default: MASSERT("Unsupported PrimType"); break; + default: prim = maple::PTY_ref; break; } return prim; } maple::MIRType *Ast2MplBuilder::MapPrimType(TypeId id) { maple::PrimType prim = MapPrim(id); + if (prim == maple::PTY_ref) return nullptr; maple::TyIdx tid(prim); return maple::GlobalTables::GetTypeTable().GetTypeFromTyIdx(tid); } @@ -131,7 +139,7 @@ maple::MIRType *Ast2MplBuilder::MapType(TreeNode *type) { maple::MIRType *mir_type = mDefaultType; - unsigned idx = type->GetStrIdx(); + unsigned idx = type->GetTypeIdx(); if (mNodeTypeMap.find(idx) != mNodeTypeMap.end()) { return mNodeTypeMap[idx]; } @@ -519,6 +527,14 @@ maple::MIRSymbol *Ast2MplBuilder::CreateSymbol(TreeNode *tnode, BlockNode *block symbol = mMirBuilder->CreateGlobalDecl(str, *mir_type, maple::kScGlobal); } + if (tnode->IsIdentifier()) { + IdentifierNode *inode = static_cast(tnode); + maple::GenericAttrs genAttrs; + MapAttr(genAttrs, inode); + maple::TypeAttrs tAttrs = genAttrs.ConvertToTypeAttrs(); + symbol->SetAttrs(tAttrs); + } + std::pair P(tnode->GetStrIdx(), block); mNameBlockVarMap[P] = symbol; @@ -526,10 +542,7 @@ maple::MIRSymbol *Ast2MplBuilder::CreateSymbol(TreeNode *tnode, BlockNode *block } maple::MIRFunction *Ast2MplBuilder::GetCurrFunc(BlockNode *block) { - maple::MIRFunction *func = nullptr; - // func = mBlockFuncMap[block]; - func = mMirModule->CurFunction(); - return func; + return block ? mMirModule->CurFunction() : nullptr; } maple::MIRClassType *Ast2MplBuilder::GetClass(BlockNode *block) { @@ -684,12 +697,25 @@ ATTRIBUTE(private) ATTRIBUTE(protected) ATTRIBUTE(public) ATTRIBUTE(static) +//ATTRIBUTE(strictfp) + case ATTR_strictfp: attr.SetAttr(maple::GENATTR_strict); break; ATTRIBUTE(default) ATTRIBUTE(synchronized) +//ATTRIBUTE(async) -// ATTRIBUTE(strictfp) - case ATTR_strictfp: attr.SetAttr(maple::GENATTR_strict); break; +//ATTRIBUTE(readonly) // Typescript +//ATTRIBUTE(getter) // Javascript getter function +//ATTRIBUTE(setter) // Javascript setter function +// added for C +ATTRIBUTE(restrict) +//ATTRIBUTE(typedef) +ATTRIBUTE(extern) +//ATTRIBUTE(auto) +//ATTRIBUTE(register) +ATTRIBUTE(inline) + +#undef ATTRIBUTE default: break; } diff --git a/src/MapleFE/ast2mpl/src/cvt_block.cpp b/src/MapleFE/ast2mpl/src/cvt_block.cpp deleted file mode 100644 index 419d1c54bd72c4aa5d0db2ac80bb82b0b40f713a..0000000000000000000000000000000000000000 --- a/src/MapleFE/ast2mpl/src/cvt_block.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -* Copyright (C) [2021] 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. -*/ - -#include "cvt_block.h" - -namespace maplefe { - -bool CvtToBlockVisitor::CvtToBlock() { - for (unsigned i = 0; i < mASTModule->GetTreesNum(); i++ ) { - TreeNode *it = mASTModule->GetTree(i); - Visit(it); - } - return mUpdated; -} - -// if-then-else -CondBranchNode *CvtToBlockVisitor::VisitCondBranchNode(CondBranchNode *node) { - TreeNode *tn = VisitTreeNode(node->GetTrueBranch()); - if (tn && !tn->IsBlock()) { - BlockNode *blk = (BlockNode*)gTreePool.NewTreeNode(sizeof(BlockNode)); - new (blk) BlockNode(); - blk->AddChild(tn); - node->SetTrueBranch(blk); - mUpdated = true; - } - tn = VisitTreeNode(node->GetFalseBranch()); - if (tn && !tn->IsBlock()) { - BlockNode *blk = (BlockNode*)gTreePool.NewTreeNode(sizeof(BlockNode)); - new (blk) BlockNode(); - blk->AddChild(tn); - node->SetFalseBranch(blk); - mUpdated = true; - } - return node; -} - -// for -ForLoopNode *CvtToBlockVisitor::VisitForLoopNode(ForLoopNode *node) { - TreeNode *tn = VisitTreeNode(node->GetBody()); - if (tn && !tn->IsBlock()) { - BlockNode *blk = (BlockNode*)gTreePool.NewTreeNode(sizeof(BlockNode)); - new (blk) BlockNode(); - blk->AddChild(tn); - node->SetBody(blk); - mUpdated = true; - } - return node; -} - -} diff --git a/src/MapleFE/ast2mpl/src/generic_attrs.cpp b/src/MapleFE/ast2mpl/src/generic_attrs.cpp index 185d327387249f9ceea60c5fd288970ac463c739..de7ccba767bcca2de929cc927b4fde5d1efeb615 100644 --- a/src/MapleFE/ast2mpl/src/generic_attrs.cpp +++ b/src/MapleFE/ast2mpl/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. @@ -13,12 +13,12 @@ * See the Mulan PSL v2 for more details. */ #include "generic_attrs.h" +#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 < kMaxATTRNum; ++i) { if (attrFlag[i] == 0) { continue; } @@ -37,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 < kMaxATTRNum; ++i) { if (attrFlag[i] == 0) { continue; } @@ -62,6 +64,16 @@ FuncAttrs GenericAttrs::ConvertToFuncAttrs() { break; } } + if (GetContentFlag(GENATTR_alias)) { + std::string name = GlobalTables::GetStrTable().GetStringFromStrIdx(std::get(contentMap[GENATTR_alias])); + attr.SetAliasFuncName(name); + } + if (GetContentFlag(GENATTR_constructor_priority)) { + attr.SetConstructorPriority(std::get(contentMap[GENATTR_constructor_priority])); + } + if (GetContentFlag(GENATTR_destructor_priority)) { + attr.SetDestructorPriority(std::get(contentMap[GENATTR_destructor_priority])); + } return attr; } @@ -89,4 +101,4 @@ FieldAttrs GenericAttrs::ConvertToFieldAttrs() { } return attr; } -} \ No newline at end of file +} diff --git a/src/MapleFE/ast2mpl/src/mpl_processor.cpp b/src/MapleFE/ast2mpl/src/mpl_processor.cpp index e66c75643e45e1dd2d50e92777fdf1c50cf68cb8..bb595901125fbcc85a7b11dcba7ae55670e0bce8 100644 --- a/src/MapleFE/ast2mpl/src/mpl_processor.cpp +++ b/src/MapleFE/ast2mpl/src/mpl_processor.cpp @@ -116,9 +116,27 @@ maple::BaseNode *Ast2MplBuilder::ProcessIdentifier(StmtExprKind skind, TreeNode return mMirBuilder->CreateExprDread(symbol); } + // check global var + symbol = GetSymbol(node, nullptr); + if (symbol) { + AST2MPLMSG("ProcessIdentifier() found global symbol", name); + return mMirBuilder->CreateExprDread(symbol); + } + maple::GStrIdx stridx = maple::GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); maple::MIRFunction *func = GetCurrFunc(block); + if (!func) { + AST2MPLMSG("ProcessIdentifier() unknown global identifier", name); + // create a global var with name and PrimType or mDefaultType + maple::MIRType *type = MapPrimType(tnode->GetTypeId()); + if (!type) { + type = mDefaultType; + } + symbol = mMirBuilder->GetOrCreateGlobalDecl(name, *type); + return mMirBuilder->CreateExprDread(symbol); + } + // check parameters if (func->IsAFormalName(stridx)) { maple::FormalDef def = func->GetFormalFromName(stridx); @@ -127,33 +145,32 @@ maple::BaseNode *Ast2MplBuilder::ProcessIdentifier(StmtExprKind skind, TreeNode } // check class fields - maple::TyIdx tyidx = func->GetFormalDefAt(0).formalTyIdx; - maple::MIRType *ctype = maple::GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyidx); - if (ctype->GetPrimType() == maple::PTY_ptr || ctype->GetPrimType() == maple::PTY_ref) { - maple::MIRPtrType *ptype = static_cast(ctype); - ctype = ptype->GetPointedType(); - } - mFieldData->ResetStrIdx(stridx); - maple::uint32 fid = 0; - bool status = mMirBuilder->TraverseToNamedField((maple::MIRStructType*)ctype, fid, mFieldData); - if (status) { - maple::MIRSymbol *sym = func->GetFormal(0); // this - maple::BaseNode *bn = mMirBuilder->CreateExprDread(sym); - maple::MIRType *ftype = maple::GlobalTables::GetTypeTable().GetTypeFromTyIdx(mFieldData->GetTyIdx()); - AST2MPLMSG("ProcessIdentifier() found match field", name); - return new maple::IreadNode(maple::OP_iread, ftype->GetPrimType(), sym->GetTyIdx(), maple::FieldID(fid), bn); - } - - // check global var - symbol = GetSymbol(node, nullptr); - if (symbol) { - AST2MPLMSG("ProcessIdentifier() found global symbol", name); - return mMirBuilder->CreateExprDread(symbol); + if (func->GetClassTyIdx()) { + maple::TyIdx tyidx = func->GetFormalDefAt(0).formalTyIdx; + maple::MIRType *ctype = maple::GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyidx); + if (ctype->GetPrimType() == maple::PTY_ptr || ctype->GetPrimType() == maple::PTY_ref) { + maple::MIRPtrType *ptype = static_cast(ctype); + ctype = ptype->GetPointedType(); + } + mFieldData->ResetStrIdx(stridx); + maple::uint32 fid = 0; + bool status = mMirBuilder->TraverseToNamedField((maple::MIRStructType*)ctype, fid, mFieldData); + if (status) { + maple::MIRSymbol *sym = func->GetFormal(0); // this + maple::BaseNode *bn = mMirBuilder->CreateExprDread(sym); + maple::MIRType *ftype = maple::GlobalTables::GetTypeTable().GetTypeFromTyIdx(mFieldData->GetTyIdx()); + AST2MPLMSG("ProcessIdentifier() found match field", name); + return new maple::IreadNode(maple::OP_iread, ftype->GetPrimType(), sym->GetTyIdx(), maple::FieldID(fid), bn); + } } AST2MPLMSG("ProcessIdentifier() unknown identifier", name); - // create a dummy var with name and mDefaultType - symbol = mMirBuilder->GetOrCreateLocalDecl(name, *mDefaultType); + // create a var with name and PrimType or mDefaultType + maple::MIRType *type = MapPrimType(tnode->GetTypeId()); + if (!type) { + type = mDefaultType; + } + symbol = mMirBuilder->GetOrCreateDeclInFunc(name, *type, *func); return mMirBuilder->CreateExprDread(symbol); } @@ -320,8 +337,47 @@ maple::BaseNode *Ast2MplBuilder::ProcessFieldDecl(StmtExprKind skind, TreeNode * maple::BaseNode *Ast2MplBuilder::ProcessDecl(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { DeclNode *node = static_cast(tnode); - TreeNode *vars = node->GetVar(); - return ProcessNode(skind, vars, block); + TreeNode *var = node->GetVar(); + IdentifierNode *inode = nullptr; + maple::BaseNode *bn = nullptr; + maple::MIRType *type = nullptr; + maple::MIRSymbol *symbol = nullptr; + bool single = true; + if (var->IsIdentifier()) { + inode = static_cast(var); + type = MapType(inode->GetType()); + symbol = CreateSymbol(inode, block); + bn = ProcessNode(SK_Expr, inode, block); + } else if (var->IsVarList()) { + VarListNode *vl = static_cast(var); + single = (vl->GetVarsNum() == 1); + for (unsigned i = 0; i < vl->GetVarsNum(); i++) { + inode = vl->GetVarAtIndex(i); + type = MapType(inode->GetType()); + symbol = CreateSymbol(inode, block); + bn = ProcessNode(SK_Expr, inode, block); + } + } + + TreeNode *init = node->GetInit(); + // single decl + if (init && single) { + if (block && !symbol->IsStatic()) { + // local, add assignment + maple::BaseNode *bn0 = ProcessNode(SK_Expr, init, block); + bn0 = new maple::DassignNode(type->GetPrimType(), bn0, symbol->GetStIdx(), 0); + maple::BlockNode *blk = mBlockNodeMap[block]; + blk->AddStatement((maple::StmtNode*)bn0); + } else { + // global or static, set as sambol init + MASSERT(init->IsLiteral()); + maple::BaseNode *val = ProcessLiteral(SK_Expr, init, nullptr); + MASSERT(val->op == maple::OP_constval); + maple::ConstvalNode *cval = static_cast(val); + symbol->SetKonst(cval->GetConstVal()); + } + } + return bn; } maple::BaseNode *Ast2MplBuilder::ProcessAssert(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { @@ -379,11 +435,6 @@ maple::BaseNode *Ast2MplBuilder::ProcessVarList(StmtExprKind skind, TreeNode *tn AST2MPLMSG("ProcessVarList() decl", inode->GetName()); maple::MIRSymbol *symbol = CreateSymbol(inode, block); - maple::GenericAttrs genAttrs; - MapAttr(genAttrs, inode); - maple::TypeAttrs tAttrs = genAttrs.ConvertToTypeAttrs(); - symbol->SetAttrs(tAttrs); - TreeNode *init = inode->GetInit(); // Init value if (init) { maple::BaseNode *bn = ProcessNode(SK_Expr, init, block); @@ -609,6 +660,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++) { @@ -640,8 +699,17 @@ maple::BaseNode *Ast2MplBuilder::ProcessBlock(StmtExprKind skind, TreeNode *tnod maple::BaseNode *Ast2MplBuilder::ProcessFunction(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { MASSERT(tnode->IsFunction() && "it is not an FunctionNode"); - NOTYETIMPL("ProcessFunction()"); - return nullptr; + + FunctionNode *ast_func = static_cast(tnode); + maple::BaseNode *bn = nullptr; + + if (mFuncMap.find(ast_func) != mFuncMap.end()) { + bn = ProcessFuncSetup(skind, tnode, block); + } else { + NOTYETIMPL("ProcessFunction() func not declare, lambda?"); + } + + return bn; } maple::BaseNode *Ast2MplBuilder::ProcessFuncDecl(StmtExprKind skind, TreeNode *tnode, BlockNode *block) { @@ -650,7 +718,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; @@ -697,7 +765,7 @@ maple::BaseNode *Ast2MplBuilder::ProcessFuncDecl(StmtExprKind skind, TreeNode *t maple::GStrIdx stridx = maple::GlobalTables::GetStrTable().GetOrCreateStrIdxFromName("this"); maple::TypeAttrs attr = maple::TypeAttrs(); maple::MIRType *sptype = mMirBuilder->GetOrCreatePointerType(stype); - maple::MIRSymbol *sym = mMirBuilder->GetOrCreateLocalDecl("this", *sptype); + maple::MIRSymbol *sym = mMirBuilder->GetOrCreateDeclInFunc("this", *sptype, *func); sym->SetStorageClass(maple::kScFormal); func->AddArgument(sym); funcvectype.push_back(sptype->GetTypeIndex()); @@ -718,7 +786,7 @@ maple::BaseNode *Ast2MplBuilder::ProcessFuncDecl(StmtExprKind skind, TreeNode *t maple::GStrIdx stridx = maple::GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(param->GetName()); maple::TypeAttrs attr = maple::TypeAttrs(); - maple::MIRSymbol *sym = mMirBuilder->GetOrCreateLocalDecl(param->GetName(), *type); + maple::MIRSymbol *sym = mMirBuilder->GetOrCreateDeclInFunc(param->GetName(), *type, *func); sym->SetStorageClass(maple::kScFormal); func->AddArgument(sym); funcvectype.push_back(type->GetTypeIndex()); @@ -726,7 +794,9 @@ maple::BaseNode *Ast2MplBuilder::ProcessFuncDecl(StmtExprKind skind, TreeNode *t } // use className|funcName|_argTypes_retType as function name - UpdateFuncName(func); + if (mMirModule->GetSrcLang() == maple::kSrcLangJava) { + UpdateFuncName(func); + } mFuncMap[ast_func] = func; mNameFuncMap[ast_func->GetStrIdx()].push_back(func); diff --git a/src/MapleFE/astopt/include/ast_info.h b/src/MapleFE/astopt/include/ast_info.h index 4753f50dace00bff128a2e2753bec54cd5d5773f..e040caf7a04ead1739f6afe6e58035a6fdacabec 100644 --- a/src/MapleFE/astopt/include/ast_info.h +++ b/src/MapleFE/astopt/include/ast_info.h @@ -46,7 +46,6 @@ class AST_INFO { std::unordered_set mWithTypeParamNodeSet; std::unordered_set mWithThisFuncSet;; std::unordered_set mFromLambda; - std::unordered_map mStrIdx2TypeIdxMap; void AddField(unsigned nid, TreeNode *node); @@ -77,6 +76,7 @@ class AST_INFO { TypeAliasNode *CreateTypeAliasNode(TreeNode *to, TreeNode *from); StructNode *CreateStructFromStructLiteral(StructLiteralNode *node); + unsigned GetAnonymousName(); TreeNode *GetAnonymousStruct(TreeNode *node); bool IsInterface(TreeNode *node); @@ -107,11 +107,6 @@ class AST_INFO { void AddFromLambda(unsigned nid) { mFromLambda.insert(nid); } bool IsFromLambda(unsigned nid) { return mFromLambda.find(nid) != mFromLambda.end(); } - - void AddBuiltInTypes(); - bool IsBuiltInType(TreeNode *node); - unsigned GetBuiltInTypeIdx(unsigned stridx); - unsigned GetBuiltInTypeIdx(TreeNode *node); }; class FillNodeInfoVisitor : public AstVisitor { @@ -153,6 +148,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/Makefile b/src/MapleFE/astopt/src/Makefile index 3d61edb58810ed11d2f63a25a32eba9c5b225f77..8334be85a08deab0723d36378fa31aeea1ef1c8f 100644 --- a/src/MapleFE/astopt/src/Makefile +++ b/src/MapleFE/astopt/src/Makefile @@ -14,7 +14,7 @@ include ../../Makefile.in BUILD=$(BUILDDIR)/astopt -$(shell $(MKDIR_P) $(BUILD)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB)) SRC=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) @@ -29,12 +29,12 @@ LIBOBJS :=$(patsubst $(BUILD)/main.o,,$(OBJS)) INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ -I $(MAPLEFE_ROOT)/astopt/include \ -I $(MAPLEFE_ROOT)/$(SRCLANG)/include \ - -I ${BUILDDIR}/ast_gen/shared + -I ${BUILDASTGEN} -TARGET=astopt.a +TARGET=libastopt.a .PHONY: all -all: $(BUILD)/$(TARGET) +all: $(BUILDLIB)/$(TARGET) -include $(DEPS) .PHONY: clean @@ -54,8 +54,8 @@ $(BUILD)/%.d : %.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILD)/$(TARGET): $(OBJS) - /usr/bin/ar rcs $(BUILD)/$(TARGET) $(OBJS) +$(BUILDLIB)/$(TARGET): $(OBJS) + /usr/bin/ar rcs $(BUILDLIB)/$(TARGET) $(OBJS) clean: rm -rf $(BUILD) 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..3bd89023e05fa461c1840a885aa14b3f03cf9065 100644 --- a/src/MapleFE/astopt/src/ast_info.cpp +++ b/src/MapleFE/astopt/src/ast_info.cpp @@ -32,8 +32,6 @@ void AST_INFO::CollectInfo() { it->SetParent(module); } - AddBuiltInTypes(); - // collect import/export info MSGNOLOC0("============== XXport info =============="); mHandler->GetASTXXport()->CollectXXportInfo(mHandler->GetHidx()); @@ -67,32 +65,10 @@ void AST_INFO::CollectInfo() { mPass = 2; MSGNOLOC0("============== merge class/interface/struct =============="); visitor.Visit(module); -} - -void AST_INFO::AddBuiltInTypes() { - // add language builtin types - TreeNode *node = NULL; -#define BUILTIN(T) \ - node = gTypeTable.CreateBuiltinType(#T, TY_Class);\ - gTypeTable.AddType(node);\ - mStrIdx2TypeIdxMap[node->GetStrIdx()] = node->GetTypeIdx(); -#include "lang_builtin.def" -} - -bool AST_INFO::IsBuiltInType(TreeNode *node) { - return mStrIdx2TypeIdxMap.find(node->GetStrIdx()) != mStrIdx2TypeIdxMap.end(); -} -unsigned AST_INFO::GetBuiltInTypeIdx(unsigned stridx) { - if (mStrIdx2TypeIdxMap.find(stridx) != mStrIdx2TypeIdxMap.end()) { - return mStrIdx2TypeIdxMap[stridx]; - } - return 0; -} - -unsigned AST_INFO::GetBuiltInTypeIdx(TreeNode *node) { - unsigned stridx = node->GetStrIdx(); - return GetBuiltInTypeIdx(stridx); + // collect function types + FunctionVisitor func_visitor(mHandler, mFlags, true); + func_visitor.Visit(module); } TypeId AST_INFO::GetTypeId(TreeNode *node) { @@ -245,16 +221,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(); @@ -422,7 +398,7 @@ IdentifierNode *AST_INFO::CreateIdentifierNode(unsigned stridx) { } UserTypeNode *AST_INFO::CreateUserTypeNode(unsigned stridx, ASTScope *scope) { - unsigned tidx = GetBuiltInTypeIdx(stridx); + unsigned tidx = gTypeTable.GetBuiltInTypeIdx(stridx); IdentifierNode *node = CreateIdentifierNode(stridx); SetTypeId(node, TY_Class); SetTypeIdx(node, tidx); @@ -490,10 +466,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,15 +646,15 @@ 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()); } else if (node->IsGenerator()) { unsigned stridx = gStringPool.GetStrIdx("Generator"); - unsigned tidx = mInfo->GetBuiltInTypeIdx(stridx); + unsigned tidx = gTypeTable.GetBuiltInTypeIdx(stridx); UserTypeNode *ut = mInfo->CreateUserTypeNode(stridx); - node->SetType(ut); + node->SetRetType(ut); } return node; } @@ -729,7 +710,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; } @@ -737,9 +726,8 @@ UserTypeNode *FillNodeInfoVisitor::VisitUserTypeNode(UserTypeNode *node) { (void) AstVisitor::VisitUserTypeNode(node); TreeNode *id = node->GetId(); if (id) { - unsigned tidx = mInfo->GetBuiltInTypeIdx(id); + unsigned tidx = gTypeTable.GetBuiltInTypeIdx(id); if (tidx) { - mInfo->SetTypeId(id, TY_Class); mInfo->SetTypeIdx(id, tidx); } if (!id->IsTypeIdNone()) { @@ -793,6 +781,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 +814,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 +848,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 +900,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..930230e293f133130dc58b52a3a951c2cced6439 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; } @@ -134,7 +136,7 @@ FieldLiteralNode *BuildIdDirectFieldVisitor::VisitFieldLiteralNode(FieldLiteralN IdentifierNode *field = static_cast(name); TreeNode *decl = mHandler->FindDecl(field); TreeNode *vtype = GetParentVarClass(decl); - if (vtype && !mHandler->GetINFO()->IsBuiltInType(vtype)) { + if (vtype && !gTypeTable.IsBuiltInType(vtype)) { // check if decl is a field of vtype // note: vtype could be in different module Module_Handler *h = mHandler->GetModuleHandler(vtype); @@ -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/autogen/src/Makefile b/src/MapleFE/autogen/src/Makefile index 7297ffdb8d3decb0a97a0bb9d936a02390535a3d..c780ac97235a0bf01bbe71f2dc392222160a155b 100644 --- a/src/MapleFE/autogen/src/Makefile +++ b/src/MapleFE/autogen/src/Makefile @@ -16,7 +16,7 @@ include ../../Makefile.in # create build first BUILD=$(BUILDDIR)/autogen -$(shell $(MKDIR_P) $(BUILD) $(BUILDDIR)/$(SRCLANG) $(BUILDDIR)/gen) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB) $(BUILDDIR)/$(SRCLANG) $(BUILDDIR)/gen) SHAREDSRC := token.cpp mempool.cpp stringmap.cpp stringpool.cpp write2file.cpp SRC := $(wildcard *.cpp) $(SHAREDSRC) @@ -35,18 +35,18 @@ SPECS := $(wildcard $(MAPLEFE_ROOT)/$(SRCLANG)/*.spec) TARGET = autogen -AUTOGENLIB = autogen.a +AUTOGENLIB = libautogen.a .PHONY: all all: $(BUILD)/$(TARGET) -$(BUILD)/$(TARGET) : $(BUILD)/$(AUTOGENLIB) - $(LD) -o $(BUILD)/$(TARGET) $(BUILD)/main.o $(BUILD)/$(AUTOGENLIB) +$(BUILD)/$(TARGET) : $(BUILDLIB)/$(AUTOGENLIB) + $(LD) -o $(BUILD)/$(TARGET) $(BUILD)/main.o $(BUILDLIB)/$(AUTOGENLIB) (cd $(BUILD); ./$(TARGET) $(SRCLANG)) (cd $(MAPLEFE_ROOT); ./scripts/maplefe-autogen.py) -$(BUILD)/$(AUTOGENLIB) : $(OBJS) - /usr/bin/ar rcs $(BUILD)/$(AUTOGENLIB) $(LIBOBJS) +$(BUILDLIB)/$(AUTOGENLIB) : $(OBJS) + /usr/bin/ar rcs $(BUILDLIB)/$(AUTOGENLIB) $(LIBOBJS) -include $(DEPS) .PHONY: clean diff --git a/src/MapleFE/c/attr.spec b/src/MapleFE/c/attr.spec index 7211303cd96c3d2ceb5755398e12958832394a0a..478c0c1c21df7597be75e558d04c88557784d0eb 100644 --- a/src/MapleFE/c/attr.spec +++ b/src/MapleFE/c/attr.spec @@ -12,7 +12,12 @@ # FIT FOR A PARTICULAR PURPOSE. # See the Mulan PSL v2 for more details. -STRUCT Attribute : (("const", const), +STRUCT Attribute : (("auto", auto), + ("const", const), + ("extern", extern), + ("inline", inline), + ("register", register), + ("restrict", restrict), ("static", static), - ("volatile", volatile), - ("restrict", restrict)) \ No newline at end of file + ("typedef", typedef), + ("volatile", volatile)) \ No newline at end of file diff --git a/src/MapleFE/c/keyword.spec b/src/MapleFE/c/keyword.spec index 2e62b807aaaf736015788008e0c36e2b1843bc51..36b95e836b0a60677cfb7edefaac605a30e5560e 100644 --- a/src/MapleFE/c/keyword.spec +++ b/src/MapleFE/c/keyword.spec @@ -46,6 +46,13 @@ STRUCT KeyWord : ((auto), (void), (volatile), (while), + (_Alignas), + (_Alignof), + (_Atomic), (_Bool), (_Complex), - (_Imaginary)) + (_Imaginary), + (_Generic), + (_Noreturn), + (_Static_assert), + (_Thread_local)) diff --git a/src/MapleFE/c/literal.spec b/src/MapleFE/c/literal.spec index 013f438418239a299bcd63ca4285bc00efd532c6..3c3e1037d51f76486234e2c60ed4520c42317d54 100644 --- a/src/MapleFE/c/literal.spec +++ b/src/MapleFE/c/literal.spec @@ -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. @@ -11,108 +11,214 @@ # 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. - -######################################################################### -## Integer ## -######################################################################### - -### Decimal rules - -rule NonZeroDigit : ONEOF('1', '2', '3', '4', '5', '6', '7', '8', '9') -rule Digit : ONEOF('0', NonZeroDigit) -rule DecimalNumeral : ONEOF('0', NonZeroDigit + ZEROORONE(Digit)) - -### Hexadecimal rules - -rule HexDigit : ONEOF('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'a', 'b', 'c', 'd', 'e', 'f', - 'A', 'B', 'C', 'D', 'E', 'F') -rule HexNumeral : ONEOF("0x" + HexDigit, "0X" + HexDigit) - -### Octal rules - -rule OctalDigit : ONEOF('0', '1', '2', '3', '4', '5', '6', '7') -rule OctalNumeral : ONEOF('0' + OctalDigit) - -rule IntegerTypeSuffix : ONEOF('L', 'l') -rule DecimalIntegerLiteral: DecimalNumeral + ZEROORONE(IntegerTypeSuffix) -rule HexIntegerLiteral : HexNumeral + ZEROORONE(IntegerTypeSuffix) -rule OctalIntegerLiteral : OctalNumeral + ZEROORONE(IntegerTypeSuffix) - -rule IntegerLiteral: ONEOF(DecimalIntegerLiteral, - HexIntegerLiteral, - OctalIntegerLiteral) - -######################################################################### -## Floating Point ## -######################################################################### - -##### Decimal floating point literal - -rule Sign : ONEOF('+', '-') -rule FloatTypeSuffix : ONEOF('f', 'F') -rule ExponentIndicator : ONEOF('e', 'E') -rule SignedInteger : ZEROORONE(Sign) + Digit -rule ExponentPart : ExponentIndicator + SignedInteger - -rule DecFPLiteral : ONEOF(Digit + '.' + ZEROORONE(Digit) + ZEROORONE(ExponentPart) + ZEROORONE(FloatTypeSuffix), - '.'+Digit + ZEROORONE(ExponentPart) + ZEROORONE(FloatTypeSuffix), - Digit + ExponentPart + ZEROORONE(FloatTypeSuffix), - Digit + ZEROORONE(ExponentPart)) - -####### Hex floating point literal - -rule BinaryExponentIndicator : ONEOF('p', 'P') -rule BinaryExponent : BinaryExponentIndicator + SignedInteger -rule HexSignificand : ONEOF(HexNumeral + ZEROORONE('.'), - "0x" + ZEROORONE(HexDigit) + '.' + HexDigit, - "0X" + ZEROORONE(HexDigit) + '.' + HexDigit) -rule HexFPLiteral: HexSignificand + BinaryExponent + ZEROORONE(FloatTypeSuffix) - -###### Floating Point Literal - -rule FPLiteral : ONEOF(DecFPLiteral, HexFPLiteral) - -######################################################################### -## Boolean ## -######################################################################### - -rule BooleanLiteral : ONEOF ("true", "false") - -######################################################################### -## Character ## -## ESCAPE is a reserved rule in reserved.spec. ## -######################################################################### - -rule UnicodeEscape: '\' + 'u' + HEXDIGIT + HEXDIGIT + HEXDIGIT + HEXDIGIT -rule RawInputCharacter : ONEOF(ASCII, ''', ESCAPE) -rule SingleCharacter: ONEOF(UnicodeEscape, RawInputCharacter) - -rule OctalEscape : ONEOF('\' + '0', '\' + '1') -rule EscapeSequence : ONEOF(ESCAPE, OctalEscape) -rule CharacterLiteral : ''' + ONEOF(SingleCharacter, EscapeSequence) + ''' - -######################################################################### -## String ## -######################################################################### -# The UnicodeEscape is limited from \u0000 to \u00ff. -rule StringUnicodeEscape: '\' + 'u' + '0' + '0' + HEXDIGIT + HEXDIGIT -rule StringCharater: ONEOF(StringUnicodeEscape, RawInputCharacter) -rule StringLiteral : '"' + ZEROORMORE(StringCharater) + '"' - -######################################################################### -## Null ## -######################################################################### +# +# A literal is the source code representation of a value of a primitive type, the +# String type, or the null type. +# +# NOTE : Make sure there is a 'rule Literal'. This is the official rule recognized +# by autogen. + +# based on C11 specification A.1 Lexical grammar + +rule UniversalCharacterName : ONEOF( + '\' + 'u' + HexQuad, + '\' + 'U' + HexQuad + HexQuad +) + +rule HexQuad : ONEOF( + HexadecimalDigit + HexadecimalDigit + HexadecimalDigit + HexadecimalDigit +) + +rule IntegerLiteral : ONEOF( + DecimalConstant + ZEROORONE(IntegerSuffix), +# OctalConstant + ZEROORONE(IntegerSuffix), +# HexadecimalConstant + ZEROORONE(IntegerSuffix) +) + +rule DecimalConstant : ONEOF( + '0', NonzeroDigit + ZEROORMORE(DIGIT) +) + +rule OctalConstant : ONEOF( + '0', + OctalConstant + OctalDigit +) + +rule HexadecimalConstant : ONEOF( + HexadecimalPrefix + HexadecimalDigit, + HexadecimalConstant + HexadecimalDigit +) + +rule HexadecimalPrefix : ONEOF( + '0' + 'x', '0' + 'X' +) + +rule NonzeroDigit : ONEOF( + '1', '2', '3', '4', '5', '6', '7', '8', '9' +) + +rule OctalDigit : ONEOF( + '0', '1', '2', '3', '4', '5', '6', '7' +) + +rule HexadecimalDigit : ONEOF( + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' +) + +rule IntegerSuffix : ONEOF( + UnsignedSuffix + ZEROORONE(LongSuffix), + UnsignedSuffix + LongLongSuffix, + LongSuffix + ZEROORONE(UnsignedSuffix), + LongLongSuffix + ZEROORONE(UnsignedSuffix) +) + +rule UnsignedSuffix : ONEOF( + 'u', 'U' +) + +rule LongSuffix : ONEOF( + 'l', 'L' +) + +rule LongLongSuffix : ONEOF( + 'l' + 'l', 'L' + 'L' +) + +rule FPLiteral : ONEOF( + DecimalFloatingConstant, + HexadecimalFloatingConstant +) + +rule DecimalFloatingConstant : ONEOF( + FractionalConstant + ZEROORONE(ExponentPart) + ZEROORONE(FloatingSuffix), + DigitSequence + ExponentPart + ZEROORONE(FloatingSuffix) +) + +rule HexadecimalFloatingConstant : ONEOF( + HexadecimalPrefix + HexadecimalFractionalConstant, + BinaryExponentPart + ZEROORONE(FloatingSuffix), + HexadecimalPrefix + HexadecimalDigitSequence, + BinaryExponentPart + ZEROORONE(FloatingSuffix) +) + +rule FractionalConstant : ONEOF( + ZEROORONE(DigitSequence) + '.' + DigitSequence, + DigitSequence '.' +) + +rule ExponentPart : ONEOF( + 'e' + ZEROORONE(Sign) + DigitSequence, + 'E' + ZEROORONE(Sign) + DigitSequence +) + +rule Sign : ONEOF( + '+', '-' +) + +rule DigitSequence : ONEOF( + DIGIT, + DIGIT + ZEROORMORE(DIGIT) + DIGIT +) + attr.property.%2 : SecondTry + +rule HexadecimalFractionalConstant : ONEOF( + ZEROORONE(HexadecimalDigitSequence) + '.', + HexadecimalDigitSequence, + HexadecimalDigitSequence + '.' +) + +rule BinaryExponentPart : ONEOF( + 'p' + ZEROORONE(Sign) + DigitSequence, + 'P' + ZEROORONE(Sign) + DigitSequence +) + +rule HexadecimalDigitSequence : ONEOF( + HexadecimalDigit, + HexadecimalDigitSequence + HexadecimalDigit +) + +rule FloatingSuffix : ONEOF( + 'f', 'l', 'F', 'L' +) + +rule EnumerationConstant : Identifier + +rule CharacterLiteral : ONEOF( + ''' + CCharSequence + ''', + 'L' + ''' + CCharSequence + ''', + 'U' + ''' + CCharSequence + ''', + 'U' + ''' + CCharSequence + ''' +) + +rule CCharSequence : ONEOF( + CharChar, + CharChar + ZEROORMORE(CharChar) + CharChar +) + attr.property.%2 : SecondTry + +rule CharChar : ONEOF( #except ' \ and \n + PrintableChar, + '"', + #EscapeSequence +) + +# printalbe characters except ' and " +rule PrintableChar : ONEOF( + CHAR, + DIGIT, + ' ', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/', + ':', ';', '<', '=', '>', '?', '@', + '[', ']', '^', '_', '`', + '{', '|', '}', '~' +) + +rule EscapeSequence : ONEOF( + ESCAPE, + OctalEscapeSequence, + HexadecimalEscapeSequence, + UniversalCharacterName +) + +rule OctalEscapeSequence : ONEOF( + '\' + OctalDigit, + '\' + OctalDigit + OctalDigit, + '\' + OctalDigit + OctalDigit + OctalDigit +) + +rule HexadecimalEscapeSequence : ONEOF( + '\' + 'x' + HexadecimalDigit, + HexadecimalEscapeSequence + HexadecimalDigit +) + +rule StringLiteral : ONEOF( + ZEROORONE(EncodingPrefix) + '"' + ZEROORONE(SCharSequence) + '"' +) + +rule EncodingPrefix : ONEOF( + 'u' + '8', 'u', 'U', 'L' +) + +rule SCharSequence : ONEOF( + StringChar, + StringChar + ZEROORMORE(StringChar) + StringChar +) + attr.property.%2 : SecondTry + +rule StringChar : ONEOF( #except " \ and \n + PrintableChar, + ''', + #EscapeSequence +) rule NullLiteral : "NULL" +rule BooleanLiteral : ONEOF("true", "false") -######################################################################### -## Literal ## -######################################################################### +rule Literal : ONEOF( + IntegerLiteral, + FPLiteral, + EnumerationConstant, + CharacterLiteral, + StringLiteral, + NullLiteral +) -rule Literal : ONEOF(IntegerLiteral, - FPLiteral, - BooleanLiteral, - CharacterLiteral, - StringLiteral, - NullLiteral) \ No newline at end of file diff --git a/src/MapleFE/c/src/Makefile b/src/MapleFE/c/src/Makefile index 6947fdd0cb0f81fba87b75fa82bcc51d37e8b91c..e405a08b06d7813ace03d1aff2d77515f5f02c52 100644 --- a/src/MapleFE/c/src/Makefile +++ b/src/MapleFE/c/src/Makefile @@ -1,80 +1,78 @@ -# -# Copyright (c) [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 ../../Makefile.in -BUILDBIN=$(BUILDDIR)/bin -BUILD=$(BUILDDIR)/c -BUILDGEN=$(BUILDDIR)/gen -BUILDASTGEN=$(BUILDDIR)/ast_gen/shared -$(shell $(MKDIR_P) $(BUILD) $(BUILDGEN)) - -SRC=$(wildcard *.cpp) -OBJ :=$(patsubst %.cpp,%.o,$(SRC)) -DEP :=$(patsubst %.cpp,%.d,$(SRC)) - -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) - -INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ - -I $(MAPLEFE_ROOT)/c/include \ - -I $(MAPLEFE_ROOT)/autogen/include \ - -I ${BUILDDIR}/ast_gen/shared \ - -I $(BUILDGEN) - -INCLUDEGEN := -I $(BUILDGEN) -I $(MAPLEFE_ROOT)/shared/include - -TARGET=c2ast - -SHAREDLIB = $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a - -.PHONY: all -all: $(BUILDBIN)/$(TARGET) - --include $(DEPS) -.PHONY: clean - -vpath %.o $(BUILD) -vpath %.d $(BUILD) - -# Pattern Rules -$(BUILD)/%.o : %.cpp - $(CXX) $(CXXFLAGS) -fpermissive $(INCLUDES) -w -c $< -o $@ - -$(BUILD)/%.d : %.cpp - @$(CXX) $(CXXFLAGS) -std=c++11 -MM $(INCLUDES) $< > $@ - @mv -f $(BUILD)/$*.d $(BUILD)/$*.d.tmp - @sed -e 's|.*:|$(BUILD)/$*.o:|' < $(BUILD)/$*.d.tmp > $(BUILD)/$*.d - @rm -f $(BUILD)/$*.d.tmp - -$(BUILDGEN)/%.o : $(BUILDGEN)/%.cpp $(BUILDGEN)/%.d - $(CXX) $(CXXFLAGS) -fpermissive $(INCLUDEGEN) -w -c $< -o $@ - -$(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp - @$(CXX) $(CXXFLAGS) -std=c++11 -MM $(INCLUDEGEN) $< > $@ - @mv -f $(BUILDGEN)/$*.d $(BUILDGEN)/$*.d.tmp - @sed -e 's|.*:|$(BUILDGEN)/$*.o:|' < $(BUILDGEN)/$*.d.tmp > $(BUILDGEN)/$*.d - @rm -f $(BUILDGEN)/$*.d.tmp - -# TARGET depends on OBJS and shared OBJS from shared directory -# as well as mapleall libraries -$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) - @mkdir -p $(BUILDBIN) - $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(SHAREDLIB) -lstdc++fs - -clean: - rm -rf $(BUILD) +# +# Copyright (c) [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 ../../Makefile.in +BUILD=$(BUILDDIR)/c +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB) $(BUILDGEN)) + +SRC=$(wildcard *.cpp) +OBJ :=$(patsubst %.cpp,%.o,$(SRC)) +DEP :=$(patsubst %.cpp,%.d,$(SRC)) + +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) + +INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ + -I $(MAPLEFE_ROOT)/c/include \ + -I $(MAPLEFE_ROOT)/autogen/include \ + -I ${BUILDDIR}/ast_gen/shared \ + -I $(BUILDGEN) \ + $(MAPLEALL_INC) + +INCLUDEGEN := -I $(BUILDGEN) -I $(MAPLEFE_ROOT)/shared/include + +TARGET=c2ast + +SHAREDLIB = -L $(BUILDLIB) -lshared -lgenast + +.PHONY: all +all: $(BUILDBIN)/$(TARGET) + +-include $(DEPS) +.PHONY: clean + +vpath %.o $(BUILD) +vpath %.d $(BUILD) + +# Pattern Rules +$(BUILD)/%.o : %.cpp + $(CXX) $(CXXFLAGS) -fpermissive $(INCLUDES) -w -c $< -o $@ + +$(BUILD)/%.d : %.cpp + @$(CXX) $(CXXFLAGS) -std=c++11 -MM $(INCLUDES) $< > $@ + @mv -f $(BUILD)/$*.d $(BUILD)/$*.d.tmp + @sed -e 's|.*:|$(BUILD)/$*.o:|' < $(BUILD)/$*.d.tmp > $(BUILD)/$*.d + @rm -f $(BUILD)/$*.d.tmp + +$(BUILDGEN)/%.o : $(BUILDGEN)/%.cpp $(BUILDGEN)/%.d + $(CXX) $(CXXFLAGS) -fpermissive $(INCLUDEGEN) -w -c $< -o $@ + +$(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp + @$(CXX) $(CXXFLAGS) -std=c++11 -MM $(INCLUDEGEN) $< > $@ + @mv -f $(BUILDGEN)/$*.d $(BUILDGEN)/$*.d.tmp + @sed -e 's|.*:|$(BUILDGEN)/$*.o:|' < $(BUILDGEN)/$*.d.tmp > $(BUILDGEN)/$*.d + @rm -f $(BUILDGEN)/$*.d.tmp + +# TARGET depends on OBJS and shared OBJS from shared directory +# as well as mapleall libraries +$(BUILDBIN)/$(TARGET): $(OBJS) + @mkdir -p $(BUILDBIN) + $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(SHAREDLIB) $(MAPLELIBS) -lstdc++fs + +clean: + rm -rf $(BUILD) diff --git a/src/MapleFE/c/src/main.cpp b/src/MapleFE/c/src/main.cpp index f2247efd5cadaca1e2d44f82036d1e305a77ee5f..4677306dbfe53879eb4448954cb60f092b872bc3 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 += ".ast"; 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..0a484fc06f822af9abcea0119ee2083a68d4d3ea 100644 --- a/src/MapleFE/c/stmt.spec +++ b/src/MapleFE/c/stmt.spec @@ -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. @@ -12,131 +12,611 @@ # FIT FOR A PARTICULAR PURPOSE. # See the Mulan PSL v2 for more details. -###################################################################### -# Expression # -###################################################################### +# based "on" C11 specification A.2 Phrase structure grammar rule PrimaryExpression : ONEOF( + Identifier, Literal, - Identifier + StringLiteral, + '(' + Expression + ')', + GenericSelection +) + +rule GenericSelection : ONEOF( + "_Generic" + '(' + AssignmentExpression + ',' + GenericAssocList + ')' ) -rule DimExprs : DimExpr + ZEROORMORE(DimExpr) +rule GenericAssocList : ONEOF( + GenericAssociation, + GenericAssocList + ',' + GenericAssociation +) -rule DimExpr : '[' + Expression + ']' +rule GenericAssociation : ONEOF( + TypeName + ':' + AssignmentExpression, + "default" + ':' + AssignmentExpression +) -rule Expression : ONEOF( - PrimaryExpression) +rule PostfixExpression : ONEOF( + PrimaryExpression, + PostfixExpression + '[' + Expression + ']', + PostfixExpression + '(' + ZEROORONE(ArgumentExpressionList) + ')', + PostfixExpression + '.' + Identifier, + PostfixExpression + "->" + Identifier, + PostfixExpression + "++", + PostfixExpression + "--", + '(' + TypeName + ')' + '{' + InitializerList + '}', + '(' + TypeName + ')' + '{' + InitializerList + ',' + '}' +) + +rule ArgumentExpressionList : ONEOF( + AssignmentExpression, + ArgumentExpressionList + ',' + AssignmentExpression +) rule UnaryExpression : ONEOF( - PreIncrementExpression, - PreDecrementExpression) + PostfixExpression, + "++" + UnaryExpression, + "--" + UnaryExpression, + UnaryOperator + CastExpression, + "sizeof" + UnaryExpression, + "sizeof" + '(' + TypeName + ')', + "_Alignof" + '(' + TypeName + ')' +) + attr.action.%2,%3 : BuildUnaryOperation(%1, %2) + attr.action.%4 : BuildUnaryOperation(%1, %2) -rule PreIncrementExpression : "++" + PrimaryExpression - attr.action : BuildUnaryOperation(%1, %2) +rule UnaryOperator: ONEOF( + '&', '*', '+', '-', '~', '!' +) -rule PreDecrementExpression : "--" + PrimaryExpression - attr.action : BuildUnaryOperation(%1, %2) +rule CastExpression : ONEOF( + UnaryExpression, + '(' + TypeName + ')' + CastExpression +) + attr.action.%2 : BuildCast(%2, %4) -###################################################################### -# Variable # -###################################################################### +rule MultiplicativeExpression : ONEOF( + CastExpression, + MultiplicativeExpression + '*' + CastExpression, + MultiplicativeExpression + '/' + CastExpression, + MultiplicativeExpression + '%' + CastExpression +) + attr.action.%2,%3,%4 : BuildBinaryOperation(%1, %2, %3) -rule GlobalVariableDeclarationStatement : VariableDeclaration + ';' - attr.property : Top +rule AdditiveExpression : ONEOF( + MultiplicativeExpression, + AdditiveExpression + '+' + MultiplicativeExpression, + AdditiveExpression + '-' + MultiplicativeExpression +) + attr.action.%2,%3 : BuildBinaryOperation(%1, %2, %3) + +rule ShiftExpression : ONEOF( + AdditiveExpression, + ShiftExpression + "<<" + AdditiveExpression, + ShiftExpression + ">>" + AdditiveExpression +) + attr.action.%2,%3 : BuildBinaryOperation(%1, %2, %3) + +rule RelationalExpression : ONEOF( + ShiftExpression, + RelationalExpression + '<' + ShiftExpression, + RelationalExpression + '>' + ShiftExpression, + RelationalExpression + "<=" + ShiftExpression, + RelationalExpression + ">=" + ShiftExpression +) + attr.action.%2,%3,%4,%5 : BuildBinaryOperation(%1, %2, %3) + +rule EqualityExpression : ONEOF( + RelationalExpression, + EqualityExpression + "==" + RelationalExpression, + EqualityExpression + "!=" + RelationalExpression +) + attr.action.%2,%3 : BuildBinaryOperation(%1, %2, %3) + +rule ANDExpression : ONEOF( + EqualityExpression, + ANDExpression + '&' + EqualityExpression +) + attr.action.%2 : BuildBinaryOperation(%1, %2, %3) + +rule ExclusiveORExpression : ONEOF( + ANDExpression, + ExclusiveORExpression + '^' + ANDExpression +) + attr.action.%2 : BuildBinaryOperation(%1, %2, %3) + +rule InclusiveORExpression : ONEOF( + ExclusiveORExpression, + InclusiveORExpression + '|' + ExclusiveORExpression +) + attr.action.%2 : BuildBinaryOperation(%1, %2, %3) + +rule LogicalANDExpression : ONEOF( + InclusiveORExpression, + LogicalANDExpression + "&&" + InclusiveORExpression +) + attr.action.%2 : BuildBinaryOperation(%1, %2, %3) + +rule LogicalORExpression : ONEOF( + LogicalANDExpression, + LogicalORExpression + "||" + LogicalANDExpression +) + attr.action.%2 : BuildBinaryOperation(%1, %2, %3) + +rule ConditionalExpression : ONEOF( + LogicalORExpression, + LogicalORExpression + '?' + Expression + ':' + ConditionalExpression +) -rule LocalVariableDeclarationStatement : VariableDeclaration + ';' +rule AssignmentExpression : ONEOF( + ConditionalExpression, + UnaryExpression + AssignmentOperator + AssignmentExpression +) + attr.action.%2 : BuildAssignment(%1, %2, %3) -rule VariableDeclaration : ZEROORMORE(VariableModifier) + Type + VariableDeclaratorList - attr.action: BuildDecl(%2, %3) - attr.action: AddModifier(%1) +rule AssignmentOperator: ONEOF( + '=', "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|=" +) + attr.property : Single + +rule Expression : ONEOF( + AssignmentExpression, + Expression + ',' + AssignmentExpression +) + +rule ConstantExpression : ONEOF( + ConditionalExpression +) + +rule Declaration : ONEOF( + ZEROORONE(DeclarationSpecifiers) + TypeSpecifiers + InitDeclaratorList + ';', + Static_assertDeclaration +) + attr.property : Single + attr.action.%1: BuildDecl(%2, %3) + attr.action.%1: AddModifier(%1) + +rule TypeSpecifiers : TypeSpecifier + ZEROORMORE(TypeSpecifier) + +rule DeclarationSpecifiers : ONEOF( + StorageClassSpecifier + ZEROORONE(DeclarationSpecifiers), + TypeQualifier + ZEROORONE(DeclarationSpecifiers), + FunctionSpecifier + ZEROORONE(DeclarationSpecifiers), + AlignmentSpecifier + ZEROORONE(DeclarationSpecifiers) +) -rule VariableModifier : ONEOF( +rule InitDeclaratorList : ONEOF( + InitDeclarator, + InitDeclaratorList + ',' + InitDeclarator +) + +rule InitDeclarator : ONEOF( + Declarator, + Declarator + '=' + Initializer +) + attr.action.%2: AddInitTo(%1, %3) + +rule StorageClassSpecifier : ONEOF( + "typedef", + "extern", "static", + "_Thread_local", + "auto", + "register" +) + attr.property : Single + +rule TypeSpecifier : ONEOF( + "void", + "char", + "short", + "int", + "long", + "float", + "double", + "signed", + "unsigned", + "_Bool", + "_Complex", + AtomicTypeSpecifier, + StructOrUnionSpecifier, + EnumSpecifier, + TypedefName +) + attr.property : Single + +rule StructOrUnionSpecifier : ONEOF( + StructOrUnion + ZEROORONE(Identifier) + '{' + StructDeclarationList + '}', + StructOrUnion + Identifier +) + +rule StructOrUnion : ONEOF( + "struct", + "union" +) + attr.property : Single + +rule StructDeclarationList : ONEOF( + StructDeclaration, + StructDeclarationList + StructDeclaration +) + +rule StructDeclaration : ONEOF( + SpecifierQualifierList + ZEROORONE(StructDeclaratorList) + ';', + Static_assertDeclaration +) + +rule SpecifierQualifierList : ONEOF( + TypeSpecifier + ZEROORONE(SpecifierQualifierList), + TypeQualifier + ZEROORONE(SpecifierQualifierList) +) + +rule StructDeclaratorList : ONEOF( + StructDeclarator, + StructDeclaratorList + ',' + StructDeclarator +) + +rule StructDeclarator : ONEOF( + Declarator, + ZEROORONE(Declarator) + ':' + ConstantExpression +) + +rule EnumSpecifier : ONEOF( + "enum" + ZEROORONE(Identifier) + '{' + EnumeratorList + '}', + "enum" + ZEROORONE(Identifier) + '{' + EnumeratorList + ',' + '}', + "enum" + Identifier +) + +rule EnumeratorList : ONEOF( + Enumerator, + EnumeratorList + ',' + Enumerator +) + +rule Enumerator : ONEOF( + EnumerationConstant, + EnumerationConstant + '=' + ConstantExpression +) + +rule AtomicTypeSpecifier : ONEOF( + "_Atomic" + '(' + TypeName + ')' +) + +rule TypeQualifier : ONEOF( "const", + "restrict", "volatile", - "restrict") + "_Atomic" +) -rule VariableDeclaratorList : VariableDeclarator + ZEROORMORE(',' + VariableDeclarator) - attr.action: BuildVarList(%1, %2) +rule FunctionSpecifier : ONEOF( + "inline", + "_Noreturn" +) -rule VariableDeclarator : VariableDeclaratorId + ZEROORONE('=' + VariableInitializer) - attr.action: AddInitTo(%1, %2) +rule AlignmentSpecifier : ONEOF( + "_Alignas" + '(' + TypeName + ')', + "_Alignas" + '(' + ConstantExpression + ')' +) -rule VariableDeclaratorId : Identifier + ZEROORONE(Dims) - attr.action: AddDimsTo(%1, %2) +rule Declarator : ONEOF( + ZEROORONE(Pointer) + DirectDeclarator +) -rule VariableInitializer : ONEOF( - Expression, - ArrayInitializer) +rule DirectDeclarator : ONEOF( + Identifier, + '(' + Declarator + ')', + DirectDeclarator + '[' + ZEROORONE(TypeQualifierList) + ZEROORONE(AssignmentExpression) + ']', + DirectDeclarator + '[' + "static" + ZEROORONE(TypeQualifierList) + AssignmentExpression + ']', + DirectDeclarator + '[' + TypeQualifierList + "static" + AssignmentExpression + ']', + DirectDeclarator + '[' + ZEROORONE(TypeQualifierList) + '*' + ']', + DirectDeclarator + '(' + ParameterTypeList + ')', + DirectDeclarator + '(' + ZEROORONE(IdentifierList) + ')' +) -rule ArrayInitializer : '{' + ZEROORONE(VariableInitializerList) + ZEROORONE(',') + '}' +rule Pointer : ONEOF( + '*' + ZEROORONE(TypeQualifierList), + '*' + ZEROORONE(TypeQualifierList) + Pointer +) -rule VariableInitializerList: VariableInitializer + ZEROORMORE(',' + VariableInitializer) +rule TypeQualifierList : ONEOF( + TypeQualifier, + TypeQualifierList + TypeQualifier +) -rule Dims : Dim + ZEROORMORE(Dim) - attr.action: BuildDims(%1, %2) +rule ParameterTypeList : ONEOF( + ParameterList, + ParameterList + ',' + "..." +) -rule Dim : '[' + ']' - attr.action: BuildDim(%1) +rule ParameterList : ONEOF( + ParameterDeclaration, + ParameterList + ',' + ParameterDeclaration +) -###################################################################### -# statement # -###################################################################### +rule ParameterDeclaration : ONEOF( + DeclarationSpecifiers + Declarator, + DeclarationSpecifiers + ZEROORONE(AbstractDeclarator) +) -rule Statement : ONEOF(LocalVariableDeclarationStatement, - ReturnStatement) - attr.property: Single +rule IdentifierList : ONEOF( + Identifier, + IdentifierList + ',' + Identifier +) -rule ReturnStatement : "return" + ZEROORONE(Expression) + ';' - attr.action : BuildReturn(%2) +rule TypeName : ONEOF( + SpecifierQualifierList + ZEROORONE(AbstractDeclarator) +) + +rule AbstractDeclarator : ONEOF( + Pointer, + ZEROORONE(Pointer) + DirectAbstractDeclarator +) -###################################################################### -# Function # -###################################################################### +rule DirectAbstractDeclarator : ONEOF( + '(' + AbstractDeclarator + ')', + ZEROORONE(DirectAbstractDeclarator) + '[' + ZEROORONE(TypeQualifierList), + ZEROORONE(AssignmentExpression) + ']', + ZEROORONE(DirectAbstractDeclarator) + '[' + "static" + ZEROORONE(TypeQualifierList), + AssignmentExpression + ']', + ZEROORONE(DirectAbstractDeclarator) + '[' + TypeQualifierList + "static", + AssignmentExpression + ']', + ZEROORONE(DirectAbstractDeclarator) + '[' + '*' + ']', + ZEROORONE(DirectAbstractDeclarator) + '(' + ZEROORONE(ParameterTypeList) + ')' +) -rule GlobalFuncDeclaration : FuncDeclaration - attr.property : Top +rule TypedefName : ONEOF( + Identifier +) + +rule Initializer : ONEOF( + AssignmentExpression, + '{' + InitializerList + '}', + '{' + InitializerList + ',' + '}' +) -rule FuncDeclaration : ZEROORMORE(FuncModifier) + FuncHeader + FuncBody - attr.action: AddModifierTo(%2, %1) - attr.action: AddFunctionBodyTo(%2, %3) +rule InitializerList : ONEOF( + ZEROORONE(Designation) + Initializer, + InitializerList + ',' + ZEROORONE(Designation) + Initializer +) -rule FuncBody : ONEOF(Block, ';') +rule Designation : ONEOF( + DesignatorList + '=' +) + +rule DesignatorList : ONEOF( + Designator, + DesignatorList + Designator +) + +rule Designator : ONEOF( + '[' + ConstantExpression + ']', + '.' + Identifier +) + +rule Static_assertDeclaration : ONEOF( + "_Static_assert" + '(' + ConstantExpression + ',' + StringLiteral + ')' + ';' +) + +rule Statement : ONEOF( + LabeledStatement, + CompoundStatement, + ExpressionStatement, + SelectionStatement, + IterationStatement, + JumpStatement +) + attr.property : Top + +rule LabeledStatement : ONEOF( + Identifier + ':' + Statement, + "case" + ConstantExpression + ':' + Statement, + "default" + ':' + Statement +) attr.property : Single -rule FuncHeader : ONEOF(Result + FuncDeclarator) - attr.action.%1: AddType(%2, %1) +rule CompoundStatement : '{' + ZEROORONE(BlockItemList) + '}' + attr.action: BuildBlock(%2) + +rule BlockItemList : BlockItem + ZEROORMORE(BlockItem) + attr.property.%2 : ZomFast + +rule BlockItem : ONEOF( + Declaration, + Statement +) + +rule ExpressionStatement : ONEOF( + ZEROORONE(Expression) + ';' +) + +rule SelectionStatement : ONEOF( + "if" + '(' + Expression + ')' + Statement, + "if" + '(' + Expression + ')' + Statement + "else" + Statement, + "switch" + '(' + Expression + ')' + Statement +) + +rule IterationStatement : ONEOF( + "while" + '(' + Expression + ')' + Statement, + "do" + Statement + "while" + '(' + Expression + ')' + ';', + "for" + '(' + ZEROORONE(Expression) + ';' + ZEROORONE(Expression) + ';' + ZEROORONE(Expression) + ')' + Statement, + "for" + '(' + Declaration + ZEROORONE(Expression) + ';' + ZEROORONE(Expression) + ')' + Statement +) attr.property : Single -rule Result : ONEOF(Type, "void") +rule JumpStatement : ONEOF( + "goto" + Identifier + ';', + "continue" + ';', + "break" + ';', + ReturnStatement +) attr.property : Single -rule FuncDeclarator : Identifier + '(' + ZEROORONE(FormalParameters) + ')' +rule ReturnStatement : "return" + ZEROORONE(Expression) + ';' + attr.action : BuildReturn(%2) + +rule TranslationUnit : ONEOF( + ExternalDeclaration, + TranslationUnit + ExternalDeclaration +) + +rule ExternalDeclaration : ONEOF( + Declaration, + FunctionDefinition +) + attr.property : Top + +rule FunctionDefinition : FuncSig + CompoundStatement + attr.action: AddFunctionBodyTo(%1, %2) + +rule FuncSig : RetType + FuncDecl + attr.action: AddType(%2, %1) + +rule RetType : ONEOF(Type, "void") + +rule FuncDecl : Identifier + '(' + ZEROORONE(FormalParameters) + ')' attr.action: BuildFunction(%1) attr.action: AddParams(%3) -rule FuncAttr : ONEOF("const", "static") - attr.property : Single +rule FormalParameters : FormalParameter + ZEROORMORE(',' + FormalParameter) -rule FuncModifier : ONEOF(FuncAttr) - attr.property : Single +rule FormalParameter : Type + Identifier + attr.action: BuildDecl(%1, %2) + +rule DeclarationList : ONEOF( + Declaration, + DeclarationList + Declaration +) + +rule preprocessingFile: ONEOF( + ZEROORONE(Group) +) + +rule Group: ONEOF( + GroupPart, + Group + GroupPart +) + +rule GroupPart: ONEOF( + IfSection, + ControlLine, + TextLine, + '#' + NonDirective +) + +rule IfSection: ONEOF( + IfGroup + ZEROORONE(ElifGroups) + ZEROORONE(ElseGroup) + EndifLine +) -rule FormalParameters : ONEOF(FormalParameter + ZEROORMORE(',' + FormalParameter)) +rule IfGroup: ONEOF( + '#' + "if" + ConstantExpression + NewLine + ZEROORONE(Group), + '#' + "ifdef" + Identifier + NewLine + ZEROORONE(Group), + '#' + "ifndef" + Identifier + NewLine + ZEROORONE(Group) +) attr.property : Single -rule FormalParameter : ZEROORMORE(VariableModifier) + Type + VariableDeclaratorId - attr.action: BuildDecl(%2, %3) - attr.action: AddModifier(%1) +rule ElifGroups: ONEOF( + ElifGroup, + ElifGroups + ElifGroup +) + +rule ElifGroup: ONEOF( + '#' + "elif" + ConstantExpression + NewLine + ZEROORONE(Group) +) -###################################################################### -# Block # -###################################################################### +rule ElseGroup: ONEOF( + '#' + "else" + NewLine + ZEROORONE(Group) +) -rule BlockStatement : ONEOF(LocalVariableDeclarationStatement, Statement) +rule EndifLine: ONEOF( + '#' + "endif" + NewLine +) + +rule ControlLine: ONEOF( + '#' + "include" + PpTokens + NewLine, + '#' + "define" + Identifier + ReplacementList + NewLine, + '#' + "define" + Identifier + Lparen + ZEROORONE(IdentifierList) + ')' + ReplacementList + NewLine, + '#' + "define" + Identifier + Lparen + "..." + ')' + ReplacementList + NewLine, + '#' + "define" + Identifier + Lparen + IdentifierList + ',' + "..." + ')' + ReplacementList + NewLine, + '#' + "undef" + Identifier + NewLine, + '#' + "line" + PpTokens + NewLine, + '#' + "error" + ZEROORONE(PpTokens) + NewLine, + '#' + "pragma" + ZEROORONE(PpTokens) + NewLine, + '#' + NewLine +) attr.property : Single -rule BlockStatements : BlockStatement + ZEROORMORE(BlockStatement) +rule TextLine: ONEOF( + ZEROORONE(PpTokens) + NewLine +) + +rule NonDirective: ONEOF( + PpTokens + NewLine +) + +rule Lparen: ONEOF( + '(' +) + +rule ReplacementList: ONEOF( + ZEROORONE(PpTokens) +) + +rule PpTokens: ONEOF( + PreprocessingToken, + PpTokens + PreprocessingToken +) + +rule NewLine: '\' + 'n' + +rule PreprocessingToken: ONEOF( + HeaderName, + Identifier, + PpNumber, + CharacterLiteral, + StringLiteral, + Punctuator, + #Each nonWhiteSpace character that cannot be one of the above +) + +rule Punctuator: ONEOF( + '[', ']', '(', ')', '{', '}', '.', "->", + "++", "--", '&', '*', '+', '-', '~', '!', '/', '%', + "<<", ">>", '<', '>', "<=", ">=", "==", "!=", '^', '|', "&&", "||", + '?', ':', ';', "...", + '=', "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", "&=", "^=", "|=", + ',', '#', "##", "<:", ":>", "<%", "%>", "%:", "%:%:" +) + +rule HeaderName: ONEOF( + '<' + HCharSequence + '>', + '"' + QCharSequence + '"' +) + +rule HCharSequence: ONEOF( + HChar, + HCharSequence + HChar +) + +rule HChar: ONEOF(CHAR, DIGIT, '-', '_') + +rule QCharSequence: ONEOF( + QChar, + QCharSequence + QChar +) + +rule QChar: ONEOF(CHAR, DIGIT, '-', '_') + +rule PpNumber: ONEOF( + DIGIT, + '.' + DIGIT, + PpNumber + DIGIT, + PpNumber + ONEOF(CHAR, '_'), + PpNumber + 'e' + Sign0, + PpNumber + 'E' + Sign0, + PpNumber + 'p' + Sign0, + PpNumber + 'P' + Sign0, + PpNumber + '.' +) + +rule Sign0 : ONEOF('+', '-') -rule Block : '{' + ZEROORONE(BlockStatements) + '}' - attr.action: BuildBlock(%2) 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/envsetup.sh b/src/MapleFE/envsetup.sh index bc75a54707313c7edd50cad8b64557d54b67b914..4f106000bc74d34cdd98aeba3f0b16e04b97fb8f 100755 --- a/src/MapleFE/envsetup.sh +++ b/src/MapleFE/envsetup.sh @@ -40,13 +40,10 @@ fi export SRCLANG=$LANGSRC export MAPLEFE_ROOT=$(cd $(dirname ${BASH_SOURCE[0]}); pwd) -export MAPLE_ROOT=$(cd ${MAPLEFE_ROOT}/../../..; pwd) - -unset MAPLEALL_ROOT -export MAPLEALL_ROOT=${MAPLE_ROOT}/OpenArkCompiler +export MAPLE_ROOT=$(cd ${MAPLEFE_ROOT}/../..; pwd) unset MAPLEALL_SRC -export MAPLEALL_SRC=${MAPLEALL_ROOT}/src/mapleall +export MAPLEALL_SRC=${MAPLE_ROOT}/src/mapleall unset BUILDDIR export BUILDDIR=${MAPLEFE_ROOT}/output/${SRCLANG} diff --git a/src/MapleFE/java/src/Makefile b/src/MapleFE/java/src/Makefile index 7715078eb86192d2422d3f29aec0b0c0a0a5c5aa..64714a24f478a2b97f74daab542bb7965e3bced5 100644 --- a/src/MapleFE/java/src/Makefile +++ b/src/MapleFE/java/src/Makefile @@ -13,11 +13,8 @@ # include ../../Makefile.in -BUILDBIN=$(BUILDDIR)/bin BUILD=$(BUILDDIR)/java -BUILDGEN=$(BUILDDIR)/gen -BUILDASTGEN=$(BUILDDIR)/ast_gen/shared -$(shell $(MKDIR_P) $(BUILD) $(BUILDGEN)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB) $(BUILDGEN)) SRC=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) @@ -33,17 +30,18 @@ DEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) $(DEPG) INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ -I $(MAPLEFE_ROOT)/java/include \ -I $(MAPLEFE_ROOT)/autogen/include \ - -I ${BUILDDIR}/ast_gen/shared \ - -I $(BUILDGEN) $(MAPLEALL_INC) + -I ${BUILDASTGEN} \ + -I $(BUILDGEN) \ + $(MAPLEALL_INC) INCLUDEGEN := -I $(BUILDGEN) -I $(MAPLEFE_ROOT)/shared/include TARGET=java2ast -SHAREDLIB = $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a +SHAREDLIB = -L $(BUILDLIB) -lshared -lgenast .PHONY: all -all: $(BUILD)/$(TARGET) +all: $(BUILDBIN)/$(TARGET) -include $(DEPS) .PHONY: clean @@ -72,7 +70,7 @@ $(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILD)/$(TARGET): $(OBJS) $(SHAREDLIB) +$(BUILDBIN)/$(TARGET): $(OBJS) @mkdir -p $(BUILDBIN) $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(SHAREDLIB) $(MAPLELIBS) diff --git a/src/MapleFE/ladetect/Makefile b/src/MapleFE/ladetect/Makefile index 3badd03259474113eedfb80b0f9aed5609b63823..46e0b4449228856f7b56102c41e04b6b8465c35f 100644 --- a/src/MapleFE/ladetect/Makefile +++ b/src/MapleFE/ladetect/Makefile @@ -16,8 +16,7 @@ include ../Makefile.in # create build first BUILD=$(BUILDDIR)/ladetect -BUILDGEN=$(BUILDDIR)/gen -$(shell $(MKDIR_P) $(BUILD) $(BUILDGEN)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB) $(BUILDGEN)) SRCG := $(wildcard $(BUILDGEN)/gen_*.cpp) OBJG := $(patsubst %.cpp, %.o, $(SRCG)) @@ -39,7 +38,7 @@ INCLUDES := -I $(MAPLEFE_ROOT)/ladetect \ INCLUDEGEN := -I $(BUILDGEN) -I $(MAPLEFE_ROOT)/shared/include -SHAREDLIB = $(BUILDDIR)/shared/shared.a +SHAREDLIB = -L $(BUILDLIB) -lshared TARGET = ladetect @@ -47,7 +46,7 @@ TARGET = ladetect all: $(BUILD)/$(TARGET) -$(BUILD)/$(TARGET) : $(OBJS) $(SHAREDLIB) +$(BUILD)/$(TARGET) : $(OBJS) $(LD) -o $(BUILD)/$(TARGET) $(OBJS) $(SHAREDLIB) (cd $(BUILD); ./$(TARGET)) diff --git a/src/MapleFE/ladetect/la_detect.cpp b/src/MapleFE/ladetect/la_detect.cpp index 49757bab478a9dc1923ba914f572f824646fe25b..87fce46b508029ac40736bb712a75fce335e87e1 100644 --- a/src/MapleFE/ladetect/la_detect.cpp +++ b/src/MapleFE/ladetect/la_detect.cpp @@ -28,8 +28,13 @@ std::string GetLookAheadString(LookAhead la) { std::string str = "{"; switch (la.mType) { case LA_Char: - str += "LA_Char, "; + str += "LA_Char, \'"; + // need escape + if (la.mData.mChar == '\\' || la.mData.mChar == '\'') { + str += "\\"; + } str += la.mData.mChar; + str += "\'"; break; case LA_String: str += "LA_String, \""; diff --git a/src/MapleFE/recdetect/Makefile b/src/MapleFE/recdetect/Makefile index 025b900d399d63e2cab3d3bb9e35a7a9eedb3ca9..fef2f438291ef54ca8fce686cf2a021131953420 100644 --- a/src/MapleFE/recdetect/Makefile +++ b/src/MapleFE/recdetect/Makefile @@ -16,8 +16,7 @@ include ../Makefile.in # create build first BUILD=$(BUILDDIR)/recdetect -BUILDGEN=$(BUILDDIR)/gen -$(shell $(MKDIR_P) $(BUILD) $(BUILDGEN)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB) $(BUILDGEN)) SRCG := $(wildcard $(BUILDGEN)/gen_*.cpp) OBJG := $(patsubst %.cpp, %.o, $(SRCG)) @@ -36,7 +35,7 @@ INCLUDES := -I $(MAPLEFE_ROOT)/recdetect \ -I $(MAPLEFE_ROOT)/shared/include \ -I $(BUILDGEN) -SHAREDLIB = $(BUILDDIR)/shared/shared.a +SHAREDLIB = -L $(BUILDLIB) -lshared TARGET = recdetect @@ -44,7 +43,7 @@ TARGET = recdetect all: $(BUILD)/$(TARGET) -$(BUILD)/$(TARGET) : $(OBJS) $(SHAREDLIB) +$(BUILD)/$(TARGET) : $(OBJS) $(LD) -o $(BUILD)/$(TARGET) $(OBJS) $(SHAREDLIB) (cd $(BUILD); ./$(TARGET)) diff --git a/src/MapleFE/scripts/build_mapleall.sh b/src/MapleFE/scripts/build_mapleall.sh index c1c5d7375cdb59f496a9c361166f40eab0b2a456..63c03a79eef871eaad7d9888eefe84a86fab69e3 100755 --- a/src/MapleFE/scripts/build_mapleall.sh +++ b/src/MapleFE/scripts/build_mapleall.sh @@ -15,14 +15,7 @@ set -e -if [ ! -d $MAPLEALL_ROOT ]; then - cd $MAPLE_ROOT - git clone https://gitee.com/openarkcompiler/OpenArkCompiler.git -b dev_MapleFE -fi - -cd $MAPLEALL_ROOT -git checkout dev_MapleFE -git pull +cd $MAPLE_ROOT source build/envsetup.sh arm debug make setup make clobber 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_builder.h b/src/MapleFE/shared/include/ast_builder.h index 74ab70396f1a38e847fe91b4cacc9c21d4dec524..ec9a1971bfae39a6f959b40f0dc30475f249578a 100644 --- a/src/MapleFE/shared/include/ast_builder.h +++ b/src/MapleFE/shared/include/ast_builder.h @@ -89,6 +89,8 @@ public: #define ACTION(K) TreeNode* K(); #include "supported_actions.def" + void RecursiveAddModifier(TreeNode *target, TreeNode *modifier); + void AddArguments(TreeNode *call, TreeNode *args); void AddParams(TreeNode *func, TreeNode *params); }; 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..2916b9b9ec600ca22aeda28f69611a49373b3469 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, @@ -210,6 +212,8 @@ public: void SetToken(Token *t) { mIsTable = false; mData.mToken = t; } RuleTable* GetTable() { return mData.mTable; } Token* GetToken() { return mData.mToken; } + + void Dump(unsigned indent); }; class RecursionTraversal; @@ -268,7 +272,7 @@ public: // It's common in dynamic loading of code in web application. void SetLexerTrace() {mLexer->SetTrace();} - void DumpIndentation(); + void DumpIndentation(unsigned indent); void DumpEnterTable(const char *tablename, unsigned indent); void DumpExitTable(const char *tablename, unsigned indent, AppealNode*); void DumpExitTable(const char *tablename, unsigned indent, AppealStatus, AppealNode *n = NULL); @@ -302,6 +306,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/parser_rec.h b/src/MapleFE/shared/include/parser_rec.h index bd79654e3d31e1ad1d2f15b31613052c9df37b69..46f0a715efe25c384ccae2b29e22a3e14410475d 100644 --- a/src/MapleFE/shared/include/parser_rec.h +++ b/src/MapleFE/shared/include/parser_rec.h @@ -116,7 +116,7 @@ public: void SetTrace(bool b){mTrace = b;} void SetIndentation(unsigned i) {mIndentation = i;} - void DumpIndentation(); + void DumpIndentation(unsigned indent); void AddVisitedLeadNode(RuleTable *rt) {mVisitedLeadNodes.PushBack(rt);} bool LeadNodeVisited(RuleTable *rt) {return mVisitedLeadNodes.Find(rt);} 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_attributes.def b/src/MapleFE/shared/include/supported_attributes.def index 86cc52600ea92b50476cd939557b8f7b454150ac..127c3a53a46128182c73896982e1ad1ef9f054ae 100644 --- a/src/MapleFE/shared/include/supported_attributes.def +++ b/src/MapleFE/shared/include/supported_attributes.def @@ -29,6 +29,15 @@ ATTRIBUTE(strictfp) ATTRIBUTE(default) ATTRIBUTE(synchronized) ATTRIBUTE(async) + ATTRIBUTE(readonly) // Typescript ATTRIBUTE(getter) // Javascript getter function ATTRIBUTE(setter) // Javascript setter function + +// added for C +ATTRIBUTE(restrict) +ATTRIBUTE(typedef) +ATTRIBUTE(extern) +ATTRIBUTE(auto) +ATTRIBUTE(register) +ATTRIBUTE(inline) 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..8e6b37b40e72d299f24fc7fd9a73a1677dec84e4 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,9 @@ private: std::vector mTypeTable; std::unordered_map mNodeId2TypeIdxMap; std::unordered_map mTypeId2TypeMap; + std::unordered_map mStrIdx2BuiltInTypeIdxMap; + std::unordered_set mPrimTypeId; + std::unordered_set mFuncTypeIdx; unsigned mPrimSize; unsigned mPreBuildSize; @@ -60,14 +65,27 @@ 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); + + bool IsBuiltInType(TreeNode *node); + unsigned GetBuiltInTypeIdx(unsigned stridx); + unsigned GetBuiltInTypeIdx(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/Makefile b/src/MapleFE/shared/src/Makefile index e09a8359da282bcbcfa5eb587cfb226eff3a9939..3fd572187d2fba2160304c5d735eb9ead00a17e1 100644 --- a/src/MapleFE/shared/src/Makefile +++ b/src/MapleFE/shared/src/Makefile @@ -14,7 +14,7 @@ include ../../Makefile.in BUILD=$(BUILDDIR)/shared -$(shell $(MKDIR_P) $(BUILD)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB)) SRC=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) @@ -36,15 +36,15 @@ ASTSRCG:=$(wildcard ${GENASTDIR}/*.cpp) ASTOBJG:=$(patsubst %.cpp,%.o,$(ASTSRCG)) ASTDEPG:=$(patsubst %.cpp,%.d,$(ASTSRCG)) -INCLUDES := -I $(MAPLEFE_ROOT)/shared/include -I ${GENASTDIR} -I ${GENDIR} +INCLUDES := -I $(MAPLEFE_ROOT)/shared/include -I ${GENASTDIR} -I ${GENDIR} -I $(MAPLEFE_ROOT)/$(SRCLANG)/include -SHAREDLIB := shared.a -GENASTLIB := genast.a -GENLIB := gen.a +SHAREDLIB := libshared.a +GENASTLIB := libgenast.a +GENLIB := libgen.a .PHONY: all gen_doc clean -all: $(BUILD)/$(SHAREDLIB) $(GENASTDIR)/$(GENASTLIB) $(GENDIR)/$(GENLIB) +all: $(BUILDLIB)/$(SHAREDLIB) $(BUILDLIB)/$(GENASTLIB) $(BUILDLIB)/$(GENLIB) -include $(DEPS) @@ -78,14 +78,14 @@ $(GENDIR)/%.o : $(GENDIR)/%.cpp $(GENDIR)/%.d : $(GENDIR)/%.cpp @$(CXX) $(CXXFLAGS) -std=c++11 -MM $(INCLUDES) $< > $@ -$(BUILD)/$(SHAREDLIB) : $(LIBOBJS) - /usr/bin/ar rcs $(BUILD)/$(SHAREDLIB) $(LIBOBJS) +$(BUILDLIB)/$(SHAREDLIB) : $(LIBOBJS) + /usr/bin/ar rcs $(BUILDLIB)/$(SHAREDLIB) $(LIBOBJS) -$(GENASTDIR)/$(GENASTLIB) : $(ASTOBJG) - /usr/bin/ar rcs $(GENASTDIR)/$(GENASTLIB) $(ASTOBJG) +$(BUILDLIB)/$(GENASTLIB) : $(ASTOBJG) + /usr/bin/ar rcs $(BUILDLIB)/$(GENASTLIB) $(ASTOBJG) -$(GENDIR)/$(GENLIB) : $(OBJG) - /usr/bin/ar rcs $(GENDIR)/$(GENLIB) $(OBJG) +$(BUILDLIB)/$(GENLIB) : $(OBJG) + /usr/bin/ar rcs $(BUILDLIB)/$(GENLIB) $(OBJG) clean: rm -rf $(BUILD) 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..d30d0e1a4679e9826c20dec60871d388de99e36a 100644 --- a/src/MapleFE/shared/src/ast_builder.cpp +++ b/src/MapleFE/shared/src/ast_builder.cpp @@ -159,6 +159,9 @@ static void add_attribute_to(TreeNode *tree, TreeNode *attr) { TreeNode *child = vl->GetExprAtIndex(i); add_attribute_to(child, attr); } + } else if (tree->IsDecl()) { + DeclNode *dn = (DeclNode*)tree; + dn->GetVar()->AddAttr(aid); } else { // The basse TreeNode has a virtual AddAttr(). tree->AddAttr(aid); @@ -176,14 +179,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); @@ -879,7 +882,7 @@ TreeNode* ASTBuilder::BuildPostfixOperation() { // For second parameter has to be an operator. TreeNode* ASTBuilder::BuildBinaryOperation() { if (mTrace) - std::cout << "In build binary" << std::endl; + std::cout << "In BuildBinaryOperation" << std::endl; MASSERT(mParams.size() == 3 && "Binary Operator has NO 3 params?"); Param p_a = mParams[0]; @@ -1040,6 +1043,8 @@ TreeNode* ASTBuilder::SetIsConst() { } treenode->SetIsConst(); + + mLastTreeNode = treenode; return mLastTreeNode; } @@ -1073,7 +1078,7 @@ TreeNode* ASTBuilder::SetIsUnique() { // Assignment is actually a binary operator. TreeNode* ASTBuilder::BuildAssignment() { if (mTrace) - std::cout << "In assignment --> BuildBinary" << std::endl; + std::cout << "In BuildAssignment --> BuildBinary" << std::endl; return BuildBinaryOperation(); } @@ -1672,9 +1677,9 @@ TreeNode* ASTBuilder::AddAsType() { if (tree_type) { node->AddAsTypes(tree_type); - mLastTreeNode = node; } + mLastTreeNode = node; return mLastTreeNode; } @@ -2277,26 +2282,10 @@ TreeNode* ASTBuilder::AddModifier() { MERROR("The modifier is not a treenode"); } } else { - mod= p_mod.mData.mTreeNode; + mod = p_mod.mData.mTreeNode; } - if (mod->IsPass()) { - PassNode *pass = (PassNode*)mod; - for (unsigned i = 0; i < pass->GetChildrenNum(); i++) { - TreeNode *child = pass->GetChild(i); - if (child->IsAnnotation()) { - AnnotationNode *a = (AnnotationNode*)child; - mLastTreeNode->AddAnnotation(a); - } else { - add_attribute_to(mLastTreeNode, child); - } - } - } else if (mod->IsAnnotation()) { - AnnotationNode *a = (AnnotationNode*)mod; - mLastTreeNode->AddAnnotation(a); - } else { - add_attribute_to(mLastTreeNode, mod); - } + RecursiveAddModifier(mLastTreeNode, mod); } else if (mParams.size() == 2) { // the two modifiers are in fixed order, with +/- at first // readonly/? the second. @@ -2354,6 +2343,32 @@ TreeNode* ASTBuilder::AddModifier() { return mLastTreeNode; } +// Takes two arguments. 1) target tree node; 2) modifier, which could be +// attr, annotation/pragma or PassNode which could contain nested PassNode +// +// modifier mod is applied to target +void ASTBuilder::RecursiveAddModifier(TreeNode *target, TreeNode *mod) { + if (mTrace) + std::cout << "In recursive AddModifier" << std::endl; + + if (mod->IsAttr()) { + AttrNode *an = static_cast(mod); + TreeNode *tn= gAttrPool.GetAttrNode(an->GetId()); + add_attribute_to(target, tn); + } else if (mod->IsPass()) { + PassNode *pass = (PassNode*)mod; + for (unsigned i = 0; i < pass->GetChildrenNum(); i++) { + TreeNode *child = pass->GetChild(i); + RecursiveAddModifier(target, child); + } + } else if (mod->IsAnnotation()) { + AnnotationNode *a = (AnnotationNode*)mod; + target->AddAnnotation(a); + } else { + MERROR("unsupported modifier."); + } +} + // Takes two arguments. 1) target tree node; 2) modifier, which could be // attr, annotation/pragma. // @@ -2374,23 +2389,7 @@ TreeNode* ASTBuilder::AddModifierTo() { MASSERT(p_mod.mIsTreeNode && "The Attr is not a treenode in AddModifierTo()"); TreeNode *mod = p_mod.mData.mTreeNode; - if (mod->IsPass()) { - PassNode *pass = (PassNode*)mod; - for (unsigned i = 0; i < pass->GetChildrenNum(); i++) { - TreeNode *child = pass->GetChild(i); - if (child->IsAnnotation()) { - AnnotationNode *a = (AnnotationNode*)child; - tree->AddAnnotation(a); - } else { - add_attribute_to(tree, child); - } - } - } else if (mod->IsAnnotation()) { - AnnotationNode *a = (AnnotationNode*)mod; - tree->AddAnnotation(a); - } else { - add_attribute_to(tree, mod); - } + RecursiveAddModifier(tree, mod); return tree; } @@ -3819,7 +3818,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 +3864,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 +4255,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..8b0b4a9d12e9a8f5f3524db35643b2d91133fd35 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; @@ -630,7 +633,7 @@ bool Lexer::TraverseTableData(TableData *data) { switch (data->mType) { - // The first thinking is I also want to check if the next text after 'curidx' is a separtor + // The first thought is to check if the next text after 'curidx' is a separtor // or operator. // // This is the case in parsing a DT_String. However, we have many rules handling DT_Char @@ -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 @@ -810,7 +815,7 @@ bool Lexer::TraverseSecondTry(const RuleTable *rule_table) { // 3. We need find the longest match. // These four are the final result if success. - // [NOTE] The reason I use 'the one after' as xxx_end, is to check if TraverseTableData() + // [NOTE] The reason we use 'the one after' as xxx_end, is to check if TraverseTableData() // really moves the curidx. Or in another word, if it matches anything or nother. // If it matches something, xxx_end will be greater than xxx_start, or else they are equal. unsigned yyy_start = curidx; diff --git a/src/MapleFE/shared/src/parser.cpp b/src/MapleFE/shared/src/parser.cpp index 12e8d953dc4e61a8ad5ddeb8efc18b7c7d9251a4..337602dfd716ba86230888d3f9dfe32d45f63fe8 100644 --- a/src/MapleFE/shared/src/parser.cpp +++ b/src/MapleFE/shared/src/parser.cpp @@ -32,6 +32,12 @@ namespace maplefe { +#define RESET "\x1B[0m" +#define BOLD "\x1B[1m" +#define RED "\x1B[31m" +#define GRN "\x1B[32m" +#define YEL "\x1B[33m" + SmallVector gTemplateLiteralNodes; ////////////////////////////////////////////////////////////////////////////////// @@ -66,7 +72,7 @@ SmallVector gTemplateLiteralNodes; // 3. Left Recursion // // MapleFE is an LL parser, and left recursion has to be handled if we allow language -// designer to write left recursion. I personally believe left recursion is a much +// designer to write left recursion. We believe left recursion is a much // simpler, more human friendly and stronger way to describe language spec. To // provide this juicy feature, parser has to do extra job. // @@ -361,6 +367,11 @@ unsigned Parser::LexOneLine() { return mActiveTokens.GetNum() - mCurToken; while (!token_num) { + if (mLexer->GetTrace() && !mLexer->EndOfLine() && !mLexer->EndOfFile() && line_begin) { + std::cout << "line: " << mLexer->GetLineNum() << " : " + << mLexer->GetLine() + mLexer->GetCuridx() << std::endl; + } + // read until end of line while (!mLexer->EndOfLine() && !mLexer->EndOfFile()) { t = mLexer->LexToken(); @@ -391,8 +402,6 @@ unsigned Parser::LexOneLine() { if (line_begin) { t->mLineBegin = true; line_begin = false; - if (mLexer->GetTrace()) - DUMP0("Set as Line First."); } mActiveTokens.PushBack(t); @@ -417,7 +426,7 @@ unsigned Parser::LexOneLine() { if (token_num) { last_token->mLineEnd = true; if (mLexer->GetTrace()) - DUMP0("Set as Line End."); + DUMP0("Set as Line End.\n"); } return token_num; @@ -576,14 +585,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) @@ -767,8 +768,8 @@ void Parser::DumpAppeal(RuleTable *table, unsigned token) { std::cout << "!!Reset the Failed flag of " << name << " @" << token << std::endl; } -void Parser::DumpIndentation() { - for (unsigned i = 0; i < mIndentation; i++) +void Parser::DumpIndentation(unsigned indent) { + for (unsigned i = 0; i < indent; i++) std::cout << " "; } @@ -786,26 +787,34 @@ void Parser::DumpExitTable(const char *table_name, unsigned indent, AppealStatus reason, AppealNode *appeal) { for (unsigned i = 0; i < indent; i++) std::cout << " "; + if (reason == SuccWasSucc || + reason == SuccStillWasSucc || + reason == Succ || + reason == SuccASI) { + std::cout << GRN; + } std::cout << "Exit " << table_name << "@" << mCurToken; if (reason == SuccWasSucc) { std::cout << " succ@WasSucc" << "}"; DumpSuccTokens(appeal); - std::cout << std::endl; + std::cout << RESET << std::endl; } else if (reason == SuccStillWasSucc) { std::cout << " succ@StillWasSucc" << "}"; DumpSuccTokens(appeal); - std::cout << std::endl; + std::cout << RESET << std::endl; } else if (reason == Succ) { std::cout << " succ" << "}"; DumpSuccTokens(appeal); - std::cout << std::endl; + std::cout << RESET << std::endl; } else if (reason == SuccASI) { std::cout << " succASI" << "}"; - std::cout << std::endl; + std::cout << RESET << std::endl; } else if (reason == FailWasFailed) 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 +885,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: @@ -962,7 +975,7 @@ bool Parser::TraverseRuleTable(RuleTable *rule_table, AppealNode *parent, Appeal // The affected can be succ later. So there is possibility both succ and fail // exist at the same time. // - // I still keep this assertion. We will see. Maybe we'll remove it. + // We still keep this assertion. We will see. Maybe we'll remove it. MASSERT(!WasFailed(rule_table, mCurToken)); // set the apppeal node @@ -998,7 +1011,7 @@ bool Parser::TraverseRuleTable(RuleTable *rule_table, AppealNode *parent, Appeal bool in_group = FindRecursionGroup(rule_table, group_id); // 1. In a recursion, a rule could fail in the first a few instances, - // but could match in a later instance. So I need check is_done. + // but could match in a later instance. So We need check is_done. // Here is an example. Node A is one of the circle node. // (a) In the first recursion instance, A is failed, but luckly it // gets appealed due to lead node is 2ndOf1st. @@ -1031,7 +1044,7 @@ bool Parser::TraverseRuleTable(RuleTable *rule_table, AppealNode *parent, Appeal return true; } else { if (mTraceTable) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << "Traverse-Pre WasSucc, mCurToken:" << saved_mCurToken; std::cout << std::endl; } @@ -1098,7 +1111,7 @@ bool Parser::TraverseRuleTable(RuleTable *rule_table, AppealNode *parent, Appeal if (rec_tra->LeadNodeVisited(rule_table)) { if (mTraceLeftRec) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": ConnectPrevious " << GetRuleTableName(rule_table) << "@" << appeal->GetStartIndex() << " node:" << appeal << std::endl; @@ -1141,7 +1154,7 @@ bool Parser::TraverseRuleTable(RuleTable *rule_table, AppealNode *parent, Appeal // It's a regular (non leadnode) table, either inside or outside of a // recursion, we just need do the regular traversal. // If it's inside a Left Recursion, it will finally goes to that - // recursion. I don't need take care here. + // recursion. We don't need take care here. bool matched = TraverseRuleTableRegular(rule_table, appeal); if (rec_tra) @@ -1210,6 +1223,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 +1281,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 +1724,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 +1780,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 +1873,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 +1925,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 +2316,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; @@ -2716,7 +2789,7 @@ TreeNode* Parser::NewTreeNode(AppealNode *appeal_node) { // a parameter list: '(' + param-lists + ')'. // if param-list is empty, it has no AST tree. // In this case, we sset mIsEmpty to true. - // 3. chidl is a sub appeal tree, and has a AST tree too. + // 3. child is a sub appeal tree, and has a AST tree too. if (child) { TreeNode *tree_node = child->GetAstTreeNode(); if (!tree_node) { @@ -3045,4 +3118,21 @@ AppealNode* AppealNode::FindIndexedChild(unsigned match, unsigned index) { return ret_child; } +void AppealNode::Dump(unsigned indent) { + for (unsigned i = 0; i < indent; i++) + std::cout << " "; + if (mAstTreeNode) { + std::cout << "TreeNode: "; + mAstTreeNode->D(); + } else if (mIsTable) { + std::cout << "rule table" << std::endl; + } else { + std::cout << "Token: "; + mData.mToken->Dump(); + } + for (unsigned i = 0; i < mChildren.GetNum(); i++) { + mChildren.ValueAtIndex(i)->Dump(indent + 2); + } +} + } diff --git a/src/MapleFE/shared/src/parser_rec.cpp b/src/MapleFE/shared/src/parser_rec.cpp index 615b78d63a065ed6bb1798dcee738794a1654ae6..72085225dd1ec6dec09e8a3675557adb69421f00 100644 --- a/src/MapleFE/shared/src/parser_rec.cpp +++ b/src/MapleFE/shared/src/parser_rec.cpp @@ -63,7 +63,7 @@ bool Parser::TraverseLeadNode(AppealNode *appeal, AppealNode *parent) { MASSERT(found_group); if (mTraceLeftRec) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": Enter LeadNode " << name << "@" << appeal->GetStartIndex() << " node:" << appeal; std::cout << " group id:" << group_id << std::endl; @@ -80,7 +80,7 @@ bool Parser::TraverseLeadNode(AppealNode *appeal, AppealNode *parent) { rec_tra->AddLeadNode(appeal); bool found = TraverseRuleTableRegular(rt, appeal); if (mTraceTable) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": Exit Other LeadNode " << name << std::endl; //DumpExitTable(...) is called in the caller. We don't dump here. } @@ -105,7 +105,7 @@ bool Parser::TraverseLeadNode(AppealNode *appeal, AppealNode *parent) { } if (mTraceLeftRec) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": Exit LeadNode " << GetRuleTableName(rt); if (appeal->IsSucc()) std::cout << " succ longest match@" << appeal->LongestMatch() << std::endl; @@ -244,7 +244,7 @@ bool RecursionTraversal::FindFirstInstance() { mParser->mAppealNodes.push_back(lead); if (mTrace) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": FirstInstance " << lead << std::endl; } @@ -290,7 +290,7 @@ bool RecursionTraversal::FindRestInstance() { AddVisitedLeadNode(mRuleTable); if (mTrace) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": RestInstance " << lead << std::endl; } @@ -303,7 +303,7 @@ bool RecursionTraversal::FindRestInstance() { return true; } else { if (mTrace) { - DumpIndentation(); + DumpIndentation(mIndentation); std::cout << ": Fake Succ. Fixed Point." << std::endl; } // Need remove it from the SuccMatch, so that later parser won't @@ -329,8 +329,8 @@ void RecursionTraversal::FinalConnection() { mSelf->CopyMatch(last); } -void RecursionTraversal::DumpIndentation() { - for (unsigned i=0; i < mIndentation; i++) +void RecursionTraversal::DumpIndentation(unsigned indent) { + for (unsigned i=0; i < indent; i++) std::cout << " "; } } diff --git a/src/MapleFE/shared/src/ruletable_util.cpp b/src/MapleFE/shared/src/ruletable_util.cpp index 65dc85557fe634d3dece1f2f5ae82b1f5d576f18..a459ac70cb2a449efca64b81d0afbcf4ab52254e 100644 --- a/src/MapleFE/shared/src/ruletable_util.cpp +++ b/src/MapleFE/shared/src/ruletable_util.cpp @@ -239,7 +239,7 @@ bool LookAheadEqual(LookAhead la_a, LookAhead la_b) { size_t len_b = strlen(la_b.mData.mString); if (len_a != len_b) return false; - return strncmp(la_a.mData.mString, la_b.mData.mString, len_a); + return (strncmp(la_a.mData.mString, la_b.mData.mString, len_a) == 0); } else if (la_a.mType == LA_Identifier && la_b.mType == LA_Identifier) { return true; } else if (la_a.mType == LA_Literal && la_b.mType == LA_Literal) { 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..ae6771c292a0035a5e667be52e27386520588dba 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); @@ -78,22 +79,30 @@ TreeNode *TypeTable::CreateBuiltinType(std::string name, TypeId tid) { id->SetParent(utype); mTypeId2TypeMap[tid] = utype; + mStrIdx2BuiltInTypeIdxMap[stridx] = tid; return utype; } 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 +118,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,24 +126,86 @@ 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); #include "supported_types.def" mPreBuildSize = size(); + + // add language builtin types + unsigned stridx = 0; +#define BUILTIN(T) \ + stridx = gStringPool.GetStrIdx(#T);\ + if (mStrIdx2BuiltInTypeIdxMap.find(stridx) == mStrIdx2BuiltInTypeIdxMap.end()) {\ + node = CreateBuiltinType(#T, TY_Class);\ + AddType(node);\ + mStrIdx2BuiltInTypeIdxMap[stridx] = node->GetTypeIdx();\ + } +#include "lang_builtin.def" return; } -TypeEntry *TypeTable::GetTypeEntryFromTypeIdx(unsigned idx) { - MASSERT(idx < mTypeTable.size() && "type index out of range"); - return mTypeTable[idx]; +bool TypeTable::IsBuiltInType(TreeNode *node) { + return mStrIdx2BuiltInTypeIdxMap.find(node->GetStrIdx()) != mStrIdx2BuiltInTypeIdxMap.end(); +} + +unsigned TypeTable::GetBuiltInTypeIdx(unsigned stridx) { + if (mStrIdx2BuiltInTypeIdxMap.find(stridx) != mStrIdx2BuiltInTypeIdxMap.end()) { + return mStrIdx2BuiltInTypeIdxMap[stridx]; + } + return 0; +} + +unsigned TypeTable::GetBuiltInTypeIdx(TreeNode *node) { + unsigned stridx = node->GetStrIdx(); + if (mStrIdx2BuiltInTypeIdxMap.find(stridx) != mStrIdx2BuiltInTypeIdxMap.end()) { + return GetBuiltInTypeIdx(stridx); + } + return 0; +} + +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/Makefile b/src/MapleFE/test/Makefile index aed83f9c0ad98a99312e7e2785030cbc13cd311a..649363ecdfd4ee788ec0e05fdac909f6c522bde1 100644 --- a/src/MapleFE/test/Makefile +++ b/src/MapleFE/test/Makefile @@ -76,8 +76,8 @@ mssetup: @cat -n $(build)/$@.mpl @echo "========================================================\n" @echo gdb --args ../output/java/java/java2mpl $(build)/$@.java $(FLAGS) - $(MAPLEALL_ROOT)/output/aarch64-clang-debug/bin/irbuild $(build)/$@.mpl - $(MAPLEALL_ROOT)/output/aarch64-clang-debug/bin/irbuild $(build)/$@.irb.mpl + $(MAPLE_ROOT)/output/aarch64-clang-debug/bin/irbuild $(build)/$@.mpl + $(MAPLE_ROOT)/output/aarch64-clang-debug/bin/irbuild $(build)/$@.irb.mpl diff -uwb $(build)/$@.irb.mpl $(build)/$@.irb.irb.mpl else ifeq ($(SRCLANG),typescript) 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/c/c2ast/assign.c b/src/MapleFE/test/c/c2ast/assign.c new file mode 100644 index 0000000000000000000000000000000000000000..f3864b8c1920f60fc86985051732694c221cfe3c --- /dev/null +++ b/src/MapleFE/test/c/c2ast/assign.c @@ -0,0 +1 @@ +i = 3; diff --git a/src/MapleFE/test/c/c2ast/assign.c.result b/src/MapleFE/test/c/c2ast/assign.c.result new file mode 100644 index 0000000000000000000000000000000000000000..92ae1ef3de77058b1acd9219a72f7f4f38ce9a67 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/assign.c.result @@ -0,0 +1,4 @@ +Matched 4 tokens. +============= Module =========== +== Sub Tree == +i Assign 3 diff --git a/src/MapleFE/test/c/c2ast/decl.c b/src/MapleFE/test/c/c2ast/decl.c new file mode 100644 index 0000000000000000000000000000000000000000..e42bb22704b627caead3820f91a09a42f3571f98 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/decl.c @@ -0,0 +1,11 @@ +char c; +short s; +int i; +long l; +unsigned char uc; +unsigned short us; +unsigned int ui; +unsigned long ul; +unsigned u; +float f; +double d; diff --git a/src/MapleFE/test/c/c2ast/decl.c.result b/src/MapleFE/test/c/c2ast/decl.c.result new file mode 100644 index 0000000000000000000000000000000000000000..c9f703fe2e67a627fc8ecfe6264188b60c9400b9 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/decl.c.result @@ -0,0 +1,34 @@ +Matched 3 tokens. +Matched 6 tokens. +Matched 9 tokens. +Matched 12 tokens. +Matched 16 tokens. +Matched 20 tokens. +Matched 24 tokens. +Matched 28 tokens. +Matched 31 tokens. +Matched 34 tokens. +Matched 37 tokens. +============= Module =========== +== Sub Tree == +Decl: c +== Sub Tree == +Decl: s +== Sub Tree == +Decl: i +== Sub Tree == +Decl: l +== Sub Tree == +Decl: uc +== Sub Tree == +Decl: us +== Sub Tree == +Decl: ui +== Sub Tree == +Decl: ul +== Sub Tree == +Decl: u +== Sub Tree == +Decl: f +== Sub Tree == +Decl: d diff --git a/src/MapleFE/test/c/c2ast/decl_init.c b/src/MapleFE/test/c/c2ast/decl_init.c new file mode 100644 index 0000000000000000000000000000000000000000..879eb3278b0ffa079446e7a4646abdb505939f1e --- /dev/null +++ b/src/MapleFE/test/c/c2ast/decl_init.c @@ -0,0 +1,8 @@ +int gi = 4; +float gf = 4.4; +int main() { + int i = 13; + float f = 14.3; + static float sf = 15.3; + return i; +} diff --git a/src/MapleFE/test/c/c2ast/decl_init.c.result b/src/MapleFE/test/c/c2ast/decl_init.c.result new file mode 100644 index 0000000000000000000000000000000000000000..f0ca4274996beeb86b19cd7de7d87432c01cf124 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/decl_init.c.result @@ -0,0 +1,15 @@ +Matched 5 tokens. +Matched 10 tokens. +Matched 35 tokens. +============= Module =========== +== Sub Tree == +Decl: gi=4 +== Sub Tree == +Decl: gf=4.4 +== Sub Tree == +func main() throws: + Decl: i=13 + Decl: f=14.3 + Decl: sf=15.3 + return i + diff --git a/src/MapleFE/test/c/c2ast/foo.c b/src/MapleFE/test/c/c2ast/foo.c new file mode 100644 index 0000000000000000000000000000000000000000..cee6194be754577236c05cde437275f841383899 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/foo.c @@ -0,0 +1,5 @@ +int k = 4; +int foo(int i) { + int j = 8; + return i + j + k; +} diff --git a/src/MapleFE/test/c/c2ast/foo.c.result b/src/MapleFE/test/c/c2ast/foo.c.result new file mode 100644 index 0000000000000000000000000000000000000000..140cbcf553f8b581842bf47f0a5365702cf4ed6c --- /dev/null +++ b/src/MapleFE/test/c/c2ast/foo.c.result @@ -0,0 +1,10 @@ +Matched 5 tokens. +Matched 25 tokens. +============= Module =========== +== Sub Tree == +Decl: k=4 +== Sub Tree == +func foo(i) throws: + Decl: j=8 + return i Add j Add k + diff --git a/src/MapleFE/test/c/c2ast/func.c b/src/MapleFE/test/c/c2ast/func.c new file mode 100644 index 0000000000000000000000000000000000000000..6b488e843813d2491f81fb38436a22bdc3352880 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/func.c @@ -0,0 +1,4 @@ +int main() { + int x = 3; + return x; +} diff --git a/src/MapleFE/test/c/c2ast/func.c.result b/src/MapleFE/test/c/c2ast/func.c.result new file mode 100644 index 0000000000000000000000000000000000000000..94832ee373ab39a1e2dd145b260f04b49ecd5673 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/func.c.result @@ -0,0 +1,7 @@ +Matched 14 tokens. +============= Module =========== +== Sub Tree == +func main() throws: + Decl: x=3 + return x + diff --git a/src/MapleFE/test/c/c2ast/generate-result.sh b/src/MapleFE/test/c/c2ast/generate-result.sh new file mode 100755 index 0000000000000000000000000000000000000000..2369a7ee425f4180e0df418995927ab35e34c42a --- /dev/null +++ b/src/MapleFE/test/c/c2ast/generate-result.sh @@ -0,0 +1,22 @@ +# Copyright (C) [2020] 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. +# + +#!/bin/bash +FILES=$(pwd)/*.c +for f in $FILES +do + echo "Generating result for $f ..." + ../../../output/c/bin/c2ast $f > $f.result +done +rm -f *.ast *.mpl diff --git a/src/MapleFE/test/c/c2ast/var_attr.c b/src/MapleFE/test/c/c2ast/var_attr.c new file mode 100644 index 0000000000000000000000000000000000000000..f052d0c2fae46688f7d3f42352e0c832c4f58591 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/var_attr.c @@ -0,0 +1,12 @@ +//auto char iauto = 7; +unsigned iunsigned = 7; +const int iconst = 7; +extern char iextern = 7; +//inline char iinline = 7; +//register char iregister = 7; +restrict int irestrict = 7; +static char istatic = 7; +//typedef char itypedef = 7; +volatile short ivolatil = 7; +const volatile short iconstvolatil = 7; +const restrict volatile static auto register int a = 9; diff --git a/src/MapleFE/test/c/c2ast/var_attr.c.result b/src/MapleFE/test/c/c2ast/var_attr.c.result new file mode 100644 index 0000000000000000000000000000000000000000..1c5c76ec47f7c06ec67d18b09abc328e04b1fa60 --- /dev/null +++ b/src/MapleFE/test/c/c2ast/var_attr.c.result @@ -0,0 +1,25 @@ +Matched 5 tokens. +Matched 11 tokens. +Matched 17 tokens. +Matched 23 tokens. +Matched 29 tokens. +Matched 35 tokens. +Matched 42 tokens. +Matched 53 tokens. +============= Module =========== +== Sub Tree == +Decl: iunsigned=7 +== Sub Tree == +Decl: iconst=7 +== Sub Tree == +Decl: iextern=7 +== Sub Tree == +Decl: irestrict=7 +== Sub Tree == +Decl: istatic=7 +== Sub Tree == +Decl: ivolatil=7 +== Sub Tree == +Decl: iconstvolatil=7 +== Sub Tree == +Decl: a=9 diff --git a/src/MapleFE/test/new_runtests.pl b/src/MapleFE/test/new_runtests.pl index 06479ff92804476597d5731effb295d0039554d3..69f1c5f50b9f4a5c7b7269facae1e74331efcd3a 100755 --- a/src/MapleFE/test/new_runtests.pl +++ b/src/MapleFE/test/new_runtests.pl @@ -10,7 +10,7 @@ use File::Find qw(find); if(!(defined $ARGV[0])) { print "------------------------------------------------\n"; - print "usage: runtests.pl [ java | java/subdirectory | typescript | typescript/subdirectory ]\n"; + print "usage: runtests.pl [ [c|java|typescript] | [c|java|typescript]/subdirectory ]\n"; print "------------------------------------------------\n"; exit; } @@ -47,6 +47,12 @@ if ($lang =~ /\Qjava\E/) { $cmnd1 = "../output/typescript/bin/ast2cpp"; $flag = "--no-imported"; $outroot = "$currdir/../output/typescript/test"; +} elsif ($lang =~ /\Qc\E/) { + $pinput = "c"; + $cmnd = "../output/c/bin/c2ast"; + $cmnd1 = "../output/c/bin/ast2mpl"; + $flag = ""; + $outroot = "$currdir/../output/c/test"; } else { print "$lang is an invalid option\n"; exit; @@ -70,7 +76,7 @@ sub listdirs { my @dirs = @_; my @files; - if ( $pinput ~~ [qw( java ts )] ) { + if ( $pinput ~~ [qw( java ts c )] ) { find({ wanted => sub { push @files, glob "\"$_/{*.$pinput,*.$pinput.result}\"" } , no_chdir => 1 }, @dirs); } else { find({ wanted => sub { push @files, $_ } , no_chdir => 1 }, @dirs); @@ -85,10 +91,10 @@ foreach my $file (@paths) { my ($filename) = ( $file =~ /([^\\\/]+)$/s ) ; my ($pathname) = dirname($file); - if ( $pinput ~~ [qw( java ts )] ) { + if ( $pinput ~~ [qw( java ts c )] ) { system("rm -rf $outroot/$file; cp -rp --parents $file $outroot/"); - if ( ($filename =~ (/(.+)[.]java$/)) || ($filename =~ (/(.+)[.]ts$/)) ) { + if ( ($filename =~ (/(.+)[.]java$/)) || ($filename =~ (/(.+)[.]ts$/)) || ($filename =~ (/(.+)[.]c$/)) ) { my $origresult = "$pwd/$file.result"; my $outresult = $file.'.result.'.$pinput; 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/ast2mpl/include/cvt_block.h b/src/MapleFE/tools/obfuscate/include/obfuscate.h similarity index 39% rename from src/MapleFE/ast2mpl/include/cvt_block.h rename to src/MapleFE/tools/obfuscate/include/obfuscate.h index 99ac1da878fed8b78a11a0465c6d7aec4a56bd33..63574ba6d02657eb5293605a36236e4a14374fe3 100644 --- a/src/MapleFE/ast2mpl/include/cvt_block.h +++ b/src/MapleFE/tools/obfuscate/include/obfuscate.h @@ -1,5 +1,5 @@ /* -* Copyright (C) [2021] Futurewei Technologies, Inc. All rights reverved. +* 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. @@ -13,28 +13,39 @@ * See the Mulan PSL v2 for more details. */ -#ifndef __AST_CVT_BLOCK_H__ -#define __AST_CVT_BLOCK_H__ +////////////////////////////////////////////////////////////////////////////////////////////// +// 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" -#include "ast.h" -#include "gen_astvisitor.h" namespace maplefe { -// CvtBlockVisitor is to fix up some tree nodes after the AST is created -class CvtToBlockVisitor : public AstVisitor { - private: - ModuleNode *mASTModule; - bool mUpdated; - - public: - CvtToBlockVisitor(ModuleNode *m) : mASTModule(m), mUpdated(false) {} - - bool CvtToBlock(); - - CondBranchNode *VisitCondBranchNode(CondBranchNode *node); - ForLoopNode *VisitForLoopNode(ForLoopNode *node); +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(); }; } 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/Makefile b/src/MapleFE/typescript/src/Makefile index 392dc308bc7852a4e8b14578efad9d2f52306413..18b895899833abd9ed5d3b3488becaf05dcf6fa0 100644 --- a/src/MapleFE/typescript/src/Makefile +++ b/src/MapleFE/typescript/src/Makefile @@ -13,11 +13,8 @@ # include ../../Makefile.in -BUILDBIN=$(BUILDDIR)/bin BUILD=$(BUILDDIR)/typescript -BUILDGEN=$(BUILDDIR)/gen -BUILDASTGEN=$(BUILDDIR)/ast_gen/shared -$(shell $(MKDIR_P) $(BUILD) $(BUILDGEN)) +$(shell $(MKDIR_P) $(BUILD) $(BUILDLIB) $(BUILDGEN)) SRC=$(wildcard *.cpp) OBJ :=$(patsubst %.cpp,%.o,$(SRC)) @@ -31,16 +28,16 @@ OBJS :=$(foreach obj,$(OBJ), $(BUILD)/$(obj)) $(OBJG) DEPS :=$(foreach dep,$(DEP), $(BUILD)/$(dep)) $(DEPG) INCLUDES := -I $(MAPLEFE_ROOT)/shared/include \ - -I $(MAPLEFE_ROOT)/typescript/include \ -I $(MAPLEFE_ROOT)/autogen/include \ - -I ${BUILDDIR}/ast_gen/shared \ + -I $(MAPLEFE_ROOT)/$(SRCLANG)/include \ + -I ${BUILDASTGEN} \ -I $(BUILDGEN) INCLUDEGEN := -I $(BUILDGEN) -I $(MAPLEFE_ROOT)/shared/include TARGET=ts2ast -SHAREDLIB = $(BUILDDIR)/shared/shared.a $(BUILDASTGEN)/genast.a +SHAREDLIB = -L $(BUILDLIB) -lshared -lgenast .PHONY: all all: $(BUILDBIN)/$(TARGET) @@ -72,7 +69,7 @@ $(BUILDGEN)/%.d : $(BUILDGEN)/%.cpp # TARGET depends on OBJS and shared OBJS from shared directory # as well as mapleall libraries -$(BUILDBIN)/$(TARGET): $(OBJS) $(SHAREDLIB) +$(BUILDBIN)/$(TARGET): $(OBJS) @mkdir -p $(BUILDBIN) $(LD) -o $(BUILDBIN)/$(TARGET) $(OBJS) $(SHAREDLIB) 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..070069af66364053092d7f2a42d8e74337924070 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", @@ -83,7 +90,6 @@ static_library("lib_hir2mpl_common") { "${HIR2MPL_ROOT}/common/src/fe_utils.cpp", "${HIR2MPL_ROOT}/common/src/fe_utils_ast.cpp", "${HIR2MPL_ROOT}/common/src/fe_utils_java.cpp", - "${HIR2MPL_ROOT}/common/src/fe_diag_manager.cpp", "${HIR2MPL_ROOT}/common/src/feir_builder.cpp", "${HIR2MPL_ROOT}/common/src/feir_stmt.cpp", "${HIR2MPL_ROOT}/common/src/feir_type.cpp", @@ -97,10 +103,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 +159,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 +196,17 @@ executable("hir2mpl") { "-L${MAPLE_PARSER_PATH}/output/c/ast_gen/shared", ] } + if (COV == 1) { + ldflags += ["--coverage"] + cflags_cc += [ + "-fprofile-arcs", + "-ftest-coverage" + ] + } + if (GPROF == 1) { + ldflags += ["-pg"] + cflags_cc += ["-pg"] + } } include_bytecode_input_jbc_directories = [ @@ -218,96 +244,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/CMakeLists.txt b/src/hir2mpl/CMakeLists.txt new file mode 100755 index 0000000000000000000000000000000000000000..e8d5a1176235593df8dff9873e0cf5ccee627a1a --- /dev/null +++ b/src/hir2mpl/CMakeLists.txt @@ -0,0 +1,490 @@ +# +# 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. +# +if (${COV_CHECK} STREQUAL "1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DENABLE_COV_CHECK=1") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DENABLE_COV_CHECK=1") +endif() + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMIR_FEATURE_FULL=1 -DHIR2MPL_FULL_INFO_DUMP=1 -DJAVA_OBJ_IN_MFILE=1") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DMIR_FEATURE_FULL=1 -DHIR2MPL_FULL_INFO_DUMP=1 -DJAVA_OBJ_IN_MFILE=1") + +if (${ONLY_C} STREQUAL "1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -DONLY_C") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -DONLY_C") +endif() + +if (${MAST} STREQUAL "1") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -DENABLE_MAST") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -DENABLE_MAST") +endif() + +set(include_directories + ${HIR2MPL_ROOT}/common/include + ${HIR2MPL_ROOT}/optimize/include + ${HIR2MPL_ROOT}/bytecode_input/class/include + ${HIR2MPL_ROOT}/bytecode_input/common/include + ${HIR2MPL_ROOT}/bytecode_input/dex/include + ${MAPLEALL_ROOT}/maple_ir/include + ${MAPLEALL_ROOT}/maple_ipa/include + ${MAPLEALL_ROOT}/maple_ipa/include/old + ${MAPLEALL_ROOT}/maple_util/include + ${MAPLEALL_ROOT}/maple_phase/include + ${MAPLEALL_ROOT}/maple_driver/include + ${MAPLEALL_ROOT}/mpl2mpl/include + ${MAPLEALL_ROOT}/maple_me/include + ${MAPLEALL_ROOT}/mempool/include + ${THIRD_PARTY_ROOT}/bounds_checking_function/include + ${HIR2MPL_ROOT}/ast_input/clang/include + ${HIR2MPL_ROOT}/ast_input/clang/lib + ${HIR2MPL_ROOT}/ast_input/common/include + ${HIR2MPL_ROOT}/ast_input/maple/include + ${HIR2MPL_ROOT}/ast_input/maple/lib + ${LLVMINC} + ${THIRD_PARTY_ROOT}/llvm_modified/clang/tools +) + +if (${MAST} STREQUAL "1") + set(include_directories + ${include_directories} + ${MAPLE_PARSER_PATH}/output/c/ast_gen/shared + ${MAPLE_PARSER_PATH}/shared/include + ${MAPLE_PARSER_PATH}/astopt/include + ) +endif() + +set(src_lib_hir2mpl_common + ${HIR2MPL_ROOT}/common/src/base64.cpp + ${HIR2MPL_ROOT}/common/src/basic_io.cpp + ${HIR2MPL_ROOT}/common/src/fe_config_parallel.cpp + ${HIR2MPL_ROOT}/common/src/fe_file_ops.cpp + ${HIR2MPL_ROOT}/common/src/fe_file_type.cpp + ${HIR2MPL_ROOT}/common/src/fe_function.cpp + ${HIR2MPL_ROOT}/common/src/fe_function_phase_result.cpp + ${HIR2MPL_ROOT}/common/src/fe_input_helper.cpp + ${HIR2MPL_ROOT}/common/src/fe_java_string_manager.cpp + ${HIR2MPL_ROOT}/common/src/fe_manager.cpp + ${HIR2MPL_ROOT}/common/src/fe_options.cpp + ${HIR2MPL_ROOT}/common/src/fe_struct_elem_info.cpp + ${HIR2MPL_ROOT}/common/src/fe_timer_ns.cpp + ${HIR2MPL_ROOT}/common/src/fe_type_hierarchy.cpp + ${HIR2MPL_ROOT}/common/src/fe_type_manager.cpp + ${HIR2MPL_ROOT}/common/src/fe_utils.cpp + ${HIR2MPL_ROOT}/common/src/fe_utils_ast.cpp + ${HIR2MPL_ROOT}/common/src/fe_utils_java.cpp + ${HIR2MPL_ROOT}/common/src/feir_builder.cpp + ${HIR2MPL_ROOT}/common/src/feir_stmt.cpp + ${HIR2MPL_ROOT}/common/src/feir_type.cpp + ${HIR2MPL_ROOT}/common/src/feir_type_helper.cpp + ${HIR2MPL_ROOT}/common/src/feir_type_infer.cpp + ${HIR2MPL_ROOT}/common/src/feir_var.cpp + ${HIR2MPL_ROOT}/common/src/feir_var_name.cpp + ${HIR2MPL_ROOT}/common/src/feir_var_reg.cpp + ${HIR2MPL_ROOT}/common/src/feir_var_type_scatter.cpp + ${HIR2MPL_ROOT}/common/src/hir2mpl_compiler.cpp + ${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 +) +if (NOT ${MAJOR_VERSION} STREQUAL "") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMAJOR_VERSION=${MAJOR_VERSION}") +endif() +if (NOT ${MINOR_VERSION} STREQUAL "") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DMINOR_VERSION=${MINOR_VERSION}") +endif() +if (NOT ${RELEASE_VERSION} STREQUAL "") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRELEASE_VERSION=\\\"${RELEASE_VERSION}\\\"") +endif() +if (NOT ${BUILD_VERSION} STREQUAL "") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DBUILD_VERSION=${BUILD_VERSION}") +endif() +if (NOT ${GIT_REVISION} STREQUAL "") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGIT_REVISION=\\\"${GIT_REVISION}\\\"") +endif() +#lib_hir2mpl_common +add_library(lib_hir2mpl_common STATIC ${src_lib_hir2mpl_common}) +set_target_properties(lib_hir2mpl_common PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + ARCHIVE_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/ar" + COMPILE_FLAGS "" +) + +set(src_lib_hir2mpl_optimize + ${HIR2MPL_ROOT}/optimize/src/ror.cpp + ${HIR2MPL_ROOT}/optimize/src/conditional_operator.cpp + ${HIR2MPL_ROOT}/optimize/src/feir_lower.cpp + ${HIR2MPL_ROOT}/optimize/src/feir_bb.cpp + ${HIR2MPL_ROOT}/optimize/src/feir_cfg.cpp + ${HIR2MPL_ROOT}/optimize/src/feir_dfg.cpp +) + +#lib_hir2mpl_optimize +add_library(lib_hir2mpl_optimize STATIC ${src_lib_hir2mpl_optimize}) +set_target_properties(lib_hir2mpl_optimize PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + ARCHIVE_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/ar" +) + +#lib_hir2mpl_input_helper +add_library(lib_hir2mpl_input_helper STATIC "${HIR2MPL_ROOT}/common/src/fe_input_helper.cpp") +set_target_properties(lib_hir2mpl_input_helper PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + ARCHIVE_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/ar" +) + +set(src_hir2mpl + ${HIR2MPL_ROOT}/common/src/hir2mpl.cpp +) + +set(deps_hir2mpl + ${LLVMLIBDIR}/libclang.so + ${LLVMLIBDIR}/libclang-cpp.so + ${LLVMLIBDIR}/libclangFrontend.a + ${LLVMLIBDIR}/libclangDriver.a + ${LLVMLIBDIR}/libclangSerialization.a + ${LLVMLIBDIR}/libclangParse.a + ${LLVMLIBDIR}/libclangSema.a + ${LLVMLIBDIR}/libclangEdit.a + ${LLVMLIBDIR}/libclangLex.a + ${LLVMLIBDIR}/libclangAnalysis.a + ${LLVMLIBDIR}/libclangAST.a + ${LLVMLIBDIR}/libclangBasic.a + ${LLVMLIBDIR}/libLLVMDemangle.a + ${LLVMLIBDIR}/libLLVMMCParser.a + ${LLVMLIBDIR}/libLLVMMC.a + ${LLVMLIBDIR}/libLLVMBitReader.a + ${LLVMLIBDIR}/libLLVMCore.a + ${LLVMLIBDIR}/libLLVMBinaryFormat.a + ${LLVMLIBDIR}/libLLVMProfileData.a + ${LLVMLIBDIR}/libLLVMOption.a + ${LLVMLIBDIR}/libLLVMSupport.a + lib_hir2mpl_ast_input_clang_lib + libmplphase + libcommandline + lib_hir2mpl_ast_input_clang + lib_hir2mpl_ast_input_common + lib_hir2mpl_input_helper + lib_hir2mpl_common + lib_hir2mpl_optimize + libdriver_option + libmaple_driver + libmplir + libmplutil + libmempool + libmpl2mpl + libHWSecureC +) + +if (NOT ${ONLY_C} STREQUAL "1") + list(APPEND deps_hir2mpl + lib_hir2mpl_bytecode_input_common + lib_hir2mpl_bytecode_input_dex + lib_hir2mpl_bytecode_input_class + libdexfile + libziparchive + libbase + ${THIRD_PARTY_ROOT}/aosp_modified/system/core/liblog/liblog.a + ) +endif() +if (${MAST} STREQUAL "1") + list(APPEND deps_hir2mpl + lib_hir2mpl_ast_input_maple_lib + lib_hir2mpl_ast_input_maple + ) +endif() + +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lz -rdynamic -L${LLVMLIBDIR}/") + +if (${MAST} STREQUAL "1") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lstdc++fs -L${MAPLE_PARSER_PATH}/output/c/ast_gen/shared") +endif() + +if (${COV} STREQUAL "1") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") +endif() + +if (${GPROF} STREQUAL "1") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") +endif() + +#hir2mpl +add_executable(hir2mpl "${src_hir2mpl}") +set_target_properties(hir2mpl PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "${deps_hir2mpl}" + RUNTIME_OUTPUT_DIRECTORY "${MAPLE_BUILD_OUTPUT}/bin" + +) + +set(inc_lib_hir2mpl_bytecode_input_class + ${HIR2MPL_ROOT}/common/include + ${HIR2MPL_ROOT}/optimize/include + ${HIR2MPL_ROOT}/bytecode_input/class/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 +) + +set(src_lib_hir2mpl_bytecode_input_class + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_attr.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_attr_item.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_bb.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_class.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_class2fe_helper.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_class_const.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_class_const_pool.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_compiler_component.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_function.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_function_context.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_input.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_opcode.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_opcode_helper.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_stack2fe_helper.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_stack_helper.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_stmt.cpp + ${HIR2MPL_ROOT}/bytecode_input/class/src/jbc_util.cpp +) + +# lib_hir2mpl_bytecode_input_class +add_library(lib_hir2mpl_bytecode_input_class STATIC ${src_lib_hir2mpl_bytecode_input_class}) +set_target_properties(lib_hir2mpl_bytecode_input_class PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${inc_lib_hir2mpl_bytecode_input_class}" + LINK_LIBRARIES "" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" +) + +if (NOT ${ONLY_C} STREQUAL "1") + set(inc_lib_hir2mpl_bytecode_input_common + ${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 + ) + + set(src_lib_hir2mpl_bytecode_input_common + ${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 + ) + # lib_hir2mpl_bytecode_input_common + add_library(lib_hir2mpl_bytecode_input_common STATIC ${src_lib_hir2mpl_bytecode_input_common}) + set_target_properties(lib_hir2mpl_bytecode_input_common PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${inc_lib_hir2mpl_bytecode_input_common}" + LINK_LIBRARIES "" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" + ) + + set(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 + ) + + set(src_lib_hir2mpl_bytecode_input_dex + ${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 + ${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 + ) + + list(APPEND include_bytecode_input_dex_directories + ${THIRD_PARTY_ROOT}/aosp_modified/system/core/include + ) + + list(APPEND include_bytecode_input_dex_directories + ${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 + ) + + set(deps_libdexfile + libdexfile + libziparchive + libbase + ${THIRD_PARTY_ROOT}/aosp_modified/system/core/liblog/liblog.a + ) + + # lib_hir2mpl_bytecode_input_dex + add_library(lib_hir2mpl_bytecode_input_dex STATIC ${src_lib_hir2mpl_bytecode_input_dex}) + set_target_properties(lib_hir2mpl_bytecode_input_dex PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_bytecode_input_dex_directories}" + LINK_LIBRARIES "${deps_libdexfile}" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" + ) +endif() + +set(src_lib_hir2mpl_ast_input_clang_lib + ${HIR2MPL_ROOT}/ast_input/clang/lib/ast_interface.cpp +) + +set(deps_lib_hir2mpl_ast_input_clang_lib + ${LLVMLIBDIR}/libclang.so + ${LLVMLIBDIR}/libclang-cpp.so + ${LLVMLIBDIR}/libclangFrontend.a + ${LLVMLIBDIR}/libclangDriver.a + ${LLVMLIBDIR}/libclangSerialization.a + ${LLVMLIBDIR}/libclangParse.a + ${LLVMLIBDIR}/libclangSema.a + ${LLVMLIBDIR}/libclangEdit.a + ${LLVMLIBDIR}/libclangLex.a + ${LLVMLIBDIR}/libclangAnalysis.a + ${LLVMLIBDIR}/libclangAST.a + ${LLVMLIBDIR}/libclangBasic.a + ${LLVMLIBDIR}/libLLVMDemangle.a + ${LLVMLIBDIR}/libLLVMMCParser.a + ${LLVMLIBDIR}/libLLVMMC.a + ${LLVMLIBDIR}/libLLVMBitReader.a + ${LLVMLIBDIR}/libLLVMCore.a + ${LLVMLIBDIR}/libLLVMBinaryFormat.a + ${LLVMLIBDIR}/libLLVMProfileData.a + ${LLVMLIBDIR}/libLLVMOption.a + ${LLVMLIBDIR}/libLLVMSupport.a +) + +set(defines + CLANG_ENABLE_ARCMT + CLANG_ENABLE_OBJC_REWRITER + CLANG_ENABLE_STATIC_ANALYZER + GTEST_HAS_RTTI=0 + _DEBUG + _GNU_SOURCE + __STDC_CONSTANT_MACROS + __STDC_FORMAT_MACROS + __STDC_LIMIT_MACROS +) + +# lib_hir2mpl_ast_input_clang_lib +add_library(lib_hir2mpl_ast_input_clang_lib STATIC ${src_lib_hir2mpl_ast_input_clang_lib}) +set_target_properties(lib_hir2mpl_ast_input_clang_lib PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "${deps_lib_hir2mpl_ast_input_clang_lib}" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" + DEFINE_SYMBOL "${defines}" +) + +# lib_hir2mpl_ast_input_common +add_library(lib_hir2mpl_ast_input_common STATIC "${HIR2MPL_ROOT}/ast_input/common/src/ast_decl.cpp") +set_target_properties(lib_hir2mpl_ast_input_common PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" +) + +set(src_lib_hir2mpl_ast_input_clang + ${HIR2MPL_ROOT}/ast_input/clang/lib/ast_type.cpp + ${HIR2MPL_ROOT}/ast_input/clang/lib/ast_util.cpp + ${HIR2MPL_ROOT}/ast_input/clang/src/ast_expr.cpp + ${HIR2MPL_ROOT}/ast_input/clang/src/ast_function.cpp + ${HIR2MPL_ROOT}/ast_input/clang/src/ast_parser.cpp + ${HIR2MPL_ROOT}/ast_input/clang/src/ast_parser_builting_func.cpp + ${HIR2MPL_ROOT}/ast_input/clang/src/ast_stmt.cpp + ${HIR2MPL_ROOT}/ast_input/clang/src/ast_struct2fe_helper.cpp +) + +set(deps_lib_hir2mpl_ast_input_clang + lib_hir2mpl_ast_input_clang_lib +) + +# lib_hir2mpl_ast_input_clang +add_library(lib_hir2mpl_ast_input_clang STATIC ${src_lib_hir2mpl_ast_input_clang}) +set_target_properties(lib_hir2mpl_ast_input_clang PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "${deps_lib_hir2mpl_ast_input_clang}" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" +) + +if (${MAST} STREQUAL "1") + set(deps_lib_hir2mpl_ast_input_maple_lib + ${MAPLE_PARSER_PATH}/output/c/ast_gen/shared/genast.a + ${MAPLE_PARSER_PATH}/output/c/shared/shared.a + ${MAPLE_PARSER_PATH}/output/c/gen/gen.a + ${MAPLE_PARSER_PATH}/output/c/astopt/astopt.a + ) +# lib_hir2mpl_ast_input_maple_lib + add_library(lib_hir2mpl_ast_input_maple_lib STATIC "${HIR2MPL_ROOT}/ast_input/maple/lib/maple_ast_interface.cpp") + set_target_properties(lib_hir2mpl_ast_input_maple_lib PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "${deps_lib_hir2mpl_ast_input_maple_lib}" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" + DEFINE_SYMBOL "DEBUG" + ) +# lib_hir2mpl_ast_input_maple + add_library(lib_hir2mpl_ast_input_maple STATIC "${HIR2MPL_ROOT}/ast_input/maple/src/maple_ast_parser.cpp") + set_target_properties(lib_hir2mpl_ast_input_maple PROPERTIES + COMPILE_FLAGS "" + INCLUDE_DIRECTORIES "${include_directories}" + LINK_LIBRARIES "lib_hir2mpl_ast_input_maple_lib" + RUNTIME_OUTPUT_DIRECTORY "${root_out_dir}/ar" + DEFINE_SYMBOL "DEBUG" + ) +endif() 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..4577b601397825a0f5b93205b2ed5d00fbc5ed66 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_builtin_func.def +++ b/src/hir2mpl/ast_input/clang/include/ast_builtin_func.def @@ -6,18 +6,28 @@ BUILTIN_FUNC(strcpy) BUILTIN_FUNC(strcmp) BUILTIN_FUNC(strlen) BUILTIN_FUNC(strchr) +BUILTIN_FUNC(strrchr) BUILTIN_FUNC(memcmp) BUILTIN_FUNC(memcpy) BUILTIN_FUNC(memset) BUILTIN_FUNC(memmove) BUILTIN_FUNC(__memcpy_chk) BUILTIN_FUNC(__memset_chk) +BUILTIN_FUNC(__strncpy_chk) +BUILTIN_FUNC(__strcpy_chk) +BUILTIN_FUNC(__stpcpy_chk) +BUILTIN_FUNC(__vsprintf_chk) +BUILTIN_FUNC(__vsnprintf_chk) +BUILTIN_FUNC(__snprintf_chk) +BUILTIN_FUNC(__sprintf_chk) +BUILTIN_FUNC(__strcat_chk) +BUILTIN_FUNC(__strncat_chk) +BUILTIN_FUNC(__mempcpy_chk) +BUILTIN_FUNC(__memmove_chk) + BUILTIN_FUNC(abs) BUILTIN_FUNC(abort) BUILTIN_FUNC(frame_address) BUILTIN_FUNC(setjmp) BUILTIN_FUNC(longjmp) -BUILTIN_FUNC(bswap32) -BUILTIN_FUNC(bswap64) -BUILTIN_FUNC(bswap16) BUILTIN_FUNC(mul_overflow) diff --git a/src/hir2mpl/ast_input/clang/include/ast_expr.h b/src/hir2mpl/ast_input/clang/include/ast_expr.h index 9c7c52ad3e183080ba57b8bdf250fd7fe4349a29..73e6ce33064f9ef2aa42327b3af02facd93fc17f 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,18 +45,24 @@ 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) {} + explicit ASTExpr(MapleAllocator &allocatorIn, ASTOp o) : op(o), vlaExprInfos(allocatorIn.Adapter()) {} virtual ~ASTExpr() = default; UniqueFEIRExpr Emit2FEExpr(std::list &stmts) const; - UniqueFEIRExpr ImplicitInitFieldValue(MIRType *type, std::list &stmts) const; + UniqueFEIRExpr ImplicitInitFieldValue(MIRType &type, std::list &stmts) const; virtual MIRType *GetType() const { return mirType; @@ -83,6 +89,10 @@ class ASTExpr { value = val; } + void SetIsConstantFolded(bool flag) { + isConstantFolded = flag; + } + bool IsConstantFolded() const { return isConstantFolded; } @@ -95,45 +105,98 @@ 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) {} + ASTExpr *IgnoreParens() { + return IgnoreParensImpl(); + } + + void SetVLASizeExprs(MapleList astExprs) { + vlaExprInfos = std::move(astExprs); + } + + void SetCallAlloca(bool isAlloc) { + isCallAlloca = isAlloc; + } + + bool IsCallAlloca() const { + return isCallAlloca; + } + protected: virtual ASTValue *GetConstantValueImpl() const { return value; } virtual MIRConst *GenerateMIRConstImpl() const; virtual UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const = 0; + virtual ASTExpr *IgnoreParensImpl(); virtual ASTDecl *GetASTDeclImpl() const { return refedDecl; } + void EmitVLASizeExprs(std::list &stmts) const { + for (auto &vlaSizeExpr : vlaExprInfos) { + (void)vlaSizeExpr->Emit2FEExpr(stmts); + } + } + ASTOp op; MIRType *mirType = nullptr; ASTDecl *refedDecl = nullptr; bool isConstantFolded = false; ASTValue *value = nullptr; + Loc loc = {0, 0, 0}; + EvaluatedFlag evaluatedflag = kNotEvaluated; + bool isRValue = false; - uint32 srcFileIdx = 0; - uint32 srcFileLineNum = 0; + private: + MapleList vlaExprInfos; + bool isCallAlloca = false; }; class ASTCastExpr : public ASTExpr { public: - ASTCastExpr() : ASTExpr(kASTOpCast) {} + explicit ASTCastExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpCast) { + (void)allocatorIn; + } ~ASTCastExpr() = default; void SetASTExpr(ASTExpr *expr) { @@ -184,6 +247,10 @@ class ASTCastExpr : public ASTExpr { isArrayToPointerDecay = flag; } + void SetIsFunctionToPointerDecay(bool flag) { + isFunctionToPointerDecay = flag; + } + bool IsBuilinFunc() const { return isBuilinFunc; } @@ -214,12 +281,13 @@ class ASTCastExpr : public ASTExpr { UniqueFEIRExpr Emit2FEExprForComplex(const UniqueFEIRExpr &subExpr, const UniqueFEIRType &srcType, std::list &stmts) const; + UniqueFEIRExpr Emit2FEExprForFunctionOrArray2Pointer(std::list &stmts) const; + private: MIRConst *GenerateMIRDoubleConst() const; MIRConst *GenerateMIRFloatConst() const; MIRConst *GenerateMIRIntConst() const; UniqueFEIRExpr EmitExprVdupVector(PrimType primtype, UniqueFEIRExpr &subExpr) const; - void CheckNonnullFieldInStruct() const; ASTExpr *child = nullptr; MIRType *src = nullptr; @@ -229,6 +297,7 @@ class ASTCastExpr : public ASTExpr { MIRType *complexType = nullptr; bool imageZero = false; bool isArrayToPointerDecay = false; + bool isFunctionToPointerDecay = false; bool isBuilinFunc = false; bool isUnoinCast = false; bool isVectorSplat = false; @@ -236,7 +305,9 @@ class ASTCastExpr : public ASTExpr { class ASTDeclRefExpr : public ASTExpr { public: - ASTDeclRefExpr() : ASTExpr(kASTOpRef) {} + explicit ASTDeclRefExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpRef) { + (void)allocatorIn; + } ~ASTDeclRefExpr() = default; protected: @@ -246,9 +317,11 @@ class ASTDeclRefExpr : public ASTExpr { class ASTUnaryOperatorExpr : public ASTExpr { public: - explicit ASTUnaryOperatorExpr(ASTOp o) : ASTExpr(o) {} + explicit ASTUnaryOperatorExpr(MapleAllocator &allocatorIn, ASTOp o) : ASTExpr(allocatorIn, o) { + (void)allocatorIn; + } virtual ~ASTUnaryOperatorExpr() = default; - void SetUOExpr(ASTExpr*); + void SetUOExpr(ASTExpr *astExpr); const ASTExpr *GetUOExpr() const { return expr; @@ -284,38 +357,48 @@ class ASTUnaryOperatorExpr : public ASTExpr { return isGlobal; } + void SetVariableArrayExpr(ASTExpr *expr) { + variableArrayExpr = expr; + } + + void SetisVariableArrayType(bool isVariableArrayTypeArg) { + isVariableArrayType = isVariableArrayTypeArg; + } + UniqueFEIRExpr ASTUOSideEffectExpr(Opcode op, std::list &stmts, const std::string &varName = "", bool post = false) const; protected: bool isGlobal = false; + bool isVariableArrayType = false; ASTExpr *expr = nullptr; MIRType *subType = nullptr; MIRType *uoType = nullptr; + ASTExpr *variableArrayExpr = nullptr; int64 pointeeLen = 0; }; -class ASTUOMinusExpr: public ASTUnaryOperatorExpr { +class ASTUOMinusExpr : public ASTUnaryOperatorExpr { public: - ASTUOMinusExpr() : ASTUnaryOperatorExpr(kASTOpMinus) {} + explicit ASTUOMinusExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpMinus) {} ~ASTUOMinusExpr() = default; private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; }; -class ASTUONotExpr: public ASTUnaryOperatorExpr { +class ASTUONotExpr : public ASTUnaryOperatorExpr { public: - ASTUONotExpr() : ASTUnaryOperatorExpr(kASTOpNot) {} + explicit ASTUONotExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpNot) {} ~ASTUONotExpr() = default; private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; }; -class ASTUOLNotExpr: 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 { @@ -329,9 +412,10 @@ class ASTUOLNotExpr: public ASTUnaryOperatorExpr { uint32 falseIdx = 0; }; -class ASTUOPostIncExpr: 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: @@ -339,9 +423,10 @@ class ASTUOPostIncExpr: public ASTUnaryOperatorExpr { std::string tempVarName; }; -class ASTUOPostDecExpr: 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: @@ -349,18 +434,18 @@ class ASTUOPostDecExpr: public ASTUnaryOperatorExpr { std::string tempVarName; }; -class ASTUOPreIncExpr: public ASTUnaryOperatorExpr { +class ASTUOPreIncExpr : public ASTUnaryOperatorExpr { public: - ASTUOPreIncExpr() : ASTUnaryOperatorExpr(kASTOpPreInc) {} + explicit ASTUOPreIncExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPreInc) {} ~ASTUOPreIncExpr() = default; private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; }; -class ASTUOPreDecExpr: public ASTUnaryOperatorExpr { +class ASTUOPreDecExpr : public ASTUnaryOperatorExpr { public: - ASTUOPreDecExpr() : ASTUnaryOperatorExpr(kASTOpPreDec) {} + explicit ASTUOPreDecExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPreDec) {} ~ASTUOPreDecExpr() = default; private: @@ -368,9 +453,9 @@ class ASTUOPreDecExpr: public ASTUnaryOperatorExpr { std::string tempVarName; }; -class ASTUOAddrOfExpr: public ASTUnaryOperatorExpr { +class ASTUOAddrOfExpr : public ASTUnaryOperatorExpr { public: - ASTUOAddrOfExpr() : ASTUnaryOperatorExpr(kASTOpAddrOf) {} + explicit ASTUOAddrOfExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpAddrOf) {} ~ASTUOAddrOfExpr() = default; protected: @@ -382,24 +467,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 { +class ASTUODerefExpr : public ASTUnaryOperatorExpr { public: - ASTUODerefExpr() : ASTUnaryOperatorExpr(kASTOpDeref) {} + explicit ASTUODerefExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpDeref) {} ~ASTUODerefExpr() = default; private: @@ -408,18 +498,18 @@ class ASTUODerefExpr: public ASTUnaryOperatorExpr { bool InsertBoundaryChecking(std::list &stmts, UniqueFEIRExpr expr) const; }; -class ASTUOPlusExpr: public ASTUnaryOperatorExpr { +class ASTUOPlusExpr : public ASTUnaryOperatorExpr { public: - ASTUOPlusExpr() : ASTUnaryOperatorExpr(kASTOpPlus) {} + explicit ASTUOPlusExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpPlus) {} ~ASTUOPlusExpr() = default; private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; }; -class ASTUORealExpr: public ASTUnaryOperatorExpr { +class ASTUORealExpr : public ASTUnaryOperatorExpr { public: - ASTUORealExpr() : ASTUnaryOperatorExpr(kASTOpReal) {} + explicit ASTUORealExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpReal) {} ~ASTUORealExpr() = default; void SetElementType(MIRType *type) { @@ -431,9 +521,9 @@ class ASTUORealExpr: public ASTUnaryOperatorExpr { MIRType *elementType = nullptr; }; -class ASTUOImagExpr: public ASTUnaryOperatorExpr { +class ASTUOImagExpr : public ASTUnaryOperatorExpr { public: - ASTUOImagExpr() : ASTUnaryOperatorExpr(kASTOpImag) {} + explicit ASTUOImagExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpImag) {} ~ASTUOImagExpr() = default; void SetElementType(MIRType *type) { @@ -445,18 +535,18 @@ class ASTUOImagExpr: public ASTUnaryOperatorExpr { MIRType *elementType = nullptr; }; -class ASTUOExtensionExpr: public ASTUnaryOperatorExpr { +class ASTUOExtensionExpr : public ASTUnaryOperatorExpr { public: - ASTUOExtensionExpr() : ASTUnaryOperatorExpr(kASTOpExtension) {} + explicit ASTUOExtensionExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpExtension) {} ~ASTUOExtensionExpr() = default; private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; }; -class ASTUOCoawaitExpr: public ASTUnaryOperatorExpr { +class ASTUOCoawaitExpr : public ASTUnaryOperatorExpr { public: - ASTUOCoawaitExpr() : ASTUnaryOperatorExpr(kASTOpCoawait) {} + explicit ASTUOCoawaitExpr(MapleAllocator &allocatorIn) : ASTUnaryOperatorExpr(allocatorIn, kASTOpCoawait) {} ~ASTUOCoawaitExpr() = default; private: @@ -465,9 +555,11 @@ class ASTUOCoawaitExpr: public ASTUnaryOperatorExpr { class ASTPredefinedExpr : public ASTExpr { public: - ASTPredefinedExpr() : ASTExpr(kASTOpPredefined) {} + explicit ASTPredefinedExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpPredefined) { + (void)allocatorIn; + } ~ASTPredefinedExpr() = default; - void SetASTExpr(ASTExpr*); + void SetASTExpr(ASTExpr *astExpr); private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; @@ -476,9 +568,11 @@ class ASTPredefinedExpr : public ASTExpr { class ASTOpaqueValueExpr : public ASTExpr { public: - ASTOpaqueValueExpr() : ASTExpr(kASTOpOpaqueValue) {} + explicit ASTOpaqueValueExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpOpaqueValue) { + (void)allocatorIn; + } ~ASTOpaqueValueExpr() = default; - void SetASTExpr(ASTExpr*); + void SetASTExpr(ASTExpr *astExpr); private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; @@ -487,50 +581,50 @@ class ASTOpaqueValueExpr : public ASTExpr { class ASTNoInitExpr : public ASTExpr { public: - ASTNoInitExpr() : ASTExpr(kASTOpNoInitExpr) {} + explicit ASTNoInitExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpNoInitExpr) { + (void)allocatorIn; + } ~ASTNoInitExpr() = default; void SetNoInitType(MIRType *type); private: + MIRConst *GenerateMIRConstImpl() const override; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; MIRType *noInitType = nullptr; }; class ASTCompoundLiteralExpr : public ASTExpr { public: - ASTCompoundLiteralExpr() : ASTExpr(kASTOpCompoundLiteralExp) {} + explicit ASTCompoundLiteralExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpCompoundLiteralExpr) { + (void)allocatorIn; + } ~ASTCompoundLiteralExpr() = default; void SetCompoundLiteralType(MIRType *clType); + void SetASTExpr(ASTExpr *astExpr); - MIRType *GetCompoundLiteralType() const { - return compoundLiteralType; + void SetAddrof(bool flag) { + isAddrof = flag; } - 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 SetVariableArrayExpr(ASTExpr *expr) { + variableArrayExpr = expr; } 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; + ASTExpr *variableArrayExpr = nullptr; }; class ASTOffsetOfExpr : public ASTExpr { public: - ASTOffsetOfExpr() : ASTExpr(kASTOpOffsetOfExpr) {} + explicit ASTOffsetOfExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpOffsetOfExpr) { + (void)allocatorIn; + } ~ASTOffsetOfExpr() = default; void SetStructType(MIRType *stype); void SetFieldName(const std::string &fName); @@ -548,7 +642,9 @@ class ASTOffsetOfExpr : public ASTExpr { class ASTInitListExpr : public ASTExpr { public: - ASTInitListExpr() : ASTExpr(kASTOpInitListExpr) {} + explicit ASTInitListExpr(MapleAllocator &allocatorIn) + : ASTExpr(allocatorIn, kASTOpInitListExpr), initExprs(allocatorIn.Adapter()), + varName("", allocatorIn.GetMemPool()) {} ~ASTInitListExpr() = default; void SetInitExprs(ASTExpr *astExpr); void SetInitListType(MIRType *type); @@ -557,7 +653,7 @@ class ASTInitListExpr : public ASTExpr { return initListType; } - std::vector GetInitExprs() const { + MapleVector GetInitExprs() const { return initExprs; } @@ -565,8 +661,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) { @@ -613,40 +709,81 @@ class ASTInitListExpr : public ASTExpr { return hasVectorType; } + void SetElemLen(size_t num) { + elemLen = num; + } + + size_t GetElemLen() const { + return elemLen; + } + 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 SolveArrayElementInitWithInitListExpr(const UniqueFEIRExpr &addrOfArray, const UniqueFEIRExpr &addrOfElementExpr, + const MIRType &elementType, const ASTExpr &subExpr, size_t index, + std::list &stmts) const; + void HandleImplicitInitSections(const UniqueFEIRExpr &addrOfArray, const ASTInitListExpr &initList, + const MIRType &elementType, std::list &stmts) const; void ProcessStructInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, std::list &stmts) const; + const ASTInitListExpr &initList, std::list &stmts) const; + void SolveInitListFullOfZero(const MIRStructType &baseStructType, FieldID baseFieldID, const UniqueFEIRVar &var, + const ASTInitListExpr &initList, std::list &stmts) const; + bool SolveInitListPartialOfZero(std::variant, UniqueFEIRExpr> &base, + FieldID fieldID, uint32 &index, const ASTInitListExpr &initList, + std::list &stmts) const; + void SolveInitListExprOrDesignatedInitUpdateExpr(std::tuple fieldInfo, ASTExpr &initExpr, + const UniqueFEIRType &baseStructPtrType, std::variant, UniqueFEIRExpr> &base, + std::list &stmts) const; + void SolveStructFieldOfArrayTypeInitWithStringLiteral(std::tuple fieldInfo, + const ASTExpr &initExpr, const UniqueFEIRType &baseStructPtrType, + std::variant, UniqueFEIRExpr> &base, std::list &stmts) const; + void SolveStructFieldOfBasicType(FieldID fieldID, const ASTExpr &initExpr, const UniqueFEIRType &baseStructPtrType, + std::variant, UniqueFEIRExpr> &base, + std::list &stmts) const; + std::tuple GetStructFieldInfo(uint32 fieldIndex, FieldID baseFieldID, + MIRStructType &structMirType) const; + UniqueFEIRExpr CalculateStartAddressForMemset(const UniqueFEIRVar &varIn, uint32 initSizeIn, FieldID fieldIDIn, + const std::variant, UniqueFEIRExpr> &baseIn) const; + UniqueFEIRExpr GetAddrofArrayFEExprByStructArrayField(MIRType &fieldType, + const 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, + const UniqueFEIRExpr &addrOfCharArray, ASTExpr *expr, + std::list &stmts) const; + void ProcessNoBaseDesignatedInitUpdater(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, const 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; + size_t elemLen = 0; 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(allocatorIn, + kASTOpBinaryConditionalOperator) { + (void)allocatorIn; + } ~ASTBinaryConditionalOperator() = default; void SetCondExpr(ASTExpr *expr); void SetFalseExpr(ASTExpr *expr); @@ -659,9 +796,12 @@ 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(allocatorIn, o) { + (void)allocatorIn; + } + explicit ASTBinaryOperatorExpr(MapleAllocator &allocatorIn) + : ASTExpr(allocatorIn, kASTOpBO), varName(FEUtils::GetSequentialName(FEUtils::kCondGoToStmtLabelNamePrefix), + allocatorIn.GetMemPool()) {} ~ASTBinaryOperatorExpr() override = default; @@ -718,10 +858,18 @@ 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: MIRConst *GenerateMIRConstImpl() const override; + MIRConst *SolveOpcodeLiorOrCior(const MIRConst &leftConst) const; + MIRConst *SolveOpcodeLandOrCand(const MIRConst &leftConst, const MIRConst &rightConst) const; + MIRConst *SolveOpcodeAdd(const MIRConst &leftConst, const MIRConst &rightConst) const; + MIRConst *SolveOpcodeSub(const MIRConst &leftConst, const MIRConst &rightConst) const; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; UniqueFEIRExpr Emit2FEExprComplexCalculations(std::list &stmts) const; UniqueFEIRExpr Emit2FEExprComplexCompare(std::list &stmts) const; @@ -738,14 +886,17 @@ 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(allocatorIn, + kASTImplicitValueInitExpr) { + (void)allocatorIn; + } ~ASTImplicitValueInitExpr() = default; protected: @@ -757,7 +908,8 @@ class ASTImplicitValueInitExpr : public ASTExpr { class ASTStringLiteral : public ASTExpr { public: - ASTStringLiteral() : ASTExpr(kASTStringLiteral) {} + explicit ASTStringLiteral(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTStringLiteral), + codeUnits(allocatorIn.Adapter()), str(allocatorIn.Adapter()) {} ~ASTStringLiteral() = default; void SetLength(size_t len) { @@ -768,14 +920,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(); + } + (void)str.insert(str.cend(), strIn.cbegin(), strIn.cend()); + } + + const std::string GetStr() const { + return std::string(str.cbegin(), str.cend()); + } + void SetIsArrayToPointerDecay(bool argIsArrayToPointerDecay) { isArrayToPointerDecay = argIsArrayToPointerDecay; } @@ -790,13 +954,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(allocatorIn, kASTSubscriptExpr) { + (void)allocatorIn; + } ~ASTArraySubscriptExpr() = default; void SetBaseExpr(ASTExpr *astExpr) { @@ -829,13 +996,21 @@ 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; + bool CheckFirstDimIfZero(const MIRType *arrType) const; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; - void InsertNonnullChecking(std::list &stmts, const UniqueFEIRExpr &idxExpr, - const UniqueFEIRExpr &addrOfArray) const; + MIRType *GetArrayTypeForPointerArray() const; + UniqueFEIRExpr SolveMultiDimArray(UniqueFEIRExpr &baseAddrFEExpr, UniqueFEIRType &arrayFEType, + bool isArrayTypeOpt, std::list &stmts) const; + UniqueFEIRExpr SolveOtherArrayType(const UniqueFEIRExpr &baseAddrFEExpr, std::list &stmts) const; + void InsertNonnullChecking(std::list &stmts, const UniqueFEIRExpr &indexExpr, + const UniqueFEIRExpr &baseAddrExpr) const; bool InsertBoundaryChecking(std::list &stmts, UniqueFEIRExpr indexExpr, UniqueFEIRExpr baseAddrFEExpr) const; @@ -843,42 +1018,41 @@ class ASTArraySubscriptExpr : public ASTExpr { MIRType *arrayType = nullptr; ASTExpr *idxExpr = nullptr; bool isVLA = false; + ASTExpr *vlaSizeExpr = nullptr; }; class ASTExprUnaryExprOrTypeTraitExpr : public ASTExpr { public: - ASTExprUnaryExprOrTypeTraitExpr() : ASTExpr(kASTExprUnaryExprOrTypeTraitExpr) {} - ~ASTExprUnaryExprOrTypeTraitExpr() = default; - - void SetIsType(bool type) { - isType = type; + explicit ASTExprUnaryExprOrTypeTraitExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, + kASTExprUnaryExprOrTypeTraitExpr) { + (void)allocatorIn; } + ~ASTExprUnaryExprOrTypeTraitExpr() = default; - void SetArgType(MIRType *type) { - argType = type; + void SetIdxExpr(ASTExpr *astExpr) { + idxExpr = astExpr; } - - void SetArgExpr(ASTExpr *astExpr) { - argExpr = astExpr; + void SetSizeExpr(ASTExpr *expr) { + sizeExpr = expr; } private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; - bool isType = false; - MIRType *argType = nullptr; - ASTExpr *argExpr = nullptr; + ASTExpr *sizeExpr = nullptr; + ASTExpr *idxExpr = nullptr; }; class ASTMemberExpr : public ASTExpr { public: - ASTMemberExpr() : ASTExpr(kASTMemberExpr) {} + explicit ASTMemberExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTMemberExpr), + memberName("", allocatorIn.GetMemPool()) {} ~ASTMemberExpr() = default; void SetBaseExpr(ASTExpr *astExpr) { baseExpr = astExpr; } - ASTExpr *GetBaseExpr() const { + const ASTExpr *GetBaseExpr() const { return baseExpr; } @@ -887,7 +1061,7 @@ class ASTMemberExpr : public ASTExpr { } std::string GetMemberName() const { - return memberName; + return memberName.c_str() == nullptr ? "" : memberName.c_str(); } void SetMemberType(MIRType *type) { @@ -925,11 +1099,11 @@ class ASTMemberExpr : public ASTExpr { private: MIRConst *GenerateMIRConstImpl() const override; UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; - const ASTMemberExpr *FindFinalMember(const ASTMemberExpr *startExpr, std::list &memberNames) const; + const ASTMemberExpr &FindFinalMember(const ASTMemberExpr &startExpr, std::list &memberNames) const; 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 +1112,17 @@ class ASTMemberExpr : public ASTExpr { class ASTDesignatedInitUpdateExpr : public ASTExpr { public: - ASTDesignatedInitUpdateExpr() : ASTExpr(kASTASTDesignatedInitUpdateExpr) {} + explicit ASTDesignatedInitUpdateExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, + kASTASTDesignatedInitUpdateExpr) { + (void)allocatorIn; + } ~ASTDesignatedInitUpdateExpr() = default; void SetBaseExpr(ASTExpr *astExpr) { baseExpr = astExpr; } - ASTExpr *GetBaseExpr() const{ + const ASTExpr *GetBaseExpr() const{ return baseExpr; } @@ -961,11 +1138,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 +1161,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 +1178,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 +1187,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,42 +1196,40 @@ class ASTBOPtrMemExpr : public ASTBinaryOperatorExpr { class ASTCallExpr : public ASTExpr { public: - ASTCallExpr() : ASTExpr(kASTOpCall), varName(FEUtils::GetSequentialName("retVar_")) {} + explicit ASTCallExpr(MapleAllocator &allocatorIn) + : ASTExpr(allocatorIn, 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; } - void SetRetType(MIRType *typeIn) { - retType = typeIn; - } - MIRType *GetRetType() const { - return retType; + return mirType; } - 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) { @@ -1073,18 +1249,26 @@ class ASTCallExpr : public ASTExpr { } bool IsNeedRetExpr() const { - return retType->GetPrimType() != PTY_void; + return mirType->GetPrimType() != PTY_void; } bool IsFirstArgRet() const { // If the return value exceeds 16 bytes, it is passed as the first parameter. - return retType->GetPrimType() == PTY_agg && retType->GetSize() > 16; + return mirType->GetPrimType() == PTY_agg && mirType->GetSize() > 16; } void SetFuncDecl(ASTFunc *decl) { 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,9 +1285,14 @@ 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; + UniqueFEIRExpr EmitBuiltinVectorLoad(std::list &stmts, bool &isFinish) const; + UniqueFEIRExpr EmitBuiltinVectorStore(std::list &stmts, bool &isFinish) const; + UniqueFEIRExpr EmitBuiltinVectorShli(std::list &stmts, bool &isFinish) const; + UniqueFEIRExpr EmitBuiltinVectorShri(std::list &stmts, bool &isFinish) const; + UniqueFEIRExpr EmitBuiltinVectorShru(std::list &stmts, bool &isFinish) const; UniqueFEIRExpr EmitBuiltinRotate(std::list &stmts, PrimType rotType, bool isLeft) const; #define EMIT_BUILTIIN_FUNC(FUNC) EmitBuiltin##FUNC(std::list &stmts) const UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Ctz); @@ -1137,7 +1326,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); @@ -1156,6 +1344,9 @@ class ASTCallExpr : public ASTExpr { UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Exp); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Expf); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Fmax); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Bswap64); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Bswap32); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Bswap16); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Fmin); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Log); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(Logf); @@ -1180,23 +1371,73 @@ 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(ObjectSize); + UniqueFEIRExpr EMIT_BUILTIIN_FUNC(ReturnAddress); UniqueFEIRExpr EMIT_BUILTIIN_FUNC(ExtractReturnAddr); @@ -1204,24 +1445,27 @@ class ASTCallExpr : public ASTExpr { #define DEF_MIR_INTRINSIC(STR, NAME, INTRN_CLASS, RETURN_TYPE, ...) \ UniqueFEIRExpr EmitBuiltin##STR(std::list &stmts) const; #include "intrinsic_vector.def" +#include "intrinsic_vector_new.def" #undef DEF_MIR_INTRINSIC 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(allocatorIn, kASTParen) { + (void)allocatorIn; + } ~ASTParenExpr() = default; void SetASTExpr(ASTExpr *astExpr) { @@ -1238,6 +1482,10 @@ class ASTParenExpr : public ASTExpr { return child->GenerateMIRConst(); } + ASTExpr *IgnoreParensImpl() override { + return child->IgnoreParens(); + } + private: UniqueFEIRExpr Emit2FEExprImpl(std::list &stmts) const override; @@ -1252,7 +1500,9 @@ class ASTParenExpr : public ASTExpr { class ASTIntegerLiteral : public ASTExpr { public: - ASTIntegerLiteral() : ASTExpr(kASTIntegerLiteral) {} + explicit ASTIntegerLiteral(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTIntegerLiteral) { + (void)allocatorIn; + } ~ASTIntegerLiteral() = default; int64 GetVal() const { @@ -1272,14 +1522,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(allocatorIn, kASTFloatingLiteral) { + (void)allocatorIn; + } ~ASTFloatingLiteral() = default; double GetVal() const { @@ -1302,12 +1554,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(allocatorIn, kASTCharacterLiteral) { + (void)allocatorIn; + } ~ASTCharacterLiteral() = default; int64 GetVal() const { @@ -1340,7 +1594,9 @@ struct VaArgInfo { class ASTVAArgExpr : public ASTExpr { public: - ASTVAArgExpr() : ASTExpr(kASTVAArgExpr) {} + explicit ASTVAArgExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTVAArgExpr) { + (void)allocatorIn; + } ~ASTVAArgExpr() = default; void SetASTExpr(ASTExpr *astExpr) { @@ -1363,12 +1619,18 @@ class ASTVAArgExpr : public ASTExpr { class ASTConstantExpr : public ASTExpr { public: - ASTConstantExpr() : ASTExpr(kConstantExpr) {} + explicit ASTConstantExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kConstantExpr) { + (void)allocatorIn; + } ~ASTConstantExpr() = default; void SetASTExpr(ASTExpr *astExpr) { child = astExpr; } + const ASTExpr *GetChild() const{ + return child; + } + protected: MIRConst *GenerateMIRConstImpl() const override; @@ -1379,7 +1641,9 @@ class ASTConstantExpr : public ASTExpr { class ASTImaginaryLiteral : public ASTExpr { public: - ASTImaginaryLiteral() : ASTExpr(kASTImaginaryLiteral) {} + explicit ASTImaginaryLiteral(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTImaginaryLiteral) { + (void)allocatorIn; + } ~ASTImaginaryLiteral() = default; void SetASTExpr(ASTExpr *astExpr) { child = astExpr; @@ -1402,7 +1666,9 @@ class ASTImaginaryLiteral : public ASTExpr { class ASTConditionalOperator : public ASTExpr { public: - ASTConditionalOperator() : ASTExpr(kASTConditionalOperator) {} + explicit ASTConditionalOperator(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTConditionalOperator) { + (void)allocatorIn; + } ~ASTConditionalOperator() = default; void SetCondExpr(ASTExpr *astExpr) { @@ -1437,7 +1703,9 @@ class ASTConditionalOperator : public ASTExpr { class ASTArrayInitLoopExpr : public ASTExpr { public: - ASTArrayInitLoopExpr() : ASTExpr(kASTOpArrayInitLoop) {} + explicit ASTArrayInitLoopExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpArrayInitLoop) { + (void)allocatorIn; + } ~ASTArrayInitLoopExpr() = default; void SetCommonExpr(ASTExpr *expr) { @@ -1455,7 +1723,9 @@ class ASTArrayInitLoopExpr : public ASTExpr { class ASTArrayInitIndexExpr : public ASTExpr { public: - ASTArrayInitIndexExpr() : ASTExpr(kASTOpArrayInitLoop) {} + explicit ASTArrayInitIndexExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpArrayInitLoop) { + (void)allocatorIn; + } ~ASTArrayInitIndexExpr() = default; void SetPrimType(MIRType *pType) { @@ -1482,7 +1752,9 @@ class ASTArrayInitIndexExpr : public ASTExpr { class ASTExprWithCleanups : public ASTExpr { public: - ASTExprWithCleanups() : ASTExpr(kASTOpExprWithCleanups) {} + explicit ASTExprWithCleanups(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpExprWithCleanups) { + (void)allocatorIn; + } ~ASTExprWithCleanups() = default; void SetSubExpr(ASTExpr *sub) { @@ -1500,7 +1772,10 @@ class ASTExprWithCleanups : public ASTExpr { class ASTMaterializeTemporaryExpr : public ASTExpr { public: - ASTMaterializeTemporaryExpr() : ASTExpr(kASTOpMaterializeTemporary) {} + explicit ASTMaterializeTemporaryExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, + kASTOpMaterializeTemporary) { + (void)allocatorIn; + } ~ASTMaterializeTemporaryExpr() = default; private: @@ -1509,7 +1784,10 @@ class ASTMaterializeTemporaryExpr : public ASTExpr { class ASTSubstNonTypeTemplateParmExpr : public ASTExpr { public: - ASTSubstNonTypeTemplateParmExpr() : ASTExpr(kASTOpSubstNonTypeTemplateParm) {} + explicit ASTSubstNonTypeTemplateParmExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, + kASTOpSubstNonTypeTemplateParm) { + (void)allocatorIn; + } ~ASTSubstNonTypeTemplateParmExpr() = default; private: @@ -1518,7 +1796,10 @@ class ASTSubstNonTypeTemplateParmExpr : public ASTExpr { class ASTDependentScopeDeclRefExpr : public ASTExpr { public: - ASTDependentScopeDeclRefExpr() : ASTExpr(kASTOpDependentScopeDeclRef) {} + explicit ASTDependentScopeDeclRefExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, + kASTOpDependentScopeDeclRef) { + (void)allocatorIn; + } ~ASTDependentScopeDeclRefExpr() = default; private: @@ -1527,13 +1808,20 @@ class ASTDependentScopeDeclRefExpr : public ASTExpr { class ASTAtomicExpr : public ASTExpr { public: - ASTAtomicExpr() : ASTExpr(kASTOpAtomic) {} + explicit ASTAtomicExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpAtomic), + varName(FEUtils::GetSequentialName("ret.var.")) { + (void)allocatorIn; + } ~ASTAtomicExpr() = default; void SetRefType(MIRType *ref) { refType = ref; } + const std::string GetRetVarName() const { + return varName.c_str(); + } + void SetAtomicOp(ASTAtomicOp op) { atomicOp = op; } @@ -1586,6 +1874,18 @@ class ASTAtomicExpr : public ASTExpr { val2Type = ty; } + void SetFirstParamType(MIRType *ty) { + firstType = ty; + } + + void SetSecondParamType(MIRType *ty) { + secondType = ty; + } + + void SetThirdParamType(MIRType *ty) { + thirdType = ty; + } + void SetFromStmt(bool fromStmt) { isFromStmt = fromStmt; } @@ -1599,17 +1899,23 @@ class ASTAtomicExpr : public ASTExpr { MIRType *refType = nullptr; MIRType *val1Type = nullptr; MIRType *val2Type = nullptr; + MIRType *firstType = nullptr; + MIRType *secondType = nullptr; + MIRType *thirdType = nullptr; ASTExpr *objExpr = nullptr; ASTExpr *valExpr1 = nullptr; ASTExpr *valExpr2 = nullptr; ASTExpr *orderExpr = nullptr; ASTAtomicOp atomicOp = kAtomicOpUndefined; bool isFromStmt = false; + const std::string varName; }; class ASTExprStmtExpr : public ASTExpr { public: - ASTExprStmtExpr() : ASTExpr(kASTOpStmtExpr) {} + explicit ASTExprStmtExpr(MapleAllocator &allocatorIn) : ASTExpr(allocatorIn, kASTOpStmtExpr) { + (void)allocatorIn; + } ~ASTExprStmtExpr() = default; void SetCompoundStmt(ASTStmt *sub) { cpdStmt = sub; @@ -1625,4 +1931,4 @@ class ASTExprStmtExpr : public ASTExpr { ASTStmt *cpdStmt = nullptr; }; } -#endif //HIR2MPL_AST_INPUT_INCLUDE_AST_EXPR_H +#endif // HIR2MPL_AST_INPUT_INCLUDE_AST_EXPR_H diff --git a/src/hir2mpl/ast_input/clang/include/ast_function.h b/src/hir2mpl/ast_input/clang/include/ast_function.h index ed97568b027d91d27ede76321702a018c80c1c3d..814c3c34a212947db099de9191eacbc47466a029 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_function.h +++ b/src/hir2mpl/ast_input/clang/include/ast_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. @@ -63,9 +63,11 @@ class ASTFunction : public FEFunction { void FinishImpl() override; bool EmitToMIR(const std::string &phaseName) override; void SetMIRFunctionInfo(); + void AddVLACleanupStmts(std::list &stmts) override; const ASTFunc2FEHelper &funcHelper; ASTFunc &astFunc; + std::list vlaCleanupStmts; bool error = false; }; } // namespace maple 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..77feeee183d978be00c89fbb9700d65b094227f3 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. @@ -18,6 +18,7 @@ #include #include "mempool_allocator.h" #include "ast_decl.h" +#include "ast_decl_builder.h" #include "ast_interface.h" namespace maple { @@ -25,14 +26,17 @@ class ASTParser { public: ASTParser(MapleAllocator &allocatorIn, uint32 fileIdxIn, const std::string &fileNameIn, MapleList &astStructsIn, MapleList &astFuncsIn, MapleList &astVarsIn, - MapleList &astFileScopeAsmsIn) - : fileIdx(fileIdxIn), fileName(fileNameIn), globalVarDecles(allocatorIn.Adapter()), + MapleList &astFileScopeAsmsIn, MapleList &astEnumsIn) + : 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) {} + astVars(astVarsIn), astFileScopeAsms(astFileScopeAsmsIn), astEnums(astEnumsIn), + vlaSizeMap(allocatorIn.Adapter()) {} virtual ~ASTParser() = default; - bool OpenFile(); + bool OpenFile(MapleAllocator &allocator); + bool Release() const; + bool Verify() const; bool PreProcessAST(); @@ -40,15 +44,15 @@ class ASTParser { bool RetrieveFuncs(MapleAllocator &allocator); bool RetrieveGlobalVars(MapleAllocator &allocator); bool RetrieveFileScopeAsms(MapleAllocator &allocator); + bool RetrieveGlobalTypeDef(MapleAllocator &allocator); + bool RetrieveEnums(MapleAllocator &allocator); - 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,19 +88,55 @@ 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 - const clang::Expr *PeelParen(const clang::Expr &expr); - const clang::Expr *PeelParen2(const clang::Expr &expr); - ASTUnaryOperatorExpr *AllocUnaryOperatorExpr(MapleAllocator &allocator, const clang::UnaryOperator &expr); + const clang::Expr *PeelParen(const clang::Expr &expr) const; + const clang::Expr *PeelParen2(const clang::Expr &expr) const; + ASTUnaryOperatorExpr *AllocUnaryOperatorExpr(MapleAllocator &allocator, const clang::UnaryOperator &expr) const; 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); - ASTExpr *ProcessExprCastExpr(MapleAllocator &allocator, const clang::CastExpr &expr); + void SaveVLASizeExpr(MapleAllocator &allocator, const clang::Type &type, MapleList &vlaSizeExprs) { + if (!type.isVariableArrayType()) { + return; + } + const clang::VariableArrayType *vlaType = llvm::cast(&type); + if (vlaSizeMap.find(vlaType->getSizeExpr()) != vlaSizeMap.cend()) { + return; // vla size expr already exists + } + const clang::QualType qualType = type.getCanonicalTypeInternal(); + ASTExpr *vlaSizeExpr = BuildExprToComputeSizeFromVLA(allocator, qualType.getCanonicalType()); + if (vlaSizeExpr == nullptr) { + return; + } + ASTDeclRefExpr *vlaSizeVarExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + MIRType *vlaSizeType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(PTY_u64); + ASTDecl *vlaSizeVar = ASTDeclsBuilder::ASTDeclBuilder( + allocator, MapleString("", allocator.GetMemPool()), FEUtils::GetSequentialName("vla_size."), + MapleVector({vlaSizeType}, allocator.Adapter())); + vlaSizeVar->SetIsParam(true); + vlaSizeVarExpr->SetASTDecl(vlaSizeVar); + ASTAssignExpr *expr = ASTDeclsBuilder::ASTStmtBuilder(allocator); + expr->SetLeftExpr(vlaSizeVarExpr); + expr->SetRightExpr(vlaSizeExpr); + vlaSizeMap[vlaType->getSizeExpr()] = vlaSizeVarExpr; + (void)vlaSizeExprs.emplace_back(expr); + SaveVLASizeExpr(allocator, *(vlaType->getElementType().getCanonicalType().getTypePtr()), vlaSizeExprs); + } + ASTExpr *ProcessTypeofExpr(MapleAllocator &allocator, clang::QualType type); + ASTBinaryOperatorExpr *AllocBinaryOperatorExpr(MapleAllocator &allocator, const clang::BinaryOperator &bo) const; + ASTExpr *ProcessExprCastExpr(MapleAllocator &allocator, const clang::CastExpr &expr, + const clang::Type **vlaType = nullptr); + ASTExpr *SolvePointerOffsetOperation(MapleAllocator &allocator, const clang::BinaryOperator &bo, + ASTBinaryOperatorExpr &astBinOpExpr, ASTExpr &astRExpr, ASTExpr &astLExpr); + ASTExpr *SolvePointerSubPointerOperation(MapleAllocator &allocator, const clang::BinaryOperator &bo, + ASTBinaryOperatorExpr &astBinOpExpr) const; #define PROCESS_EXPR(CLASS) ProcessExpr##CLASS(MapleAllocator&, const clang::CLASS&) ASTExpr *PROCESS_EXPR(UnaryOperator); ASTExpr *PROCESS_EXPR(AddrLabelExpr); @@ -143,7 +183,16 @@ class ASTParser { ASTExpr *PROCESS_EXPR(ChooseExpr); ASTExpr *PROCESS_EXPR(GenericSelectionExpr); + MapleVector SolveFuncParameterDecls(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, + MapleVector &typeDescIn, std::list &stmts); + GenericAttrs SolveFunctionAttributes(const clang::FunctionDecl &funcDecl, std::string &funcName) const; ASTDecl *ProcessDecl(MapleAllocator &allocator, const clang::Decl &decl); + ASTStmt *SolveFunctionBody(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, ASTFunc &astFunc, + const std::list &stmts); + + void SetInitExprForASTVar(MapleAllocator &allocator, const clang::VarDecl &varDecl, const GenericAttrs &attrs, + ASTVar &astVar); + void SetAlignmentForASTVar(const clang::VarDecl &varDecl, ASTVar &astVar) const; #define PROCESS_DECL(CLASS) ProcessDecl##CLASS##Decl(MapleAllocator &allocator, const clang::CLASS##Decl&) ASTDecl *PROCESS_DECL(Field); ASTDecl *PROCESS_DECL(Function); @@ -157,11 +206,12 @@ class ASTParser { ASTDecl *PROCESS_DECL(Label); ASTDecl *PROCESS_DECL(StaticAssert); - static ASTExpr *GetAddrShiftExpr(MapleAllocator &allocator, ASTExpr *expr, uint32 typeSize); + 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 ProcessNonnullFuncAttrs(const clang::FunctionDecl &funcDecl, ASTFunc &astFunc) const; + 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 +229,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); @@ -200,22 +250,33 @@ class ASTParser { ASTValue *TranslateConstantValue2ASTValue(MapleAllocator &allocator, const clang::Expr *expr) const; ASTValue *TranslateLValue2ASTValue(MapleAllocator &allocator, const clang::Expr::EvalResult &result, const clang::Expr *expr) const; - void TraverseDecl(const clang::Decl *decl, std::function const &functor); + void TraverseDecl(const clang::Decl *decl, std::function const &functor) const; ASTDecl *GetAstDeclOfDeclRefExpr(MapleAllocator &allocator, const clang::Expr &expr); - uint32 GetSizeFromQualType(const clang::QualType qualType); + uint32 GetSizeFromQualType(const clang::QualType qualType) const; + ASTExpr *GetSizeOfExpr(MapleAllocator &allocator, const clang::UnaryExprOrTypeTraitExpr &expr, + clang::QualType qualType); + ASTExpr *GetSizeOfType(MapleAllocator &allocator, const clang::QualType &qualType); ASTExpr *GetTypeSizeFromQualType(MapleAllocator &allocator, const clang::QualType qualType); - uint32_t GetAlignOfType(const clang::QualType currQualType, clang::UnaryExprOrTypeTrait exprKind); - uint32_t GetAlignOfExpr(const clang::Expr &expr, clang::UnaryExprOrTypeTrait exprKind); + uint32_t GetAlignOfType(const clang::QualType currQualType, clang::UnaryExprOrTypeTrait exprKind) const; + uint32_t GetAlignOfExpr(const clang::Expr &expr, clang::UnaryExprOrTypeTrait exprKind) const; ASTExpr *BuildExprToComputeSizeFromVLA(MapleAllocator &allocator, const clang::QualType &qualType); ASTExpr *ProcessExprBinaryOperatorComplex(MapleAllocator &allocator, const clang::BinaryOperator &bo); - + bool CheckIncContinueStmtExpr(const clang::Stmt &bodyStmt) const; + void CheckVarNameValid(std::string varName); + void ParserExprVLASizeExpr(MapleAllocator &allocator, const clang::Type &type, ASTExpr &expr); + void ParserStmtVLASizeExpr(MapleAllocator &allocator, const clang::Type &type, std::list &stmts); + void SetAtomExprValType(MapleAllocator &allocator, const clang::AtomicExpr &atomicExpr, ASTAtomicExpr &astExpr); + void SetAtomExchangeType(MapleAllocator &allocator, const clang::AtomicExpr &atomicExpr, ASTAtomicExpr &astExpr); + clang::Expr *GetAtomValExpr(clang::Expr *valExpr); + clang::QualType GetPointeeType(const clang::Expr &expr); + bool IsNeedGetPointeeType(const clang::FunctionDecl &funcDecl) const; using FuncPtrBuiltinFunc = ASTExpr *(ASTParser::*)(MapleAllocator &allocator, const clang::CallExpr &expr, std::stringstream &ss) const; static std::map InitBuiltinFuncPtrMap(); ASTExpr *ProcessBuiltinFuncByName(MapleAllocator &allocator, const clang::CallExpr &expr, std::stringstream &ss, const std::string &name) const; ASTExpr *ParseBuiltinFunc(MapleAllocator &allocator, const clang::CallExpr &expr, std::stringstream &ss) const; -#define PARSE_BUILTIIN_FUNC(FUNC) ParseBuiltin##FUNC(MapleAllocator &allocator, const clang::CallExpr &expr,\ +#define PARSE_BUILTIIN_FUNC(FUNC) ParseBuiltin##FUNC(MapleAllocator &allocator, const clang::CallExpr &expr, \ std::stringstream &ss) const ASTExpr *PARSE_BUILTIIN_FUNC(ClassifyType); ASTExpr *PARSE_BUILTIIN_FUNC(ConstantP); @@ -238,9 +299,9 @@ ASTExpr *ParseBuiltinFunc(MapleAllocator &allocator, const clang::CallExpr &expr static std::map builtingFuncPtrMap; uint32 fileIdx; - const std::string fileName; - std::unique_ptr astFile; - AstUnitDecl *astUnitDecl = nullptr; + const MapleString fileName; + LibAstFile *astFile = nullptr; + const AstUnitDecl *astUnitDecl = nullptr; MapleList globalVarDecles; MapleList funcDecles; MapleList recordDecles; @@ -252,6 +313,8 @@ ASTExpr *ParseBuiltinFunc(MapleAllocator &allocator, const clang::CallExpr &expr MapleList &astFuncs; MapleList &astVars; MapleList &astFileScopeAsms; + MapleList &astEnums; + MapleMap vlaSizeMap; }; } // namespace maple #endif // HIR2MPL_AST_INPUT_INCLUDE_AST_PARSER_H diff --git a/src/hir2mpl/ast_input/clang/include/ast_stmt.h b/src/hir2mpl/ast_input/clang/include/ast_stmt.h index 4a053bb43957715bdcf1de748b3fb429c28cfe38..06cca3d5361e81a5d5993be196d1f980137a244b 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,78 @@ enum SafeSS { class ASTStmt { public: - explicit ASTStmt(ASTStmtOp o = kASTStmtNone) : op(o) {} + explicit ASTStmt(MapleAllocator &allocatorIn, ASTStmtOp o = kASTStmtNone) : exprs(allocatorIn.Adapter()), op(o), + vlaExprInfos(allocatorIn.Adapter()) {} 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; + } + void SetVLASizeExprs(MapleList astExprs) { + if (!astExprs.empty()) { + vlaExprInfos = std::move(astExprs); + } + } + + void EmitVLASizeExprs(std::list &stmts) const { + for (auto &vlaSizeExpr : vlaExprInfos) { + (void)vlaSizeExpr->Emit2FEExpr(stmts); + } + } + + void SetCallAlloca(bool isAlloc) { + isCallAlloca = isAlloc; + } + + bool IsCallAlloca() const { + return isCallAlloca; } protected: virtual std::list Emit2FEStmtImpl() const = 0; + MapleVector exprs; ASTStmtOp op; - std::vector exprs; + Loc loc = {0, 0, 0}; + MapleList vlaExprInfos; - uint32 srcFileIdx = 0; - uint32 srcFileLineNum = 0; + private: + bool isCallAlloca = false; }; class ASTStmtDummy : public ASTStmt { public: - ASTStmtDummy() : ASTStmt(kASTStmtDummy) {} + explicit ASTStmtDummy(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtDummy) {} ~ASTStmtDummy() = default; private: @@ -78,11 +109,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 +124,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 +152,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 +161,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 +185,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 +204,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) { @@ -183,34 +234,41 @@ class ASTWhileStmt : public ASTStmt { bodyStmt = astStmt; } + void SetNestContinueLabel(bool isContinueLabel) { + hasNestContinueLabel = isContinueLabel; + } + private: std::list Emit2FEStmtImpl() const override; ASTExpr *condExpr = nullptr; ASTStmt *bodyStmt = nullptr; + bool hasNestContinueLabel = false; + mutable bool hasEmitted2MIRScope = false; }; 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; + mutable bool hasEmitted2MIRScope = false; }; class ASTBreakStmt : public ASTStmt { public: - ASTBreakStmt() : ASTStmt(kASTStmtBreak) {} + explicit ASTBreakStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtBreak) {} ~ASTBreakStmt() override = default; private: @@ -219,26 +277,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 +314,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 +323,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 +332,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 +346,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 +360,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) { @@ -338,11 +406,12 @@ class ASTSwitchStmt : public ASTStmt { ASTStmt *bodyStmt = nullptr; MIRType *condType = nullptr; bool hasDefualt = false; + mutable bool hasEmitted2MIRScope = false; }; class ASTCaseStmt : public ASTStmt { public: - ASTCaseStmt() : ASTStmt(kASTStmtCase) {} + explicit ASTCaseStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCase) {} ~ASTCaseStmt() = default; void SetLHS(ASTExpr *l) { @@ -396,7 +465,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 +483,7 @@ class ASTDefaultStmt : public ASTStmt { class ASTNullStmt : public ASTStmt { public: - ASTNullStmt() : ASTStmt(kASTStmtNull) {} + explicit ASTNullStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtNull) {} ~ASTNullStmt() = default; private: @@ -423,27 +492,36 @@ class ASTNullStmt : public ASTStmt { class ASTDeclStmt : public ASTStmt { public: - ASTDeclStmt() : ASTStmt(kASTStmtDecl) {} + explicit ASTDeclStmt(MapleAllocator &allocatorIn) + : ASTStmt(allocatorIn, kASTStmtDecl), + subDecls(allocatorIn.Adapter()), + subDeclInfos(allocatorIn.Adapter()) {} ~ASTDeclStmt() = default; void SetSubDecl(ASTDecl *decl) { subDecls.emplace_back(decl); + (void)subDeclInfos.emplace_back(decl); + } + + void SetVLASizeExpr(ASTExpr *astExpr) { + (void)subDeclInfos.emplace_back(astExpr); } - const std::list& GetSubDecls() const { + const MapleList &GetSubDecls() const { return subDecls; } private: std::list Emit2FEStmtImpl() const override; - void InsertBoundaryVar(ASTDecl *ptrDecl, std::list &stmts) const; - std::list subDecls; + MapleList subDecls; + // saved vla size exprs before a vla decl + MapleList> subDeclInfos; }; class ASTCompoundAssignOperatorStmt : public ASTStmt { public: - ASTCompoundAssignOperatorStmt() : ASTStmt(kASTStmtCAO) {} + explicit ASTCompoundAssignOperatorStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtCAO) {} ~ASTCompoundAssignOperatorStmt() override = default; private: @@ -452,7 +530,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 +539,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 +548,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 +557,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 +566,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 +575,8 @@ 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 +585,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 +594,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 +613,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 +622,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 +636,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 +645,19 @@ class ASTAtomicExprStmt : public ASTStmt { class ASTGCCAsmStmt : public ASTStmt { public: - ASTGCCAsmStmt() : ASTStmt(kASTStmtGCCAsmStmt) {} + explicit ASTGCCAsmStmt(MapleAllocator &allocatorIn) : ASTStmt(allocatorIn, kASTStmtGCCAsmStmt), + allocator(allocatorIn), 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 +684,19 @@ 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; + MapleAllocator &allocator; + 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 +705,39 @@ 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..3879607e44882f576f68a004eeb99765fb685e61 100644 --- a/src/hir2mpl/ast_input/clang/include/ast_struct2fe_helper.h +++ b/src/hir2mpl/ast_input/clang/include/ast_struct2fe_helper.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,9 +21,13 @@ namespace maple { class ASTStruct2FEHelper : public FEInputStructHelper { public: - ASTStruct2FEHelper(MapleAllocator &allocator, const ASTStruct &structIn); + ASTStruct2FEHelper(MapleAllocator &allocator, ASTStruct &structIn); ~ASTStruct2FEHelper() = default; + const ASTStruct &GetASTStruct() const { + return astStruct; + } + protected: bool ProcessDeclImpl() override; void InitFieldHelpersImpl() override; @@ -36,11 +40,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 { @@ -67,9 +71,21 @@ class ASTFileScopeAsm2FEHelper : public FEInputFileScopeAsmHelper { const ASTFileScopeAsm &astAsm; }; +class ASTEnum2FEHelper : public FEInputEnumHelper { + public: + ASTEnum2FEHelper(MapleAllocator &allocatorIn, const ASTEnumDecl &astEnumIn) + : FEInputEnumHelper(allocatorIn), + astEnum(astEnumIn) {} + ~ASTEnum2FEHelper() = default; + + protected: + bool ProcessDeclImpl(MapleAllocator &allocator) override; + const ASTEnumDecl &astEnum; +}; + class ASTStructField2FEHelper : public FEInputFieldHelper { public: - ASTStructField2FEHelper(MapleAllocator &allocator, const ASTField &fieldIn, const MIRType &structTypeIn) + ASTStructField2FEHelper(MapleAllocator &allocator, ASTField &fieldIn, MIRType &structTypeIn) : FEInputFieldHelper(allocator), field(fieldIn), structType(structTypeIn) {} ~ASTStructField2FEHelper() = default; @@ -77,8 +93,8 @@ class ASTStructField2FEHelper : public FEInputFieldHelper { protected: bool ProcessDeclImpl(MapleAllocator &allocator) override; bool ProcessDeclWithContainerImpl(MapleAllocator &allocator) override; - const ASTField &field; - const MIRType &structType; + ASTField &field; + MIRType &structType; }; class ASTFunc2FEHelper : public FEInputMethodHelper { @@ -93,7 +109,7 @@ class ASTFunc2FEHelper : public FEInputMethodHelper { return func; } - const std::string &GetSrcFileName() const; + const std::string GetSrcFileName() const; protected: bool ProcessDeclImpl(MapleAllocator &allocator) override; @@ -108,6 +124,8 @@ class ASTFunc2FEHelper : public FEInputMethodHelper { bool IsNativeImpl() const override; bool HasCodeImpl() const override; + void SolveFunctionArguments() const; + void SolveFunctionAttributes(); ASTFunc &func; bool firstArgRet = false; }; 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..cbf2a41f2c88906bafe44a2067789c72c9b28009 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,78 @@ 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 +BUILTIN_FUNC_EMIT("__builtin_extract_return_addr", &ASTCallExpr::EmitBuiltinExtractReturnAddr) +BUILTIN_FUNC_EMIT("__builtin_object_size", &ASTCallExpr::EmitBuiltinObjectSize) + +BUILTIN_FUNC_EMIT("__builtin_bswap64", &ASTCallExpr::EmitBuiltinBswap64) +BUILTIN_FUNC_EMIT("__builtin_bswap32", &ASTCallExpr::EmitBuiltinBswap32) +BUILTIN_FUNC_EMIT("__builtin_bswap16", &ASTCallExpr::EmitBuiltinBswap16) \ No newline at end of file diff --git a/src/hir2mpl/ast_input/clang/include/builtin_func_parse.def b/src/hir2mpl/ast_input/clang/include/builtin_func_parse.def index 888736e5c9dc81d40f2ada87112948126763f4ac..9765fdb7b7b51a24ce6b4e0240e1e525649be7a3 100644 --- a/src/hir2mpl/ast_input/clang/include/builtin_func_parse.def +++ b/src/hir2mpl/ast_input/clang/include/builtin_func_parse.def @@ -16,5 +16,4 @@ BUILTIN_FUNC_PARSE("__builtin_signbitl", &ASTParser::ParseBuiltinSignBitl) BUILTIN_FUNC_PARSE("__builtin_trap", &ASTParser::ParseBuiltinTrap) BUILTIN_FUNC_PARSE("__builtin_copysignf", &ASTParser::ParseBuiltinCopysignf) BUILTIN_FUNC_PARSE("__builtin_copysign", &ASTParser::ParseBuiltinCopysign) -BUILTIN_FUNC_PARSE("__builtin_copysignl", &ASTParser::ParseBuiltinCopysignl) -BUILTIN_FUNC_PARSE("__builtin_object_size", &ASTParser::ParseBuiltinObjectsize) \ No newline at end of file +BUILTIN_FUNC_PARSE("__builtin_copysignl", &ASTParser::ParseBuiltinCopysignl) \ 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..e8410d58b464382a21e7ffd6726bab4efeca218e 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_interface.cpp +++ b/src/hir2mpl/ast_input/clang/lib/ast_interface.cpp @@ -19,14 +19,43 @@ #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::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"}, + {clang::attr::Alias, "alias"}}; +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()); - if (translationUnit == nullptr) { - return false; - } + index = clang_createIndex(excludeDeclFromPCH, displayDiagnostics); + translationUnit = clang_createTranslationUnit(index, fileName.c_str()); + CHECK_FATAL(translationUnit != nullptr, "The astfile %s content format is Non-conformance or astfile" + " version is different from hir2mpl version.", fileName.c_str()); clang::ASTUnit *astUnit = translationUnit->TheASTUnit; if (astUnit == nullptr) { return false; @@ -46,6 +75,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; } @@ -54,11 +92,11 @@ AstASTContext *LibAstFile::GetNonConstAstContext() const { return astContext; } -AstUnitDecl *LibAstFile::GetAstUnitDecl() { +const AstUnitDecl *LibAstFile::GetAstUnitDecl() const { 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(); @@ -78,48 +116,44 @@ std::string LibAstFile::GetMangledName(const clang::NamedDecl &decl) { return mangledName; } -Pos LibAstFile::GetDeclPosInfo(const clang::Decl &decl) const { - clang::FullSourceLoc fullLocation = astContext->getFullLoc(decl.getBeginLoc()); - return std::make_pair(static_cast(fullLocation.getSpellingLineNumber()), - 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 { - if (srcLoc.isInvalid()) { - return std::make_pair(0, 0); +Loc LibAstFile::GetLOC(const clang::SourceLocation &srcLoc) const { + clang::PresumedLoc pLoc = astContext->getSourceManager().getPresumedLoc(srcLoc); + if (pLoc.isInvalid()) { + 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 = pLoc.getFilename(); + if (fileName.empty()) { + return {0, 0, 0}; } - std::string fileName = pLOC.getFilename(); + unsigned line = pLoc.getLine(); + unsigned colunm = pLoc.getColumn(); 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 { @@ -135,6 +169,7 @@ uint32 LibAstFile::GetMaxAlign(const clang::Decl &decl) const { } uint32 LibAstFile::RetrieveAggTypeAlign(const clang::Type *ty) const { + ASSERT_NOT_NULL(ty); if (ty->isRecordType()) { const auto *recordType = llvm::cast(ty); clang::RecordDecl *recordDecl = recordType->getDecl(); @@ -146,14 +181,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, bool isConst) const { + if (isConst && (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,12 +214,31 @@ 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: case clang::Decl::Var: { const auto *varDecl = llvm::cast(&decl); const clang::StorageClass storageClass = varDecl->getStorageClass(); + if (storageClass == clang::SC_Extern) { + varDecl = varDecl->getPreviousDecl(); + while (varDecl != nullptr) { + auto preClass = varDecl->getStorageClass(); + if (preClass == clang::SC_Static) { + GetSClassAttrs(preClass, genAttrs); + break; + } + varDecl = varDecl->getPreviousDecl(); + } + } GetSClassAttrs(storageClass, genAttrs); break; } @@ -195,7 +249,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); @@ -215,7 +269,7 @@ void LibAstFile::GetAccessAttrs(AccessKind access, GenericAttrs &genAttrs) { return; } -void LibAstFile::GetQualAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs) { +void LibAstFile::GetQualAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs) const { switch (decl.getKind()) { case clang::Decl::Function: case clang::Decl::CXXMethod: @@ -234,7 +288,12 @@ void LibAstFile::GetQualAttrs(const clang::NamedDecl &decl, GenericAttrs &genAtt } } -void LibAstFile::CollectAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs, AccessKind access) { +void LibAstFile::GetQualAttrs(const clang::QualType &qualType, GenericAttrs &genAttrs, bool isSourceType) const { + uint32_t qualifiers = qualType.getCVRQualifiers(); + GetCVRAttrs(qualifiers, genAttrs, isSourceType); +} + +void LibAstFile::CollectAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs, AccessKind access) const { GetStorageAttrs(decl, genAttrs); GetAccessAttrs(access, genAttrs); GetQualAttrs(decl, genAttrs); @@ -258,7 +317,13 @@ void LibAstFile::CollectAttrs(const clang::NamedDecl &decl, GenericAttrs &genAtt } } -void LibAstFile::CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs &genAttrs, AccessKind access) { +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) const { CollectAttrs(decl, genAttrs, access); if (decl.isVirtualAsWritten()) { genAttrs.SetAttr(GENATTR_virtual); @@ -274,6 +339,12 @@ 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.hasAttr()) { + genAttrs.SetAttr(GENATTR_gnu_inline); + } if (decl.isDefaulted()) { genAttrs.SetAttr(GENATTR_default); } @@ -305,40 +376,73 @@ void LibAstFile::CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs genAttrs.SetAttr(GENATTR_destructor_priority); genAttrs.InsertIntContentMap(GENATTR_destructor_priority, destructorAttr->getPriority()); } - CheckUnsupportedFuncAttrs(decl); -} - -void LibAstFile::CheckUnsupportedFuncAttrs(const clang::FunctionDecl &decl) { - std::string unsupportedFuncAttrs = ""; - if (decl.hasAttr()) { - unsupportedFuncAttrs += " no_instrument_function"; - } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " stdcall"; + // one element vector type in rettype + if (LibAstFile::IsOneElementVector(decl.getReturnType())) { + genAttrs.SetAttr(GENATTR_oneelem_simd); } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " cdecl"; + if (FEOptions::GetInstance().IsEnableSafeRegion()) { + if (decl.getSafeSpecifier() == clang::SS_Unsafe) { + genAttrs.SetAttr(GENATTR_unsafed); + } else if (decl.getSafeSpecifier() == clang::SS_Safe || FEOptions::GetInstance().IsDefaultSafe()) { + genAttrs.SetAttr(GENATTR_safed); + } } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " long_call"; + // If a non-static function defined with inline has the following 2 kinds function declaration, it should be + // an externally visible function: + // (1) non-inline func decl + // (2) inline explicit extern func decl + if (decl.isThisDeclarationADefinition() && genAttrs.GetAttr(GENATTR_inline) && + !genAttrs.GetAttr(GENATTR_gnu_inline) && !genAttrs.GetAttr(GENATTR_static)) { + bool isExternallyVisible = false; + for (clang::FunctionDecl *funcDecl : decl.redecls()) { + // skip func definition and block scope func decl + if (!funcDecl->isThisDeclarationADefinition() && !funcDecl->isLocalExternDecl()) { + const bool declInline = funcDecl->isInlineSpecified(); + const bool declExtern = funcDecl->getStorageClass() == clang::SC_Extern; + if (!declInline || (declInline && declExtern)) { + isExternallyVisible = true; + break; + } + } + } + if (isExternallyVisible) { + genAttrs.SetAttr(GENATTR_extern); + } } - if (decl.hasAttr()) { - unsupportedFuncAttrs += " short_call"; + // If a function is defined with attrinute 'gnu_inline' but without 'extern', the 'extern' from function declarations + // should be ignored. + if (decl.isThisDeclarationADefinition() && genAttrs.GetAttr(GENATTR_gnu_inline)) { + auto sc = decl.getStorageClass(); + if (sc == clang::SC_Extern || sc == clang::SC_PrivateExtern) { + genAttrs.SetAttr(GENATTR_extern); + } else { + genAttrs.ResetAttr(GENATTR_extern); + } } - if(decl.hasAttr() || decl.hasAttr()) { - unsupportedFuncAttrs += " interrupt"; + CheckUnsupportedFuncAttrs(decl); +} + +void LibAstFile::CheckUnsupportedFuncAttrs(const clang::FunctionDecl &decl) const { + if (!decl.hasAttrs()) { + return; } - 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()); } -void LibAstFile::CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAttrs, AccessKind access) { +void LibAstFile::CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAttrs, AccessKind access) const { CollectAttrs(decl, genAttrs, access); // handle __thread if (decl.getTLSKind() == clang::VarDecl::TLS_Static) { @@ -353,24 +457,70 @@ void LibAstFile::CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAt CheckUnsupportedVarAttrs(decl); } -void LibAstFile::CheckUnsupportedVarAttrs(const clang::VarDecl &decl) { - std::string unsupportedVarAttrs = ""; - if(decl.hasAttr()) { - unsupportedVarAttrs += " mode"; - } - if(decl.hasAttr()) { - unsupportedVarAttrs += " nocommon"; +void LibAstFile::CheckUnsupportedVarAttrs(const clang::VarDecl &decl) const { + 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) const { + 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) const { + 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) const { + 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 +548,60 @@ 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); - if (it == unnamedSymbolMap.end()) { - std::string name = FEUtils::GetSequentialName("unNamed"); - if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - name = name + GetAstFileNameHashStr(); +const std::string LibAstFile::GetOrCreateMappedUnnamedName(const clang::Decl &decl) { + uint32 uid; + if (FEOptions::GetInstance().GetFuncInlineSize() != 0 && !decl.getLocation().isMacroID()) { + // use loc as key for wpaa mode + Loc l = GetLOC(decl.getLocation()); + CHECK_FATAL(l.fileIdx != 0, "loc is invaild"); + std::map::const_iterator itLoc = unnamedLocMap.find(l); + if (itLoc == unnamedLocMap.cend()) { + uid = FEUtils::GetSequentialNumber(); + unnamedLocMap[l] = uid; + } else { + uid = itLoc->second; } - unnamedSymbolMap[id] = name; + return FEUtils::GetSequentialName0("unnamed.", uid); } - return unnamedSymbolMap[id]; + std::map::const_iterator it = unnamedSymbolMap.find(decl.getID()); + if (it == unnamedSymbolMap.cend()) { + uid = FEUtils::GetSequentialNumber(); + unnamedSymbolMap[decl.getID()] = uid; + } else { + uid = it->second; + } + return FEUtils::GetSequentialName0("unnamed.", uid); } -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]; +const std::string LibAstFile::GetDeclName(const clang::NamedDecl &decl, bool isRename) { + std::string name = decl.getNameAsString(); + if (name.empty()) { + name = GetOrCreateMappedUnnamedName(decl); + } + if (isRename && !decl.isDefinedOutsideFunctionOrMethod()) { + Loc l = GetLOC(decl.getLocation()); + std::stringstream ss; + ss << name << "_" << l.line << "_" << l.column; + name = ss.str(); + } + return name; } -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 +625,54 @@ void LibAstFile::EmitTypeName(const clang::RecordType &recoType, std::stringstre } nsStack.pop(); } - auto nameStr = recoDecl->getName().str(); + auto nameStr = recordDecl->getName().str(); + if (nameStr.empty()) { + nameStr = GetTypedefNameFromUnnamedStruct(*recordDecl); + } if (nameStr.empty()) { - uint32_t id = recoType.getDecl()->getLocation().getRawEncoding(); - nameStr = GetOrCreateMappedUnnamedName(id); + nameStr = GetOrCreateMappedUnnamedName(*recordDecl); } ss << nameStr; } else { - uint32_t id = recoType.getDecl()->getLocation().getRawEncoding(); - ss << GetOrCreateMappedUnnamedName(id); + ss << GetOrCreateMappedUnnamedName(*recordDecl); + } + if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { + std::string recordStr = recordDecl->getDefinition() == nullptr ? "" : GetRecordLayoutString(*recordDecl); + std::string filename = astContext->getSourceManager().getFilename(recordDecl->getLocation()).str(); + ss << FEUtils::GetFileNameHashStr(filename + recordStr); + } + CHECK_FATAL(ss.rdbuf()->in_avail() != 0, "stringstream is empty"); +} + +std::string LibAstFile::GetRecordLayoutString(const clang::RecordDecl &recordDecl) { + std::stringstream recordLayoutStr; + const clang::ASTRecordLayout &recordLayout = GetContext()->getASTRecordLayout(&recordDecl); + unsigned int fieldCount = recordLayout.getFieldCount(); + uint64_t recordSize = static_cast(recordLayout.getSize().getQuantity()); + recordLayoutStr << std::to_string(fieldCount) << std::to_string(recordSize); + clang::RecordDecl::field_iterator it = recordDecl.field_begin(); + for (unsigned i = 0, e = recordLayout.getFieldCount(); i != e; ++i, ++it) { + const clang::FieldDecl *fieldDecl = *it; + recordLayoutStr << std::to_string(recordLayout.getFieldOffset(i)); + std::string fieldName = GetMangledName(*fieldDecl); + if (fieldName.empty()) { + fieldName = GetOrCreateMappedUnnamedName(*fieldDecl); + } + recordLayoutStr << fieldName; } + return recordLayoutStr.str(); +} - if (!recoDecl->isDefinedOutsideFunctionOrMethod()) { - Pos p = GetDeclPosInfo(*recoDecl); - 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 { + // typedef is parsed in debug mode + if (FEOptions::GetInstance().IsDbgFriendly()) { + return std::string(); + } + 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..e27fc3c5f0bdbfb9d495c0dc8403cf67352dc0ac 100644 --- a/src/hir2mpl/ast_input/clang/lib/ast_interface.h +++ b/src/hir2mpl/ast_input/clang/lib/ast_interface.h @@ -21,9 +21,9 @@ #include "mpl_logging.h" #include "generic_attrs.h" #include "fe_utils.h" +#include "clang/Basic/AttrKinds.h" namespace maple { -using Pos = std::pair; enum AccessKind { kPublic, kProtected, @@ -33,52 +33,68 @@ enum AccessKind { class LibAstFile { public: - explicit LibAstFile(MapleList &recordDeclesIn) : recordDecles(recordDeclesIn) {} + explicit LibAstFile(MapleAllocator &allocatorIn, MapleList &recordDeclesIn, + MapleList &enumDeclesIn) + : recordDeclSet(allocatorIn.Adapter()), + unnamedSymbolMap(allocatorIn.Adapter()), compoundLiteralExprInitSymbolMap(allocatorIn.Adapter()), + recordDecles(recordDeclesIn), enumDecles(enumDeclesIn), 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); - const std::string GetOrCreateMappedUnnamedName(uint32_t id); - const std::string GetOrCreateCompoundLiteralExprInitName(uint32_t id); - + const AstUnitDecl *GetAstUnitDecl() const; + std::string GetMangledName(const clang::NamedDecl &decl) const; + const std::string GetOrCreateMappedUnnamedName(const clang::Decl &decl); + const std::string GetDeclName(const clang::NamedDecl &decl, bool isRename = false); 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, - TypeAttrs &elemAttr, std::vector &operands); - - void CollectBaseEltTypeAndDimFromVariaArrayDecl(const clang::QualType &qualType, MIRType *&elemType, - TypeAttrs &elemAttr, uint8_t &dim); - - void CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(const clang::QualType qualType, MIRType *&elemType, - TypeAttrs &elemAttr, std::vector &operands); - - void GetCVRAttrs(uint32_t qualifiers, GenericAttrs &genAttrs); + 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; + std::string GetRecordLayoutString(const clang::RecordDecl &recordDecl); + void CollectBaseEltTypeAndSizesFromConstArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, + TypeAttrs &elemAttr, std::vector &operands, + bool isSourceType); + void CollectBaseEltTypeAndDimFromVariaArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, + TypeAttrs &elemAttr, uint8_t &dim, bool isSourceType); + void CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(const clang::QualType currQualType, MIRType *&elemType, + TypeAttrs &elemAttr, std::vector &operands, + bool isSourceType); + void CollectBaseEltTypeFromArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, TypeAttrs &elemAttr, + bool isSourceType = false); + void GetCVRAttrs(uint32_t qualifiers, GenericAttrs &genAttrs, bool isConst = true) 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 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 CheckUnsupportedFuncAttrs(const clang::FunctionDecl &decl); - void CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAttrs, AccessKind access); - void CheckUnsupportedVarAttrs(const clang::VarDecl &decl); - MIRType *CvtPrimType(const clang::QualType qualType) const; - PrimType CvtPrimType(const clang::BuiltinType::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); + void GetAccessAttrs(AccessKind access, GenericAttrs &genAttrs) const; + void GetQualAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs) const; + void GetQualAttrs(const clang::QualType &qualType, GenericAttrs &genAttrs, bool isSourceType) const; + void CollectAttrs(const clang::NamedDecl &decl, GenericAttrs &genAttrs, AccessKind access) const; + void CollectFuncAttrs(const clang::FunctionDecl &decl, GenericAttrs &genAttrs, AccessKind access) const; + void CollectFuncReturnVarAttrs(const clang::CallExpr &expr, GenericAttrs &genAttrs) const; + void CheckUnsupportedFuncAttrs(const clang::FunctionDecl &decl) const; + void CollectVarAttrs(const clang::VarDecl &decl, GenericAttrs &genAttrs, AccessKind access) const; + void CheckUnsupportedVarAttrs(const clang::VarDecl &decl) const; + void CollectRecordAttrs(const clang::RecordDecl &decl, GenericAttrs &genAttrs) const; + void CheckUnsupportedTypeAttrs(const clang::RecordDecl &decl) const; + void CollectFieldAttrs(const clang::FieldDecl &decl, GenericAttrs &genAttrs, AccessKind access) const; + MIRType *CvtPrimType(const clang::QualType qualType, bool isSourceType = false) const; + PrimType CvtPrimType(const clang::BuiltinType::Kind kind, bool isSourceType) const; + MIRType *CvtPrimType2SourceType(const clang::BuiltinType::Kind kind) const; + MIRType *CvtSourceType(const clang::QualType qualType); + MIRType *CvtType(const clang::QualType qualType, bool isSourceType = false, const clang::Type **vlaType = nullptr); + MIRType *CvtOtherType(const clang::QualType srcType, bool isSourceType, const clang::Type **vlaType); + MIRType *CvtArrayType(const clang::QualType &srcType, bool isSourceType, const clang::Type **vlaType); + MIRType *CvtFunctionType(const clang::QualType srcType, bool isSourceType); + MIRType *CvtEnumType(const clang::QualType &qualType, bool isSourceType); + MIRType *CvtRecordType(const clang::QualType qualType); 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); + MIRType *CvtTypedef(const clang::QualType &qualType); + MIRType *CvtTypedefDecl(const clang::TypedefNameDecl &typedefDecl); + bool TypeHasMayAlias(const clang::QualType srcType) const; static bool IsOneElementVector(const clang::QualType &qualType); static bool IsOneElementVector(const clang::Type &type); @@ -87,30 +103,32 @@ 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; - RecordDeclMap recordDeclMap; - std::set recordDeclSet; - std::map unnamedSymbolMap; - std::map CompoundLiteralExprInitSymbolMap; + MapleSet recordDeclSet; + MapleMap unnamedSymbolMap; + MapleMap compoundLiteralExprInitSymbolMap; MIRModule *module = nullptr; MapleList &recordDecles; + MapleList &enumDecles; clang::ASTContext *astContext = nullptr; clang::TranslationUnitDecl *astUnitDecl = nullptr; clang::MangleContext *mangleContext = nullptr; - std::string astFileName; + CXTranslationUnit translationUnit = nullptr; + CXIndex index = nullptr; + MapleString astFileName; + static std::map unnamedLocMap; }; } // 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..87e9f0555863d0b837913de7ddd3ac6b6e82a646 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 @@ -46,25 +46,30 @@ const int kDefaultIndent = 1; #ifdef ASTDEBUG #define LOCATION __func__ << "() at " << __FILE__ << ":" << __LINE__ -#define DUMPINFO(stmtClass, s) \ - if (maple::ast2mplDebug > kDebugLevelOne) { \ - std::cout << LOCATION << '\n'; \ - s->dump(); \ - std::cout << " " << '\n'; \ - } - -#define NOTYETHANDLED(s) \ - std::cout << "\n" << LOCATION << " <<<<<<<<<<<<<<<<<< Not Yet Handled: " << s << "<<<<<<<<<<<<<<<<<<" << '\n'; \ - if (maple::ast2mplOption & kCheckAssertion) { \ - ASSERT(false, "Not yet handled"); \ - } \ +#define DUMPINFO(stmtClass, s) \ + do { \ + if (maple::ast2mplDebug > kDebugLevelOne) { \ + std::cout << LOCATION << '\n'; \ + s->dump(); \ + std::cout << " " << '\n'; \ + } \ + } while (0) + +#define NOTYETHANDLED(s) \ + do { \ + std::cout << "\n" << LOCATION << " <<<<<<<<<<<<<<<<<< Not Yet Handled: " << s << "<<<<<<<<<<<<<<<<<<" << '\n'; \ + if ((maple::ast2mplOption & kCheckAssertion) != 0) { \ + ASSERT(false, "Not yet handled"); \ + } \ + } while (0) + // print empty line #define DEBUGPRINT_N(n) \ do { \ if (maple::ast2mplDebug >= n) { \ std::cout << " " << '\n'; \ } \ - } while (0); + } while (0) // print indent #define DEBUGPRINTIND(n) \ @@ -72,7 +77,7 @@ const int kDefaultIndent = 1; if (maple::ast2mplDebug > kDebugLevelZero) { \ PrintIndentation(n); \ } \ - } while (0); + } while (0) // print str #define DEBUGPRINT_S_LEVEL(str, level) \ @@ -81,7 +86,7 @@ const int kDefaultIndent = 1; PrintIndentation(ast2mplDebugIndent); \ std::cout << " " << str << '\n'; \ } \ - } while (0); + } while (0) #define DEBUGPRINT_FUNC(name) \ do { \ @@ -92,7 +97,7 @@ const int kDefaultIndent = 1; std::cout << name << " {" << '\n'; \ } \ Util::SetIndent(ind); \ - } while (0); + } while (0) #define DEBUGPRINT_FUNC_END(name) \ do { \ @@ -103,7 +108,7 @@ const int kDefaultIndent = 1; std::cout << "}\n" << '\n'; \ } \ Util::SetIndent(ind); \ - } while (0); + } while (0) #define DEBUGPRINT_NODE(node, type) \ do { \ @@ -113,7 +118,7 @@ const int kDefaultIndent = 1; static_cast(node)->Print(static_cast(module), 0); \ std::cout << "\n"; \ } \ - } while (0); + } while (0) // print var = val #define DEBUGPRINT_V_LEVEL(var, level) \ @@ -122,7 +127,7 @@ const int kDefaultIndent = 1; PrintIndentation(maple::ast2mplDebugIndent); \ std::cout << LOCATION << " " << #var << " = " << var << '\n'; \ } \ - } while (0); + } while (0) #define DEBUGPRINT_X_LEVEL(var, level) \ do { \ @@ -130,7 +135,7 @@ const int kDefaultIndent = 1; PrintIndentation(maple::ast2mplDebugIndent); \ std::cout << LOCATION << " " << #var << " = " << std::hex << "0x" << var << std::dec << '\n'; \ } \ - } while (0); + } while (0) // print var = val #define DEBUGPRINT_V_LEVEL_PURE(var, level) \ @@ -139,7 +144,7 @@ const int kDefaultIndent = 1; PrintIndentation(maple::ast2mplDebugIndent); \ std::cout << #var << " = " << var << '\n'; \ } \ - } while (0); + } while (0) // print val0 val1 #define DEBUGPRINT_NN_LEVEL(var0, var1, level) \ @@ -148,7 +153,7 @@ const int kDefaultIndent = 1; PrintIndentation(maple::ast2mplDebugIndent); \ std::cout << var0 << " " << var1; \ } \ - } while (0); + } while (0) // print var0 = val0, var1 = val1 #define DEBUGPRINT_VV_LEVEL(var0, var1, level) \ @@ -157,7 +162,7 @@ const int kDefaultIndent = 1; PrintIndentation(maple::ast2mplDebugIndent); \ std::cout << LOCATION << " " << #var0 << " = " << var0 << ", " << #var1 << " = " << var1 << '\n'; \ } \ - } while (0); + } while (0) // print val0, var = val #define DEBUGPRINT_SV_LEVEL(val0, var, level) \ @@ -166,7 +171,7 @@ const int kDefaultIndent = 1; PrintIndentation(maple::ast2mplDebugIndent); \ std::cout << LOCATION << " " << val0 << ", " << #var << " = " << var << '\n'; \ } \ - } while (0); + } while (0) #define DEBUGPRINT_SX_LEVEL(val0, var, level) \ do { \ @@ -175,7 +180,7 @@ const int kDefaultIndent = 1; std::cout << LOCATION << " " << val0 << ", " << #var << " = " << std::hex << "0x" << var << std::dec \ << '\n'; \ } \ - } while (0); + } while (0) #else #define DUMPINFO(stmtClass, s) @@ -247,7 +252,9 @@ const int kDefaultIndent = 1; // A: module->fileinfo, B:"filename", // C: stridx, D:module->fileinfo_isstring, E:true; #define SET_INFO_PAIR(a, b, c, d, e) \ - a.emplace_back(builder->GetOrCreateStringIndex(b), c); \ - d.emplace_back(e) - + do { \ + (a).emplace_back(builder->GetOrCreateStringIndex(b), c); \ + (d).emplace_back(e) \ + } while (0) +} // 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..60e36a72bcea15c1ce5da2036ac6b29c93287f99 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,9 +17,13 @@ #include "ast_util.h" #include "fe_manager.h" #include "fe_options.h" +#include "fe_macros.h" +#include "driver_options.h" +#include "triple.h" namespace maple { -MIRType *LibAstFile::CvtPrimType(const clang::QualType qualType) const { +std::map LibAstFile::unnamedLocMap; +MIRType *LibAstFile::CvtPrimType(const clang::QualType qualType, bool isSourceType) const { clang::QualType srcType = qualType.getCanonicalType(); if (srcType.isNull()) { return nullptr; @@ -28,32 +32,58 @@ MIRType *LibAstFile::CvtPrimType(const clang::QualType qualType) const { MIRType *destType = nullptr; if (llvm::isa(srcType)) { const auto *builtinType = llvm::cast(srcType); - PrimType primType = CvtPrimType(builtinType->getKind()); + if (isSourceType) { + MIRType *sourceType = CvtPrimType2SourceType(builtinType->getKind()); + if (sourceType != nullptr) { + return sourceType; + } + } + PrimType primType = CvtPrimType(builtinType->getKind(), isSourceType); destType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(primType); } return destType; } -PrimType LibAstFile::CvtPrimType(const clang::BuiltinType::Kind kind) const { +MIRType *LibAstFile::CvtPrimType2SourceType(const clang::BuiltinType::Kind kind) const { + static const std::unordered_map kPrimType2SourceTypeMap = { + {clang::BuiltinType::ULong, kDbgULong}, + {clang::BuiltinType::Long, kDbgLong}, + {clang::BuiltinType::LongDouble, kDbgLongDouble}, + {clang::BuiltinType::SChar, kDbgSignedChar}, + {clang::BuiltinType::Char_U, kDbgChar}, + {clang::BuiltinType::UChar, kDbgUnsignedChar}, + {clang::BuiltinType::UInt, kDbgUnsignedInt}, + {clang::BuiltinType::Short, kDbgShort}, + {clang::BuiltinType::Int, kDbgInt}, + {clang::BuiltinType::LongLong, kDbgLongLong}, + {clang::BuiltinType::Int128, kDbgInt128}, + {clang::BuiltinType::UShort, kDbgUnsignedShort}, + {clang::BuiltinType::ULongLong, kDbgUnsignedLongLong}, + {clang::BuiltinType::UInt128, kDbgUnsignedInt128} + }; + auto it = kPrimType2SourceTypeMap.find(kind); + if (it != kPrimType2SourceTypeMap.end()) { + return FEManager::GetTypeManager().GetOrCreateTypeByNameType(it->second); + } + return nullptr; +} + +PrimType LibAstFile::CvtPrimType(const clang::BuiltinType::Kind kind, bool isSourceType) const { switch (kind) { case clang::BuiltinType::Bool: return PTY_u1; case clang::BuiltinType::Char_U: - return FEOptions::GetInstance().IsUseSignedChar() ? PTY_i8 : PTY_u8; + return (FEOptions::GetInstance().IsUseSignedChar() || isSourceType) ? PTY_i8 : PTY_u8; case clang::BuiltinType::UChar: return PTY_u8; case clang::BuiltinType::WChar_U: - return FEOptions::GetInstance().IsUseSignedChar() ? PTY_i16 : PTY_u16; + return (FEOptions::GetInstance().IsUseSignedChar() || isSourceType) ? PTY_i16 : PTY_u16; case clang::BuiltinType::UShort: return PTY_u16; case clang::BuiltinType::UInt: return PTY_u32; case clang::BuiltinType::ULong: -#if ILP32 - return PTY_u32; -#else - return PTY_u64; -#endif + return Triple::GetTriple().GetEnvironment() == Triple::GNUILP32 ? PTY_u32 : PTY_u64; case clang::BuiltinType::ULongLong: return PTY_u64; case clang::BuiltinType::UInt128: @@ -69,16 +99,11 @@ 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 + return Triple::GetTriple().GetEnvironment() == Triple::GNUILP32 ? PTY_i32 : 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 +113,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; @@ -111,13 +140,43 @@ bool LibAstFile::TypeHasMayAlias(const clang::QualType srcType) { return false; } -MIRType *LibAstFile::CvtType(const clang::QualType qualType) { +MIRType *LibAstFile::CvtTypedef(const clang::QualType &qualType) { + const clang::TypedefType *typedefType = llvm::dyn_cast(qualType); + if (typedefType == nullptr) { + return nullptr; + } + return CvtTypedefDecl(*typedefType->getDecl()); +} + +MIRType *LibAstFile::CvtTypedefDecl(const clang::TypedefNameDecl &typedefDecl) { + std::string typedefName = GetDeclName(typedefDecl, true); + MIRTypeByName *typdefType = nullptr; + clang::QualType underlyTy = typedefDecl.getCanonicalDecl()->getUnderlyingType(); + MIRType *type = CvtType(underlyTy, true); + if (type != nullptr) { + typdefType = FEManager::GetTypeManager().CreateTypedef(typedefName, *type); + } + return typdefType; +} + +MIRType *LibAstFile::CvtSourceType(const clang::QualType qualType) { + return CvtType(qualType, true); +} + +MIRType *LibAstFile::CvtType(const clang::QualType qualType, bool isSourceType, const clang::Type **vlaType) { clang::QualType srcType = qualType.getCanonicalType(); + if (isSourceType) { + MIRType *nameType = CvtTypedef(qualType); + if (nameType != nullptr) { + return nameType; + } + srcType = qualType; + } if (srcType.isNull()) { return nullptr; } - MIRType *destType = CvtPrimType(srcType); + MIRType *destType = CvtPrimType(srcType, isSourceType); if (destType != nullptr) { return destType; } @@ -125,16 +184,19 @@ MIRType *LibAstFile::CvtType(const clang::QualType qualType) { // handle pointer types const clang::QualType srcPteType = srcType->getPointeeType(); if (!srcPteType.isNull()) { - MIRType *mirPointeeType = CvtType(srcPteType); + MIRType *mirPointeeType = CvtType(srcPteType, isSourceType, vlaType); if (mirPointeeType == nullptr) { return nullptr; } - TypeAttrs attrs; + + GenericAttrs genAttrs; + GetQualAttrs(srcPteType, genAttrs, isSourceType); + TypeAttrs attrs = genAttrs.ConvertToTypeAttrs(); // 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,50 +208,80 @@ 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; } - return CvtOtherType(srcType); + return CvtOtherType(srcType, isSourceType, vlaType); } -MIRType *LibAstFile::CvtOtherType(const clang::QualType srcType) { +MIRType *LibAstFile::CvtOtherType(const clang::QualType srcType, bool isSourceType, const clang::Type **vlaType) { MIRType *destType = nullptr; if (srcType->isArrayType()) { - destType = CvtArrayType(srcType); + destType = CvtArrayType(srcType, isSourceType, vlaType); } else if (srcType->isRecordType()) { destType = CvtRecordType(srcType); // isComplexType() does not include complex integers (a GCC extension) } else if (srcType->isAnyComplexType()) { destType = CvtComplexType(srcType); } else if (srcType->isFunctionType()) { - destType = CvtFunctionType(srcType); + destType = CvtFunctionType(srcType, isSourceType); } else if (srcType->isEnumeralType()) { - const clang::EnumType *enumTy = llvm::dyn_cast(srcType); - clang::QualType qt = enumTy->getDecl()->getIntegerType(); - destType = CvtType(qt); + destType = CvtEnumType(srcType, isSourceType); } else if (srcType->isAtomicType()) { const auto *atomicType = llvm::cast(srcType); destType = CvtType(atomicType->getValueType()); } else if (srcType->isVectorType()) { destType = CvtVectorType(srcType); } - CHECK_NULL_FATAL(destType); + CHECK_FATAL(destType != nullptr, "unsupport type %s", srcType.getAsString().c_str()); return destType; } -MIRType *LibAstFile::CvtRecordType(const clang::QualType srcType) { +MIRType *LibAstFile::CvtEnumType(const clang::QualType &qualType, bool isSourceType) { + const clang::EnumType *enumTy = llvm::dyn_cast(qualType.getCanonicalType()); + CHECK_NULL_FATAL(enumTy); + clang::EnumDecl *enumDecl = enumTy->getDecl(); + if (enumDecl->getDefinition() != nullptr) { + enumDecl = enumDecl->getDefinition(); + } + MIRType *type = nullptr; + if (isSourceType) { + auto itor = std::find(enumDecles.cbegin(), enumDecles.cend(), enumDecl); + if (itor == enumDecles.end()) { + (void)enumDecles.emplace_back(enumDecl); + } + std::string enumName = GetDeclName(*enumDecl, true); + MIRTypeByName *typdefType = FEManager::GetTypeManager().GetOrCreateTypeByNameType(enumName); + type = typdefType; + } else { + if (enumDecl->getIntegerType().isNull()) { + FE_ERR(kLncErr, GetLOC(enumDecl->getLocation()), "Incomplete Enums Type is not support."); + } else { + clang::QualType qt = enumDecl->getIntegerType(); + type = CvtType(qt, isSourceType); + } + } + return type; +} + +MIRType *LibAstFile::CvtRecordType(const clang::QualType qualType) { + clang::QualType srcType = qualType.getCanonicalType(); 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); } @@ -198,50 +290,61 @@ MIRType *LibAstFile::CvtRecordType(const clang::QualType srcType) { std::stringstream ss; EmitTypeName(srcType, ss); std::string name(ss.str()); - if (!ASTUtil::IsValidName(name)) { - uint32_t id = recordType->getDecl()->getLocation().getRawEncoding(); - name = GetOrCreateMappedUnnamedName(id); - } else if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - name = name + GetAstFileNameHashStr(); + if (!recordDecl->isDefinedOutsideFunctionOrMethod()) { + Loc l = GetLOC(recordDecl->getLocation()); + std::stringstream ss; + ss << name << "_" << l.line << "_" << l.column; + name = ss.str(); } type = FEManager::GetTypeManager().GetOrCreateStructType(name); type->SetMIRTypeKind(srcType->isUnionType() ? kTypeUnion : kTypeStruct); + if (recordType->isIncompleteType()) { + type->SetMIRTypeKind(kTypeStructIncomplete); + } return recordDecl->isLambda() ? GlobalTables::GetTypeTable().GetOrCreatePointerType(*type) : type; } -MIRType *LibAstFile::CvtArrayType(const clang::QualType srcType) { +MIRType *LibAstFile::CvtArrayType(const clang::QualType &srcType, bool isSourceType, const clang::Type **vlaType) { MIRType *elemType = nullptr; TypeAttrs elemAttrs; std::vector operands; uint8_t dim = 0; if (srcType->isConstantArrayType()) { - CollectBaseEltTypeAndSizesFromConstArrayDecl(srcType, elemType, elemAttrs, operands); + CollectBaseEltTypeAndSizesFromConstArrayDecl(srcType, elemType, elemAttrs, operands, isSourceType); ASSERT(operands.size() < kMaxArrayDim, "The max array dimension is kMaxArrayDim"); dim = static_cast(operands.size()); } else if (srcType->isIncompleteArrayType()) { - const auto *arrayType = llvm::cast(srcType); - CollectBaseEltTypeAndSizesFromConstArrayDecl(arrayType->getElementType(), elemType, elemAttrs, operands); + const clang::ArrayType *arrType = srcType->getAsArrayTypeUnsafe(); + const auto *inArrType = llvm::cast(arrType); + CollectBaseEltTypeAndSizesFromConstArrayDecl( + inArrType->getElementType(), elemType, elemAttrs, operands, isSourceType); dim = static_cast(operands.size()); ASSERT(operands.size() < kMaxArrayDim, "The max array dimension is kMaxArrayDim"); } else if (srcType->isVariableArrayType()) { - CollectBaseEltTypeAndDimFromVariaArrayDecl(srcType, elemType, elemAttrs, dim); + CollectBaseEltTypeAndDimFromVariaArrayDecl(srcType, elemType, elemAttrs, dim, isSourceType); } else if (srcType->isDependentSizedArrayType()) { - CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(srcType, elemType, elemAttrs, operands); + CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(srcType, elemType, elemAttrs, operands, isSourceType); + ASSERT(operands.size() < kMaxArrayDim, "The max array dimension is kMaxArrayDim"); dim = static_cast(operands.size()); } else { NOTYETHANDLED(srcType.getAsString().c_str()); } - uint32_t *sizeArray = nullptr; uint32_t tempSizeArray[kMaxArrayDim]; MIRType *retType = nullptr; if (dim > 0) { + CHECK_NULL_FATAL(elemType); if (!srcType->isVariableArrayType()) { for (uint8_t k = 0; k < dim; ++k) { tempSizeArray[k] = operands[k]; } - sizeArray = tempSizeArray; + uint32_t *sizeArray = tempSizeArray; + retType = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dim, sizeArray, elemAttrs); + } else { + retType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*elemType, PTY_ptr, elemAttrs); + if (vlaType != nullptr) { + *vlaType = srcType.getCanonicalType().getTypePtr(); + } } - retType = GlobalTables::GetTypeTable().GetOrCreateArrayType(*elemType, dim, sizeArray, elemAttrs); } else { bool asFlag = srcType->isIncompleteArrayType(); CHECK_FATAL(asFlag, "Incomplete Array Type"); @@ -256,24 +359,45 @@ 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); return FEManager::GetTypeManager().GetOrCreateComplexStructType(*destElemType); } -MIRType *LibAstFile::CvtFunctionType(const clang::QualType srcType) { - const auto *funcType = llvm::cast(srcType); - MIRType *retType = CvtType(funcType->getReturnType()); +MIRType *LibAstFile::CvtFunctionType(const clang::QualType srcType, bool isSourceType) { + const auto *funcType = srcType.getTypePtr()->castAs(); + CHECK_NULL_FATAL(funcType); + MIRType *retType = CvtType(funcType->getReturnType(), isSourceType); std::vector argsVec; std::vector attrsVec; - if (srcType->isFunctionProtoType()) { - const auto *funcProtoType = llvm::cast(srcType); + bool isFirstArgRet = false; + const clang::QualType &retQualType = funcType->getReturnType().getCanonicalType(); + // setup first_arg_retrun if ret struct size > 16 + if (!isSourceType && retQualType->isRecordType()) { + const auto *recordType = llvm::cast(retQualType); + clang::RecordDecl *recordDecl = recordType->getDecl(); + const clang::ASTRecordLayout &layout = astContext->getASTRecordLayout(recordDecl->getDefinition()); + const unsigned twoByteSize = 16; + if (layout.getSize().getQuantity() > twoByteSize) { + MIRType *ptrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*retType); + GenericAttrs genAttrs; + if (IsOneElementVector(retQualType)) { + genAttrs.SetAttr(GENATTR_oneelem_simd); + } + attrsVec.push_back(genAttrs.ConvertToTypeAttrs()); + argsVec.push_back(ptrType->GetTypeIndex()); + retType = GlobalTables::GetTypeTable().GetVoid(); + isFirstArgRet = true; + } + } + if (funcType->isFunctionProtoType()) { + const auto *funcProtoType = funcType->castAs(); using ItType = clang::FunctionProtoType::param_type_iterator; for (ItType it = funcProtoType->param_type_begin(); it != funcProtoType->param_type_end(); ++it) { clang::QualType protoQualType = *it; - argsVec.push_back(CvtType(protoQualType)->GetTypeIndex()); + argsVec.push_back(CvtType(protoQualType, isSourceType)->GetTypeIndex()); GenericAttrs genAttrs; // collect storage class, access, and qual attributes // ASTCompiler::GetSClassAttrs(SC_Auto, genAttrs); -- no-op @@ -284,88 +408,106 @@ MIRType *LibAstFile::CvtFunctionType(const clang::QualType srcType) { } attrsVec.push_back(genAttrs.ConvertToTypeAttrs()); } + // The 'void' is allowed only as a single parameter to a function with no other parameters (C99 6.7.5.3p10). + // e.g. 'int foo(void)'. But parameter list of FunctionProtoType is empty. + // The void parameter source type is needs to be recorded in the debuginfo. + if (isSourceType && argsVec.empty()) { + argsVec.push_back(GlobalTables::GetTypeTable().GetVoid()->GetTypeIndex()); + } } MIRType *mirFuncType = GlobalTables::GetTypeTable().GetOrCreateFunctionType( retType->GetTypeIndex(), argsVec, attrsVec); + if (isFirstArgRet) { + static_cast(mirFuncType)->SetFirstArgReturn(); + } return GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirFuncType); } void LibAstFile::CollectBaseEltTypeAndSizesFromConstArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, - TypeAttrs &elemAttr, std::vector &operands) { + TypeAttrs &elemAttr, std::vector &operands, + bool isSourceType) { + if (isSourceType) { + MIRType *nameType = CvtTypedef(currQualType); + if (nameType != nullptr) { + elemType = nameType; + return; + } + } const clang::Type *ptrType = currQualType.getTypePtrOrNull(); ASSERT(ptrType != nullptr, "Null type", currQualType.getAsString().c_str()); if (ptrType->isArrayType()) { - bool asFlag = ptrType->isConstantArrayType(); - ASSERT(asFlag, "Must be a ConstantArrayType", currQualType.getAsString().c_str()); - const auto *constArrayType = llvm::cast(ptrType); + const clang::ArrayType *arrType = ptrType->getAsArrayTypeUnsafe(); + ASSERT(arrType->isConstantArrayType(), "Must be a ConstantArrayType", currQualType.getAsString().c_str()); + const auto *constArrayType = llvm::dyn_cast(arrType); ASSERT(constArrayType != nullptr, "ERROR : null pointer!"); llvm::APInt size = constArrayType->getSize(); - asFlag = size.getSExtValue() >= 0; - ASSERT(asFlag, "Array Size must be positive or zero", currQualType.getAsString().c_str()); + ASSERT(size.getSExtValue() >= 0, "Array Size must be positive or zero", currQualType.getAsString().c_str()); operands.push_back(size.getSExtValue()); - CollectBaseEltTypeAndSizesFromConstArrayDecl(constArrayType->getElementType(), elemType, elemAttr, operands); + CollectBaseEltTypeAndSizesFromConstArrayDecl(constArrayType->getElementType(), elemType, elemAttr, operands, + isSourceType); } 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, isSourceType); } } void LibAstFile::CollectBaseEltTypeAndDimFromVariaArrayDecl(const clang::QualType &currQualType, MIRType *&elemType, - TypeAttrs &elemAttr, uint8_t &dim) { + TypeAttrs &elemAttr, uint8_t &dim, bool isSourceType) { + if (isSourceType) { + MIRType *nameType = CvtTypedef(currQualType); + if (nameType != nullptr) { + elemType = nameType; + return; + } + } const clang::Type *ptrType = currQualType.getTypePtrOrNull(); ASSERT(ptrType != nullptr, "Null type", currQualType.getAsString().c_str()); if (ptrType->isArrayType()) { - const auto *arrayType = llvm::cast(ptrType); - CollectBaseEltTypeAndDimFromVariaArrayDecl(arrayType->getElementType(), elemType, elemAttr, dim); + const auto *arrayType = ptrType->getAsArrayTypeUnsafe(); + CollectBaseEltTypeAndDimFromVariaArrayDecl(arrayType->getElementType(), elemType, elemAttr, dim, isSourceType); ++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, isSourceType); } } void LibAstFile::CollectBaseEltTypeAndDimFromDependentSizedArrayDecl( - const clang::QualType currQualType, MIRType *&elemType, TypeAttrs &elemAttr, std::vector &operands) { + const clang::QualType currQualType, MIRType *&elemType, TypeAttrs &elemAttr, std::vector &operands, + bool isSourceType) { + if (isSourceType) { + MIRType *nameType = CvtTypedef(currQualType); + if (nameType != nullptr) { + elemType = nameType; + return; + } + } const clang::Type *ptrType = currQualType.getTypePtrOrNull(); ASSERT(ptrType != nullptr, "ERROR:null pointer!"); if (ptrType->isArrayType()) { - const auto *arrayType = llvm::dyn_cast(ptrType); + const auto *arrayType = ptrType->getAsArrayTypeUnsafe(); ASSERT(arrayType != nullptr, "ERROR:null pointer!"); // variable sized operands.push_back(0); - CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(arrayType->getElementType(), elemType, elemAttr, operands); + CollectBaseEltTypeAndDimFromDependentSizedArrayDecl(arrayType->getElementType(), elemType, elemAttr, operands, + isSourceType); } 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, isSourceType); + } +} + +void LibAstFile::CollectBaseEltTypeFromArrayDecl(const clang::QualType &currQualType, + MIRType *&elemType, TypeAttrs &elemAttr, bool isSourceType) { + elemType = CvtType(currQualType, isSourceType); + // 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..2759e5cf443f9b82d380fef7f0449e2fec8ad527 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,19 @@ bool ASTUtil::InsertFuncSet(const GStrIdx &idx) { static std::set funcIdxSet; return funcIdxSet.insert(idx).second; } + +bool ASTUtil::HasTypdefType(clang::QualType qualType) { + if (llvm::isa(qualType)) { + return true; + } + auto pointerType = llvm::dyn_cast(qualType); + if (pointerType != nullptr) { + return HasTypdefType(qualType->getPointeeType()); + } + const auto *arrayType = llvm::dyn_cast(qualType); + if (arrayType != nullptr) { + return HasTypdefType(arrayType->getElementType()); + } + return false; +} } // 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..af364ffe73c1765f184cb1666bb794b7ca3875e4 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" @@ -42,8 +43,6 @@ class ASTUtil { static uint32 GetDim(MIRType &type); static std::string GetTypeString(MIRType &type); - - static MIRType *CvtPrimType(const clang::QualType type); static Opcode CvtUnaryOpcode(uint32_t opcode); static Opcode CvtBinaryOpcode(uint32_t opcode, PrimType pty = PTY_begin); static Opcode CvtBinaryAssignOpcode(uint32_t opcode); @@ -51,6 +50,7 @@ class ASTUtil { static bool IsVoidPointerType(const TyIdx &tyIdx); static std::string AdjustFuncName(std::string funcName); static bool InsertFuncSet(const GStrIdx &idx); + static bool HasTypdefType(clang::QualType qualType); template static std::string Join(const Range &elements, const char *delimiter) { diff --git a/src/hir2mpl/ast_input/clang/lib/sys/arm_neon.h b/src/hir2mpl/ast_input/clang/lib/sys/arm_neon.h index 4e213d0a4bff117e62b3b2ab47f4b83e12fef39d..ea005ee521155c5c027f840361846b5ff89ba7b6 100644 --- a/src/hir2mpl/ast_input/clang/lib/sys/arm_neon.h +++ b/src/hir2mpl/ast_input/clang/lib/sys/arm_neon.h @@ -58,26 +58,50 @@ typedef struct int8x8x2_t { int8x8_t val[2]; } int8x8x2_t; +typedef struct int8x16x2_t { + int8x16_t val[2]; +} int8x16x2_t; + typedef struct int16x4x2_t { int16x4_t val[2]; } int16x4x2_t; +typedef struct int16x8x2_t { + int16x8_t val[2]; +} int16x8x2_t; + typedef struct int32x2x2_t { int32x2_t val[2]; } int32x2x2_t; +typedef struct int32x4x2_t { + int32x4_t val[2]; +} int32x4x2_t; + typedef struct uint8x8x2_t { uint8x8_t val[2]; } uint8x8x2_t; +typedef struct uint8x16x2_t { + uint8x16_t val[2]; +} uint8x16x2_t; + typedef struct uint16x4x2_t { uint16x4_t val[2]; } uint16x4x2_t; +typedef struct uint16x8x2_t { + uint16x8_t val[2]; +} uint16x8x2_t; + typedef struct uint32x2x2_t { uint32x2_t val[2]; } uint32x2x2_t; +typedef struct uint32x4x2_t { + uint32x4_t val[2]; +} uint32x4x2_t; + typedef struct float32x2x2_t { float32x2_t val[2]; } float32x2x2_t; @@ -97,6 +121,17 @@ int64x2_t __builtin_mpl_vector_abs_v2i64(int64x2_t); float32x4_t __builtin_mpl_vector_abs_v4f32(float32x4_t); float64x2_t __builtin_mpl_vector_abs_v2f64(float64x2_t); +// vecTy vector_mov_narrow(vecTy src) +// copies each element of the operand vector to the corresponding element of the destination vector. +// The result element is half the width of the operand element, and values are saturated to the result width. +// The results are the same type as the operands. +uint8x8_t __builtin_mpl_vector_mov_narrow_v8u16(uint16x8_t); +uint16x4_t __builtin_mpl_vector_mov_narrow_v4u32(uint32x4_t); +uint32x2_t __builtin_mpl_vector_mov_narrow_v2u64(uint64x2_t); +int8x8_t __builtin_mpl_vector_mov_narrow_v8i16(int16x8_t); +int16x4_t __builtin_mpl_vector_mov_narrow_v4i32(int32x4_t); +int32x2_t __builtin_mpl_vector_mov_narrow_v2i64(int64x2_t); + // vecTy vector_addl_low(vecTy src1, vecTy src2) // Add each element of the source vector to second source // widen the result into the destination vector. @@ -243,24 +278,8 @@ float32x2_t __builtin_mpl_vector_get_high_v4f32(float32x4_t); // scalarTy vector_get_element(vecTy src, int n) // Get the nth element of the source vector. -int64_t __builtin_mpl_vector_get_element_v2i64(int64x2_t, int32_t); -int32_t __builtin_mpl_vector_get_element_v4i32(int32x4_t, int32_t); -int16_t __builtin_mpl_vector_get_element_v8i16(int16x8_t, int32_t); -int8_t __builtin_mpl_vector_get_element_v16i8(int8x16_t, int32_t); -uint64_t __builtin_mpl_vector_get_element_v2u64(uint64x2_t, int32_t); -uint32_t __builtin_mpl_vector_get_element_v4u32(uint32x4_t, int32_t); -uint16_t __builtin_mpl_vector_get_element_v8u16(uint16x8_t, int32_t); -uint8_t __builtin_mpl_vector_get_element_v16u8(uint8x16_t, int32_t); float64_t __builtin_mpl_vector_get_element_v2f64(float64x2_t, int32_t); float32_t __builtin_mpl_vector_get_element_v4f32(float32x4_t, int32_t); -int64_t __builtin_mpl_vector_get_element_v1i64(int64x1_t, int32_t); -int32_t __builtin_mpl_vector_get_element_v2i32(int32x2_t, int32_t); -int16_t __builtin_mpl_vector_get_element_v4i16(int16x4_t, int32_t); -int8_t __builtin_mpl_vector_get_element_v8i8(int8x8_t, int32_t); -uint64_t __builtin_mpl_vector_get_element_v1u64(uint64x1_t, int32_t); -uint32_t __builtin_mpl_vector_get_element_v2u32(uint32x2_t, int32_t); -uint16_t __builtin_mpl_vector_get_element_v4u16(uint16x4_t, int32_t); -uint8_t __builtin_mpl_vector_get_element_v8u8(uint8x8_t, int32_t); float64_t __builtin_mpl_vector_get_element_v1f64(float64x1_t, int32_t); float32_t __builtin_mpl_vector_get_element_v2f32(float32x2_t, int32_t); @@ -502,17 +521,6 @@ uint64x2_t __builtin_mpl_vector_widen_high_v2u32(uint32x4_t); uint32x4_t __builtin_mpl_vector_widen_high_v4u16(uint16x8_t); uint16x8_t __builtin_mpl_vector_widen_high_v8u8(uint8x16_t); -// vecArrTy vector_zip(vecTy a, vecTy b) -// Interleave the upper half of elements from a and b into the destination -// vector. -int32x2x2_t __builtin_mpl_vector_zip_v2i32(int32x2_t, int32x2_t); -int16x4x2_t __builtin_mpl_vector_zip_v4i16(int16x4_t, int16x4_t); -int8x8x2_t __builtin_mpl_vector_zip_v8i8(int8x8_t, int8x8_t); -uint32x2x2_t __builtin_mpl_vector_zip_v2u32(uint32x2_t, uint32x2_t); -uint16x4x2_t __builtin_mpl_vector_zip_v4u16(uint16x4_t, uint16x4_t); -uint8x8x2_t __builtin_mpl_vector_zip_v8u8(uint8x8_t, uint8x8_t); -float32x2x2_t __builtin_mpl_vector_zip_v2f32(float32x2_t, float32x2_t); - // vecTy vector_load(scalarTy *ptr) // Load the elements pointed to by ptr into a vector. int64x2_t __builtin_mpl_vector_load_v2i64(int64_t *); @@ -604,40 +612,40 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); // ************************* // vabdl -#define vabdl_s8(a, b) __builtin_mpl_vector_labssub_low_v8i8(a, b); -#define vabdl_s16(a, b) __builtin_mpl_vector_labssub_low_v4i16(a, b); -#define vabdl_s32(a, b) __builtin_mpl_vector_labssub_low_v2i32(a, b); -#define vabdl_u8(a, b) __builtin_mpl_vector_labssub_low_v8u8(a, b); -#define vabdl_u16(a, b) __builtin_mpl_vector_labssub_low_v4u16(a, b); -#define vabdl_u32(a, b) __builtin_mpl_vector_labssub_low_v2u32(a, b); +#define vabdl_s8(a, b) __builtin_mpl_vector_labssub_low_v8i8(a, b) +#define vabdl_s16(a, b) __builtin_mpl_vector_labssub_low_v4i16(a, b) +#define vabdl_s32(a, b) __builtin_mpl_vector_labssub_low_v2i32(a, b) +#define vabdl_u8(a, b) __builtin_mpl_vector_labssub_low_v8u8(a, b) +#define vabdl_u16(a, b) __builtin_mpl_vector_labssub_low_v4u16(a, b) +#define vabdl_u32(a, b) __builtin_mpl_vector_labssub_low_v2u32(a, b) // vabdl_high -#define vabdl_high_s8(a, b) __builtin_mpl_vector_labssub_high_v8i8(a, b); -#define vabdl_high_s16(a, b) __builtin_mpl_vector_labssub_high_v4i16(a, b); -#define vabdl_high_s32(a, b) __builtin_mpl_vector_labssub_high_v2i32(a, b); -#define vabdl_high_u8(a, b) __builtin_mpl_vector_labssub_high_v8u8(a, b); -#define vabdl_high_u16(a, b) __builtin_mpl_vector_labssub_high_v4u16(a, b); -#define vabdl_high_u32(a, b) __builtin_mpl_vector_labssub_high_v2u32(a, b); +#define vabdl_high_s8(a, b) __builtin_mpl_vector_labssub_high_v8i8(a, b) +#define vabdl_high_s16(a, b) __builtin_mpl_vector_labssub_high_v4i16(a, b) +#define vabdl_high_s32(a, b) __builtin_mpl_vector_labssub_high_v2i32(a, b) +#define vabdl_high_u8(a, b) __builtin_mpl_vector_labssub_high_v8u8(a, b) +#define vabdl_high_u16(a, b) __builtin_mpl_vector_labssub_high_v4u16(a, b) +#define vabdl_high_u32(a, b) __builtin_mpl_vector_labssub_high_v2u32(a, b) // vabs -#define vabs_s8(a) __builtin_mpl_vector_abs_v8i8(a); -#define vabs_s16(a) __builtin_mpl_vector_abs_v4i16(a); -#define vabs_s32(a) __builtin_mpl_vector_abs_v2i32(a); -#define vabs_s64(a) __builtin_mpl_vector_abs_v1i64(a); -#define vabs_f32(a) __builtin_mpl_vector_abs_v2f32(a); -#define vabs_f64(a) __builtin_mpl_vector_abs_v1f64(a); -#define vabsq_s8(a) __builtin_mpl_vector_abs_v16i8(a); -#define vabsq_s16(a) __builtin_mpl_vector_abs_v8i16(a); -#define vabsq_s32(a) __builtin_mpl_vector_abs_v4i32(a); -#define vabsq_s64(a) __builtin_mpl_vector_abs_v2i64(a); -#define vabsq_f32(a) __builtin_mpl_vector_abs_v4f32(a); -#define vabsq_f64(a) __builtin_mpl_vector_abs_v2f64(a); +#define vabs_s8(a) __builtin_mpl_vector_abs_v8i8(a) +#define vabs_s16(a) __builtin_mpl_vector_abs_v4i16(a) +#define vabs_s32(a) __builtin_mpl_vector_abs_v2i32(a) +#define vabs_s64(a) __builtin_mpl_vector_abs_v1i64(a) +#define vabs_f32(a) __builtin_mpl_vector_abs_v2f32(a) +#define vabs_f64(a) __builtin_mpl_vector_abs_v1f64(a) +#define vabsq_s8(a) __builtin_mpl_vector_abs_v16i8(a) +#define vabsq_s16(a) __builtin_mpl_vector_abs_v8i16(a) +#define vabsq_s32(a) __builtin_mpl_vector_abs_v4i32(a) +#define vabsq_s64(a) __builtin_mpl_vector_abs_v2i64(a) +#define vabsq_f32(a) __builtin_mpl_vector_abs_v4f32(a) +#define vabsq_f64(a) __builtin_mpl_vector_abs_v2f64(a) // vaddv #define vaddv_s8(a) __builtin_mpl_vector_sum_v8i8(a) #define vaddv_s16(a) __builtin_mpl_vector_sum_v4i16(a) #define vaddv_s32(a) __builtin_mpl_vector_sum_v2i32(a) -#define vaddv_u8 (a) __builtin_mpl_vector_sum_v8u8(a) +#define vaddv_u8(a) __builtin_mpl_vector_sum_v8u8(a) #define vaddv_u16(a) __builtin_mpl_vector_sum_v4u16(a) #define vaddv_u32(a) __builtin_mpl_vector_sum_v2u32(a) #define vaddv_f32(a) __builtin_mpl_vector_sum_v2f32(a) @@ -652,6 +660,14 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vaddvq_f32(a) __builtin_mpl_vector_sum_v4f32(a) #define vaddvq_f64(a) __builtin_mpl_vector_sum_v2f64(a) +// vqmovn +#define vqmovn_u16(a) __builtin_mpl_vector_mov_narrow_v8u16(a) +#define vqmovn_u32(a) __builtin_mpl_vector_mov_narrow_v4u32(a) +#define vqmovn_u64(a) __builtin_mpl_vector_mov_narrow_v2u64(a) +#define vqmovn_s16(a) __builtin_mpl_vector_mov_narrow_v8i16(a) +#define vqmovn_s32(a) __builtin_mpl_vector_mov_narrow_v4i32(a) +#define vqmovn_s64(a) __builtin_mpl_vector_mov_narrow_v2i64(a) + // vaddl #define vaddl_s8(a, b) __builtin_mpl_vector_addl_low_v8i8(a, b) #define vaddl_s16(a, b) __builtin_mpl_vector_addl_low_v4i16(a, b) @@ -707,6 +723,8 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vaddq_f16(a, b) (a + b) #define vaddq_f32(a, b) (a + b) #define vaddq_f64(a, b) (a + b) +#define vaddd_s64(a, b) (a + b) +#define vaddd_u64(a, b) (a + b) // vand #define vand_s8(a, b) (a & b) @@ -726,6 +744,24 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vandq_u32(a, b) (a & b) #define vandq_u64(a, b) (a & b) +// vand +#define vorr_s8(a, b) (a | b) +#define vorr_s16(a, b) (a | b) +#define vorr_s32(a, b) (a | b) +#define vorr_s64(a, b) (a | b) +#define vorr_u8(a, b) (a | b) +#define vorr_u16(a, b) (a | b) +#define vorr_u32(a, b) (a | b) +#define vorr_u64(a, b) (a | b) +#define vorrq_s8(a, b) (a | b) +#define vorrq_s16(a, b) (a | b) +#define vorrq_s32(a, b) (a | b) +#define vorrq_s64(a, b) (a | b) +#define vorrq_u8(a, b) (a | b) +#define vorrq_u16(a, b) (a | b) +#define vorrq_u32(a, b) (a | b) +#define vorrq_u64(a, b) (a | b) + // vdup #define vdup_n_s8(a) __builtin_mpl_vector_from_scalar_v8i8(a) #define vdup_n_s16(a) __builtin_mpl_vector_from_scalar_v4i16(a) @@ -773,6 +809,32 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vceqq_f16(a, b) (a == b) #define vceqq_f32(a, b) (a == b) #define vceqq_f64(a, b) (a == b) +#define vceqd_s64(a, b) (a == b) +#define vceqd_u64(a, b) (a == b) + +// vceqz +#define vceqz_s8(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_s8(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_s16(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_s16(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_s32(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_s32(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_u8(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_u8(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_u16(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_u16(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_u32(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_u32(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_p8(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_p8(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_s64(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_s64(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_u64(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_u64(a) ((a == 0) ? -1LL : 0LL) +#define vceqz_p64(a) ((a == 0) ? -1LL : 0LL) +#define vceqzq_p64(a) ((a == 0) ? -1LL : 0LL) +#define vceqzd_s64(a) ((a == 0) ? -1LL : 0LL) +#define vceqzd_u64(a) ((a == 0) ? -1LL : 0LL) // vcgt #define vcgt_s8(a, b) (a > b) @@ -797,6 +859,19 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vcgtq_f16(a, b) (a > b) #define vcgtq_f32(a, b) (a > b) #define vcgtq_f64(a, b) (a > b) +#define vcgtd_s64(a, b) (a > b) +#define vcgtd_u64(a, b) (a > b) + +// vcgtz +#define vcgtz_s8(a) (a > 0) +#define vcgtzq_s8(a) (a > 0) +#define vcgtz_s16(a) (a > 0) +#define vcgtzq_s16(a) (a > 0) +#define vcgtz_s32(a) (a > 0) +#define vcgtzq_s32(a) (a > 0) +#define vcgtz_s64(a) (a > 0) +#define vcgtzq_s64(a) (a > 0) +#define vcgtzd_s64(a) (a > 0) // vcge #define vcge_s8(a, b) (a >= b) @@ -821,6 +896,19 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vcgeq_f16(a, b) (a >= b) #define vcgeq_f32(a, b) (a >= b) #define vcgeq_f64(a, b) (a >= b) +#define vcged_s64(a, b) (a >= b) +#define vcged_u64(a, b) (a >= b) + +// vcgez +#define vcgez_s8(a) (a >= 0) +#define vcgezq_s8(a) (a >= 0) +#define vcgez_s16(a) (a >= 0) +#define vcgezq_s16(a) (a >= 0) +#define vcgez_s32(a) (a >= 0) +#define vcgezq_s32(a) (a >= 0) +#define vcgez_s64(a) (a >= 0) +#define vcgezq_s64(a) (a >= 0) +#define vcgezd_s64(a) (a >= 0) // vclt #define vclt_s8(a, b) (a < b) @@ -845,6 +933,19 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vcltq_f16(a, b) (a < b) #define vcltq_f32(a, b) (a < b) #define vcltq_f64(a, b) (a < b) +#define vcltd_s64(a, b) (a < b) +#define vcltd_u64(a, b) (a < b) + +// vcltz +#define vcltz_s8(a) (a < 0) +#define vcltzq_s8(a) (a < 0) +#define vcltz_s16(a) (a < 0) +#define vcltzq_s16(a) (a < 0) +#define vcltz_s32(a) (a < 0) +#define vcltzq_s32(a) (a < 0) +#define vcltz_s64(a) (a < 0) +#define vcltzq_s64(a) (a < 0) +#define vcltzd_s64(a) (a < 0) // vcle #define vcle_s8(a, b) (a <= b) @@ -869,6 +970,19 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vcleq_f16(a, b) (a <= b) #define vcleq_f32(a, b) (a <= b) #define vcleq_f64(a, b) (a <= b) +#define vcled_s64(a, b) (a <= b) +#define vcled_u64(a, b) (a <= b) + +// vclez +#define vclez_s8(a) (a <= 0) +#define vclezq_s8(a) (a <= 0) +#define vclez_s16(a) (a <= 0) +#define vclezq_s16(a) (a <= 0) +#define vclez_s32(a) (a <= 0) +#define vclezq_s32(a) (a <= 0) +#define vclez_s64(a) (a <= 0) +#define vclezq_s64(a) (a <= 0) +#define vclezd_s64(a) (a <= 0) // veor #define veor_s8(a, b) (a ^ b) @@ -926,25 +1040,9 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vget_high_f64(a) __builtin_mpl_vector_get_high_v1f64(a) // vget_lane -#define vget_lane_s8(a, n) __builtin_mpl_vector_get_element_v8i8(a, n) -#define vget_lane_s16(a, n) __builtin_mpl_vector_get_element_v4i16(a, n) -#define vget_lane_s32(a, n) __builtin_mpl_vector_get_element_v2i32(a, n) -#define vget_lane_s64(a, n) __builtin_mpl_vector_get_element_v1i64(a, n) -#define vget_lane_u8(a, n) __builtin_mpl_vector_get_element_v8u8(a, n) -#define vget_lane_u16(a, n) __builtin_mpl_vector_get_element_v4u16(a, n) -#define vget_lane_u32(a, n) __builtin_mpl_vector_get_element_v2u32(a, n) -#define vget_lane_u64(a, n) __builtin_mpl_vector_get_element_v1u64(a, n) #define vget_lane_f16(a, n) __builtin_mpl_vector_get_element_v4f16(a, n) #define vget_lane_f32(a, n) __builtin_mpl_vector_get_element_v2f32(a, n) #define vget_lane_f64(a, n) __builtin_mpl_vector_get_element_v1f64(a, n) -#define vgetq_lane_s8(a, n) __builtin_mpl_vector_get_element_v16i8(a, n) -#define vgetq_lane_s16(a, n) __builtin_mpl_vector_get_element_v8i16(a, n) -#define vgetq_lane_s32(a, n) __builtin_mpl_vector_get_element_v4i32(a, n) -#define vgetq_lane_s64(a, n) __builtin_mpl_vector_get_element_v2i64(a, n) -#define vgetq_lane_u8(a, n) __builtin_mpl_vector_get_element_v16u8(a, n) -#define vgetq_lane_u16(a, n) __builtin_mpl_vector_get_element_v8u16(a, n) -#define vgetq_lane_u32(a, n) __builtin_mpl_vector_get_element_v4u32(a, n) -#define vgetq_lane_u64(a, n) __builtin_mpl_vector_get_element_v2u64(a, n) #define vgetq_lane_f16(a, n) __builtin_mpl_vector_get_element_v8f16(a, n) #define vgetq_lane_f32(a, n) __builtin_mpl_vector_get_element_v4f32(a, n) #define vgetq_lane_f64(a, n) __builtin_mpl_vector_get_element_v2f64(a, n) @@ -1026,6 +1124,20 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vmovn_high_u32(a, b) __builtin_mpl_vector_narrow_high_v4u32(a, b) #define vmovn_high_u16(a, b) __builtin_mpl_vector_narrow_high_v8u16(a, b) +// vmul +#define vmul_s8(a, b) (a * b) +#define vmulq_s8(a, b) (a * b) +#define vmul_s16(a, b) (a * b) +#define vmulq_s16(a, b) (a * b) +#define vmul_s32(a, b) (a * b) +#define vmulq_s32(a, b) (a * b) +#define vmul_u8(a, b) (a * b) +#define vmulq_u8(a, b) (a * b) +#define vmul_u16(a, b) (a * b) +#define vmulq_u16(a, b) (a * b) +#define vmul_u32(a, b) (a * b) +#define vmulq_u32(a, b) (a * b) + // vmull #define vmull_s8(a, b) __builtin_mpl_vector_mull_low_v8i8(a, b) #define vmull_s16(a, b) __builtin_mpl_vector_mull_low_v4i16(a, b) @@ -1061,18 +1173,18 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vorq_u64(a, b) (a | b) // vpadal (add and accumulate long pairwise) -#define vpadal_s8(a,b) __builtin_mpl_vector_pairwise_adalp_v8i8(a, b) -#define vpadal_s16(a,b) __builtin_mpl_vector_pairwise_adalp_v4i16(a, b) -#define vpadal_s32(a,b) __builtin_mpl_vector_pairwise_adalp_v2i32(a, b) -#define vpadal_u8(a,b) __builtin_mpl_vector_pairwise_adalp_v8u8(a, b) -#define vpadal_u16(a,b) __builtin_mpl_vector_pairwise_adalp_v4u16(a, b) -#define vpadal_u32(a,b) __builtin_mpl_vector_pairwise_adalp_v2u32(a, b) -#define vpadalq_s8(a,b) __builtin_mpl_vector_pairwise_adalp_v16i8(a, b) -#define vpadalq_s16(a,b) __builtin_mpl_vector_pairwise_adalp_v8i16(a, b) -#define vpadalq_s32(a,b) __builtin_mpl_vector_pairwise_adalp_v4i32(a, b) -#define vpadalq_u8(a,b) __builtin_mpl_vector_pairwise_adalp_v16u8(a, b) -#define vpadalq_u16(a,b) __builtin_mpl_vector_pairwise_adalp_v8u16(a, b) -#define vpadalq_u32(a,b) __builtin_mpl_vector_pairwise_adalp_v4u32(a, b) +#define vpadal_s8(a, b) __builtin_mpl_vector_pairwise_adalp_v8i8(a, b) +#define vpadal_s16(a, b) __builtin_mpl_vector_pairwise_adalp_v4i16(a, b) +#define vpadal_s32(a, b) __builtin_mpl_vector_pairwise_adalp_v2i32(a, b) +#define vpadal_u8(a, b) __builtin_mpl_vector_pairwise_adalp_v8u8(a, b) +#define vpadal_u16(a, b) __builtin_mpl_vector_pairwise_adalp_v4u16(a, b) +#define vpadal_u32(a, b) __builtin_mpl_vector_pairwise_adalp_v2u32(a, b) +#define vpadalq_s8(a, b) __builtin_mpl_vector_pairwise_adalp_v16i8(a, b) +#define vpadalq_s16(a, b) __builtin_mpl_vector_pairwise_adalp_v8i16(a, b) +#define vpadalq_s32(a, b) __builtin_mpl_vector_pairwise_adalp_v4i32(a, b) +#define vpadalq_u8(a, b) __builtin_mpl_vector_pairwise_adalp_v16u8(a, b) +#define vpadalq_u16(a, b) __builtin_mpl_vector_pairwise_adalp_v8u16(a, b) +#define vpadalq_u32(a, b) __builtin_mpl_vector_pairwise_adalp_v4u32(a, b) // vpaddl #define vpaddl_s8(a) __builtin_mpl_vector_pairwise_add_v8i8(a) @@ -1251,22 +1363,22 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vshlq_u64(a, b) (a << b) // vshl_n -#define vshlq_n_s64(a, n) __builtin_mpl_vector_shli_v2i64(a, n); -#define vshlq_n_s32(a, n) __builtin_mpl_vector_shli_v4i32(a, n); -#define vshlq_n_s16(a, n) __builtin_mpl_vector_shli_v8i16(a, n); -#define vshlq_n_s8(a, n) __builtin_mpl_vector_shli_v16i8(a, n); -#define vshlq_n_u64(a, n) __builtin_mpl_vector_shli_v2u64(a, n); -#define vshlq_n_u32(a, n) __builtin_mpl_vector_shli_v4u32(a, n); -#define vshlq_n_u16(a, n) __builtin_mpl_vector_shli_v8u16(a, n); -#define vshlq_n_u8(a, n) __builtin_mpl_vector_shli_v16u8(a, n); -#define vshl_n_s64(a, n) __builtin_mpl_vector_shli_v1i64(a, n); -#define vshl_n_s32(a, n) __builtin_mpl_vector_shli_v2i32(a, n); -#define vshl_n_s16(a, n) __builtin_mpl_vector_shli_v4i16(a, n); -#define vshl_n_s8(a, n) __builtin_mpl_vector_shli_v8i8(a, n); -#define vshl_n_u64(a, n) __builtin_mpl_vector_shli_v1u64(a, n); -#define vshl_n_u32(a, n) __builtin_mpl_vector_shli_v2u32(a, n); -#define vshl_n_u16(a, n) __builtin_mpl_vector_shli_v4u16(a, n); -#define vshl_n_u8(a, n) __builtin_mpl_vector_shli_v8u8(a, n); +#define vshlq_n_s64(a, n) __builtin_mpl_vector_shli_v2i64(a, n) +#define vshlq_n_s32(a, n) __builtin_mpl_vector_shli_v4i32(a, n) +#define vshlq_n_s16(a, n) __builtin_mpl_vector_shli_v8i16(a, n) +#define vshlq_n_s8(a, n) __builtin_mpl_vector_shli_v16i8(a, n) +#define vshlq_n_u64(a, n) __builtin_mpl_vector_shli_v2u64(a, n) +#define vshlq_n_u32(a, n) __builtin_mpl_vector_shli_v4u32(a, n) +#define vshlq_n_u16(a, n) __builtin_mpl_vector_shli_v8u16(a, n) +#define vshlq_n_u8(a, n) __builtin_mpl_vector_shli_v16u8(a, n) +#define vshl_n_s64(a, n) __builtin_mpl_vector_shli_v1i64(a, n) +#define vshl_n_s32(a, n) __builtin_mpl_vector_shli_v2i32(a, n) +#define vshl_n_s16(a, n) __builtin_mpl_vector_shli_v4i16(a, n) +#define vshl_n_s8(a, n) __builtin_mpl_vector_shli_v8i8(a, n) +#define vshl_n_u64(a, n) __builtin_mpl_vector_shli_v1u64(a, n) +#define vshl_n_u32(a, n) __builtin_mpl_vector_shli_v2u32(a, n) +#define vshl_n_u16(a, n) __builtin_mpl_vector_shli_v4u16(a, n) +#define vshl_n_u8(a, n) __builtin_mpl_vector_shli_v8u8(a, n) // vshr #define vshr_s8(a, b) (a >> b) @@ -1287,22 +1399,22 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vshrq_u64(a, b) (a >> b) // vshr_n -#define vshrq_n_s64(a, n) __builtin_mpl_vector_shri_v2i64(a, n); -#define vshrq_n_s32(a, n) __builtin_mpl_vector_shri_v4i32(a, n); -#define vshrq_n_s16(a, n) __builtin_mpl_vector_shri_v8i16(a, n); -#define vshrq_n_s8(a, n) __builtin_mpl_vector_shri_v16i8(a, n); -#define vshrq_n_u64(a, n) __builtin_mpl_vector_shru_v2u64(a, n); -#define vshrq_n_u32(a, n) __builtin_mpl_vector_shru_v4u32(a, n); -#define vshrq_n_u16(a, n) __builtin_mpl_vector_shru_v8u16(a, n); -#define vshrq_n_u8(a, n) __builtin_mpl_vector_shru_v16u8(a, n); -#define vshr_n_s64(a, n) __builtin_mpl_vector_shri_v1i64(a, n); -#define vshr_n_s32(a, n) __builtin_mpl_vector_shri_v2i32(a, n); -#define vshr_n_s16(a, n) __builtin_mpl_vector_shri_v4i16(a, n); -#define vshr_n_s8(a, n) __builtin_mpl_vector_shri_v8i8(a, n); -#define vshr_n_u64(a, n) __builtin_mpl_vector_shru_v1u64(a, n); -#define vshr_n_u32(a, n) __builtin_mpl_vector_shru_v2u32(a, n); -#define vshr_n_u16(a, n) __builtin_mpl_vector_shru_v4u16(a, n); -#define vshr_n_u8(a, n) __builtin_mpl_vector_shru_v8u8(a, n); +#define vshrq_n_s64(a, n) __builtin_mpl_vector_shri_v2i64(a, n) +#define vshrq_n_s32(a, n) __builtin_mpl_vector_shri_v4i32(a, n) +#define vshrq_n_s16(a, n) __builtin_mpl_vector_shri_v8i16(a, n) +#define vshrq_n_s8(a, n) __builtin_mpl_vector_shri_v16i8(a, n) +#define vshrq_n_u64(a, n) __builtin_mpl_vector_shru_v2u64(a, n) +#define vshrq_n_u32(a, n) __builtin_mpl_vector_shru_v4u32(a, n) +#define vshrq_n_u16(a, n) __builtin_mpl_vector_shru_v8u16(a, n) +#define vshrq_n_u8(a, n) __builtin_mpl_vector_shru_v16u8(a, n) +#define vshr_n_s64(a, n) __builtin_mpl_vector_shri_v1i64(a, n) +#define vshr_n_s32(a, n) __builtin_mpl_vector_shri_v2i32(a, n) +#define vshr_n_s16(a, n) __builtin_mpl_vector_shri_v4i16(a, n) +#define vshr_n_s8(a, n) __builtin_mpl_vector_shri_v8i8(a, n) +#define vshr_n_u64(a, n) __builtin_mpl_vector_shru_v1u64(a, n) +#define vshr_n_u32(a, n) __builtin_mpl_vector_shru_v2u32(a, n) +#define vshr_n_u16(a, n) __builtin_mpl_vector_shru_v4u16(a, n) +#define vshr_n_u8(a, n) __builtin_mpl_vector_shru_v8u8(a, n) // vshrn_n #define vshrn_n_s16(a, n) __builtin_mpl_vector_shr_narrow_low_v8i16(a, n) @@ -1359,6 +1471,8 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vsubq_f16(a, b) (a - b) #define vsubq_f32(a, b) (a - b) #define vsubq_f64(a, b) (a - b) +#define vsubd_s64(a, b) (a - b) +#define vsubd_u64(a, b) (a - b) // vsub[lw] #define vsubl_s8(a, b) __builtin_mpl_vector_subl_low_v8i8(a, b) @@ -1386,13 +1500,1604 @@ uint64x2_t __builtin_mpl_vector_subw_high_v2u32(uint64x2_t, uint32x4_t); #define vsubw_high_u16(a, b) __builtin_mpl_vector_subw_high_v4u16(a, b) #define vsubw_high_u32(a, b) __builtin_mpl_vector_subw_high_v2u32(a, b) -// vzip -#define vzip_s8(a, b) __builtin_mpl_vector_zip_v8i8(a, b) -#define vzip_s16(a, b) __builtin_mpl_vector_zip_v4i16(a, b) -#define vzip_s32(a, b) __builtin_mpl_vector_zip_v2i32(a, b) -#define vzip_u8(a, b) __builtin_mpl_vector_zip_v8u8(a, b) -#define vzip_u16(a, b) __builtin_mpl_vector_zip_v4u16(a, b) -#define vzip_u32(a, b) __builtin_mpl_vector_zip_v2u32(a, b) -#define vzip_f32(a, b) __builtin_mpl_vector_zip_v2f32(a, b) +uint8_t __builtin_mpl_vector_get_lane_v8u8(uint8x8_t a, const int lane); +#define vget_lane_u8(a, lane) __builtin_mpl_vector_get_lane_v8u8(a, lane) + +uint16_t __builtin_mpl_vector_get_lane_v4u16(uint16x4_t a, const int lane); +#define vget_lane_u16(a, lane) __builtin_mpl_vector_get_lane_v4u16(a, lane) + +uint32_t __builtin_mpl_vector_get_lane_v2u32(uint32x2_t a, const int lane); +#define vget_lane_u32(a, lane) __builtin_mpl_vector_get_lane_v2u32(a, lane) + +uint64_t __builtin_mpl_vector_get_lane_v1u64(uint64x1_t a, const int lane); +#define vget_lane_u64(a, lane) __builtin_mpl_vector_get_lane_v1u64(a, lane) + +int8_t __builtin_mpl_vector_get_lane_v8i8(int8x8_t a, const int lane); +#define vget_lane_s8(a, lane) __builtin_mpl_vector_get_lane_v8i8(a, lane) + +int16_t __builtin_mpl_vector_get_lane_v4i16(int16x4_t a, const int lane); +#define vget_lane_s16(a, lane) __builtin_mpl_vector_get_lane_v4i16(a, lane) + +int32_t __builtin_mpl_vector_get_lane_v2i32(int32x2_t a, const int lane); +#define vget_lane_s32(a, lane) __builtin_mpl_vector_get_lane_v2i32(a, lane) + +int64_t __builtin_mpl_vector_get_lane_v1i64(int64x1_t a, const int lane); +#define vget_lane_s64(a, lane) __builtin_mpl_vector_get_lane_v1i64(a, lane) + +uint8_t __builtin_mpl_vector_getq_lane_v16u8(uint8x16_t a, const int lane); +#define vgetq_lane_u8(a, lane) __builtin_mpl_vector_getq_lane_v16u8(a, lane) + +uint16_t __builtin_mpl_vector_getq_lane_v8u16(uint16x8_t a, const int lane); +#define vgetq_lane_u16(a, lane) __builtin_mpl_vector_getq_lane_v8u16(a, lane) + +uint32_t __builtin_mpl_vector_getq_lane_v4u32(uint32x4_t a, const int lane); +#define vgetq_lane_u32(a, lane) __builtin_mpl_vector_getq_lane_v4u32(a, lane) + +uint64_t __builtin_mpl_vector_getq_lane_v2u64(uint64x2_t a, const int lane); +#define vgetq_lane_u64(a, lane) __builtin_mpl_vector_getq_lane_v2u64(a, lane) + +int8_t __builtin_mpl_vector_getq_lane_v16i8(int8x16_t a, const int lane); +#define vgetq_lane_s8(a, lane) __builtin_mpl_vector_getq_lane_v16i8(a, lane) + +int16_t __builtin_mpl_vector_getq_lane_v8i16(int16x8_t a, const int lane); +#define vgetq_lane_s16(a, lane) __builtin_mpl_vector_getq_lane_v8i16(a, lane) + +int32_t __builtin_mpl_vector_getq_lane_v4i32(int32x4_t a, const int lane); +#define vgetq_lane_s32(a, lane) __builtin_mpl_vector_getq_lane_v4i32(a, lane) + +int64_t __builtin_mpl_vector_getq_lane_v2i64(int64x2_t a, const int lane); +#define vgetq_lane_s64(a, lane) __builtin_mpl_vector_getq_lane_v2i64(a, lane) + +int8x8_t __builtin_mpl_vector_abd_v8i8(int8x8_t a, int8x8_t b); +#define vabd_s8(a, b) __builtin_mpl_vector_abd_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_abdq_v16i8(int8x16_t a, int8x16_t b); +#define vabdq_s8(a, b) __builtin_mpl_vector_abdq_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_abd_v4i16(int16x4_t a, int16x4_t b); +#define vabd_s16(a, b) __builtin_mpl_vector_abd_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_abdq_v8i16(int16x8_t a, int16x8_t b); +#define vabdq_s16(a, b) __builtin_mpl_vector_abdq_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_abd_v2i32(int32x2_t a, int32x2_t b); +#define vabd_s32(a, b) __builtin_mpl_vector_abd_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_abdq_v4i32(int32x4_t a, int32x4_t b); +#define vabdq_s32(a, b) __builtin_mpl_vector_abdq_v4i32(a, b) + +uint8x8_t __builtin_mpl_vector_abd_v8u8(uint8x8_t a, uint8x8_t b); +#define vabd_u8(a, b) __builtin_mpl_vector_abd_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_abdq_v16u8(uint8x16_t a, uint8x16_t b); +#define vabdq_u8(a, b) __builtin_mpl_vector_abdq_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_abd_v4u16(uint16x4_t a, uint16x4_t b); +#define vabd_u16(a, b) __builtin_mpl_vector_abd_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_abdq_v8u16(uint16x8_t a, uint16x8_t b); +#define vabdq_u16(a, b) __builtin_mpl_vector_abdq_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_abd_v2u32(uint32x2_t a, uint32x2_t b); +#define vabd_u32(a, b) __builtin_mpl_vector_abd_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_abdq_v4u32(uint32x4_t a, uint32x4_t b); +#define vabdq_u32(a, b) __builtin_mpl_vector_abdq_v4u32(a, b) + +int8x8_t __builtin_mpl_vector_max_v8i8(int8x8_t a, int8x8_t b); +#define vmax_s8(a, b) __builtin_mpl_vector_max_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_maxq_v16i8(int8x16_t a, int8x16_t b); +#define vmaxq_s8(a, b) __builtin_mpl_vector_maxq_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_max_v4i16(int16x4_t a, int16x4_t b); +#define vmax_s16(a, b) __builtin_mpl_vector_max_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_maxq_v8i16(int16x8_t a, int16x8_t b); +#define vmaxq_s16(a, b) __builtin_mpl_vector_maxq_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_max_v2i32(int32x2_t a, int32x2_t b); +#define vmax_s32(a, b) __builtin_mpl_vector_max_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_maxq_v4i32(int32x4_t a, int32x4_t b); +#define vmaxq_s32(a, b) __builtin_mpl_vector_maxq_v4i32(a, b) + +uint8x8_t __builtin_mpl_vector_max_v8u8(uint8x8_t a, uint8x8_t b); +#define vmax_u8(a, b) __builtin_mpl_vector_max_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_maxq_v16u8(uint8x16_t a, uint8x16_t b); +#define vmaxq_u8(a, b) __builtin_mpl_vector_maxq_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_max_v4u16(uint16x4_t a, uint16x4_t b); +#define vmax_u16(a, b) __builtin_mpl_vector_max_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_maxq_v8u16(uint16x8_t a, uint16x8_t b); +#define vmaxq_u16(a, b) __builtin_mpl_vector_maxq_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_max_v2u32(uint32x2_t a, uint32x2_t b); +#define vmax_u32(a, b) __builtin_mpl_vector_max_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_maxq_v4u32(uint32x4_t a, uint32x4_t b); +#define vmaxq_u32(a, b) __builtin_mpl_vector_maxq_v4u32(a, b) + +int8x8_t __builtin_mpl_vector_min_v8i8(int8x8_t a, int8x8_t b); +#define vmin_s8(a, b) __builtin_mpl_vector_min_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_minq_v16i8(int8x16_t a, int8x16_t b); +#define vminq_s8(a, b) __builtin_mpl_vector_minq_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_min_v4i16(int16x4_t a, int16x4_t b); +#define vmin_s16(a, b) __builtin_mpl_vector_min_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_minq_v8i16(int16x8_t a, int16x8_t b); +#define vminq_s16(a, b) __builtin_mpl_vector_minq_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_min_v2i32(int32x2_t a, int32x2_t b); +#define vmin_s32(a, b) __builtin_mpl_vector_min_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_minq_v4i32(int32x4_t a, int32x4_t b); +#define vminq_s32(a, b) __builtin_mpl_vector_minq_v4i32(a, b) + +uint8x8_t __builtin_mpl_vector_min_v8u8(uint8x8_t a, uint8x8_t b); +#define vmin_u8(a, b) __builtin_mpl_vector_min_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_minq_v16u8(uint8x16_t a, uint8x16_t b); +#define vminq_u8(a, b) __builtin_mpl_vector_minq_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_min_v4u16(uint16x4_t a, uint16x4_t b); +#define vmin_u16(a, b) __builtin_mpl_vector_min_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_minq_v8u16(uint16x8_t a, uint16x8_t b); +#define vminq_u16(a, b) __builtin_mpl_vector_minq_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_min_v2u32(uint32x2_t a, uint32x2_t b); +#define vmin_u32(a, b) __builtin_mpl_vector_min_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_minq_v4u32(uint32x4_t a, uint32x4_t b); +#define vminq_u32(a, b) __builtin_mpl_vector_minq_v4u32(a, b) + +uint32x2_t __builtin_mpl_vector_recpe_v2u32(uint32x2_t a); +#define vrecpe_u32(a) __builtin_mpl_vector_recpe_v2u32(a) + +uint32x4_t __builtin_mpl_vector_recpeq_v4u32(uint32x4_t a); +#define vrecpeq_u32(a) __builtin_mpl_vector_recpeq_v4u32(a) + +int8x8_t __builtin_mpl_vector_padd_v8i8(int8x8_t a, int8x8_t b); +#define vpadd_s8(a, b) __builtin_mpl_vector_padd_v8i8(a, b) + +int16x4_t __builtin_mpl_vector_padd_v4i16(int16x4_t a, int16x4_t b); +#define vpadd_s16(a, b) __builtin_mpl_vector_padd_v4i16(a, b) + +int32x2_t __builtin_mpl_vector_padd_v2i32(int32x2_t a, int32x2_t b); +#define vpadd_s32(a, b) __builtin_mpl_vector_padd_v2i32(a, b) + +uint8x8_t __builtin_mpl_vector_padd_v8u8(uint8x8_t a, uint8x8_t b); +#define vpadd_u8(a, b) __builtin_mpl_vector_padd_v8u8(a, b) + +uint16x4_t __builtin_mpl_vector_padd_v4u16(uint16x4_t a, uint16x4_t b); +#define vpadd_u16(a, b) __builtin_mpl_vector_padd_v4u16(a, b) + +uint32x2_t __builtin_mpl_vector_padd_v2u32(uint32x2_t a, uint32x2_t b); +#define vpadd_u32(a, b) __builtin_mpl_vector_padd_v2u32(a, b) + +int8x16_t __builtin_mpl_vector_paddq_v16i8(int8x16_t a, int8x16_t b); +#define vpaddq_s8(a, b) __builtin_mpl_vector_paddq_v16i8(a, b) + +int16x8_t __builtin_mpl_vector_paddq_v8i16(int16x8_t a, int16x8_t b); +#define vpaddq_s16(a, b) __builtin_mpl_vector_paddq_v8i16(a, b) + +int32x4_t __builtin_mpl_vector_paddq_v4i32(int32x4_t a, int32x4_t b); +#define vpaddq_s32(a, b) __builtin_mpl_vector_paddq_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_paddq_v2i64(int64x2_t a, int64x2_t b); +#define vpaddq_s64(a, b) __builtin_mpl_vector_paddq_v2i64(a, b) + +uint8x16_t __builtin_mpl_vector_paddq_v16u8(uint8x16_t a, uint8x16_t b); +#define vpaddq_u8(a, b) __builtin_mpl_vector_paddq_v16u8(a, b) + +uint16x8_t __builtin_mpl_vector_paddq_v8u16(uint16x8_t a, uint16x8_t b); +#define vpaddq_u16(a, b) __builtin_mpl_vector_paddq_v8u16(a, b) + +uint32x4_t __builtin_mpl_vector_paddq_v4u32(uint32x4_t a, uint32x4_t b); +#define vpaddq_u32(a, b) __builtin_mpl_vector_paddq_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_paddq_v2u64(uint64x2_t a, uint64x2_t b); +#define vpaddq_u64(a, b) __builtin_mpl_vector_paddq_v2u64(a, b) + +int64_t __builtin_mpl_vector_paddd_v2i64(int64x2_t a); +#define vpaddd_s64(a) __builtin_mpl_vector_paddd_v2i64(a) + +uint64_t __builtin_mpl_vector_paddd_v2u64(uint64x2_t a); +#define vpaddd_u64(a) __builtin_mpl_vector_paddd_v2u64(a) + +int8x8_t __builtin_mpl_vector_pmax_v8i8(int8x8_t a, int8x8_t b); +#define vpmax_s8(a, b) __builtin_mpl_vector_pmax_v8i8(a, b) + +int16x4_t __builtin_mpl_vector_pmax_v4i16(int16x4_t a, int16x4_t b); +#define vpmax_s16(a, b) __builtin_mpl_vector_pmax_v4i16(a, b) + +int32x2_t __builtin_mpl_vector_pmax_v2i32(int32x2_t a, int32x2_t b); +#define vpmax_s32(a, b) __builtin_mpl_vector_pmax_v2i32(a, b) + +uint8x8_t __builtin_mpl_vector_pmax_v8u8(uint8x8_t a, uint8x8_t b); +#define vpmax_u8(a, b) __builtin_mpl_vector_pmax_v8u8(a, b) + +uint16x4_t __builtin_mpl_vector_pmax_v4u16(uint16x4_t a, uint16x4_t b); +#define vpmax_u16(a, b) __builtin_mpl_vector_pmax_v4u16(a, b) + +uint32x2_t __builtin_mpl_vector_pmax_v2u32(uint32x2_t a, uint32x2_t b); +#define vpmax_u32(a, b) __builtin_mpl_vector_pmax_v2u32(a, b) + +int8x16_t __builtin_mpl_vector_pmaxq_v16i8(int8x16_t a, int8x16_t b); +#define vpmaxq_s8(a, b) __builtin_mpl_vector_pmaxq_v16i8(a, b) + +int16x8_t __builtin_mpl_vector_pmaxq_v8i16(int16x8_t a, int16x8_t b); +#define vpmaxq_s16(a, b) __builtin_mpl_vector_pmaxq_v8i16(a, b) + +int32x4_t __builtin_mpl_vector_pmaxq_v4i32(int32x4_t a, int32x4_t b); +#define vpmaxq_s32(a, b) __builtin_mpl_vector_pmaxq_v4i32(a, b) + +uint8x16_t __builtin_mpl_vector_pmaxq_v16u8(uint8x16_t a, uint8x16_t b); +#define vpmaxq_u8(a, b) __builtin_mpl_vector_pmaxq_v16u8(a, b) + +uint16x8_t __builtin_mpl_vector_pmaxq_v8u16(uint16x8_t a, uint16x8_t b); +#define vpmaxq_u16(a, b) __builtin_mpl_vector_pmaxq_v8u16(a, b) + +uint32x4_t __builtin_mpl_vector_pmaxq_v4u32(uint32x4_t a, uint32x4_t b); +#define vpmaxq_u32(a, b) __builtin_mpl_vector_pmaxq_v4u32(a, b) + +int8x8_t __builtin_mpl_vector_pmin_v8i8(int8x8_t a, int8x8_t b); +#define vpmin_s8(a, b) __builtin_mpl_vector_pmin_v8i8(a, b) + +int16x4_t __builtin_mpl_vector_pmin_v4i16(int16x4_t a, int16x4_t b); +#define vpmin_s16(a, b) __builtin_mpl_vector_pmin_v4i16(a, b) + +int32x2_t __builtin_mpl_vector_pmin_v2i32(int32x2_t a, int32x2_t b); +#define vpmin_s32(a, b) __builtin_mpl_vector_pmin_v2i32(a, b) + +uint8x8_t __builtin_mpl_vector_pmin_v8u8(uint8x8_t a, uint8x8_t b); +#define vpmin_u8(a, b) __builtin_mpl_vector_pmin_v8u8(a, b) + +uint16x4_t __builtin_mpl_vector_pmin_v4u16(uint16x4_t a, uint16x4_t b); +#define vpmin_u16(a, b) __builtin_mpl_vector_pmin_v4u16(a, b) + +uint32x2_t __builtin_mpl_vector_pmin_v2u32(uint32x2_t a, uint32x2_t b); +#define vpmin_u32(a, b) __builtin_mpl_vector_pmin_v2u32(a, b) + +int8x16_t __builtin_mpl_vector_pminq_v16i8(int8x16_t a, int8x16_t b); +#define vpminq_s8(a, b) __builtin_mpl_vector_pminq_v16i8(a, b) + +int16x8_t __builtin_mpl_vector_pminq_v8i16(int16x8_t a, int16x8_t b); +#define vpminq_s16(a, b) __builtin_mpl_vector_pminq_v8i16(a, b) + +int32x4_t __builtin_mpl_vector_pminq_v4i32(int32x4_t a, int32x4_t b); +#define vpminq_s32(a, b) __builtin_mpl_vector_pminq_v4i32(a, b) + +uint8x16_t __builtin_mpl_vector_pminq_v16u8(uint8x16_t a, uint8x16_t b); +#define vpminq_u8(a, b) __builtin_mpl_vector_pminq_v16u8(a, b) + +uint16x8_t __builtin_mpl_vector_pminq_v8u16(uint16x8_t a, uint16x8_t b); +#define vpminq_u16(a, b) __builtin_mpl_vector_pminq_v8u16(a, b) + +uint32x4_t __builtin_mpl_vector_pminq_v4u32(uint32x4_t a, uint32x4_t b); +#define vpminq_u32(a, b) __builtin_mpl_vector_pminq_v4u32(a, b) + +int8x8_t __builtin_mpl_vector_maxv_v8i8(int8x8_t a); +#define vmaxv_s8(a) vget_lane_s8(__builtin_mpl_vector_maxv_v8i8(a), 0) + +int8x16_t __builtin_mpl_vector_maxvq_v16i8(int8x16_t a); +#define vmaxvq_s8(a) vgetq_lane_s8(__builtin_mpl_vector_maxvq_v16i8(a), 0) + +int16x4_t __builtin_mpl_vector_maxv_v4i16(int16x4_t a); +#define vmaxv_s16(a) vget_lane_s16(__builtin_mpl_vector_maxv_v4i16(a), 0) + +int16x8_t __builtin_mpl_vector_maxvq_v8i16(int16x8_t a); +#define vmaxvq_s16(a) vgetq_lane_s16(__builtin_mpl_vector_maxvq_v8i16(a), 0) + +int32x2_t __builtin_mpl_vector_maxv_v2i32(int32x2_t a); +#define vmaxv_s32(a) vget_lane_s32(__builtin_mpl_vector_maxv_v2i32(a), 0) + +int32x4_t __builtin_mpl_vector_maxvq_v4i32(int32x4_t a); +#define vmaxvq_s32(a) vgetq_lane_s32(__builtin_mpl_vector_maxvq_v4i32(a), 0) + +uint8x8_t __builtin_mpl_vector_maxv_v8u8(uint8x8_t a); +#define vmaxv_u8(a) vget_lane_u8(__builtin_mpl_vector_maxv_v8u8(a), 0) + +uint8x16_t __builtin_mpl_vector_maxvq_v16u8(uint8x16_t a); +#define vmaxvq_u8(a) vgetq_lane_u8(__builtin_mpl_vector_maxvq_v16u8(a), 0) + +uint16x4_t __builtin_mpl_vector_maxv_v4u16(uint16x4_t a); +#define vmaxv_u16(a) vget_lane_u16(__builtin_mpl_vector_maxv_v4u16(a), 0) + +uint16x8_t __builtin_mpl_vector_maxvq_v8u16(uint16x8_t a); +#define vmaxvq_u16(a) vgetq_lane_u16(__builtin_mpl_vector_maxvq_v8u16(a), 0) + +uint32x2_t __builtin_mpl_vector_maxv_v2u32(uint32x2_t a); +#define vmaxv_u32(a) vget_lane_u32(__builtin_mpl_vector_maxv_v2u32(a), 0) + +uint32x4_t __builtin_mpl_vector_maxvq_v4u32(uint32x4_t a); +#define vmaxvq_u32(a) vgetq_lane_u32(__builtin_mpl_vector_maxvq_v4u32(a), 0) + +int8x8_t __builtin_mpl_vector_minv_v8i8(int8x8_t a); +#define vminv_s8(a) vget_lane_s8(__builtin_mpl_vector_minv_v8i8(a), 0) + +int8x16_t __builtin_mpl_vector_minvq_v16i8(int8x16_t a); +#define vminvq_s8(a) vgetq_lane_s8(__builtin_mpl_vector_minvq_v16i8(a), 0) + +int16x4_t __builtin_mpl_vector_minv_v4i16(int16x4_t a); +#define vminv_s16(a) vget_lane_s16(__builtin_mpl_vector_minv_v4i16(a), 0) + +int16x8_t __builtin_mpl_vector_minvq_v8i16(int16x8_t a); +#define vminvq_s16(a) vgetq_lane_s16(__builtin_mpl_vector_minvq_v8i16(a), 0) + +int32x2_t __builtin_mpl_vector_minv_v2i32(int32x2_t a); +#define vminv_s32(a) vget_lane_s32(__builtin_mpl_vector_minv_v2i32(a), 0) + +int32x4_t __builtin_mpl_vector_minvq_v4i32(int32x4_t a); +#define vminvq_s32(a) vgetq_lane_s32(__builtin_mpl_vector_minvq_v4i32(a), 0) + +uint8x8_t __builtin_mpl_vector_minv_v8u8(uint8x8_t a); +#define vminv_u8(a) vget_lane_u8(__builtin_mpl_vector_minv_v8u8(a), 0) + +uint8x16_t __builtin_mpl_vector_minvq_v16u8(uint8x16_t a); +#define vminvq_u8(a) vgetq_lane_u8(__builtin_mpl_vector_minvq_v16u8(a), 0) + +uint16x4_t __builtin_mpl_vector_minv_v4u16(uint16x4_t a); +#define vminv_u16(a) vget_lane_u16(__builtin_mpl_vector_minv_v4u16(a), 0) + +uint16x8_t __builtin_mpl_vector_minvq_v8u16(uint16x8_t a); +#define vminvq_u16(a) vgetq_lane_u16(__builtin_mpl_vector_minvq_v8u16(a), 0) + +uint32x2_t __builtin_mpl_vector_minv_v2u32(uint32x2_t a); +#define vminv_u32(a) vget_lane_u32(__builtin_mpl_vector_minv_v2u32(a), 0) + +uint32x4_t __builtin_mpl_vector_minvq_v4u32(uint32x4_t a); +#define vminvq_u32(a) vgetq_lane_u32(__builtin_mpl_vector_minvq_v4u32(a), 0) + +uint8x8_t __builtin_mpl_vector_tst_v8i8(int8x8_t a, int8x8_t b); +#define vtst_s8(a, b) __builtin_mpl_vector_tst_v8i8(a, b) + +uint8x16_t __builtin_mpl_vector_tstq_v16i8(int8x16_t a, int8x16_t b); +#define vtstq_s8(a, b) __builtin_mpl_vector_tstq_v16i8(a, b) + +uint16x4_t __builtin_mpl_vector_tst_v4i16(int16x4_t a, int16x4_t b); +#define vtst_s16(a, b) __builtin_mpl_vector_tst_v4i16(a, b) + +uint16x8_t __builtin_mpl_vector_tstq_v8i16(int16x8_t a, int16x8_t b); +#define vtstq_s16(a, b) __builtin_mpl_vector_tstq_v8i16(a, b) + +uint32x2_t __builtin_mpl_vector_tst_v2i32(int32x2_t a, int32x2_t b); +#define vtst_s32(a, b) __builtin_mpl_vector_tst_v2i32(a, b) + +uint32x4_t __builtin_mpl_vector_tstq_v4i32(int32x4_t a, int32x4_t b); +#define vtstq_s32(a, b) __builtin_mpl_vector_tstq_v4i32(a, b) + +uint8x8_t __builtin_mpl_vector_tst_v8u8(uint8x8_t a, uint8x8_t b); +#define vtst_u8(a, b) __builtin_mpl_vector_tst_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_tstq_v16u8(uint8x16_t a, uint8x16_t b); +#define vtstq_u8(a, b) __builtin_mpl_vector_tstq_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_tst_v4u16(uint16x4_t a, uint16x4_t b); +#define vtst_u16(a, b) __builtin_mpl_vector_tst_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_tstq_v8u16(uint16x8_t a, uint16x8_t b); +#define vtstq_u16(a, b) __builtin_mpl_vector_tstq_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_tst_v2u32(uint32x2_t a, uint32x2_t b); +#define vtst_u32(a, b) __builtin_mpl_vector_tst_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_tstq_v4u32(uint32x4_t a, uint32x4_t b); +#define vtstq_u32(a, b) __builtin_mpl_vector_tstq_v4u32(a, b) + +uint64x1_t __builtin_mpl_vector_tst_v1i64(int64x1_t a, int64x1_t b); +#define vtst_s64(a, b) __builtin_mpl_vector_tst_v1i64(a, b) + +uint64x2_t __builtin_mpl_vector_tstq_v2i64(int64x2_t a, int64x2_t b); +#define vtstq_s64(a, b) __builtin_mpl_vector_tstq_v2i64(a, b) + +uint64x1_t __builtin_mpl_vector_tst_v1u64(uint64x1_t a, uint64x1_t b); +#define vtst_u64(a, b) __builtin_mpl_vector_tst_v1u64(a, b) + +uint64x2_t __builtin_mpl_vector_tstq_v2u64(uint64x2_t a, uint64x2_t b); +#define vtstq_u64(a, b) __builtin_mpl_vector_tstq_v2u64(a, b) + +#define vtstd_s64(a, b) ((a & b) ? -1ll : 0ll) + +#define vtstd_u64(a, b) ((a & b) ? -1ll : 0ll) + +int8x8_t __builtin_mpl_vector_qmovnh_i16(int16x4_t a); +#define vqmovnh_s16(a) vget_lane_s8( \ + __builtin_mpl_vector_qmovnh_i16(__builtin_mpl_vector_from_scalar_v4i16(a)), 0) + +int16x4_t __builtin_mpl_vector_qmovns_i32(int32x2_t a); +#define vqmovns_s32(a) vget_lane_s16( \ + __builtin_mpl_vector_qmovns_i32(__builtin_mpl_vector_from_scalar_v2i32(a)), 0) + +int32x2_t __builtin_mpl_vector_qmovnd_i64(int64x1_t a); +#define vqmovnd_s64(a) vget_lane_s32( \ + __builtin_mpl_vector_qmovnd_i64(__builtin_mpl_vector_from_scalar_v1i64(a)), 0) + +uint8x8_t __builtin_mpl_vector_qmovnh_u16(uint16x4_t a); +#define vqmovnh_u16(a) vget_lane_u8( \ + __builtin_mpl_vector_qmovnh_u16(__builtin_mpl_vector_from_scalar_v4u16(a)), 0) + +uint16x4_t __builtin_mpl_vector_qmovns_u32(uint32x2_t a); +#define vqmovns_u32(a) vget_lane_u16( \ + __builtin_mpl_vector_qmovns_u32(__builtin_mpl_vector_from_scalar_v2u32(a)), 0) + +uint32x2_t __builtin_mpl_vector_qmovnd_u64(uint64x1_t a); +#define vqmovnd_u64(a) vget_lane_u32( \ + __builtin_mpl_vector_qmovnd_u64(__builtin_mpl_vector_from_scalar_v1u64(a)), 0) + +int8x16_t __builtin_mpl_vector_qmovn_high_v16i8(int8x8_t a, int16x8_t b); +#define vqmovn_high_s16(a, b) __builtin_mpl_vector_qmovn_high_v16i8(a, b) + +int16x8_t __builtin_mpl_vector_qmovn_high_v8i16(int16x4_t a, int32x4_t b); +#define vqmovn_high_s32(a, b) __builtin_mpl_vector_qmovn_high_v8i16(a, b) + +int32x4_t __builtin_mpl_vector_qmovn_high_v4i32(int32x2_t a, int64x2_t b); +#define vqmovn_high_s64(a, b) __builtin_mpl_vector_qmovn_high_v4i32(a, b) + +uint8x16_t __builtin_mpl_vector_qmovn_high_v16u8(uint8x8_t a, uint16x8_t b); +#define vqmovn_high_u16(a, b) __builtin_mpl_vector_qmovn_high_v16u8(a, b) + +uint16x8_t __builtin_mpl_vector_qmovn_high_v8u16(uint16x4_t a, uint32x4_t b); +#define vqmovn_high_u32(a, b) __builtin_mpl_vector_qmovn_high_v8u16(a, b) + +uint32x4_t __builtin_mpl_vector_qmovn_high_v4u32(uint32x2_t a, uint64x2_t b); +#define vqmovn_high_u64(a, b) __builtin_mpl_vector_qmovn_high_v4u32(a, b) + +uint8x8_t __builtin_mpl_vector_qmovun_v8u8(int16x8_t a); +#define vqmovun_s16(a) __builtin_mpl_vector_qmovun_v8u8(a) + +uint16x4_t __builtin_mpl_vector_qmovun_v4u16(int32x4_t a); +#define vqmovun_s32(a) __builtin_mpl_vector_qmovun_v4u16(a) + +uint32x2_t __builtin_mpl_vector_qmovun_v2u32(int64x2_t a); +#define vqmovun_s64(a) __builtin_mpl_vector_qmovun_v2u32(a) + +uint8x8_t __builtin_mpl_vector_qmovunh_i16(int16x4_t a); +#define vqmovunh_s16(a) vget_lane_s8( \ + __builtin_mpl_vector_qmovunh_i16(__builtin_mpl_vector_from_scalar_v4i16(a)), 0) + +uint16x4_t __builtin_mpl_vector_qmovuns_i32(int32x2_t a); +#define vqmovuns_s32(a) vget_lane_s16( \ + __builtin_mpl_vector_qmovuns_i32(__builtin_mpl_vector_from_scalar_v2i32(a)), 0) + +uint32x2_t __builtin_mpl_vector_qmovund_i64(int64x1_t a); +#define vqmovund_s64(a) vget_lane_s32( \ + __builtin_mpl_vector_qmovund_i64(__builtin_mpl_vector_from_scalar_v1i64(a)), 0) + +uint8x16_t __builtin_mpl_vector_qmovun_high_v16u8(uint8x8_t a, int16x8_t b); +#define vqmovun_high_s16(a, b) __builtin_mpl_vector_qmovun_high_v16u8(a, b) + +uint16x8_t __builtin_mpl_vector_qmovun_high_v8u16(uint16x4_t a, int32x4_t b); +#define vqmovun_high_s32(a, b) __builtin_mpl_vector_qmovun_high_v8u16(a, b) + +uint32x4_t __builtin_mpl_vector_qmovun_high_v4u32(uint32x2_t a, int64x2_t b); +#define vqmovun_high_s64(a, b) __builtin_mpl_vector_qmovun_high_v4u32(a, b) + +int16x4_t __builtin_mpl_vector_mul_n_v4i16(int16x4_t a, int16_t b); +#define vmul_n_s16(a, b) __builtin_mpl_vector_mul_n_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_mulq_n_v8i16(int16x8_t a, int16_t b); +#define vmulq_n_s16(a, b) __builtin_mpl_vector_mulq_n_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_mul_n_v2i32(int32x2_t a, int32_t b); +#define vmul_n_s32(a, b) __builtin_mpl_vector_mul_n_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_mulq_n_v4i32(int32x4_t a, int32_t b); +#define vmulq_n_s32(a, b) __builtin_mpl_vector_mulq_n_v4i32(a, b) + +uint16x4_t __builtin_mpl_vector_mul_n_v4u16(uint16x4_t a, uint16_t b); +#define vmul_n_u16(a, b) __builtin_mpl_vector_mul_n_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_mulq_n_v8u16(uint16x8_t a, uint16_t b); +#define vmulq_n_u16(a, b) __builtin_mpl_vector_mulq_n_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_mul_n_v2u32(uint32x2_t a, uint32_t b); +#define vmul_n_u32(a, b) __builtin_mpl_vector_mul_n_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_mulq_n_v4u32(uint32x4_t a, uint32_t b); +#define vmulq_n_u32(a, b) __builtin_mpl_vector_mulq_n_v4u32(a, b) + +int16x4_t __builtin_mpl_vector_mul_lane_v4i16(int16x4_t a, int16x4_t b, const int c); +#define vmul_lane_s16(a, b, c) __builtin_mpl_vector_mul_lane_v4i16(a, b, c) + +int16x8_t __builtin_mpl_vector_mulq_lane_v8i16(int16x8_t a, int16x4_t b, const int c); +#define vmulq_lane_s16(a, b, c) __builtin_mpl_vector_mulq_lane_v8i16(a, b, c) + +int32x2_t __builtin_mpl_vector_mul_lane_v2i32(int32x2_t a, int32x2_t b, const int c); +#define vmul_lane_s32(a, b, c) __builtin_mpl_vector_mul_lane_v2i32(a, b, c) + +int32x4_t __builtin_mpl_vector_mulq_lane_v4i32(int32x4_t a, int32x2_t b, const int c); +#define vmulq_lane_s32(a, b, c) __builtin_mpl_vector_mulq_lane_v4i32(a, b, c) + +uint16x4_t __builtin_mpl_vector_mul_lane_v4u16(uint16x4_t a, uint16x4_t b, const int c); +#define vmul_lane_u16(a, b, c) __builtin_mpl_vector_mul_lane_v4u16(a, b, c) + +uint16x8_t __builtin_mpl_vector_mulq_lane_v8u16(uint16x8_t a, uint16x4_t b, const int c); +#define vmulq_lane_u16(a, b, c) __builtin_mpl_vector_mulq_lane_v8u16(a, b, c) + +uint32x2_t __builtin_mpl_vector_mul_lane_v2u32(uint32x2_t a, uint32x2_t b, const int c); +#define vmul_lane_u32(a, b, c) __builtin_mpl_vector_mul_lane_v2u32(a, b, c) + +uint32x4_t __builtin_mpl_vector_mulq_lane_v4u32(uint32x4_t a, uint32x2_t b, const int c); +#define vmulq_lane_u32(a, b, c) __builtin_mpl_vector_mulq_lane_v4u32(a, b, c) + +int16x4_t __builtin_mpl_vector_mul_laneq_v4i16(int16x4_t a, int16x8_t b, const int c); +#define vmul_laneq_s16(a, b, c) __builtin_mpl_vector_mul_laneq_v4i16(a, b, c) + +int16x8_t __builtin_mpl_vector_mulq_laneq_v8i16(int16x8_t a, int16x8_t b, const int c); +#define vmulq_laneq_s16(a, b, c) __builtin_mpl_vector_mulq_laneq_v8i16(a, b, c) + +int32x2_t __builtin_mpl_vector_mul_laneq_v2i32(int32x2_t a, int32x4_t b, const int c); +#define vmul_laneq_s32(a, b, c) __builtin_mpl_vector_mul_laneq_v2i32(a, b, c) + +int32x4_t __builtin_mpl_vector_mulq_laneq_v4i32(int32x4_t a, int32x4_t b, const int c); +#define vmulq_laneq_s32(a, b, c) __builtin_mpl_vector_mulq_laneq_v4i32(a, b, c) + +uint16x4_t __builtin_mpl_vector_mul_laneq_v4u16(uint16x4_t a, uint16x8_t b, const int c); +#define vmul_laneq_u16(a, b, c) __builtin_mpl_vector_mul_laneq_v4u16(a, b, c) + +uint16x8_t __builtin_mpl_vector_mulq_laneq_v8u16(uint16x8_t a, uint16x8_t b, const int c); +#define vmulq_laneq_u16(a, b, c) __builtin_mpl_vector_mulq_laneq_v8u16(a, b, c) + +uint32x2_t __builtin_mpl_vector_mul_laneq_v2u32(uint32x2_t a, uint32x4_t b, const int c); +#define vmul_laneq_u32(a, b, c) __builtin_mpl_vector_mul_laneq_v2u32(a, b, c) + +uint32x4_t __builtin_mpl_vector_mulq_laneq_v4u32(uint32x4_t a, uint32x4_t b, const int c); +#define vmulq_laneq_u32(a, b, c) __builtin_mpl_vector_mulq_laneq_v4u32(a, b, c) + +int32x4_t __builtin_mpl_vector_mull_n_v4i32(int16x4_t a, int16_t b); +#define vmull_n_s16(a, b) __builtin_mpl_vector_mull_n_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_mull_n_v2i64(int32x2_t a, int32_t b); +#define vmull_n_s32(a, b) __builtin_mpl_vector_mull_n_v2i64(a, b) + +uint32x4_t __builtin_mpl_vector_mull_n_v4u32(uint16x4_t a, uint16_t b); +#define vmull_n_u16(a, b) __builtin_mpl_vector_mull_n_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_mull_n_v2u64(uint32x2_t a, uint32_t b); +#define vmull_n_u32(a, b) __builtin_mpl_vector_mull_n_v2u64(a, b) + +int32x4_t __builtin_mpl_vector_mull_high_n_v4i32(int16x8_t a, int16_t b); +#define vmull_high_n_s16(a, b) __builtin_mpl_vector_mull_high_n_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_mull_high_n_v2i64(int32x4_t a, int32_t b); +#define vmull_high_n_s32(a, b) __builtin_mpl_vector_mull_high_n_v2i64(a, b) + +uint32x4_t __builtin_mpl_vector_mull_high_n_v4u32(uint16x8_t a, uint16_t b); +#define vmull_high_n_u16(a, b) __builtin_mpl_vector_mull_high_n_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_mull_high_n_v2u64(uint32x4_t a, uint32_t b); +#define vmull_high_n_u32(a, b) __builtin_mpl_vector_mull_high_n_v2u64(a, b) + +int32x4_t __builtin_mpl_vector_mull_lane_v4i32(int16x4_t a, int16x4_t b, const int c); +#define vmull_lane_s16(a, b, c) __builtin_mpl_vector_mull_lane_v4i32(a, b, c) + +int64x2_t __builtin_mpl_vector_mull_lane_v2i64(int32x2_t a, int32x2_t b, const int c); +#define vmull_lane_s32(a, b, c) __builtin_mpl_vector_mull_lane_v2i64(a, b, c) + +uint32x4_t __builtin_mpl_vector_mull_lane_v4u32(uint16x4_t a, uint16x4_t b, const int c); +#define vmull_lane_u16(a, b, c) __builtin_mpl_vector_mull_lane_v4u32(a, b, c) + +uint64x2_t __builtin_mpl_vector_mull_lane_v2u64(uint32x2_t a, uint32x2_t b, const int c); +#define vmull_lane_u32(a, b, c) __builtin_mpl_vector_mull_lane_v2u64(a, b, c) + +int32x4_t __builtin_mpl_vector_mull_high_lane_v4i32(int16x8_t a, int16x4_t b, const int c); +#define vmull_high_lane_s16(a, b, c) __builtin_mpl_vector_mull_high_lane_v4i32(a, b, c) + +int64x2_t __builtin_mpl_vector_mull_high_lane_v2i64(int32x4_t a, int32x2_t b, const int c); +#define vmull_high_lane_s32(a, b, c) __builtin_mpl_vector_mull_high_lane_v2i64(a, b, c) + +uint32x4_t __builtin_mpl_vector_mull_high_lane_v4u32(uint16x8_t a, uint16x4_t b, const int c); +#define vmull_high_lane_u16(a, b, c) __builtin_mpl_vector_mull_high_lane_v4u32(a, b, c) + +uint64x2_t __builtin_mpl_vector_mull_high_lane_v2u64(uint32x4_t a, uint32x2_t b, const int c); +#define vmull_high_lane_u32(a, b, c) __builtin_mpl_vector_mull_high_lane_v2u64(a, b, c) + +int32x4_t __builtin_mpl_vector_mull_laneq_v4i32(int16x4_t a, int16x8_t b, const int c); +#define vmull_laneq_s16(a, b, c) __builtin_mpl_vector_mull_laneq_v4i32(a, b, c) + +int64x2_t __builtin_mpl_vector_mull_laneq_v2i64(int32x2_t a, int32x4_t b, const int c); +#define vmull_laneq_s32(a, b, c) __builtin_mpl_vector_mull_laneq_v2i64(a, b, c) + +uint32x4_t __builtin_mpl_vector_mull_laneq_v4u32(uint16x4_t a, uint16x8_t b, const int c); +#define vmull_laneq_u16(a, b, c) __builtin_mpl_vector_mull_laneq_v4u32(a, b, c) + +uint64x2_t __builtin_mpl_vector_mull_laneq_v2u64(uint32x2_t a, uint32x4_t b, const int c); +#define vmull_laneq_u32(a, b, c) __builtin_mpl_vector_mull_laneq_v2u64(a, b, c) + +int32x4_t __builtin_mpl_vector_mull_high_laneq_v4i32(int16x8_t a, int16x8_t b, const int c); +#define vmull_high_laneq_s16(a, b, c) __builtin_mpl_vector_mull_high_laneq_v4i32(a, b, c) + +int64x2_t __builtin_mpl_vector_mull_high_laneq_v2i64(int32x4_t a, int32x4_t b, const int c); +#define vmull_high_laneq_s32(a, b, c) __builtin_mpl_vector_mull_high_laneq_v2i64(a, b, c) + +uint32x4_t __builtin_mpl_vector_mull_high_laneq_v4u32(uint16x8_t a, uint16x8_t b, const int c); +#define vmull_high_laneq_u16(a, b, c) __builtin_mpl_vector_mull_high_laneq_v4u32(a, b, c) + +uint64x2_t __builtin_mpl_vector_mull_high_laneq_v2u64(uint32x4_t a, uint32x4_t b, const int c); +#define vmull_high_laneq_u32(a, b, c) __builtin_mpl_vector_mull_high_laneq_v2u64(a, b, c) + +int8x8_t __builtin_mpl_vector_neg_v8i8(int8x8_t a); +#define vneg_s8(a) __builtin_mpl_vector_neg_v8i8(a) + +int8x16_t __builtin_mpl_vector_negq_v16i8(int8x16_t a); +#define vnegq_s8(a) __builtin_mpl_vector_negq_v16i8(a) + +int16x4_t __builtin_mpl_vector_neg_v4i16(int16x4_t a); +#define vneg_s16(a) __builtin_mpl_vector_neg_v4i16(a) + +int16x8_t __builtin_mpl_vector_negq_v8i16(int16x8_t a); +#define vnegq_s16(a) __builtin_mpl_vector_negq_v8i16(a) + +int32x2_t __builtin_mpl_vector_neg_v2i32(int32x2_t a); +#define vneg_s32(a) __builtin_mpl_vector_neg_v2i32(a) + +int32x4_t __builtin_mpl_vector_negq_v4i32(int32x4_t a); +#define vnegq_s32(a) __builtin_mpl_vector_negq_v4i32(a) + +int64x1_t __builtin_mpl_vector_neg_v1i64(int64x1_t a); +#define vneg_s64(a) __builtin_mpl_vector_neg_v1i64(a) + +int64_t __builtin_mpl_vector_negd_v1i64(int64_t a); +#define vnegd_s64(a) __builtin_mpl_vector_negd_v1i64(a) + +int64x2_t __builtin_mpl_vector_negq_v2i64(int64x2_t a); +#define vnegq_s64(a) __builtin_mpl_vector_negq_v2i64(a) + +int8x8_t __builtin_mpl_vector_mvn_v8i8(int8x8_t a); +#define vmvn_s8(a) __builtin_mpl_vector_mvn_v8i8(a) + +int8x16_t __builtin_mpl_vector_mvnq_v16i8(int8x16_t a); +#define vmvnq_s8(a) __builtin_mpl_vector_mvnq_v16i8(a) + +int16x4_t __builtin_mpl_vector_mvn_v4i16(int16x4_t a); +#define vmvn_s16(a) __builtin_mpl_vector_mvn_v4i16(a) + +int16x8_t __builtin_mpl_vector_mvnq_v8i16(int16x8_t a); +#define vmvnq_s16(a) __builtin_mpl_vector_mvnq_v8i16(a) + +int32x2_t __builtin_mpl_vector_mvn_v2i32(int32x2_t a); +#define vmvn_s32(a) __builtin_mpl_vector_mvn_v2i32(a) + +int32x4_t __builtin_mpl_vector_mvnq_v4i32(int32x4_t a); +#define vmvnq_s32(a) __builtin_mpl_vector_mvnq_v4i32(a) + +uint8x8_t __builtin_mpl_vector_mvn_v8u8(uint8x8_t a); +#define vmvn_u8(a) __builtin_mpl_vector_mvn_v8u8(a) + +uint8x16_t __builtin_mpl_vector_mvnq_v16u8(uint8x16_t a); +#define vmvnq_u8(a) __builtin_mpl_vector_mvnq_v16u8(a) + +uint16x4_t __builtin_mpl_vector_mvn_v4u16(uint16x4_t a); +#define vmvn_u16(a) __builtin_mpl_vector_mvn_v4u16(a) + +uint16x8_t __builtin_mpl_vector_mvnq_v8u16(uint16x8_t a); +#define vmvnq_u16(a) __builtin_mpl_vector_mvnq_v8u16(a) + +uint32x2_t __builtin_mpl_vector_mvn_v2u32(uint32x2_t a); +#define vmvn_u32(a) __builtin_mpl_vector_mvn_v2u32(a) + +uint32x4_t __builtin_mpl_vector_mvnq_v4u32(uint32x4_t a); +#define vmvnq_u32(a) __builtin_mpl_vector_mvnq_v4u32(a) + +int8x8_t __builtin_mpl_vector_orn_v8i8(int8x8_t a, int8x8_t b); +#define vorn_s8(a, b) __builtin_mpl_vector_orn_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_ornq_v16i8(int8x16_t a, int8x16_t b); +#define vornq_s8(a, b) __builtin_mpl_vector_ornq_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_orn_v4i16(int16x4_t a, int16x4_t b); +#define vorn_s16(a, b) __builtin_mpl_vector_orn_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_ornq_v8i16(int16x8_t a, int16x8_t b); +#define vornq_s16(a, b) __builtin_mpl_vector_ornq_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_orn_v2i32(int32x2_t a, int32x2_t b); +#define vorn_s32(a, b) __builtin_mpl_vector_orn_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_ornq_v4i32(int32x4_t a, int32x4_t b); +#define vornq_s32(a, b) __builtin_mpl_vector_ornq_v4i32(a, b) + +int64x1_t __builtin_mpl_vector_orn_v1i64(int64x1_t a, int64x1_t b); +#define vorn_s64(a, b) __builtin_mpl_vector_orn_v1i64(a, b) + +int64x2_t __builtin_mpl_vector_ornq_v2i64(int64x2_t a, int64x2_t b); +#define vornq_s64(a, b) __builtin_mpl_vector_ornq_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_orn_v8u8(uint8x8_t a, uint8x8_t b); +#define vorn_u8(a, b) __builtin_mpl_vector_orn_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_ornq_v16u8(uint8x16_t a, uint8x16_t b); +#define vornq_u8(a, b) __builtin_mpl_vector_ornq_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_orn_v4u16(uint16x4_t a, uint16x4_t b); +#define vorn_u16(a, b) __builtin_mpl_vector_orn_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_ornq_v8u16(uint16x8_t a, uint16x8_t b); +#define vornq_u16(a, b) __builtin_mpl_vector_ornq_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_orn_v2u32(uint32x2_t a, uint32x2_t b); +#define vorn_u32(a, b) __builtin_mpl_vector_orn_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_ornq_v4u32(uint32x4_t a, uint32x4_t b); +#define vornq_u32(a, b) __builtin_mpl_vector_ornq_v4u32(a, b) + +uint64x1_t __builtin_mpl_vector_orn_v1u64(uint64x1_t a, uint64x1_t b); +#define vorn_u64(a, b) __builtin_mpl_vector_orn_v1u64(a, b) + +uint64x2_t __builtin_mpl_vector_ornq_v2u64(uint64x2_t a, uint64x2_t b); +#define vornq_u64(a, b) __builtin_mpl_vector_ornq_v2u64(a, b) + +int8x8_t __builtin_mpl_vector_cls_v8i8(int8x8_t a); +#define vcls_s8(a) __builtin_mpl_vector_cls_v8i8(a) + +int8x16_t __builtin_mpl_vector_clsq_v16i8(int8x16_t a); +#define vclsq_s8(a) __builtin_mpl_vector_clsq_v16i8(a) + +int16x4_t __builtin_mpl_vector_cls_v4i16(int16x4_t a); +#define vcls_s16(a) __builtin_mpl_vector_cls_v4i16(a) + +int16x8_t __builtin_mpl_vector_clsq_v8i16(int16x8_t a); +#define vclsq_s16(a) __builtin_mpl_vector_clsq_v8i16(a) + +int32x2_t __builtin_mpl_vector_cls_v2i32(int32x2_t a); +#define vcls_s32(a) __builtin_mpl_vector_cls_v2i32(a) + +int32x4_t __builtin_mpl_vector_clsq_v4i32(int32x4_t a); +#define vclsq_s32(a) __builtin_mpl_vector_clsq_v4i32(a) + +int8x8_t __builtin_mpl_vector_cls_v8u8(uint8x8_t a); +#define vcls_u8(a) __builtin_mpl_vector_cls_v8u8(a) + +int8x16_t __builtin_mpl_vector_clsq_v16u8(uint8x16_t a); +#define vclsq_u8(a) __builtin_mpl_vector_clsq_v16u8(a) + +int16x4_t __builtin_mpl_vector_cls_v4u16(uint16x4_t a); +#define vcls_u16(a) __builtin_mpl_vector_cls_v4u16(a) + +int16x8_t __builtin_mpl_vector_clsq_v8u16(uint16x8_t a); +#define vclsq_u16(a) __builtin_mpl_vector_clsq_v8u16(a) + +int32x2_t __builtin_mpl_vector_cls_v2u32(uint32x2_t a); +#define vcls_u32(a) __builtin_mpl_vector_cls_v2u32(a) + +int32x4_t __builtin_mpl_vector_clsq_v4u32(uint32x4_t a); +#define vclsq_u32(a) __builtin_mpl_vector_clsq_v4u32(a) + +int8x8_t __builtin_mpl_vector_clz_v8i8(int8x8_t a); +#define vclz_s8(a) __builtin_mpl_vector_clz_v8i8(a) + +int8x16_t __builtin_mpl_vector_clzq_v16i8(int8x16_t a); +#define vclzq_s8(a) __builtin_mpl_vector_clzq_v16i8(a) + +int16x4_t __builtin_mpl_vector_clz_v4i16(int16x4_t a); +#define vclz_s16(a) __builtin_mpl_vector_clz_v4i16(a) + +int16x8_t __builtin_mpl_vector_clzq_v8i16(int16x8_t a); +#define vclzq_s16(a) __builtin_mpl_vector_clzq_v8i16(a) + +int32x2_t __builtin_mpl_vector_clz_v2i32(int32x2_t a); +#define vclz_s32(a) __builtin_mpl_vector_clz_v2i32(a) + +int32x4_t __builtin_mpl_vector_clzq_v4i32(int32x4_t a); +#define vclzq_s32(a) __builtin_mpl_vector_clzq_v4i32(a) + +uint8x8_t __builtin_mpl_vector_clz_v8u8(uint8x8_t a); +#define vclz_u8(a) __builtin_mpl_vector_clz_v8u8(a) + +uint8x16_t __builtin_mpl_vector_clzq_v16u8(uint8x16_t a); +#define vclzq_u8(a) __builtin_mpl_vector_clzq_v16u8(a) + +uint16x4_t __builtin_mpl_vector_clz_v4u16(uint16x4_t a); +#define vclz_u16(a) __builtin_mpl_vector_clz_v4u16(a) + +uint16x8_t __builtin_mpl_vector_clzq_v8u16(uint16x8_t a); +#define vclzq_u16(a) __builtin_mpl_vector_clzq_v8u16(a) + +uint32x2_t __builtin_mpl_vector_clz_v2u32(uint32x2_t a); +#define vclz_u32(a) __builtin_mpl_vector_clz_v2u32(a) + +uint32x4_t __builtin_mpl_vector_clzq_v4u32(uint32x4_t a); +#define vclzq_u32(a) __builtin_mpl_vector_clzq_v4u32(a) + +int8x8_t __builtin_mpl_vector_cnt_v8i8(int8x8_t a); +#define vcnt_s8(a) __builtin_mpl_vector_cnt_v8i8(a) + +int8x16_t __builtin_mpl_vector_cntq_v16i8(int8x16_t a); +#define vcntq_s8(a) __builtin_mpl_vector_cntq_v16i8(a) + +uint8x8_t __builtin_mpl_vector_cnt_v8u8(uint8x8_t a); +#define vcnt_u8(a) __builtin_mpl_vector_cnt_v8u8(a) + +uint8x16_t __builtin_mpl_vector_cntq_v16u8(uint8x16_t a); +#define vcntq_u8(a) __builtin_mpl_vector_cntq_v16u8(a) + +int8x8_t __builtin_mpl_vector_bic_v8i8(int8x8_t a, int8x8_t b); +#define vbic_s8(a, b) __builtin_mpl_vector_bic_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_bicq_v16i8(int8x16_t a, int8x16_t b); +#define vbicq_s8(a, b) __builtin_mpl_vector_bicq_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_bic_v4i16(int16x4_t a, int16x4_t b); +#define vbic_s16(a, b) __builtin_mpl_vector_bic_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_bicq_v8i16(int16x8_t a, int16x8_t b); +#define vbicq_s16(a, b) __builtin_mpl_vector_bicq_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_bic_v2i32(int32x2_t a, int32x2_t b); +#define vbic_s32(a, b) __builtin_mpl_vector_bic_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_bicq_v4i32(int32x4_t a, int32x4_t b); +#define vbicq_s32(a, b) __builtin_mpl_vector_bicq_v4i32(a, b) + +int64x1_t __builtin_mpl_vector_bic_v1i64(int64x1_t a, int64x1_t b); +#define vbic_s64(a, b) __builtin_mpl_vector_bic_v1i64(a, b) + +int64x2_t __builtin_mpl_vector_bicq_v2i64(int64x2_t a, int64x2_t b); +#define vbicq_s64(a, b) __builtin_mpl_vector_bicq_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_bic_v8u8(uint8x8_t a, uint8x8_t b); +#define vbic_u8(a, b) __builtin_mpl_vector_bic_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_bicq_v16u8(uint8x16_t a, uint8x16_t b); +#define vbicq_u8(a, b) __builtin_mpl_vector_bicq_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_bic_v4u16(uint16x4_t a, uint16x4_t b); +#define vbic_u16(a, b) __builtin_mpl_vector_bic_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_bicq_v8u16(uint16x8_t a, uint16x8_t b); +#define vbicq_u16(a, b) __builtin_mpl_vector_bicq_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_bic_v2u32(uint32x2_t a, uint32x2_t b); +#define vbic_u32(a, b) __builtin_mpl_vector_bic_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_bicq_v4u32(uint32x4_t a, uint32x4_t b); +#define vbicq_u32(a, b) __builtin_mpl_vector_bicq_v4u32(a, b) + +uint64x1_t __builtin_mpl_vector_bic_v1u64(uint64x1_t a, uint64x1_t b); +#define vbic_u64(a, b) __builtin_mpl_vector_bic_v1u64(a, b) + +uint64x2_t __builtin_mpl_vector_bicq_v2u64(uint64x2_t a, uint64x2_t b); +#define vbicq_u64(a, b) __builtin_mpl_vector_bicq_v2u64(a, b) + +int8x8_t __builtin_mpl_vector_bsl_v8i8(uint8x8_t a, int8x8_t b, int8x8_t c); +#define vbsl_s8(a, b, c) __builtin_mpl_vector_bsl_v8i8(a, b, c) + +int8x16_t __builtin_mpl_vector_bslq_v16i8(uint8x16_t a, int8x16_t b, int8x16_t c); +#define vbslq_s8(a, b, c) __builtin_mpl_vector_bslq_v16i8(a, b, c) + +int16x4_t __builtin_mpl_vector_bsl_v4i16(uint16x4_t a, int16x4_t b, int16x4_t c); +#define vbsl_s16(a, b, c) __builtin_mpl_vector_bsl_v4i16(a, b, c) + +int16x8_t __builtin_mpl_vector_bslq_v8i16(uint16x8_t a, int16x8_t b, int16x8_t c); +#define vbslq_s16(a, b, c) __builtin_mpl_vector_bslq_v8i16(a, b, c) + +int32x2_t __builtin_mpl_vector_bsl_v2i32(uint32x2_t a, int32x2_t b, int32x2_t c); +#define vbsl_s32(a, b, c) __builtin_mpl_vector_bsl_v2i32(a, b, c) + +int32x4_t __builtin_mpl_vector_bslq_v4i32(uint32x4_t a, int32x4_t b, int32x4_t c); +#define vbslq_s32(a, b, c) __builtin_mpl_vector_bslq_v4i32(a, b, c) + +int64x1_t __builtin_mpl_vector_bsl_v1i64(uint64x1_t a, int64x1_t b, int64x1_t c); +#define vbsl_s64(a, b, c) __builtin_mpl_vector_bsl_v1i64(a, b, c) + +int64x2_t __builtin_mpl_vector_bslq_v2i64(uint64x2_t a, int64x2_t b, int64x2_t c); +#define vbslq_s64(a, b, c) __builtin_mpl_vector_bslq_v2i64(a, b, c) + +uint8x8_t __builtin_mpl_vector_bsl_v8u8(uint8x8_t a, uint8x8_t b, uint8x8_t c); +#define vbsl_u8(a, b, c) __builtin_mpl_vector_bsl_v8u8(a, b, c) + +uint8x16_t __builtin_mpl_vector_bslq_v16u8(uint8x16_t a, uint8x16_t b, uint8x16_t c); +#define vbslq_u8(a, b, c) __builtin_mpl_vector_bslq_v16u8(a, b, c) + +uint16x4_t __builtin_mpl_vector_bsl_v4u16(uint16x4_t a, uint16x4_t b, uint16x4_t c); +#define vbsl_u16(a, b, c) __builtin_mpl_vector_bsl_v4u16(a, b, c) + +uint16x8_t __builtin_mpl_vector_bslq_v8u16(uint16x8_t a, uint16x8_t b, uint16x8_t c); +#define vbslq_u16(a, b, c) __builtin_mpl_vector_bslq_v8u16(a, b, c) + +uint32x2_t __builtin_mpl_vector_bsl_v2u32(uint32x2_t a, uint32x2_t b, uint32x2_t c); +#define vbsl_u32(a, b, c) __builtin_mpl_vector_bsl_v2u32(a, b, c) + +uint32x4_t __builtin_mpl_vector_bslq_v4u32(uint32x4_t a, uint32x4_t b, uint32x4_t c); +#define vbslq_u32(a, b, c) __builtin_mpl_vector_bslq_v4u32(a, b, c) + +uint64x1_t __builtin_mpl_vector_bsl_v1u64(uint64x1_t a, uint64x1_t b, uint64x1_t c); +#define vbsl_u64(a, b, c) __builtin_mpl_vector_bsl_v1u64(a, b, c) + +uint64x2_t __builtin_mpl_vector_bslq_v2u64(uint64x2_t a, uint64x2_t b, uint64x2_t c); +#define vbslq_u64(a, b, c) __builtin_mpl_vector_bslq_v2u64(a, b, c) + +int8x8_t __builtin_mpl_vector_copy_lane_v8i8(int8x8_t a, const int lane1, int8x8_t b, const int lane2); +#define vcopy_lane_s8(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v8i8(a, lane1, b, lane2) + +int8x16_t __builtin_mpl_vector_copyq_lane_v16i8(int8x16_t a, const int lane1, int8x8_t b, const int lane2); +#define vcopyq_lane_s8(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v16i8(a, lane1, b, lane2) + +int16x4_t __builtin_mpl_vector_copy_lane_v4i16(int16x4_t a, const int lane1, int16x4_t b, const int lane2); +#define vcopy_lane_s16(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v4i16(a, lane1, b, lane2) + +int16x8_t __builtin_mpl_vector_copyq_lane_v8i16(int16x8_t a, const int lane1, int16x4_t b, const int lane2); +#define vcopyq_lane_s16(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v8i16(a, lane1, b, lane2) + +int32x2_t __builtin_mpl_vector_copy_lane_v2i32(int32x2_t a, const int lane1, int32x2_t b, const int lane2); +#define vcopy_lane_s32(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v2i32(a, lane1, b, lane2) + +int32x4_t __builtin_mpl_vector_copyq_lane_v4i32(int32x4_t a, const int lane1, int32x2_t b, const int lane2); +#define vcopyq_lane_s32(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v4i32(a, lane1, b, lane2) + +int64x1_t __builtin_mpl_vector_copy_lane_v1i64(int64x1_t a, const int lane1, int64x1_t b, const int lane2); +#define vcopy_lane_s64(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v1i64(a, lane1, b, lane2) + +int64x2_t __builtin_mpl_vector_copyq_lane_v2i64(int64x2_t a, const int lane1, int64x1_t b, const int lane2); +#define vcopyq_lane_s64(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v2i64(a, lane1, b, lane2) + +uint8x8_t __builtin_mpl_vector_copy_lane_v8u8(uint8x8_t a, const int lane1, uint8x8_t b, const int lane2); +#define vcopy_lane_u8(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v8u8(a, lane1, b, lane2) + +uint8x16_t __builtin_mpl_vector_copyq_lane_v16u8(uint8x16_t a, const int lane1, uint8x8_t b, const int lane2); +#define vcopyq_lane_u8(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v16u8(a, lane1, b, lane2) + +uint16x4_t __builtin_mpl_vector_copy_lane_v4u16(uint16x4_t a, const int lane1, uint16x4_t b, const int lane2); +#define vcopy_lane_u16(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v4u16(a, lane1, b, lane2) + +uint16x8_t __builtin_mpl_vector_copyq_lane_v8u16(uint16x8_t a, const int lane1, uint16x4_t b, const int lane2); +#define vcopyq_lane_u16(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v8u16(a, lane1, b, lane2) + +uint32x2_t __builtin_mpl_vector_copy_lane_v2u32(uint32x2_t a, const int lane1, uint32x2_t b, const int lane2); +#define vcopy_lane_u32(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v2u32(a, lane1, b, lane2) + +uint32x4_t __builtin_mpl_vector_copyq_lane_v4u32(uint32x4_t a, const int lane1, uint32x2_t b, const int lane2); +#define vcopyq_lane_u32(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v4u32(a, lane1, b, lane2) + +uint64x1_t __builtin_mpl_vector_copy_lane_v1u64(uint64x1_t a, const int lane1, uint64x1_t b, const int lane2); +#define vcopy_lane_u64(a, lane1, b, lane2) __builtin_mpl_vector_copy_lane_v1u64(a, lane1, b, lane2) + +uint64x2_t __builtin_mpl_vector_copyq_lane_v2u64(uint64x2_t a, const int lane1, uint64x1_t b, const int lane2); +#define vcopyq_lane_u64(a, lane1, b, lane2) __builtin_mpl_vector_copyq_lane_v2u64(a, lane1, b, lane2) + +int8x8_t __builtin_mpl_vector_copy_laneq_v8i8(int8x8_t a, const int lane1, int8x16_t b, const int lane2); +#define vcopy_laneq_s8(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v8i8(a, lane1, b, lane2) + +int8x16_t __builtin_mpl_vector_copyq_laneq_v16i8(int8x16_t a, const int lane1, int8x16_t b, const int lane2); +#define vcopyq_laneq_s8(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v16i8(a, lane1, b, lane2) + +int16x4_t __builtin_mpl_vector_copy_laneq_v4i16(int16x4_t a, const int lane1, int16x8_t b, const int lane2); +#define vcopy_laneq_s16(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v4i16(a, lane1, b, lane2) + +int16x8_t __builtin_mpl_vector_copyq_laneq_v8i16(int16x8_t a, const int lane1, int16x8_t b, const int lane2); +#define vcopyq_laneq_s16(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v8i16(a, lane1, b, lane2) + +int32x2_t __builtin_mpl_vector_copy_laneq_v2i32(int32x2_t a, const int lane1, int32x4_t b, const int lane2); +#define vcopy_laneq_s32(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v2i32(a, lane1, b, lane2) + +int32x4_t __builtin_mpl_vector_copyq_laneq_v4i32(int32x4_t a, const int lane1, int32x4_t b, const int lane2); +#define vcopyq_laneq_s32(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v4i32(a, lane1, b, lane2) + +int64x1_t __builtin_mpl_vector_copy_laneq_v1i64(int64x1_t a, const int lane1, int64x2_t b, const int lane2); +#define vcopy_laneq_s64(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v1i64(a, lane1, b, lane2) + +int64x2_t __builtin_mpl_vector_copyq_laneq_v2i64(int64x2_t a, const int lane1, int64x2_t b, const int lane2); +#define vcopyq_laneq_s64(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v2i64(a, lane1, b, lane2) + +uint8x8_t __builtin_mpl_vector_copy_laneq_v8u8(uint8x8_t a, const int lane1, uint8x16_t b, const int lane2); +#define vcopy_laneq_u8(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v8u8(a, lane1, b, lane2) + +uint8x16_t __builtin_mpl_vector_copyq_laneq_v16u8(uint8x16_t a, const int lane1, uint8x16_t b, const int lane2); +#define vcopyq_laneq_u8(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v16u8(a, lane1, b, lane2) + +uint16x4_t __builtin_mpl_vector_copy_laneq_v4u16(uint16x4_t a, const int lane1, uint16x8_t b, const int lane2); +#define vcopy_laneq_u16(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v4u16(a, lane1, b, lane2) + +uint16x8_t __builtin_mpl_vector_copyq_laneq_v8u16(uint16x8_t a, const int lane1, uint16x8_t b, const int lane2); +#define vcopyq_laneq_u16(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v8u16(a, lane1, b, lane2) + +uint32x2_t __builtin_mpl_vector_copy_laneq_v2u32(uint32x2_t a, const int lane1, uint32x4_t b, const int lane2); +#define vcopy_laneq_u32(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v2u32(a, lane1, b, lane2) + +uint32x4_t __builtin_mpl_vector_copyq_laneq_v4u32(uint32x4_t a, const int lane1, uint32x4_t b, const int lane2); +#define vcopyq_laneq_u32(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v4u32(a, lane1, b, lane2) + +uint64x1_t __builtin_mpl_vector_copy_laneq_v1u64(uint64x1_t a, const int lane1, uint64x2_t b, const int lane2); +#define vcopy_laneq_u64(a, lane1, b, lane2) __builtin_mpl_vector_copy_laneq_v1u64(a, lane1, b, lane2) + +uint64x2_t __builtin_mpl_vector_copyq_laneq_v2u64(uint64x2_t a, const int lane1, uint64x2_t b, const int lane2); +#define vcopyq_laneq_u64(a, lane1, b, lane2) __builtin_mpl_vector_copyq_laneq_v2u64(a, lane1, b, lane2) + +int8x8_t __builtin_mpl_vector_rbit_v8i8(int8x8_t a); +#define vrbit_s8(a) __builtin_mpl_vector_rbit_v8i8(a) + +int8x16_t __builtin_mpl_vector_rbitq_v16i8(int8x16_t a); +#define vrbitq_s8(a) __builtin_mpl_vector_rbitq_v16i8(a) + +uint8x8_t __builtin_mpl_vector_rbit_v8u8(uint8x8_t a); +#define vrbit_u8(a) __builtin_mpl_vector_rbit_v8u8(a) + +uint8x16_t __builtin_mpl_vector_rbitq_v16u8(uint8x16_t a); +#define vrbitq_u8(a) __builtin_mpl_vector_rbitq_v16u8(a) + +int8x8_t __builtin_mpl_vector_create_v8i8(uint64_t a); +#define vcreate_s8(a) __builtin_mpl_vector_create_v8i8(a) + +int16x4_t __builtin_mpl_vector_create_v4i16(uint64_t a); +#define vcreate_s16(a) __builtin_mpl_vector_create_v4i16(a) + +int32x2_t __builtin_mpl_vector_create_v2i32(uint64_t a); +#define vcreate_s32(a) __builtin_mpl_vector_create_v2i32(a) + +int64x1_t __builtin_mpl_vector_create_v1i64(uint64_t a); +#define vcreate_s64(a) __builtin_mpl_vector_create_v1i64(a) + +uint8x8_t __builtin_mpl_vector_create_v8u8(uint64_t a); +#define vcreate_u8(a) __builtin_mpl_vector_create_v8u8(a) + +uint16x4_t __builtin_mpl_vector_create_v4u16(uint64_t a); +#define vcreate_u16(a) __builtin_mpl_vector_create_v4u16(a) + +uint32x2_t __builtin_mpl_vector_create_v2u32(uint64_t a); +#define vcreate_u32(a) __builtin_mpl_vector_create_v2u32(a) + +uint64x1_t __builtin_mpl_vector_create_v1u64(uint64_t a); +#define vcreate_u64(a) __builtin_mpl_vector_create_v1u64(a) + +int8x8_t __builtin_mpl_vector_mov_n_v8i8(int8_t a); +#define vmov_n_s8(a) __builtin_mpl_vector_mov_n_v8i8(a) + +int8x16_t __builtin_mpl_vector_movq_n_v16i8(int8_t a); +#define vmovq_n_s8(a) __builtin_mpl_vector_movq_n_v16i8(a) + +int16x4_t __builtin_mpl_vector_mov_n_v4i16(int16_t a); +#define vmov_n_s16(a) __builtin_mpl_vector_mov_n_v4i16(a) + +int16x8_t __builtin_mpl_vector_movq_n_v8i16(int16_t a); +#define vmovq_n_s16(a) __builtin_mpl_vector_movq_n_v8i16(a) + +int32x2_t __builtin_mpl_vector_mov_n_v2i32(int32_t a); +#define vmov_n_s32(a) __builtin_mpl_vector_mov_n_v2i32(a) + +int32x4_t __builtin_mpl_vector_movq_n_v4i32(int32_t a); +#define vmovq_n_s32(a) __builtin_mpl_vector_movq_n_v4i32(a) + +int64x1_t __builtin_mpl_vector_mov_n_v1i64(int64_t a); +#define vmov_n_s64(a) __builtin_mpl_vector_mov_n_v1i64(a) + +int64x2_t __builtin_mpl_vector_movq_n_v2i64(int64_t a); +#define vmovq_n_s64(a) __builtin_mpl_vector_movq_n_v2i64(a) + +uint8x8_t __builtin_mpl_vector_mov_n_v8u8(uint8_t a); +#define vmov_n_u8(a) __builtin_mpl_vector_mov_n_v8u8(a) + +uint8x16_t __builtin_mpl_vector_movq_n_v16u8(uint8_t a); +#define vmovq_n_u8(a) __builtin_mpl_vector_movq_n_v16u8(a) + +uint16x4_t __builtin_mpl_vector_mov_n_v4u16(uint16_t a); +#define vmov_n_u16(a) __builtin_mpl_vector_mov_n_v4u16(a) + +uint16x8_t __builtin_mpl_vector_movq_n_v8u16(uint16_t a); +#define vmovq_n_u16(a) __builtin_mpl_vector_movq_n_v8u16(a) + +uint32x2_t __builtin_mpl_vector_mov_n_v2u32(uint32_t a); +#define vmov_n_u32(a) __builtin_mpl_vector_mov_n_v2u32(a) + +uint32x4_t __builtin_mpl_vector_movq_n_v4u32(uint32_t a); +#define vmovq_n_u32(a) __builtin_mpl_vector_movq_n_v4u32(a) + +uint64x1_t __builtin_mpl_vector_mov_n_v1u64(uint64_t a); +#define vmov_n_u64(a) __builtin_mpl_vector_mov_n_v1u64(a) + +uint64x2_t __builtin_mpl_vector_movq_n_v2u64(uint64_t a); +#define vmovq_n_u64(a) __builtin_mpl_vector_movq_n_v2u64(a) + +int8x8_t __builtin_mpl_vector_dup_lane_v8i8(int8x8_t a, const int lane); +#define vdup_lane_s8(a, lane) __builtin_mpl_vector_dup_lane_v8i8(a, lane) + +int8x16_t __builtin_mpl_vector_dupq_lane_v16i8(int8x8_t a, const int lane); +#define vdupq_lane_s8(a, lane) __builtin_mpl_vector_dupq_lane_v16i8(a, lane) + +int16x4_t __builtin_mpl_vector_dup_lane_v4i16(int16x4_t a, const int lane); +#define vdup_lane_s16(a, lane) __builtin_mpl_vector_dup_lane_v4i16(a, lane) + +int16x8_t __builtin_mpl_vector_dupq_lane_v8i16(int16x4_t a, const int lane); +#define vdupq_lane_s16(a, lane) __builtin_mpl_vector_dupq_lane_v8i16(a, lane) + +int32x2_t __builtin_mpl_vector_dup_lane_v2i32(int32x2_t a, const int lane); +#define vdup_lane_s32(a, lane) __builtin_mpl_vector_dup_lane_v2i32(a, lane) + +int32x4_t __builtin_mpl_vector_dupq_lane_v4i32(int32x2_t a, const int lane); +#define vdupq_lane_s32(a, lane) __builtin_mpl_vector_dupq_lane_v4i32(a, lane) + +int64x1_t __builtin_mpl_vector_dup_lane_v1i64(int64x1_t a, const int lane); +#define vdup_lane_s64(a, lane) __builtin_mpl_vector_dup_lane_v1i64(a, lane) + +int64x2_t __builtin_mpl_vector_dupq_lane_v2i64(int64x1_t a, const int lane); +#define vdupq_lane_s64(a, lane) __builtin_mpl_vector_dupq_lane_v2i64(a, lane) + +uint8x8_t __builtin_mpl_vector_dup_lane_v8u8(uint8x8_t a, const int lane); +#define vdup_lane_u8(a, lane) __builtin_mpl_vector_dup_lane_v8u8(a, lane) + +uint8x16_t __builtin_mpl_vector_dupq_lane_v16u8(uint8x8_t a, const int lane); +#define vdupq_lane_u8(a, lane) __builtin_mpl_vector_dupq_lane_v16u8(a, lane) + +uint16x4_t __builtin_mpl_vector_dup_lane_v4u16(uint16x4_t a, const int lane); +#define vdup_lane_u16(a, lane) __builtin_mpl_vector_dup_lane_v4u16(a, lane) + +uint16x8_t __builtin_mpl_vector_dupq_lane_v8u16(uint16x4_t a, const int lane); +#define vdupq_lane_u16(a, lane) __builtin_mpl_vector_dupq_lane_v8u16(a, lane) + +uint32x2_t __builtin_mpl_vector_dup_lane_v2u32(uint32x2_t a, const int lane); +#define vdup_lane_u32(a, lane) __builtin_mpl_vector_dup_lane_v2u32(a, lane) + +uint32x4_t __builtin_mpl_vector_dupq_lane_v4u32(uint32x2_t a, const int lane); +#define vdupq_lane_u32(a, lane) __builtin_mpl_vector_dupq_lane_v4u32(a, lane) + +uint64x1_t __builtin_mpl_vector_dup_lane_v1u64(uint64x1_t a, const int lane); +#define vdup_lane_u64(a, lane) __builtin_mpl_vector_dup_lane_v1u64(a, lane) + +uint64x2_t __builtin_mpl_vector_dupq_lane_v2u64(uint64x1_t a, const int lane); +#define vdupq_lane_u64(a, lane) __builtin_mpl_vector_dupq_lane_v2u64(a, lane) + +int8x8_t __builtin_mpl_vector_dup_laneq_v8i8(int8x16_t a, const int lane); +#define vdup_laneq_s8(a, lane) __builtin_mpl_vector_dup_laneq_v8i8(a, lane) + +int8x16_t __builtin_mpl_vector_dupq_laneq_v16i8(int8x16_t a, const int lane); +#define vdupq_laneq_s8(a, lane) __builtin_mpl_vector_dupq_laneq_v16i8(a, lane) + +int16x4_t __builtin_mpl_vector_dup_laneq_v4i16(int16x8_t a, const int lane); +#define vdup_laneq_s16(a, lane) __builtin_mpl_vector_dup_laneq_v4i16(a, lane) + +int16x8_t __builtin_mpl_vector_dupq_laneq_v8i16(int16x8_t a, const int lane); +#define vdupq_laneq_s16(a, lane) __builtin_mpl_vector_dupq_laneq_v8i16(a, lane) + +int32x2_t __builtin_mpl_vector_dup_laneq_v2i32(int32x4_t a, const int lane); +#define vdup_laneq_s32(a, lane) __builtin_mpl_vector_dup_laneq_v2i32(a, lane) + +int32x4_t __builtin_mpl_vector_dupq_laneq_v4i32(int32x4_t a, const int lane); +#define vdupq_laneq_s32(a, lane) __builtin_mpl_vector_dupq_laneq_v4i32(a, lane) + +int64x1_t __builtin_mpl_vector_dup_laneq_v1i64(int64x2_t a, const int lane); +#define vdup_laneq_s64(a, lane) __builtin_mpl_vector_dup_laneq_v1i64(a, lane) + +int64x2_t __builtin_mpl_vector_dupq_laneq_v2i64(int64x2_t a, const int lane); +#define vdupq_laneq_s64(a, lane) __builtin_mpl_vector_dupq_laneq_v2i64(a, lane) + +uint8x8_t __builtin_mpl_vector_dup_laneq_v8u8(uint8x16_t a, const int lane); +#define vdup_laneq_u8(a, lane) __builtin_mpl_vector_dup_laneq_v8u8(a, lane) + +uint8x16_t __builtin_mpl_vector_dupq_laneq_v16u8(uint8x16_t a, const int lane); +#define vdupq_laneq_u8(a, lane) __builtin_mpl_vector_dupq_laneq_v16u8(a, lane) + +uint16x4_t __builtin_mpl_vector_dup_laneq_v4u16(uint16x8_t a, const int lane); +#define vdup_laneq_u16(a, lane) __builtin_mpl_vector_dup_laneq_v4u16(a, lane) + +uint16x8_t __builtin_mpl_vector_dupq_laneq_v8u16(uint16x8_t a, const int lane); +#define vdupq_laneq_u16(a, lane) __builtin_mpl_vector_dupq_laneq_v8u16(a, lane) + +uint32x2_t __builtin_mpl_vector_dup_laneq_v2u32(uint32x4_t a, const int lane); +#define vdup_laneq_u32(a, lane) __builtin_mpl_vector_dup_laneq_v2u32(a, lane) + +uint32x4_t __builtin_mpl_vector_dupq_laneq_v4u32(uint32x4_t a, const int lane); +#define vdupq_laneq_u32(a, lane) __builtin_mpl_vector_dupq_laneq_v4u32(a, lane) + +uint64x1_t __builtin_mpl_vector_dup_laneq_v1u64(uint64x2_t a, const int lane); +#define vdup_laneq_u64(a, lane) __builtin_mpl_vector_dup_laneq_v1u64(a, lane) + +uint64x2_t __builtin_mpl_vector_dupq_laneq_v2u64(uint64x2_t a, const int lane); +#define vdupq_laneq_u64(a, lane) __builtin_mpl_vector_dupq_laneq_v2u64(a, lane) + +int8x16_t __builtin_mpl_vector_combine_v16i8(int8x8_t a, int8x8_t high); +#define vcombine_s8(a, high) __builtin_mpl_vector_combine_v16i8(a, high) + +int16x8_t __builtin_mpl_vector_combine_v8i16(int16x4_t a, int16x4_t high); +#define vcombine_s16(a, high) __builtin_mpl_vector_combine_v8i16(a, high) + +int32x4_t __builtin_mpl_vector_combine_v4i32(int32x2_t a, int32x2_t high); +#define vcombine_s32(a, high) __builtin_mpl_vector_combine_v4i32(a, high) + +int64x2_t __builtin_mpl_vector_combine_v2i64(int64x1_t a, int64x1_t high); +#define vcombine_s64(a, high) __builtin_mpl_vector_combine_v2i64(a, high) + +uint8x16_t __builtin_mpl_vector_combine_v16u8(uint8x8_t a, uint8x8_t high); +#define vcombine_u8(a, high) __builtin_mpl_vector_combine_v16u8(a, high) + +uint16x8_t __builtin_mpl_vector_combine_v8u16(uint16x4_t a, uint16x4_t high); +#define vcombine_u16(a, high) __builtin_mpl_vector_combine_v8u16(a, high) + +uint32x4_t __builtin_mpl_vector_combine_v4u32(uint32x2_t a, uint32x2_t high); +#define vcombine_u32(a, high) __builtin_mpl_vector_combine_v4u32(a, high) + +uint64x2_t __builtin_mpl_vector_combine_v2u64(uint64x1_t a, uint64x1_t high); +#define vcombine_u64(a, high) __builtin_mpl_vector_combine_v2u64(a, high) + +int8_t __builtin_mpl_vector_dupb_lane_v8i8(int8x8_t a, const int lane); +#define vdupb_lane_s8(a, lane) __builtin_mpl_vector_dupb_lane_v8i8(a, lane) + +int16_t __builtin_mpl_vector_duph_lane_v4i16(int16x4_t a, const int lane); +#define vduph_lane_s16(a, lane) __builtin_mpl_vector_duph_lane_v4i16(a, lane) + +int32_t __builtin_mpl_vector_dups_lane_v2i32(int32x2_t a, const int lane); +#define vdups_lane_s32(a, lane) __builtin_mpl_vector_dups_lane_v2i32(a, lane) + +int64_t __builtin_mpl_vector_dupd_lane_v1i64(int64x1_t a, const int lane); +#define vdupd_lane_s64(a, lane) __builtin_mpl_vector_dupd_lane_v1i64(a, lane) + +uint8_t __builtin_mpl_vector_dupb_lane_v8u8(uint8x8_t a, const int lane); +#define vdupb_lane_u8(a, lane) __builtin_mpl_vector_dupb_lane_v8u8(a, lane) + +uint16_t __builtin_mpl_vector_duph_lane_v4u16(uint16x4_t a, const int lane); +#define vduph_lane_u16(a, lane) __builtin_mpl_vector_duph_lane_v4u16(a, lane) + +uint32_t __builtin_mpl_vector_dups_lane_v2u32(uint32x2_t a, const int lane); +#define vdups_lane_u32(a, lane) __builtin_mpl_vector_dups_lane_v2u32(a, lane) + +uint64_t __builtin_mpl_vector_dupd_lane_v1u64(uint64x1_t a, const int lane); +#define vdupd_lane_u64(a, lane) __builtin_mpl_vector_dupd_lane_v1u64(a, lane) + +int8_t __builtin_mpl_vector_dupb_laneq_v16i8(int8x16_t a, const int lane); +#define vdupb_laneq_s8(a, lane) __builtin_mpl_vector_dupb_laneq_v16i8(a, lane) + +int16_t __builtin_mpl_vector_duph_laneq_v8i16(int16x8_t a, const int lane); +#define vduph_laneq_s16(a, lane) __builtin_mpl_vector_duph_laneq_v8i16(a, lane) + +int32_t __builtin_mpl_vector_dups_laneq_v4i32(int32x4_t a, const int lane); +#define vdups_laneq_s32(a, lane) __builtin_mpl_vector_dups_laneq_v4i32(a, lane) + +int64_t __builtin_mpl_vector_dupd_laneq_v2i64(int64x2_t a, const int lane); +#define vdupd_laneq_s64(a, lane) __builtin_mpl_vector_dupd_laneq_v2i64(a, lane) + +uint8_t __builtin_mpl_vector_dupb_laneq_v16u8(uint8x16_t a, const int lane); +#define vdupb_laneq_u8(a, lane) __builtin_mpl_vector_dupb_laneq_v16u8(a, lane) + +uint16_t __builtin_mpl_vector_duph_laneq_v8u16(uint16x8_t a, const int lane); +#define vduph_laneq_u16(a, lane) __builtin_mpl_vector_duph_laneq_v8u16(a, lane) + +uint32_t __builtin_mpl_vector_dups_laneq_v4u32(uint32x4_t a, const int lane); +#define vdups_laneq_u32(a, lane) __builtin_mpl_vector_dups_laneq_v4u32(a, lane) + +uint64_t __builtin_mpl_vector_dupd_laneq_v2u64(uint64x2_t a, const int lane); +#define vdupd_laneq_u64(a, lane) __builtin_mpl_vector_dupd_laneq_v2u64(a, lane) + +int8x8_t __builtin_mpl_vector_rev64_v8i8(int8x8_t a); +#define vrev64_s8(a) __builtin_mpl_vector_rev64_v8i8(a) + +int8x16_t __builtin_mpl_vector_rev64q_v16i8(int8x16_t a); +#define vrev64q_s8(a) __builtin_mpl_vector_rev64q_v16i8(a) + +int16x4_t __builtin_mpl_vector_rev64_v4i16(int16x4_t a); +#define vrev64_s16(a) __builtin_mpl_vector_rev64_v4i16(a) + +int16x8_t __builtin_mpl_vector_rev64q_v8i16(int16x8_t a); +#define vrev64q_s16(a) __builtin_mpl_vector_rev64q_v8i16(a) + +int32x2_t __builtin_mpl_vector_rev64_v2i32(int32x2_t a); +#define vrev64_s32(a) __builtin_mpl_vector_rev64_v2i32(a) + +int32x4_t __builtin_mpl_vector_rev64q_v4i32(int32x4_t a); +#define vrev64q_s32(a) __builtin_mpl_vector_rev64q_v4i32(a) + +uint8x8_t __builtin_mpl_vector_rev64_v8u8(uint8x8_t a); +#define vrev64_u8(a) __builtin_mpl_vector_rev64_v8u8(a) + +uint8x16_t __builtin_mpl_vector_rev64q_v16u8(uint8x16_t a); +#define vrev64q_u8(a) __builtin_mpl_vector_rev64q_v16u8(a) + +uint16x4_t __builtin_mpl_vector_rev64_v4u16(uint16x4_t a); +#define vrev64_u16(a) __builtin_mpl_vector_rev64_v4u16(a) + +uint16x8_t __builtin_mpl_vector_rev64q_v8u16(uint16x8_t a); +#define vrev64q_u16(a) __builtin_mpl_vector_rev64q_v8u16(a) + +uint32x2_t __builtin_mpl_vector_rev64_v2u32(uint32x2_t a); +#define vrev64_u32(a) __builtin_mpl_vector_rev64_v2u32(a) + +uint32x4_t __builtin_mpl_vector_rev64q_v4u32(uint32x4_t a); +#define vrev64q_u32(a) __builtin_mpl_vector_rev64q_v4u32(a) + +int8x8_t __builtin_mpl_vector_rev16_v8i8(int8x8_t a); +#define vrev16_s8(a) __builtin_mpl_vector_rev16_v8i8(a) + +int8x16_t __builtin_mpl_vector_rev16q_v16i8(int8x16_t a); +#define vrev16q_s8(a) __builtin_mpl_vector_rev16q_v16i8(a) + +uint8x8_t __builtin_mpl_vector_rev16_v8u8(uint8x8_t a); +#define vrev16_u8(a) __builtin_mpl_vector_rev16_v8u8(a) + +uint8x16_t __builtin_mpl_vector_rev16q_v16u8(uint8x16_t a); +#define vrev16q_u8(a) __builtin_mpl_vector_rev16q_v16u8(a) + +int8x8_t __builtin_mpl_vector_zip1_v8i8(int8x8_t a, int8x8_t b); +#define vzip1_s8(a, b) __builtin_mpl_vector_zip1_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_zip1q_v16i8(int8x16_t a, int8x16_t b); +#define vzip1q_s8(a, b) __builtin_mpl_vector_zip1q_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_zip1_v4i16(int16x4_t a, int16x4_t b); +#define vzip1_s16(a, b) __builtin_mpl_vector_zip1_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_zip1q_v8i16(int16x8_t a, int16x8_t b); +#define vzip1q_s16(a, b) __builtin_mpl_vector_zip1q_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_zip1_v2i32(int32x2_t a, int32x2_t b); +#define vzip1_s32(a, b) __builtin_mpl_vector_zip1_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_zip1q_v4i32(int32x4_t a, int32x4_t b); +#define vzip1q_s32(a, b) __builtin_mpl_vector_zip1q_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_zip1q_v2i64(int64x2_t a, int64x2_t b); +#define vzip1q_s64(a, b) __builtin_mpl_vector_zip1q_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_zip1_v8u8(uint8x8_t a, uint8x8_t b); +#define vzip1_u8(a, b) __builtin_mpl_vector_zip1_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_zip1q_v16u8(uint8x16_t a, uint8x16_t b); +#define vzip1q_u8(a, b) __builtin_mpl_vector_zip1q_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_zip1_v4u16(uint16x4_t a, uint16x4_t b); +#define vzip1_u16(a, b) __builtin_mpl_vector_zip1_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_zip1q_v8u16(uint16x8_t a, uint16x8_t b); +#define vzip1q_u16(a, b) __builtin_mpl_vector_zip1q_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_zip1_v2u32(uint32x2_t a, uint32x2_t b); +#define vzip1_u32(a, b) __builtin_mpl_vector_zip1_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_zip1q_v4u32(uint32x4_t a, uint32x4_t b); +#define vzip1q_u32(a, b) __builtin_mpl_vector_zip1q_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_zip1q_v2u64(uint64x2_t a, uint64x2_t b); +#define vzip1q_u64(a, b) __builtin_mpl_vector_zip1q_v2u64(a, b) + +int8x8_t __builtin_mpl_vector_zip2_v8i8(int8x8_t a, int8x8_t b); +#define vzip2_s8(a, b) __builtin_mpl_vector_zip2_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_zip2q_v16i8(int8x16_t a, int8x16_t b); +#define vzip2q_s8(a, b) __builtin_mpl_vector_zip2q_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_zip2_v4i16(int16x4_t a, int16x4_t b); +#define vzip2_s16(a, b) __builtin_mpl_vector_zip2_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_zip2q_v8i16(int16x8_t a, int16x8_t b); +#define vzip2q_s16(a, b) __builtin_mpl_vector_zip2q_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_zip2_v2i32(int32x2_t a, int32x2_t b); +#define vzip2_s32(a, b) __builtin_mpl_vector_zip2_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_zip2q_v4i32(int32x4_t a, int32x4_t b); +#define vzip2q_s32(a, b) __builtin_mpl_vector_zip2q_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_zip2q_v2i64(int64x2_t a, int64x2_t b); +#define vzip2q_s64(a, b) __builtin_mpl_vector_zip2q_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_zip2_v8u8(uint8x8_t a, uint8x8_t b); +#define vzip2_u8(a, b) __builtin_mpl_vector_zip2_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_zip2q_v16u8(uint8x16_t a, uint8x16_t b); +#define vzip2q_u8(a, b) __builtin_mpl_vector_zip2q_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_zip2_v4u16(uint16x4_t a, uint16x4_t b); +#define vzip2_u16(a, b) __builtin_mpl_vector_zip2_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_zip2q_v8u16(uint16x8_t a, uint16x8_t b); +#define vzip2q_u16(a, b) __builtin_mpl_vector_zip2q_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_zip2_v2u32(uint32x2_t a, uint32x2_t b); +#define vzip2_u32(a, b) __builtin_mpl_vector_zip2_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_zip2q_v4u32(uint32x4_t a, uint32x4_t b); +#define vzip2q_u32(a, b) __builtin_mpl_vector_zip2q_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_zip2q_v2u64(uint64x2_t a, uint64x2_t b); +#define vzip2q_u64(a, b) __builtin_mpl_vector_zip2q_v2u64(a, b) + +#define vzip_s8(a, b) (int8x8x2_t){vzip1_s8((a), (b)), vzip2_s8((a), (b))} +#define vzip_s16(a, b) (int16x4x2_t){vzip1_s16((a), (b)), vzip2_s16((a), (b))} +#define vzip_u8(a, b) (uint8x8x2_t){vzip1_u8((a), (b)), vzip2_u8((a), (b))} +#define vzip_u16(a, b) (uint16x4x2_t){vzip1_u16((a), (b)), vzip2_u16((a), (b))} +#define vzip_s32(a, b) (int32x2x2_t){vzip1_s32((a), (b)), vzip2_s32((a), (b))} +#define vzip_u32(a, b) (uint32x2x2_t){vzip1_u32((a), (b)), vzip2_u32((a), (b))} +#define vzipq_s8(a, b) (int8x16x2_t){vzip1q_s8((a), (b)), vzip2q_s8((a), (b))} +#define vzipq_s16(a, b) (int16x8x2_t){vzip1q_s16((a), (b)), vzip2q_s16((a), (b))} +#define vzipq_s32(a, b) (int32x4x2_t){vzip1q_s32((a), (b)), vzip2q_s32((a), (b))} +#define vzipq_u8(a, b) (uint8x16x2_t){vzip1q_u8((a), (b)), vzip2q_u8((a), (b))} +#define vzipq_u16(a, b) (uint16x8x2_t){vzip1q_u16((a), (b)), vzip2q_u16((a), (b))} +#define vzipq_u32(a, b) (uint32x4x2_t){vzip1q_u32((a), (b)), vzip2q_u32((a), (b))} + +int8x8_t __builtin_mpl_vector_uzp1_v8i8(int8x8_t a, int8x8_t b); +#define vuzp1_s8(a, b) __builtin_mpl_vector_uzp1_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_uzp1q_v16i8(int8x16_t a, int8x16_t b); +#define vuzp1q_s8(a, b) __builtin_mpl_vector_uzp1q_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_uzp1_v4i16(int16x4_t a, int16x4_t b); +#define vuzp1_s16(a, b) __builtin_mpl_vector_uzp1_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_uzp1q_v8i16(int16x8_t a, int16x8_t b); +#define vuzp1q_s16(a, b) __builtin_mpl_vector_uzp1q_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_uzp1_v2i32(int32x2_t a, int32x2_t b); +#define vuzp1_s32(a, b) __builtin_mpl_vector_uzp1_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_uzp1q_v4i32(int32x4_t a, int32x4_t b); +#define vuzp1q_s32(a, b) __builtin_mpl_vector_uzp1q_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_uzp1q_v2i64(int64x2_t a, int64x2_t b); +#define vuzp1q_s64(a, b) __builtin_mpl_vector_uzp1q_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_uzp1_v8u8(uint8x8_t a, uint8x8_t b); +#define vuzp1_u8(a, b) __builtin_mpl_vector_uzp1_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_uzp1q_v16u8(uint8x16_t a, uint8x16_t b); +#define vuzp1q_u8(a, b) __builtin_mpl_vector_uzp1q_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_uzp1_v4u16(uint16x4_t a, uint16x4_t b); +#define vuzp1_u16(a, b) __builtin_mpl_vector_uzp1_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_uzp1q_v8u16(uint16x8_t a, uint16x8_t b); +#define vuzp1q_u16(a, b) __builtin_mpl_vector_uzp1q_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_uzp1_v2u32(uint32x2_t a, uint32x2_t b); +#define vuzp1_u32(a, b) __builtin_mpl_vector_uzp1_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_uzp1q_v4u32(uint32x4_t a, uint32x4_t b); +#define vuzp1q_u32(a, b) __builtin_mpl_vector_uzp1q_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_uzp1q_v2u64(uint64x2_t a, uint64x2_t b); +#define vuzp1q_u64(a, b) __builtin_mpl_vector_uzp1q_v2u64(a, b) + +int8x8_t __builtin_mpl_vector_uzp2_v8i8(int8x8_t a, int8x8_t b); +#define vuzp2_s8(a, b) __builtin_mpl_vector_uzp2_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_uzp2q_v16i8(int8x16_t a, int8x16_t b); +#define vuzp2q_s8(a, b) __builtin_mpl_vector_uzp2q_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_uzp2_v4i16(int16x4_t a, int16x4_t b); +#define vuzp2_s16(a, b) __builtin_mpl_vector_uzp2_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_uzp2q_v8i16(int16x8_t a, int16x8_t b); +#define vuzp2q_s16(a, b) __builtin_mpl_vector_uzp2q_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_uzp2_v2i32(int32x2_t a, int32x2_t b); +#define vuzp2_s32(a, b) __builtin_mpl_vector_uzp2_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_uzp2q_v4i32(int32x4_t a, int32x4_t b); +#define vuzp2q_s32(a, b) __builtin_mpl_vector_uzp2q_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_uzp2q_v2i64(int64x2_t a, int64x2_t b); +#define vuzp2q_s64(a, b) __builtin_mpl_vector_uzp2q_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_uzp2_v8u8(uint8x8_t a, uint8x8_t b); +#define vuzp2_u8(a, b) __builtin_mpl_vector_uzp2_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_uzp2q_v16u8(uint8x16_t a, uint8x16_t b); +#define vuzp2q_u8(a, b) __builtin_mpl_vector_uzp2q_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_uzp2_v4u16(uint16x4_t a, uint16x4_t b); +#define vuzp2_u16(a, b) __builtin_mpl_vector_uzp2_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_uzp2q_v8u16(uint16x8_t a, uint16x8_t b); +#define vuzp2q_u16(a, b) __builtin_mpl_vector_uzp2q_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_uzp2_v2u32(uint32x2_t a, uint32x2_t b); +#define vuzp2_u32(a, b) __builtin_mpl_vector_uzp2_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_uzp2q_v4u32(uint32x4_t a, uint32x4_t b); +#define vuzp2q_u32(a, b) __builtin_mpl_vector_uzp2q_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_uzp2q_v2u64(uint64x2_t a, uint64x2_t b); +#define vuzp2q_u64(a, b) __builtin_mpl_vector_uzp2q_v2u64(a, b) + +#define vuzp_s8(a, b) (int8x8x2_t){vuzp1_s8((a), (b)), vuzp2_s8((a), (b))} +#define vuzp_s16(a, b) (int16x4x2_t){vuzp1_s16((a), (b)), vuzp2_s16((a), (b))} +#define vuzp_s32(a, b) (int32x2x2_t){vuzp1_s32((a), (b)), vuzp2_s32((a), (b))} +#define vuzp_u8(a, b) (uint8x8x2_t){vuzp1_u8((a), (b)), vuzp2_u8((a), (b))} +#define vuzp_u16(a, b) (uint16x4x2_t){vuzp1_u16((a), (b)), vuzp2_u16((a), (b))} +#define vuzp_u32(a, b) (uint32x2x2_t){vuzp1_u32((a), (b)), vuzp2_u32((a), (b))} +#define vuzpq_s8(a, b) (int8x16x2_t){vuzp1q_s8((a), (b)), vuzp2q_s8((a), (b))} +#define vuzpq_s16(a, b) (int16x8x2_t){vuzp1q_s16((a), (b)), vuzp2q_s16((a), (b))} +#define vuzpq_s32(a, b) (int32x4x2_t){vuzp1q_s32((a), (b)), vuzp2q_s32((a), (b))} +#define vuzpq_u8(a, b) (uint8x16x2_t){vuzp1q_u8((a), (b)), vuzp2q_u8((a), (b))} +#define vuzpq_u16(a, b) (uint16x8x2_t){vuzp1q_u16((a), (b)), vuzp2q_u16((a), (b))} +#define vuzpq_u32(a, b) (uint32x4x2_t){vuzp1q_u32((a), (b)), vuzp2q_u32((a), (b))} + +int8x8_t __builtin_mpl_vector_trn1_v8i8(int8x8_t a, int8x8_t b); +#define vtrn1_s8(a, b) __builtin_mpl_vector_trn1_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_trn1q_v16i8(int8x16_t a, int8x16_t b); +#define vtrn1q_s8(a, b) __builtin_mpl_vector_trn1q_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_trn1_v4i16(int16x4_t a, int16x4_t b); +#define vtrn1_s16(a, b) __builtin_mpl_vector_trn1_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_trn1q_v8i16(int16x8_t a, int16x8_t b); +#define vtrn1q_s16(a, b) __builtin_mpl_vector_trn1q_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_trn1_v2i32(int32x2_t a, int32x2_t b); +#define vtrn1_s32(a, b) __builtin_mpl_vector_trn1_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_trn1q_v4i32(int32x4_t a, int32x4_t b); +#define vtrn1q_s32(a, b) __builtin_mpl_vector_trn1q_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_trn1q_v2i64(int64x2_t a, int64x2_t b); +#define vtrn1q_s64(a, b) __builtin_mpl_vector_trn1q_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_trn1_v8u8(uint8x8_t a, uint8x8_t b); +#define vtrn1_u8(a, b) __builtin_mpl_vector_trn1_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_trn1q_v16u8(uint8x16_t a, uint8x16_t b); +#define vtrn1q_u8(a, b) __builtin_mpl_vector_trn1q_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_trn1_v4u16(uint16x4_t a, uint16x4_t b); +#define vtrn1_u16(a, b) __builtin_mpl_vector_trn1_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_trn1q_v8u16(uint16x8_t a, uint16x8_t b); +#define vtrn1q_u16(a, b) __builtin_mpl_vector_trn1q_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_trn1_v2u32(uint32x2_t a, uint32x2_t b); +#define vtrn1_u32(a, b) __builtin_mpl_vector_trn1_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_trn1q_v4u32(uint32x4_t a, uint32x4_t b); +#define vtrn1q_u32(a, b) __builtin_mpl_vector_trn1q_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_trn1q_v2u64(uint64x2_t a, uint64x2_t b); +#define vtrn1q_u64(a, b) __builtin_mpl_vector_trn1q_v2u64(a, b) + +int8x8_t __builtin_mpl_vector_trn2_v8i8(int8x8_t a, int8x8_t b); +#define vtrn2_s8(a, b) __builtin_mpl_vector_trn2_v8i8(a, b) + +int8x16_t __builtin_mpl_vector_trn2q_v16i8(int8x16_t a, int8x16_t b); +#define vtrn2q_s8(a, b) __builtin_mpl_vector_trn2q_v16i8(a, b) + +int16x4_t __builtin_mpl_vector_trn2_v4i16(int16x4_t a, int16x4_t b); +#define vtrn2_s16(a, b) __builtin_mpl_vector_trn2_v4i16(a, b) + +int16x8_t __builtin_mpl_vector_trn2q_v8i16(int16x8_t a, int16x8_t b); +#define vtrn2q_s16(a, b) __builtin_mpl_vector_trn2q_v8i16(a, b) + +int32x2_t __builtin_mpl_vector_trn2_v2i32(int32x2_t a, int32x2_t b); +#define vtrn2_s32(a, b) __builtin_mpl_vector_trn2_v2i32(a, b) + +int32x4_t __builtin_mpl_vector_trn2q_v4i32(int32x4_t a, int32x4_t b); +#define vtrn2q_s32(a, b) __builtin_mpl_vector_trn2q_v4i32(a, b) + +int64x2_t __builtin_mpl_vector_trn2q_v2i64(int64x2_t a, int64x2_t b); +#define vtrn2q_s64(a, b) __builtin_mpl_vector_trn2q_v2i64(a, b) + +uint8x8_t __builtin_mpl_vector_trn2_v8u8(uint8x8_t a, uint8x8_t b); +#define vtrn2_u8(a, b) __builtin_mpl_vector_trn2_v8u8(a, b) + +uint8x16_t __builtin_mpl_vector_trn2q_v16u8(uint8x16_t a, uint8x16_t b); +#define vtrn2q_u8(a, b) __builtin_mpl_vector_trn2q_v16u8(a, b) + +uint16x4_t __builtin_mpl_vector_trn2_v4u16(uint16x4_t a, uint16x4_t b); +#define vtrn2_u16(a, b) __builtin_mpl_vector_trn2_v4u16(a, b) + +uint16x8_t __builtin_mpl_vector_trn2q_v8u16(uint16x8_t a, uint16x8_t b); +#define vtrn2q_u16(a, b) __builtin_mpl_vector_trn2q_v8u16(a, b) + +uint32x2_t __builtin_mpl_vector_trn2_v2u32(uint32x2_t a, uint32x2_t b); +#define vtrn2_u32(a, b) __builtin_mpl_vector_trn2_v2u32(a, b) + +uint32x4_t __builtin_mpl_vector_trn2q_v4u32(uint32x4_t a, uint32x4_t b); +#define vtrn2q_u32(a, b) __builtin_mpl_vector_trn2q_v4u32(a, b) + +uint64x2_t __builtin_mpl_vector_trn2q_v2u64(uint64x2_t a, uint64x2_t b); +#define vtrn2q_u64(a, b) __builtin_mpl_vector_trn2q_v2u64(a, b) + +#define vtrn_s8(a, b) (int8x8x2_t){vtrn1_s8((a), (b)), vtrn2_s8((a), (b))} +#define vtrn_s16(a, b) (int16x4x2_t){vtrn1_s16((a), (b)), vtrn2_s16((a), (b))} +#define vtrn_s32(a, b) (int32x2x2_t){vtrn1_s32((a), (b)), vtrn2_s32((a), (b))} +#define vtrn_u8(a, b) (uint8x8x2_t){vtrn1_u8((a), (b)), vtrn2_u8((a), (b))} +#define vtrn_u16(a, b) (uint16x4x2_t){vtrn1_u16((a), (b)), vtrn2_u16((a), (b))} +#define vtrn_u32(a, b) (uint32x2x2_t){vtrn1_u32((a), (b)), vtrn2_u32((a), (b))} +#define vtrnq_s8(a, b) (int8x16x2_t){vtrn1q_s8((a), (b)), vtrn2q_s8((a), (b))} +#define vtrnq_s16(a, b) (int16x8x2_t){vtrn1q_s16((a), (b)), vtrn2q_s16((a), (b))} +#define vtrnq_s32(a, b) (int32x4x2_t){vtrn1q_s32((a), (b)), vtrn2q_s32((a), (b))} +#define vtrnq_u8(a, b) (uint8x16x2_t){vtrn1q_u8((a), (b)), vtrn2q_u8((a), (b))} +#define vtrnq_u16(a, b) (uint16x8x2_t){vtrn1q_u16((a), (b)), vtrn2q_u16((a), (b))} +#define vtrnq_u32(a, b) (uint32x4x2_t){vtrn1q_u32((a), (b)), vtrn2q_u32((a), (b))} #endif /* __ARM_NEON_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..ff53c48d3aff5807cead0921124e87b30306f33f 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_expr.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_expr.cpp @@ -26,9 +26,107 @@ #include "enhance_c_checker.h" #include "ror.h" #include "conditional_operator.h" +#include "fe_macros.h" + +#include namespace maple { + +namespace { + const uint32 kOneByte = 8; + +template +std::optional GenerateConstCommon(Opcode op, const T p0, const 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) \ + do { \ + 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()); \ + } \ + } while (0) + + 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) { @@ -54,19 +152,19 @@ MIRConst *ASTValue::Translate2MIRConst() const { } case PTY_i8: { return GlobalTables::GetIntConstTable().GetOrCreateIntConst( - val.i8, *GlobalTables::GetTypeTable().GetPrimType(PTY_i8)); + static_cast(static_cast(val.i8)), *GlobalTables::GetTypeTable().GetPrimType(PTY_i8)); } case PTY_i16: { return GlobalTables::GetIntConstTable().GetOrCreateIntConst( - val.i16, *GlobalTables::GetTypeTable().GetPrimType(PTY_i16)); + static_cast(static_cast(val.i16)), *GlobalTables::GetTypeTable().GetPrimType(PTY_i16)); } case PTY_i32: { return GlobalTables::GetIntConstTable().GetOrCreateIntConst( - val.i32, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + static_cast(static_cast(val.i32)), *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); } case PTY_i64: { return GlobalTables::GetIntConstTable().GetOrCreateIntConst( - val.i64, *GlobalTables::GetTypeTable().GetPrimType(PTY_i64)); + static_cast(val.i64), *GlobalTables::GetTypeTable().GetPrimType(PTY_i64)); } case PTY_f32: { return FEManager::GetModule().GetMemPool()->New( @@ -89,43 +187,46 @@ 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; } -UniqueFEIRExpr ASTExpr::ImplicitInitFieldValue(MIRType *type, std::list &stmts) const { +UniqueFEIRExpr ASTExpr::ImplicitInitFieldValue(MIRType &type, std::list &stmts) const { UniqueFEIRExpr implicitInitFieldExpr; - MIRTypeKind noInitExprKind = type->GetKind(); + MIRTypeKind noInitExprKind = type.GetKind(); if (noInitExprKind == kTypeStruct || noInitExprKind == kTypeUnion) { - auto *structType = static_cast(type); + auto *structType = static_cast(&type); std::string tmpName = FEUtils::GetSequentialName("implicitInitStruct_"); - UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, *type); + UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, type); for (size_t i = 0; i < structType->GetFieldsSize(); ++i) { FieldID fieldID = 0; FEUtils::TraverseToNamedField(*structType, structType->GetElemStrIdx(i), fieldID); MIRType *fieldType = structType->GetFieldType(fieldID); - UniqueFEIRExpr fieldExpr = ImplicitInitFieldValue(fieldType, stmts); + UniqueFEIRExpr fieldExpr = ImplicitInitFieldValue(*fieldType, stmts); UniqueFEIRStmt fieldStmt = std::make_unique(tmpVar->Clone(), std::move(fieldExpr), fieldID); stmts.emplace_back(std::move(fieldStmt)); } implicitInitFieldExpr = FEIRBuilder::CreateExprDRead(std::move(tmpVar)); } else if (noInitExprKind == kTypeArray) { - auto *arrayType = static_cast(type); + auto *arrayType = static_cast(&type); size_t elemSize = arrayType->GetElemType()->GetSize(); CHECK_FATAL(elemSize != 0, "elemSize is 0"); size_t numElems = arrayType->GetSize() / elemSize; - UniqueFEIRType typeNative = FEIRTypeHelper::CreateTypeNative(*type); + UniqueFEIRType typeNative = FEIRTypeHelper::CreateTypeNative(type); std::string tmpName = FEUtils::GetSequentialName("implicitInitArray_"); - UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, *type); + UniqueFEIRVar tmpVar = FEIRBuilder::CreateVarNameForC(tmpName, type); UniqueFEIRExpr arrayExpr = FEIRBuilder::CreateExprDRead(tmpVar->Clone()); for (uint32 i = 0; i < numElems; ++i) { UniqueFEIRExpr exprIndex = FEIRBuilder::CreateExprConstI32(i); MIRType *fieldType = arrayType->GetElemType(); - UniqueFEIRExpr exprElem = ImplicitInitFieldValue(fieldType, stmts); + UniqueFEIRExpr exprElem = ImplicitInitFieldValue(*fieldType, stmts); UniqueFEIRType typeNativeTmp = typeNative->Clone(); UniqueFEIRExpr arrayExprTmp = arrayExpr->Clone(); auto stmt = FEIRBuilder::CreateStmtArrayStoreOneStmtForC(std::move(exprElem), std::move(arrayExprTmp), @@ -138,7 +239,7 @@ UniqueFEIRExpr ASTExpr::ImplicitInitFieldValue(MIRType *type, std::list(static_cast(0), PTY_ptr); } else { CHECK_FATAL(noInitExprKind == kTypeScalar, "noInitExprKind isn't kTypeScalar"); - implicitInitFieldExpr = FEIRBuilder::CreateExprConstAnyScalar(type->GetPrimType(), 0); + implicitInitFieldExpr = FEIRBuilder::CreateExprConstAnyScalar(type.GetPrimType(), 0); } return implicitInitFieldExpr; } @@ -148,6 +249,10 @@ MIRConst *ASTExpr::GenerateMIRConstImpl() const { return value->Translate2MIRConst(); } +ASTExpr *ASTExpr::IgnoreParensImpl() { + return this; +} + // ---------- ASTDeclRefExpr --------- MIRConst *ASTDeclRefExpr::GenerateMIRConstImpl() const { MIRType *mirType = refedDecl->GetTypeDesc().front(); @@ -187,7 +292,7 @@ UniqueFEIRExpr ASTDeclRefExpr::Emit2FEExprImpl(std::list &stmts) } else { if (refedDecl->GetDeclKind() == kASTEnumConstant) { return FEIRBuilder::CreateExprConstAnyScalar(refedDecl->GetTypeDesc().front()->GetPrimType(), - static_cast(refedDecl)->GetValue()); + static_cast(refedDecl)->GetValue().GetExtValue()); } UniqueFEIRVar feirVar = FEIRBuilder::CreateVarNameForC(refedDecl->GenerateUniqueVarName(), *mirType, refedDecl->IsGlobal(), false); @@ -198,6 +303,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; } @@ -209,8 +320,8 @@ std::string ASTCallExpr::CvtBuiltInFuncName(std::string builtInName) const { #include "ast_builtin_func.def" #undef BUILTIN_FUNC }; - auto it = cvtMap.find(builtInName); - if (it != cvtMap.end()) { + std::map::const_iterator it = cvtMap.find(builtInName); + if (it != cvtMap.cend()) { return cvtMap.find(builtInName)->second; } else { return builtInName; @@ -226,7 +337,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(), *mirType, false, false); UniqueFEIRExpr expr = FEIRBuilder::CreateExprAddrofVar(var->Clone()); callStmt->AddExprArgReverse(std::move(expr)); } @@ -245,12 +356,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(), *mirType, false, false); + var->SetAttrs(GetReturnVarAttrs()); UniqueFEIRVar dreadVar = var->Clone(); if (!IsFirstArgRet()) { callStmt->SetVar(var->Clone()); @@ -262,17 +373,24 @@ std::unique_ptr ASTCallExpr::GenCallStmt() const { MemPool *mp = FEManager::GetManager().GetStructElemMempool(); std::unique_ptr callStmt; if (isIcall) { - callStmt = std::make_unique(); + auto icallStmt = std::make_unique(); + CHECK_FATAL(calleeExpr->GetType()->IsMIRPtrType(), "cannot find func pointer for icall"); + MIRFuncType *funcType = static_cast(calleeExpr->GetType())->GetPointedFuncType(); + CHECK_FATAL(funcType != nullptr, "cannot find func prototype for icall"); + icallStmt->SetPrototype(FEIRTypeHelper::CreateTypeNative(*funcType)); + callStmt = std::move(icallStmt); } 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()) { retTypeInfo = mp->New(*GlobalTables::GetTypeTable().GetPrimType(PTY_void)); } else { - retTypeInfo = mp->New(*retType); + retTypeInfo = mp->New(*mirType); } info->SetReturnType(retTypeInfo); Opcode op; @@ -283,7 +401,6 @@ std::unique_ptr ASTCallExpr::GenCallStmt() const { } callStmt = std::make_unique(*info, op, nullptr, false); } - callStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); return callStmt; } @@ -313,12 +430,9 @@ MIRConst *ASTCastExpr::GenerateMIRConstImpl() const { if (isArrayToPointerDecay && feExpr->GetKind() == FEIRNodeKind::kExprAddrof) { return FEManager::GetModule().GetMemPool()->New( GetConstantValue()->val.strIdx, *GlobalTables::GetTypeTable().GetPrimType(PTY_a64)); - } else if (isArrayToPointerDecay && child->GetASTOp() == kASTOpRef) { - ASTDecl *astDecl = static_cast(child)->GetASTDecl(); - CHECK_FATAL(astDecl->GetDeclKind() == kASTVar, "Invalid"); - MIRSymbol *mirSymbol = static_cast(astDecl)->Translate2MIRSymbol(); - return FEManager::GetModule().GetMemPool()->New(mirSymbol->GetStIdx(), 0, - *(astDecl->GetTypeDesc().front())); + } else if (isArrayToPointerDecay && child->IgnoreParens()->GetASTOp() == kASTOpCompoundLiteralExpr) { + static_cast(child->IgnoreParens())->SetAddrof(true); + return child->GenerateMIRConst(); } else if (isNeededCvt) { if (dst->GetPrimType() == PTY_f64) { return GenerateMIRDoubleConst(); @@ -334,6 +448,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 +459,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 +476,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 +487,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 +499,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) { @@ -423,6 +546,7 @@ MIRConst *ASTCastExpr::GenerateMIRIntConst() const { static_cast(static_cast(childConst)->GetValue()), *GlobalTables::GetTypeTable().GetPrimType(PTY_a64)); } + case kConstAddrofFunc: case kConstAddrof: { return FEManager::GetModule().GetMemPool()->New( static_cast(static_cast(childConst)->GetOffset()), @@ -479,34 +603,45 @@ UniqueFEIRExpr ASTCastExpr::Emit2FEExprForComplex(const UniqueFEIRExpr &subExpr, return dreadAgg; } -UniqueFEIRExpr ASTCastExpr::Emit2FEExprImpl(std::list &stmts) const { +UniqueFEIRExpr ASTCastExpr::Emit2FEExprForFunctionOrArray2Pointer(std::list &stmts) const { const ASTExpr *childExpr = child; CHECK_FATAL(childExpr != nullptr, "childExpr is nullptr"); - if (isArrayToPointerDecay) { - auto childFEExpr = childExpr->Emit2FEExpr(stmts); - if (childFEExpr->GetKind() == kExprDRead) { - return std::make_unique( - static_cast(childFEExpr.get())->GetVar()->Clone(), childFEExpr->GetFieldID()); - } else if (childFEExpr->GetKind() == kExprIRead) { - auto iread = static_cast(childFEExpr.get()); - if (iread->GetFieldID() == 0) { - auto addrOfExpr = iread->GetClonedOpnd(); - ENCChecker::ReduceBoundaryChecking(stmts, addrOfExpr); - return addrOfExpr; - } else { - return std::make_unique(iread->GetClonedPtrType(), iread->GetFieldID(), - iread->GetClonedOpnd()); - } - } else if (childFEExpr->GetKind() == kExprIAddrof || childFEExpr->GetKind() == kExprAddrofVar || - childFEExpr->GetKind() == kExprAddrofFunc || childFEExpr->GetKind() == kExprAddrof) { - return childFEExpr; + auto childFEExpr = childExpr->Emit2FEExpr(stmts); + if (childFEExpr->GetKind() == kExprDRead) { + return std::make_unique( + static_cast(childFEExpr.get())->GetVar()->Clone(), childFEExpr->GetFieldID()); + } else if (childFEExpr->GetKind() == kExprIRead) { + auto iread = static_cast(childFEExpr.get()); + if (iread->GetFieldID() == 0) { + auto addrOfExpr = iread->GetClonedOpnd(); + ENCChecker::ReduceBoundaryChecking(stmts, addrOfExpr); + return addrOfExpr; } else { - CHECK_FATAL(false, "unsupported expr kind %d", childFEExpr->GetKind()); + return std::make_unique(iread->GetClonedPtrType(), iread->GetFieldID(), iread->GetClonedOpnd()); } + } else if (childFEExpr->GetKind() == kExprIAddrof || childFEExpr->GetKind() == kExprAddrofVar || + childFEExpr->GetKind() == kExprAddrofFunc || childFEExpr->GetKind() == kExprAddrof) { + return childFEExpr; + } else { + CHECK_FATAL(false, "unsupported expr kind %d", childFEExpr->GetKind()); + } +} + +UniqueFEIRExpr ASTCastExpr::Emit2FEExprImpl(std::list &stmts) const { + const ASTExpr *childExpr = child; + CHECK_FATAL(childExpr != nullptr, "childExpr is nullptr"); + if (isArrayToPointerDecay || isFunctionToPointerDecay) { + return Emit2FEExprForFunctionOrArray2Pointer(stmts); } + EmitVLASizeExprs(stmts); 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()); + (void)stmts.emplace_back(std::move(unionStmt)); + return FEIRBuilder::CreateExprDRead(std::move(unionVar)); } if (isBitCast) { if (src->GetPrimType() == dst->GetPrimType() && src->IsScalarType()) { @@ -515,8 +650,12 @@ UniqueFEIRExpr ASTCastExpr::Emit2FEExprImpl(std::list &stmts) co } UniqueFEIRType dstType = std::make_unique(*dst); if (dst->GetKind() == kTypePointer) { - CheckNonnullFieldInStruct(); - return subExpr; + MIRType *funcType = static_cast(dst)->GetPointedFuncType(); + if (funcType != nullptr) { + return std::make_unique(std::move(dstType), OP_retype, std::move(subExpr)); + } else { + return subExpr; + } } else { return std::make_unique(std::move(dstType), OP_retype, std::move(subExpr)); } @@ -645,15 +784,35 @@ UniqueFEIRExpr ASTUnaryOperatorExpr::ASTUOSideEffectExpr(Opcode op, std::listClone(), childFEIRExpr->Clone()); - readSelfstmt->SetDummy(); + if (!IsRValue()) { + readSelfstmt->SetDummy(); + } stmts.emplace_back(std::move(readSelfstmt)); } PrimType subPrimType = subType->GetPrimType(); + UniqueFEIRType sizeType = (subPrimType == PTY_ptr) ? std::make_unique(*GlobalTables::GetTypeTable(). + GetPrimType(PTY_i64)) : std::make_unique(*GlobalTables::GetTypeTable().GetPrimType(PTY_ptr)); UniqueFEIRExpr subExpr = (subPrimType == PTY_ptr) ? std::make_unique(pointeeLen, PTY_i32) : FEIRBuilder::CreateExprConstAnyScalar(subPrimType, 1); - UniqueFEIRExpr sideEffectExpr = FEIRBuilder::CreateExprMathBinary(op, childFEIRExpr->Clone(), std::move(subExpr)); + UniqueFEIRExpr sideEffectExpr = FEIRBuilder::CreateExprMathBinary(op, childFEIRExpr->Clone(), subExpr->Clone()); UniqueFEIRStmt sideEffectStmt = FEIRBuilder::AssginStmtField(childFEIRExpr->Clone(), std::move(sideEffectExpr), 0); + if (isVariableArrayType) { + subExpr = variableArrayExpr->Emit2FEExpr(stmts); + UniqueFEIRExpr opndExpr = FEIRBuilder::CreateExprConstAnyScalar(PTY_i64, 1); + UniqueFEIRExpr feIdxExpr = FEIRBuilder::CreateExprBinary(sizeType->Clone(), OP_mul, std::move(opndExpr), + std::move(subExpr)); + sideEffectExpr = FEIRBuilder::CreateExprMathBinary(op, childFEIRExpr->Clone(), std::move(feIdxExpr)); + sideEffectStmt = FEIRBuilder::AssginStmtField(childFEIRExpr->Clone(), std::move(sideEffectExpr), 0); + } else { + /* deal this case: bool u, u++/++u, u value always is 1; if u--/--u, u value always is ~u */ + if (uoType == GlobalTables::GetTypeTable().GetPrimType(PTY_u1) && op == OP_add) { + sideEffectStmt = FEIRBuilder::AssginStmtField(childFEIRExpr->Clone(), std::move(subExpr), 0); + } else if (uoType == GlobalTables::GetTypeTable().GetPrimType(PTY_u1) && op == OP_sub) { + UniqueFEIRExpr notExpr = std::make_unique(OP_lnot, childFEIRExpr->Clone()); + sideEffectStmt = FEIRBuilder::AssginStmtField(childFEIRExpr->Clone(), std::move(notExpr), 0); + } + } stmts.emplace_back(std::move(sideEffectStmt)); if (post) { @@ -680,22 +839,14 @@ 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 kASTOpRef: + case kASTOpCompoundLiteralExpr: { + static_cast(expr)->SetAddrof(true); + return expr->GenerateMIRConst(); + } + case kASTOpRef: { + expr->SetIsConstantFolded(false); + return expr->GenerateMIRConst(); + } case kASTSubscriptExpr: case kASTMemberExpr: { return expr->GenerateMIRConst(); @@ -731,6 +882,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)); + (void)stmts.emplace_back(std::move(tmpStmt)); + return FEIRBuilder::CreateExprAddrofVar(std::move(tmpVar)); } else { CHECK_FATAL(false, "unsupported expr kind %d", childFEIRExpr->GetKind()); } @@ -740,32 +897,30 @@ 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 { + std::list subStmts; // To delete redundant bounds checks in one ASTUODerefExpr stmts. ASTExpr *childExpr = expr; CHECK_FATAL(childExpr != nullptr, "childExpr is nullptr"); - UniqueFEIRExpr childFEIRExpr = childExpr->Emit2FEExpr(stmts); + UniqueFEIRExpr childFEIRExpr = childExpr->Emit2FEExpr(subStmts); UniqueFEIRType retType = std::make_unique(*uoType); UniqueFEIRType ptrType = std::make_unique(*subType); - if (uoType->GetKind() == kTypePointer && - static_cast(uoType)->GetPointedType()->GetKind() == kTypeFunction) { - return childFEIRExpr; - } - InsertNonnullChecking(stmts, childFEIRExpr->Clone()); - if (InsertBoundaryChecking(stmts, childFEIRExpr->Clone())) { + InsertNonnullChecking(subStmts, childFEIRExpr->Clone()); + if (InsertBoundaryChecking(subStmts, childFEIRExpr->Clone())) { childFEIRExpr->SetIsBoundaryChecking(true); } UniqueFEIRExpr derefExpr = FEIRBuilder::CreateExprIRead(std::move(retType), std::move(ptrType), std::move(childFEIRExpr)); + stmts.splice(stmts.end(), subStmts); return derefExpr; } @@ -775,7 +930,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)); } } @@ -804,14 +958,14 @@ UniqueFEIRExpr ASTUORealExpr::Emit2FEExprImpl(std::list &stmts) } UniqueFEIRExpr ASTUOImagExpr::Emit2FEExprImpl(std::list &stmts) const { - ASTExpr *childExpr = expr; - ASTOp astOP = childExpr->GetASTOp(); + ASTExpr *childrenExpr = expr; + ASTOp astOP = childrenExpr->GetASTOp(); UniqueFEIRExpr subFEIRExpr; - if (astOP == kASTStringLiteral || astOP == kASTIntegerLiteral || astOP == kASTFloatingLiteral || - astOP == kASTCharacterLiteral || astOP == kASTImaginaryLiteral) { - subFEIRExpr = childExpr->Emit2FEExpr(stmts); + if (astOP == kASTStringLiteral || astOP == kASTCharacterLiteral || astOP == kASTImaginaryLiteral || + astOP == kASTIntegerLiteral || astOP == kASTFloatingLiteral) { + subFEIRExpr = childrenExpr->Emit2FEExpr(stmts); } else { - subFEIRExpr = childExpr->Emit2FEExpr(stmts); + subFEIRExpr = childrenExpr->Emit2FEExpr(stmts); FEIRNodeKind subNodeKind = subFEIRExpr->GetKind(); if (subNodeKind == kExprIRead) { static_cast(subFEIRExpr.get())->SetFieldID(kComplexImagID); @@ -895,9 +1049,11 @@ UniqueFEIRExpr ASTBinaryConditionalOperator::Emit2FEExprImpl(std::listClone(); UniqueFEIRVar tempVarCloned2 = tempVar->Clone(); UniqueFEIRStmt retTrueStmt = FEIRBuilder::CreateStmtDAssign(std::move(tempVar), std::move(trueFEIRExpr)); + retTrueStmt->SetSrcLoc(condExpr->GetSrcLoc()); std::list trueStmts; trueStmts.emplace_back(std::move(retTrueStmt)); UniqueFEIRStmt retFalseStmt = FEIRBuilder::CreateStmtDAssign(std::move(tempVarCloned1), std::move(falseFEIRExpr)); + retFalseStmt->SetSrcLoc(falseExpr->GetSrcLoc()); falseStmts.emplace_back(std::move(retFalseStmt)); UniqueFEIRStmt stmtIf = FEIRBuilder::CreateStmtIf(std::move(condFEIRExpr), trueStmts, falseStmts); stmts.emplace_back(std::move(stmtIf)); @@ -913,8 +1069,13 @@ void ASTBinaryConditionalOperator::SetFalseExpr(ASTExpr *expr) { } // ---------- ASTNoInitExpr ---------- +MIRConst *ASTNoInitExpr::GenerateMIRConstImpl() const { + MIRIntConst *intConst = FEManager::GetModule().GetMemPool()->New(*noInitType); + return intConst; +} + UniqueFEIRExpr ASTNoInitExpr::Emit2FEExprImpl(std::list &stmts) const { - return ImplicitInitFieldValue(noInitType, stmts); + return ImplicitInitFieldValue(*noInitType, stmts); } void ASTNoInitExpr::SetNoInitType(MIRType *type) { @@ -924,11 +1085,20 @@ 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 (variableArrayExpr != nullptr) { + (void)variableArrayExpr->Emit2FEExpr(stmts); + } + 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)); + (void)stmts.emplace_back(std::move(tmpStmt)); + } feirExpr = FEIRBuilder::CreateExprDRead(std::move(tmpVar)); } else { feirExpr = child->Emit2FEExpr(stmts); @@ -936,7 +1106,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 +1154,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) { @@ -976,22 +1171,24 @@ MIRConst *ASTInitListExpr::GenerateMIRConstImpl() const { } MIRConst *ASTInitListExpr::GenerateMIRConstForArray() const { - if (initExprs.size() == 1 && initExprs[0]->GetASTOp() == kASTStringLiteral) { + CHECK_FATAL(initListType->GetKind() == kTypeArray, "Must be array type"); + auto arrayMirType = static_cast(initListType); + if (arrayMirType->GetDim() == 1 && initExprs.size() == 1 && initExprs[0]->GetASTOp() == kASTStringLiteral) { return initExprs[0]->GenerateMIRConst(); } MIRAggConst *aggConst = FEManager::GetModule().GetMemPool()->New(FEManager::GetModule(), *initListType); - CHECK_FATAL(initListType->GetKind() == kTypeArray, "Must be array type"); - auto arrayMirType = static_cast(initListType); 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); } if (HasArrayFiller()) { + if (arrayFillerExpr->GetASTOp() == kASTOpNoInitExpr) { + return aggConst; + } auto fillerConst = arrayFillerExpr->GenerateMIRConst(); for (uint32 i = initExprs.size(); i < arrayMirType->GetSizeArrayItem(0); ++i) { aggConst->AddItem(fillerConst, 0); @@ -1016,36 +1213,44 @@ 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); + EmitVLASizeExprs(stmts); if (initListType->GetKind() == MIRTypeKind::kTypeArray) { UniqueFEIRExpr arrayExpr = FEIRBuilder::CreateExprAddrofVar(feirVar->Clone()); auto base = std::variant, UniqueFEIRExpr>(arrayExpr->Clone()); - ProcessInitList(base, const_cast(this), stmts); + ProcessInitList(base, *this, stmts); } else if (initListType->IsStructType()) { auto base = std::variant, UniqueFEIRExpr>(std::make_pair(feirVar->Clone(), 0)); - ProcessInitList(base, const_cast(this), stmts); + ProcessInitList(base, *this, stmts); } else if (isTransparent) { CHECK_FATAL(initExprs.size() == 1, "Transparent init list size must be 1"); return initExprs[0]->Emit2FEExpr(stmts); } else if (hasVectorType) { auto base = std::variant, UniqueFEIRExpr>(std::make_pair(feirVar->Clone(), 0)); - ProcessInitList(base, const_cast(this), stmts); + ProcessInitList(base, *this, stmts); } else { CHECK_FATAL(true, "Unsupported init list type"); } @@ -1053,9 +1258,9 @@ 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 (initList.initListType->GetKind() == kTypeArray) { if (std::holds_alternative(base)) { ProcessArrayInitList(std::get(base)->Clone(), initList, stmts); } else { @@ -1064,12 +1269,12 @@ void ASTInitListExpr::ProcessInitList(std::variantSetFieldID(std::get>(base).second); ProcessArrayInitList(addrExpr->Clone(), initList, stmts); } - } else if (initList->initListType->GetKind() == kTypeStruct || initList->initListType->GetKind() == kTypeUnion) { + } else if (initList.initListType->GetKind() == kTypeStruct || initList.initListType->GetKind() == kTypeUnion) { ProcessStructInitList(base, initList, stmts); - } else if (initList->isTransparent) { - CHECK_FATAL(initList->initExprs.size() == 1, "Transparent init list size must be 1"); - auto feExpr = initList->initExprs[0]->Emit2FEExpr(stmts); - MIRType *retType = initList->initListType; + } else if (initList.isTransparent) { + CHECK_FATAL(initList.initExprs.size() == 1, "Transparent init list size must be 1"); + auto feExpr = initList.initExprs[0]->Emit2FEExpr(stmts); + MIRType *retType = initList.initListType; MIRType *retPtrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*retType); UniqueFEIRType fePtrType = std::make_unique(*retPtrType); if (std::holds_alternative(base)) { @@ -1082,7 +1287,7 @@ void ASTInitListExpr::ProcessInitList(std::variantClone(), feExpr->Clone(), fieldID); stmts.emplace_back(std::move(stmt)); } - } else if (initList->HasVectorType()) { + } else if (initList.HasVectorType()) { ProcessVectorInitList(base, initList, stmts); } } @@ -1097,6 +1302,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 +1313,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 elemSize = arrayType->GetElemType()->GetSize(); - ProcessImplicitInit(addrOfCharArray->Clone(), stringLength, dimSize, elemSize, stmts); + uint32 dimSize = arrayType->GetSizeArrayItem(static_cast(arrayType->GetDim() - 1)); + uint32 elemSize = static_cast(arrayType->GetElemType()->GetSize()); + 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, const Loc loc) const { if (initSize >= total) { return; } @@ -1142,18 +1349,44 @@ 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)); } void ASTInitListExpr::ProcessDesignatedInitUpdater( - std::variant, UniqueFEIRExpr> &base, + std::variant, UniqueFEIRExpr> &base, const UniqueFEIRExpr &addrOfCharArray, ASTExpr *expr, std::list &stmts) const { auto designatedInitUpdateExpr = static_cast(expr); - ASTExpr *baseExpr = designatedInitUpdateExpr->GetBaseExpr(); + const ASTExpr *baseExpr = designatedInitUpdateExpr->GetBaseExpr(); ASTExpr *updaterExpr = designatedInitUpdateExpr->GetUpdaterExpr(); auto feExpr = baseExpr->Emit2FEExpr(stmts); + size_t stringLength = static_cast(baseExpr)->GetLength(); + CHECK_FATAL(stringLength <= INT_MAX, "Too large length range"); + if (std::holds_alternative(base)) { + std::unique_ptr> argExprList = std::make_unique>(); + argExprList->emplace_back(addrOfCharArray->Clone()); + argExprList->emplace_back(feExpr->Clone()); + 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(feExpr->GetLoc()); + stmts.emplace_back(std::move(memcpyStmt)); + } + static_cast(updaterExpr)->SetElemLen(stringLength); + ProcessInitList(base, *(static_cast(updaterExpr)), stmts); +} + +void ASTInitListExpr::ProcessNoBaseDesignatedInitUpdater( + std::variant, UniqueFEIRExpr> &base, + ASTExpr *expr, std::list &stmts) const { + auto designatedInitUpdateExpr = static_cast(expr); + 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,21 +1398,189 @@ 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, + FieldID 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, + FieldID baseFieldID, + MIRStructType &structMirType) const { + FieldID curFieldID = 0; + (void)FEUtils::TraverseToNamedField(structMirType, structMirType.GetElemStrIdx(fieldIndex), curFieldID); + FieldID fieldID = baseFieldID + curFieldID; + MIRType *fieldMirType = structMirType.GetFieldType(curFieldID); + uint32 fieldTypeSize = static_cast(fieldMirType->GetSize()); + return std::make_tuple(fieldID, fieldTypeSize, fieldMirType); +} + +void ASTInitListExpr::SolveInitListFullOfZero(const MIRStructType &baseStructType, FieldID baseFieldID, + const UniqueFEIRVar &var, const ASTInitListExpr &initList, + std::list &stmts) const { + MIRStructType *currStructType = static_cast(initList.initListType); + if (baseStructType.GetKind() == kTypeStruct) { + std::tuple fieldInfo = GetStructFieldInfo(0, baseFieldID, *currStructType); + FieldID 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, static_cast(currStructType->GetSize()), 1, stmts, + initList.GetSrcLoc()); + } else { // kTypeUnion + UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), 0); + ProcessImplicitInit(addrOfExpr->Clone(), 0, static_cast(currStructType->GetSize()), 1, stmts, + initList.GetSrcLoc()); + } +} + +bool ASTInitListExpr::SolveInitListPartialOfZero(std::variant, UniqueFEIRExpr> &base, + FieldID fieldID, uint32 &index, const ASTInitListExpr &initList, std::list &stmts) const { + UniqueFEIRVar var; + MIRStructType *baseStructMirType = nullptr; + if (std::holds_alternative(base)) { + var = std::get(base)->GetVarUses().front()->Clone(); + baseStructMirType = static_cast(initList.initListType); + } else { + var = std::get>(base).first->Clone(); + baseStructMirType = static_cast(var->GetType()->GenerateMIRTypeAuto()); + } + FieldID baseFieldID = 0; + if (!std::holds_alternative(base)) { + baseFieldID = std::get>(base).second; + } + MIRStructType *curStructMirType = static_cast(initList.initListType); + uint32 fieldsCount = 0; + int64 initBitSize = baseStructMirType->GetBitOffsetFromBaseAddr(fieldID); // in bit + uint32 fieldSizeOfLastZero = 0; // in byte + FieldID fieldIdOfLastZero = fieldID; + uint32 start = index; + while (index < initList.initExprs.size() && initList.initExprs[index] != nullptr && + initList.initExprs[index]->GetEvaluatedFlag() == kEvaluatedAsZero) { + std::tuple fieldInfo = GetStructFieldInfo(index, baseFieldID, *curStructMirType); + uint32 curFieldTypeSize = std::get<1>(fieldInfo); + MIRType *fieldMirType = std::get<2>(fieldInfo); + if (fieldMirType->GetKind() == kTypeBitField) { + break; + } + fieldSizeOfLastZero = curFieldTypeSize; + fieldIdOfLastZero = std::get<0>(fieldInfo); + ++fieldsCount; + ++index; + } + // consider struct alignment + int64 fieldsBitSize = + (baseStructMirType->GetBitOffsetFromBaseAddr(fieldIdOfLastZero) + fieldSizeOfLastZero * kOneByte) - initBitSize; + if (fieldsCount >= 2 && fieldsBitSize % kOneByte == 0 && (fieldsBitSize / kOneByte) % 4 == 0) { + auto addrOfExpr = CalculateStartAddressForMemset(var, static_cast(initBitSize / 8), fieldID, base); + ProcessImplicitInit(addrOfExpr->Clone(), 0, static_cast(fieldsBitSize / kOneByte), 1, stmts, + initList.initExprs[start]->GetSrcLoc()); + --index; + return true; + } else { + index -= fieldsCount; + return false; + } +} + +void ASTInitListExpr::SolveInitListExprOrDesignatedInitUpdateExpr(std::tuple fieldInfo, + ASTExpr &initExpr, const UniqueFEIRType &baseStructPtrType, std::variant, + UniqueFEIRExpr> &base, std::list &stmts) const { + std::variant, UniqueFEIRExpr> subBase; + FieldID fieldID = std::get<0>(fieldInfo); + MIRType *fieldMirType = std::get<2>(fieldInfo); + if (std::holds_alternative(base)) { + auto addrOfElemExpr = std::make_unique(baseStructPtrType->Clone(), fieldID, + std::get(base)->Clone()); + subBase = std::variant, UniqueFEIRExpr>(addrOfElemExpr->Clone()); + } else { + auto subVar = std::get>(base).first->Clone(); + subBase = std::variant, UniqueFEIRExpr>( + std::make_pair(subVar->Clone(), static_cast(fieldID))); + } + if (initExpr.GetASTOp() == kASTOpInitListExpr) { + ProcessInitList(subBase, *(static_cast(&initExpr)), stmts); + } else { + if (base.index() == 0) { + ProcessNoBaseDesignatedInitUpdater(subBase, static_cast(&initExpr), stmts); + } else { + auto addrOfElement = std::make_unique(baseStructPtrType->Clone(), fieldID, + std::get(base)->Clone()); + auto addrOfArrayExpr = GetAddrofArrayFEExprByStructArrayField(*fieldMirType, addrOfElement->Clone()); + ProcessDesignatedInitUpdater(subBase, addrOfArrayExpr->Clone(), &initExpr, stmts); + } + } +} + +void ASTInitListExpr::SolveStructFieldOfArrayTypeInitWithStringLiteral(std::tuple fieldInfo, + const ASTExpr &initExpr, const UniqueFEIRType &baseStructPtrType, + std::variant, UniqueFEIRExpr> &base, std::list &stmts) const { + auto elemExpr = initExpr.Emit2FEExpr(stmts); + if (elemExpr == nullptr) { + return; + } + FieldID fieldID = std::get<0>(fieldInfo); + MIRType *fieldMirType = std::get<2>(fieldInfo); + if (std::holds_alternative(base)) { + auto addrOfElement = std::make_unique(baseStructPtrType->Clone(), fieldID, + std::get(base)->Clone()); + auto addrOfArrayExpr = GetAddrofArrayFEExprByStructArrayField(*fieldMirType, addrOfElement->Clone()); + ProcessStringLiteralInitList(addrOfArrayExpr->Clone(), elemExpr->Clone(), + static_cast(&initExpr)->GetLength(), stmts); + } else { + auto subVar = std::get>(base).first->Clone(); + auto addrOfElement = std::make_unique(subVar->Clone()); + addrOfElement->SetFieldID(fieldID); + auto addrOfArrayExpr = GetAddrofArrayFEExprByStructArrayField(*fieldMirType, addrOfElement->Clone()); + ProcessStringLiteralInitList(addrOfArrayExpr->Clone(), elemExpr->Clone(), + static_cast(&initExpr)->GetLength(), stmts); + } +} + +void ASTInitListExpr::SolveStructFieldOfBasicType(FieldID fieldID, const ASTExpr &initExpr, + const UniqueFEIRType &baseStructPtrType, + std::variant, UniqueFEIRExpr> &base, + std::list &stmts) const { + auto elemExpr = initExpr.Emit2FEExpr(stmts); + if (elemExpr == nullptr) { + return; + } + if (std::holds_alternative(base)) { + auto stmt = std::make_unique(baseStructPtrType->Clone(), std::get(base)->Clone(), + elemExpr->Clone(), fieldID); + stmt->SetSrcLoc(initExpr.GetSrcLoc()); + (void)stmts.emplace_back(std::move(stmt)); + } else { + auto subVar = std::get>(base).first->Clone(); + auto stmt = std::make_unique(subVar->Clone(), elemExpr->Clone(), fieldID); + stmt->SetSrcLoc(initExpr.GetSrcLoc()); + (void)stmts.emplace_back(std::move(stmt)); + } } void ASTInitListExpr::ProcessStructInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, + const ASTInitListExpr &initList, std::list &stmts) const { MIRType *baseStructMirPtrType = nullptr; MIRStructType *baseStructMirType = nullptr; UniqueFEIRType baseStructFEType = nullptr; UniqueFEIRType baseStructFEPtrType = nullptr; - MIRStructType *curStructMirType = static_cast(initList->initListType); + MIRStructType *curStructMirType = static_cast(initList.initListType); UniqueFEIRVar var; if (std::holds_alternative(base)) { var = std::get(base)->GetVarUses().front()->Clone(); - baseStructMirType = static_cast(initList->initListType); + baseStructMirType = static_cast(initList.initListType); baseStructMirPtrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*baseStructMirType); baseStructFEType = FEIRTypeHelper::CreateTypeNative(*baseStructMirType); baseStructFEPtrType = std::make_unique(*baseStructMirPtrType); @@ -1196,100 +1597,120 @@ void ASTInitListExpr::ProcessStructInitList(std::variant>(base).second; } - if (initList->initExprs.size() == 0) { + if (initList.initExprs.size() == 0) { UniqueFEIRExpr addrOfExpr = std::make_unique(var->Clone(), 0); - ProcessImplicitInit(addrOfExpr->Clone(), 0, curStructMirType->GetSize(), 1, stmts); + ProcessImplicitInit(addrOfExpr->Clone(), 0, static_cast(curStructMirType->GetSize()), 1, stmts, + initList.GetSrcLoc()); + return; + } + + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && initList.GetEvaluatedFlag() == kEvaluatedAsZero) { + SolveInitListFullOfZero(*baseStructMirType, baseFieldID, var, initList, stmts); return; } uint32 curFieldTypeSize = 0; uint32 offset = 0; - for (size_t i = 0; i < initList->initExprs.size(); ++i) { - if (initList->initExprs[i] == nullptr) { + for (uint32 i = 0; i < initList.initExprs.size(); ++i) { + if (initList.initExprs[i] == nullptr) { continue; // skip anonymous field } - FieldID curFieldID = 0; - uint32 fieldIdx = (curStructMirType->GetKind() == 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()); + uint32 fieldIdx = (curStructMirType->GetKind() == kTypeUnion) ? initList.GetUnionInitFieldIdx() : i; + std::tuple fieldInfo = GetStructFieldInfo(fieldIdx, baseFieldID, *curStructMirType); + FieldID fieldID = std::get<0>(fieldInfo); + curFieldTypeSize = std::get<1>(fieldInfo); + MIRType *fieldMirType = std::get<2>(fieldInfo); offset += curFieldTypeSize; + // 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) / kOneByte) % 4 == 0) { + if (SolveInitListPartialOfZero(base, fieldID, i, initList, stmts)) { + continue; + } + } - 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)); - } else { - addrOfExpr = std::make_unique(var->Clone(), fieldID); - } - 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, static_cast(fieldMirType->GetSize()), 1, stmts, + initList.initExprs[i]->GetSrcLoc()); continue; } - if (initList->initExprs[i]->GetASTOp() == kASTOpInitListExpr || - initList->initExprs[i]->GetASTOp() == kASTASTDesignatedInitUpdateExpr) { - std::variant, UniqueFEIRExpr> subBase; - if (std::holds_alternative(base)) { - auto addrOfElemExpr = std::make_unique(baseStructFEPtrType->Clone(), fieldID, - std::get(base)->Clone()); - subBase = std::variant, UniqueFEIRExpr>(addrOfElemExpr->Clone()); - } else { - auto subVar = std::get>(base).first->Clone(); - subBase = std::variant, UniqueFEIRExpr>( - std::make_pair(subVar->Clone(), fieldID)); - } - if (initList->initExprs[i]->GetASTOp() == kASTOpInitListExpr) { - ProcessInitList(subBase, static_cast(initList->initExprs[i]), stmts); - } else { - ProcessDesignatedInitUpdater(subBase, static_cast(initList->initExprs[i]), stmts); - } + if (initList.initExprs[i]->GetASTOp() == kASTOpInitListExpr || + initList.initExprs[i]->GetASTOp() == kASTASTDesignatedInitUpdateExpr) { + SolveInitListExprOrDesignatedInitUpdateExpr(fieldInfo, *(initList.initExprs[i]), baseStructFEPtrType, base, stmts); + } else if (fieldMirType->GetKind() == kTypeArray && initList.initExprs[i]->GetASTOp() == kASTStringLiteral) { + SolveStructFieldOfArrayTypeInitWithStringLiteral(fieldInfo, *(initList.initExprs[i]), + baseStructFEPtrType, base, stmts); } else { - auto elemExpr = initList->initExprs[i]->Emit2FEExpr(stmts); - 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(), - 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()); - stmts.emplace_back(std::move(stmt)); - } - } else { - auto subVar = std::get>(base).first->Clone(); - if (fieldMirType->GetKind() == kTypeArray && initList->initExprs[i]->GetASTOp() == kASTStringLiteral) { - auto addrOfElement = std::make_unique(subVar->Clone()); - addrOfElement->SetFieldID(static_cast(fieldID)); - ProcessStringLiteralInitList(addrOfElement->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()); - stmts.emplace_back(std::move(stmt)); - } - } + SolveStructFieldOfBasicType(fieldID, *(initList.initExprs[i]), baseStructFEPtrType, base, stmts); } } // Handling Incomplete Union Initialization if (curStructMirType->GetKind() == 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()); + } +} + +UniqueFEIRExpr ASTInitListExpr::GetAddrofArrayFEExprByStructArrayField(MIRType &fieldType, + const 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::SolveArrayElementInitWithInitListExpr(const UniqueFEIRExpr &addrOfArray, + const UniqueFEIRExpr &addrOfElementExpr, + const MIRType &elementType, const ASTExpr &subExpr, + size_t index, std::list &stmts) const { + auto base = std::variant, UniqueFEIRExpr>(addrOfElementExpr->Clone()); + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && subExpr.GetEvaluatedFlag() == kEvaluatedAsZero) { + UniqueFEIRExpr realAddr = addrOfArray->Clone(); + if (index > 0) { + UniqueFEIRExpr idxExpr = FEIRBuilder::CreateExprConstI32(static_cast(index)); + 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, static_cast(elementType.GetSize()), 1, stmts, + subExpr.GetSrcLoc()); + } else { + ProcessInitList(base, *(static_cast(&subExpr)), stmts); + } +} + +void ASTInitListExpr::HandleImplicitInitSections(const UniqueFEIRExpr &addrOfArray, const ASTInitListExpr &initList, + const MIRType &elementType, std::list &stmts) const { + auto arrayMirType = static_cast(initList.initListType); + auto allSize = arrayMirType->GetSize(); + auto elemSize = elementType.GetSize(); + if (initList.GetElemLen() != 0) { + elemSize = initList.GetElemLen(); } + CHECK_FATAL(elemSize != 0, "elemSize should not 0"); + auto allElemCnt = allSize / elemSize; + ProcessImplicitInit(addrOfArray->Clone(), static_cast(initList.initExprs.size()), allElemCnt, elemSize, stmts, + initList.GetSrcLoc()); } -void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, ASTInitListExpr *initList, +void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, const ASTInitListExpr &initList, std::list &stmts) const { - auto arrayMirType = static_cast(initList->initListType); + auto arrayMirType = static_cast(initList.initListType); UniqueFEIRType arrayFEType = FEIRTypeHelper::CreateTypeNative(*arrayMirType); MIRType *elementType; if (arrayMirType->GetDim() > 1) { @@ -1303,42 +1724,51 @@ void ASTInitListExpr::ProcessArrayInitList(const UniqueFEIRExpr &addrOfArray, AS elementType = arrayMirType->GetElemType(); } auto elementPtrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*elementType); - auto elementPtrFEType = FEIRTypeHelper::CreateTypeNative(*elementPtrType); CHECK_FATAL(initExprs.size() <= INT_MAX, "invalid index"); - for (size_t i = 0; i < initList->initExprs.size(); ++i) { + if (!FEOptions::GetInstance().IsNpeCheckDynamic() && initList.GetEvaluatedFlag() == kEvaluatedAsZero) { + ProcessImplicitInit(addrOfArray->Clone(), 0, static_cast(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) { - auto base = std::variant, UniqueFEIRExpr>(addrOfElemExpr->Clone()); - ProcessInitList(base, static_cast(initList->initExprs[i]), stmts); - } else { - UniqueFEIRExpr elemExpr = initList->initExprs[i]->Emit2FEExpr(stmts); - if (elementType->GetKind() == kTypeArray && initList->initExprs[i]->GetASTOp() == kASTStringLiteral) { - ProcessStringLiteralInitList(addrOfElemExpr->Clone(), elemExpr->Clone(), - static_cast(initList->initExprs[i])->GetLength(), stmts); - } else { - auto stmt = FEIRBuilder::CreateStmtIAssign(elementPtrFEType->Clone(), addrOfElemExpr->Clone(), - elemExpr->Clone(), - 0); - stmts.emplace_back(std::move(stmt)); + const ASTExpr *subExpr = initList.initExprs[i]; + while (subExpr->GetASTOp() == kConstantExpr) { + subExpr = static_cast(subExpr)->GetChild(); + } + if (subExpr->GetASTOp() == kASTOpInitListExpr) { + SolveArrayElementInitWithInitListExpr(addrOfArray, addrOfElemExpr, *elementType, *subExpr, i, stmts); + continue; + } + if (subExpr->GetASTOp() == kASTOpNoInitExpr) { + continue; + } + UniqueFEIRExpr elemExpr = subExpr->Emit2FEExpr(stmts); + if ((elementType->GetKind() == kTypeArray || arrayMirType->GetDim() == 1) && + subExpr->GetASTOp() == kASTStringLiteral) { + ProcessStringLiteralInitList(addrOfElemExpr->Clone(), elemExpr->Clone(), + static_cast(subExpr)->GetLength(), stmts); + if (arrayMirType->GetDim() == 1) { + return; } + continue; } + auto stmt = FEIRBuilder::CreateStmtIAssign(FEIRTypeHelper::CreateTypeNative(*elementPtrType)->Clone(), + addrOfElemExpr->Clone(), elemExpr->Clone(), 0); + stmt->SetSrcLoc(initList.initExprs[i]->GetSrcLoc()); + stmts.emplace_back(std::move(stmt)); } - // handling implicit initialization sections - auto allSize = arrayMirType->GetSize(); - 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); + HandleImplicitInitSections(addrOfArray, initList, *elementType, stmts); } void ASTInitListExpr::ProcessVectorInitList(std::variant, UniqueFEIRExpr> &base, - ASTInitListExpr *initList, std::list &stmts) const { - UniqueFEIRType srcType = FEIRTypeHelper::CreateTypeNative(*initList->initListType); + const ASTInitListExpr &initList, std::list &stmts) const { + UniqueFEIRType srcType = FEIRTypeHelper::CreateTypeNative(*(initList.initListType)); if (std::holds_alternative(base)) { CHECK_FATAL(false, "unsupported case"); } else { @@ -1350,15 +1780,15 @@ void ASTInitListExpr::ProcessVectorInitList(std::variantClone()); } - for (size_t index = 0; index < initList->initExprs.size(); ++index) { + for (size_t index = 0; index < initList.initExprs.size(); ++index) { UniqueFEIRExpr indexExpr = FEIRBuilder::CreateExprConstI32(index); - UniqueFEIRExpr elemExpr = initList->initExprs[index]->Emit2FEExpr(stmts); + UniqueFEIRExpr elemExpr = initList.initExprs[index]->Emit2FEExpr(stmts); std::vector> argOpnds; argOpnds.push_back(std::move(elemExpr)); argOpnds.push_back(dreadVar->Clone()); argOpnds.push_back(std::move(indexExpr)); UniqueFEIRExpr intrinsicExpr = std::make_unique( - srcType->Clone(), SetVectorSetLane(*initList->initListType), argOpnds); + srcType->Clone(), SetVectorSetLane(*(initList.initListType)), argOpnds); auto stmt = FEIRBuilder::CreateStmtDAssignAggField(srcVar->Clone(), std::move(intrinsicExpr), fieldID); stmts.emplace_back(std::move(stmt)); } @@ -1366,12 +1796,12 @@ void ASTInitListExpr::ProcessVectorInitList(std::variant &stmts) const { - return ImplicitInitFieldValue(mirType, stmts); + return ImplicitInitFieldValue(*mirType, stmts); } MIRConst *ASTStringLiteral::GenerateMIRConstImpl() const { @@ -1443,7 +1873,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; + (void)codeUnitsVec.insert(codeUnitsVec.cend(), codeUnits.cbegin(), codeUnits.cend()); + UniqueFEIRExpr expr = std::make_unique(codeUnitsVec, elemType, GetStr()); CHECK_NULL_FATAL(expr); return expr; } @@ -1485,8 +1917,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,30 +1934,84 @@ 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)); } } +MIRType *ASTArraySubscriptExpr::GetArrayTypeForPointerArray() const { + MIRType *arrayTypeOpt = nullptr; + MIRPtrType *ptrTy = static_cast(arrayType); + MIRType *pointedTy = ptrTy->GetPointedType(); + if (pointedTy->GetKind() == kTypeArray) { + MIRArrayType *pointedArrTy = static_cast(pointedTy); + std::vector sizeArray{1}; + for (uint32 i = 0; i < pointedArrTy->GetDim(); ++i) { + sizeArray.push_back(pointedArrTy->GetSizeArrayItem(i)); + } + MIRArrayType newArrTy(pointedArrTy->GetElemTyIdx(), sizeArray); + arrayTypeOpt = static_cast(GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(newArrTy)); + } else { + arrayTypeOpt = GlobalTables::GetTypeTable().GetOrCreateArrayType(*pointedTy, 1); + } + return arrayTypeOpt; +} + +UniqueFEIRExpr ASTArraySubscriptExpr::SolveMultiDimArray(UniqueFEIRExpr &baseAddrFEExpr, UniqueFEIRType &arrayFEType, + bool isArrayTypeOpt, std::list &stmts) const { + std::list feIdxExprs; + if (baseAddrFEExpr->GetKind() == kExprAddrofArray && !isArrayTypeOpt) { + auto baseArrayExpr = static_cast(baseAddrFEExpr.get()); + for (auto &e : baseArrayExpr->GetExprIndexs()) { + (void)feIdxExprs.emplace_back(e->Clone()); + } + arrayFEType = baseArrayExpr->GetTypeArray()->Clone(); + baseAddrFEExpr = baseArrayExpr->GetExprArray()->Clone(); + } + auto feIdxExpr = idxExpr->Emit2FEExpr(stmts); + if (isArrayTypeOpt) { + InsertNonnullChecking(stmts, feIdxExpr, baseAddrFEExpr); + } + (void)feIdxExprs.emplace_back(std::move(feIdxExpr)); + return FEIRBuilder::CreateExprAddrofArray(arrayFEType->Clone(), baseAddrFEExpr->Clone(), "", feIdxExprs); +} + +UniqueFEIRExpr ASTArraySubscriptExpr::SolveOtherArrayType(const UniqueFEIRExpr &baseAddrFEExpr, + std::list &stmts) const { + std::vector offsetExprs; + UniqueFEIRExpr offsetExpr; + auto feIdxExpr = idxExpr->Emit2FEExpr(stmts); + PrimType indexPty = feIdxExpr->GetPrimType(); + UniqueFEIRType sizeType = IsSignedInteger(indexPty) ? std::make_unique(*GlobalTables::GetTypeTable(). + GetPrimType(PTY_i64)) : std::make_unique(*GlobalTables::GetTypeTable().GetPrimType(PTY_ptr)); + feIdxExpr = IsSignedInteger(indexPty) ? FEIRBuilder::CreateExprCvtPrim(std::move(feIdxExpr), GetRegPrimType( + indexPty), PTY_i64) : FEIRBuilder::CreateExprCvtPrim(std::move(feIdxExpr), GetRegPrimType(indexPty), PTY_ptr); + 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)); + } + (void)offsetExprs.emplace_back(std::move(feIdxExpr)); + if (offsetExprs.size() != 0) { + offsetExpr = std::move(offsetExprs[0]); + for (size_t i = 1; i < offsetExprs.size(); i++) { + offsetExpr = FEIRBuilder::CreateExprBinary(std::move(sizeType), OP_add, std::move(offsetExpr), + std::move(offsetExprs[i])); + } + } + return FEIRBuilder::CreateExprBinary(std::move(sizeType), OP_add, baseAddrFEExpr->Clone(), std::move(offsetExpr)); +} + UniqueFEIRExpr ASTArraySubscriptExpr::Emit2FEExprImpl(std::list &stmts) const { - auto baseAddrFEExpr = baseExpr->Emit2FEExpr(stmts); + std::list subStmts; // To delete redundant bounds checks in one ASTArraySubscriptExpr stmts. + auto baseAddrFEExpr = baseExpr->Emit2FEExpr(subStmts); auto retFEType = std::make_unique(*mirType); MIRType *arrayTypeOpt = arrayType; bool isArrayTypeOpt = false; if (arrayTypeOpt->GetKind() == kTypePointer && !isVLA) { - MIRPtrType *ptrTy = static_cast(arrayTypeOpt); - MIRType *pointedTy = ptrTy->GetPointedType(); - if (pointedTy->GetKind() == kTypeArray) { - MIRArrayType *pointedArrTy = static_cast(pointedTy); - std::vector sizeArray{1}; - for (uint32 i = 0; i < pointedArrTy->GetDim(); ++i) { - sizeArray.push_back(pointedArrTy->GetSizeArrayItem(i)); - } - MIRArrayType newArrTy(pointedArrTy->GetElemTyIdx(), sizeArray); - arrayTypeOpt = static_cast(GlobalTables::GetTypeTable().GetOrCreateMIRTypeNode(newArrTy)); - } else { - arrayTypeOpt = GlobalTables::GetTypeTable().GetOrCreateArrayType(*pointedTy, 1); - } + arrayTypeOpt = GetArrayTypeForPointerArray(); isArrayTypeOpt = true; } UniqueFEIRType arrayFEType = std::make_unique(*arrayTypeOpt); @@ -1533,80 +2019,35 @@ UniqueFEIRExpr ASTArraySubscriptExpr::Emit2FEExprImpl(std::list auto fePtrType = std::make_unique(*mirPtrType); UniqueFEIRExpr addrOfArray; if (arrayTypeOpt->GetKind() == MIRTypeKind::kTypeArray && !isVLA) { - if(CheckFirstDimIfZero(arrayTypeOpt)) { + if (CheckFirstDimIfZero(arrayTypeOpt)) { // return multi-dim array addr directly if its first dim size was 0. + stmts.splice(stmts.end(), subStmts); return baseAddrFEExpr; } - std::list feIdxExprs; - if (baseAddrFEExpr->GetKind() == kExprAddrofArray && !isArrayTypeOpt) { - auto baseArrayExpr = static_cast(baseAddrFEExpr.get()); - for (auto &e : baseArrayExpr->GetExprIndexs()) { - feIdxExprs.emplace_back(e->Clone()); - } - arrayFEType = baseArrayExpr->GetTypeArray()->Clone(); - baseAddrFEExpr = baseArrayExpr->GetExprArray()->Clone(); - } - auto feIdxExpr = idxExpr->Emit2FEExpr(stmts); - if (isArrayTypeOpt) { - InsertNonnullChecking(stmts, feIdxExpr, baseAddrFEExpr); - } - feIdxExprs.emplace_back(std::move(feIdxExpr)); - addrOfArray = FEIRBuilder::CreateExprAddrofArray(arrayFEType->Clone(), baseAddrFEExpr->Clone(), "", feIdxExprs); + addrOfArray = SolveMultiDimArray(baseAddrFEExpr, arrayFEType, isArrayTypeOpt, subStmts); } else { - std::vector offsetExprs; - UniqueFEIRExpr offsetExpr; - auto feIdxExpr = idxExpr->Emit2FEExpr(stmts); - PrimType indexPty = feIdxExpr->GetPrimType(); - UniqueFEIRType sizeType; - if (IsSignedInteger(indexPty)) { - sizeType = std::make_unique(*GlobalTables::GetTypeTable().GetPrimType(PTY_i64)); - feIdxExpr = FEIRBuilder::CreateExprCvtPrim(std::move(feIdxExpr), GetRegPrimType(indexPty), PTY_i64); - } else { - sizeType = std::make_unique(*GlobalTables::GetTypeTable().GetPrimType(PTY_ptr)); - feIdxExpr = FEIRBuilder::CreateExprCvtPrim(std::move(feIdxExpr), - GetSignedPrimType(GetRegPrimType(indexPty)), PTY_ptr); - } - 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)); - } - offsetExprs.emplace_back(std::move(feIdxExpr)); - if (offsetExprs.size() == 1) { - offsetExpr = std::move(offsetExprs[0]); - } else if (offsetExprs.size() >= 2) { - offsetExpr = FEIRBuilder::CreateExprBinary(sizeType->Clone(), OP_add, std::move(offsetExprs[0]), - std::move(offsetExprs[1])); - if (offsetExprs.size() >= 3) { - for (size_t i = 2; i < offsetExprs.size(); i++) { - offsetExpr = FEIRBuilder::CreateExprBinary(sizeType->Clone(), OP_add, std::move(offsetExpr), - std::move(offsetExprs[i])); - } - } - } - if (isVLA) { - baseAddrFEExpr = FEIRBuilder::CreateExprDRead(baseAddrFEExpr->GetVarUses().front()->Clone()); - } - addrOfArray = FEIRBuilder::CreateExprBinary(std::move(sizeType), OP_add, baseAddrFEExpr->Clone(), - std::move(offsetExpr)); + addrOfArray = SolveOtherArrayType(baseAddrFEExpr, subStmts); } - if (InsertBoundaryChecking(stmts, addrOfArray->Clone(), std::move(baseAddrFEExpr))) { + if (InsertBoundaryChecking(subStmts, addrOfArray->Clone(), std::move(baseAddrFEExpr))) { addrOfArray->SetIsBoundaryChecking(true); } + stmts.splice(stmts.end(), subStmts); return FEIRBuilder::CreateExprIRead(std::move(retFEType), fePtrType->Clone(), addrOfArray->Clone()); } UniqueFEIRExpr ASTExprUnaryExprOrTypeTraitExpr::Emit2FEExprImpl(std::list &stmts) const { - (void)stmts; - CHECK_FATAL(false, "NIY"); - return nullptr; + CHECK_NULL_FATAL(sizeExpr); + if (idxExpr != nullptr) { + (void)idxExpr->Emit2FEExpr(stmts); + } + return sizeExpr->Emit2FEExpr(stmts); } MIRConst *ASTMemberExpr::GenerateMIRConstImpl() const { uint64 fieldOffset = fieldOffsetBits / kOneByte; - ASTExpr *base = baseExpr; + const ASTExpr *base = baseExpr; while (base->GetASTOp() == 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(); } @@ -1628,13 +2069,13 @@ MIRConst *ASTMemberExpr::GenerateMIRConstImpl() const { konst->GetType(), konst->GetOffset() + static_cast(fieldOffset)); } -const ASTMemberExpr *ASTMemberExpr::FindFinalMember(const ASTMemberExpr *startExpr, +const ASTMemberExpr &ASTMemberExpr::FindFinalMember(const ASTMemberExpr &startExpr, std::list &memberNames) const { - memberNames.emplace_back(startExpr->memberName); - if (startExpr->isArrow || startExpr->baseExpr->GetASTOp() != kASTMemberExpr) { + (void)memberNames.emplace_back(startExpr.GetMemberName()); + if (startExpr.isArrow || startExpr.baseExpr->GetASTOp() != kASTMemberExpr) { return startExpr; } - return FindFinalMember(static_cast(startExpr->baseExpr), memberNames); + return FindFinalMember(*(static_cast(startExpr.baseExpr)), memberNames); } void ASTMemberExpr::InsertNonnullChecking(std::list &stmts, UniqueFEIRExpr baseFEExpr) const { @@ -1643,24 +2084,24 @@ 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); - const ASTMemberExpr *finalMember = FindFinalMember(static_cast(baseExpr), memberNameList); - baseFEExpr = finalMember->baseExpr->Emit2FEExpr(stmts); - tmpIsArrow = finalMember->isArrow; - tmpBaseType = finalMember->baseType; - fieldName = ASTUtil::Join(memberNameList, "."); + (void)memberNameList.emplace_back(GetMemberName()); + const ASTMemberExpr &finalMember = FindFinalMember(*(static_cast(baseExpr)), memberNameList); + baseFEExpr = finalMember.baseExpr->Emit2FEExpr(stmts); + tmpIsArrow = finalMember.isArrow; + tmpBaseType = finalMember.baseType; + fieldName = ASTUtil::Join(memberNameList, "$"); // add structure nesting relationship } else { baseFEExpr = baseExpr->Emit2FEExpr(stmts); } @@ -1707,7 +2148,17 @@ UniqueFEIRExpr ASTMemberExpr::Emit2FEExprImpl(std::list &stmts) // ---------- ASTDesignatedInitUpdateExpr ---------- MIRConst *ASTDesignatedInitUpdateExpr::GenerateMIRConstImpl() const { - return FEManager::GetModule().GetMemPool()->New(FEManager::GetModule(), *initListType); + auto *base = static_cast(baseExpr->GenerateMIRConst()); + auto *update = static_cast(updaterExpr->GenerateMIRConst()); + auto mirConsts = update->GetConstVec(); + for (int i = 0; i < mirConsts.size(); ++i) { + if (mirConsts[i]->GetKind() == kConstInvalid) { + continue; + } else { + base->SetConstVecItem(i, *mirConsts[i]); + } + } + return base; } UniqueFEIRExpr ASTDesignatedInitUpdateExpr::Emit2FEExprImpl(std::list &stmts) const { @@ -1720,40 +2171,92 @@ UniqueFEIRExpr ASTDesignatedInitUpdateExpr::Emit2FEExprImpl(std::listGenerateMIRConst(); + if (!rightConst->IsZero()) { + return GlobalTables::GetIntConstTable().GetOrCreateIntConst( + 1, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + } else { + return GlobalTables::GetIntConstTable().GetOrCreateIntConst( + 0, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + } + } +} + +MIRConst *ASTBinaryOperatorExpr::SolveOpcodeLandOrCand(const MIRConst &leftConst, const MIRConst &rightConst) const { + if (leftConst.IsZero()) { + return GlobalTables::GetIntConstTable().GetOrCreateIntConst( + 0, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + } else if (rightConst.IsZero()) { + return GlobalTables::GetIntConstTable().GetOrCreateIntConst( + 0, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + } else { + return GlobalTables::GetIntConstTable().GetOrCreateIntConst( + 1, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + } +} + +MIRConst *ASTBinaryOperatorExpr::SolveOpcodeAdd(const MIRConst &leftConst, const MIRConst &rightConst) const { + const MIRIntConst *constInt = nullptr; + const MIRConst *baseConst = nullptr; + if (leftConst.GetKind() == kConstInt) { + constInt = static_cast(&leftConst); + baseConst = &rightConst; + } else if (rightConst.GetKind() == kConstInt) { + constInt = static_cast(&rightConst); + baseConst = &leftConst; + } else { + CHECK_FATAL(false, "Unsupported yet"); + } + int64 value = constInt->GetExtValue(); + ASSERT_NOT_NULL(baseConst); + if (baseConst->GetKind() == kConstStrConst) { + std::string str = GlobalTables::GetUStrTable().GetStringFromStrIdx( + static_cast(baseConst)->GetValue()); + CHECK_FATAL(str.length() >= static_cast(value), "Invalid operation"); + str = str.substr(static_cast(value)); + UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str); + return FEManager::GetModule().GetMemPool()->New( + strIdx, *GlobalTables::GetTypeTable().GetPrimType(PTY_a64)); + } else if (baseConst->GetKind() == kConstAddrof) { + const MIRAddrofConst *konst = static_cast(baseConst); + auto idx = konst->GetSymbolIndex(); + auto id = konst->GetFieldID(); + auto ty = konst->GetType(); + auto offset = konst->GetOffset(); + return FEManager::GetModule().GetMemPool()->New(idx, id, ty, offset + value); + } else { + CHECK_FATAL(false, "NIY"); + } +} + +MIRConst *ASTBinaryOperatorExpr::SolveOpcodeSub(const MIRConst &leftConst, const MIRConst &rightConst) const { + CHECK_FATAL(leftConst.GetKind() == kConstAddrof && rightConst.GetKind() == kConstInt, "Unsupported"); + const MIRAddrofConst *konst = static_cast(&leftConst); + auto idx = konst->GetSymbolIndex(); + auto id = konst->GetFieldID(); + auto ty = konst->GetType(); + auto offset = konst->GetOffset(); + int64 value = static_cast(&rightConst)->GetExtValue(); + return FEManager::GetModule().GetMemPool()->New(idx, id, ty, offset - value); +} + MIRConst *ASTBinaryOperatorExpr::GenerateMIRConstImpl() const { MIRConst *leftConst = leftExpr->GenerateMIRConst(); MIRConst *rightConst = nullptr; if (opcode == OP_lior || opcode == OP_cior) { - if (!leftConst->IsZero()) { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(1, - *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); - } else { - rightConst = rightExpr->GenerateMIRConst(); - if (!rightConst->IsZero()) { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(1, - *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); - } else { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(0, - *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); - } - } + return SolveOpcodeLiorOrCior(*leftConst); } 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()) { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(0, - *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); - } else if (rightConst->IsZero()) { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(0, - *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); - } else { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(1, - *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); - } + return SolveOpcodeLandOrCand(*leftConst, *rightConst); } if (leftConst->GetKind() == rightConst->GetKind()) { if (isConstantFolded) { @@ -1779,45 +2282,9 @@ MIRConst *ASTBinaryOperatorExpr::GenerateMIRConstImpl() const { } } if (opcode == OP_add) { - MIRIntConst *constInt = nullptr; - MIRConst *baseConst = nullptr; - if (leftConst->GetKind() == kConstInt) { - constInt = static_cast(leftConst); - baseConst = rightConst; - } else if (rightConst->GetKind() == kConstInt) { - constInt = static_cast(rightConst); - baseConst = leftConst; - } else { - CHECK_FATAL(false, "Unsupported yet"); - } - int64 value = constInt->GetValue(); - if (baseConst->GetKind() == kConstStrConst) { - std::string str = - GlobalTables::GetUStrTable().GetStringFromStrIdx(static_cast(baseConst)->GetValue()); - CHECK_FATAL(str.length() >= static_cast(value), "Invalid operation"); - str = str.substr(static_cast(value)); - UStrIdx strIdx = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(str); - return FEManager::GetModule().GetMemPool()->New( - strIdx, *GlobalTables::GetTypeTable().GetPrimType(PTY_a64)); - } else if (baseConst->GetKind() == kConstAddrof) { - MIRAddrofConst *konst = static_cast(baseConst); - auto idx = konst->GetSymbolIndex(); - auto id = konst->GetFieldID(); - auto ty = konst->GetType(); - auto offset = konst->GetOffset(); - return FEManager::GetModule().GetMemPool()->New(idx, id, ty, offset + value); - } else { - CHECK_FATAL(false, "NIY"); - } + return SolveOpcodeAdd(*leftConst, *rightConst); } else if (opcode == OP_sub) { - CHECK_FATAL(leftConst->GetKind() == kConstAddrof && rightConst->GetKind() == kConstInt, "Unsupported"); - MIRAddrofConst *konst = static_cast(leftConst); - auto idx = konst->GetSymbolIndex(); - auto id = konst->GetFieldID(); - auto ty = konst->GetType(); - auto offset = konst->GetOffset(); - int64 value = static_cast(rightConst)->GetValue(); - return FEManager::GetModule().GetMemPool()->New(idx, id, ty, offset - value); + return SolveOpcodeSub(*leftConst, *rightConst); } else { CHECK_FATAL(false, "NIY"); } @@ -1907,8 +2374,8 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperate(std::listSetShortCircuitIdx(trueLabelIdx, falseLabelIdx); - std::string rightCondLabel = FEUtils::GetSequentialName0("shortCircuit_", rightCondLabelIdx); - std::string fallthrouLabel = FEUtils::GetSequentialName0("shortCircuit_", fallthrouLabelIdx); - std::string jumpToLabel = FEUtils::GetSequentialName0("shortCircuit_", jumpToLabelIdx); + std::string rightCondLabel = FEUtils::GetSequentialName0(FEUtils::kCondGoToStmtLabelNamePrefix, rightCondLabelIdx); + std::string fallthrouLabel = FEUtils::GetSequentialName0(FEUtils::kCondGoToStmtLabelNamePrefix, fallthrouLabelIdx); + std::string jumpToLabel = FEUtils::GetSequentialName0(FEUtils::kCondGoToStmtLabelNamePrefix, jumpToLabelIdx); // brfalse/brtrue label (leftCond) auto leftFEExpr = leftExpr->Emit2FEExpr(stmts); if (leftFEExpr != nullptr) { auto leftCond = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(leftFEExpr)); UniqueFEIRStmt leftCondGoToExpr = std::make_unique(leftCond->Clone(), op, jumpToLabel); + leftCondGoToExpr->SetSrcLoc(leftExpr->GetSrcLoc()); stmts.emplace_back(std::move(leftCondGoToExpr)); } auto rightCondlabelStmt = std::make_unique(rightCondLabel); - rightCondlabelStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + rightCondlabelStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(rightCondlabelStmt)); // brfalse/brtrue label (rightCond) @@ -1950,7 +2418,9 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperate(std::list(rightCond->Clone(), op, jumpToLabel); + rightCondGoToExpr->SetSrcLoc(rightExpr->GetSrcLoc()); UniqueFEIRStmt goStmt = FEIRBuilder::CreateStmtGoto(fallthrouLabel); + goStmt->SetSrcLoc(rightExpr->GetSrcLoc()); stmts.emplace_back(std::move(rightCondGoToExpr)); stmts.emplace_back(std::move(goStmt)); } @@ -1958,17 +2428,21 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprLogicOperate(std::listSetSrcLoc(rightExpr->GetSrcLoc()); auto trueCircuit = std::make_unique(shortCircuit->Clone(), std::move(trueConst), 0); + trueCircuit->SetSrcLoc(rightExpr->GetSrcLoc()); auto falseCircuit = std::make_unique(shortCircuit->Clone(), std::move(falseConst), 0); + falseCircuit->SetSrcLoc(rightExpr->GetSrcLoc()); auto labelFallthrouStmt = std::make_unique(fallthrouLabel); + labelFallthrouStmt->SetSrcLoc(rightExpr->GetSrcLoc()); auto labelJumpToStmt = std::make_unique(jumpToLabel); + labelJumpToStmt->SetSrcLoc(rightExpr->GetSrcLoc()); auto labelNextStmt = std::make_unique(nextLabel); - labelJumpToStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); - labelNextStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + labelNextStmt->SetSrcLoc(rightExpr->GetSrcLoc()); 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,8 +2461,8 @@ 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); - std::string labelName = FEUtils::GetSequentialName("shortCircuit_label_"); + UniqueFEIRVar shortCircuit = FEIRBuilder::CreateVarNameForC(GetVarName(), *tempVarType); + std::string labelName = FEUtils::GetSequentialName(FEUtils::kCondGoToStmtLabelNamePrefix + "label_"); auto leftFEExpr = leftExpr->Emit2FEExpr(lStmts); leftFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(leftFEExpr)); auto leftStmt = std::make_unique(shortCircuit->Clone(), leftFEExpr->Clone(), 0); @@ -2006,7 +2480,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); @@ -2030,19 +2503,18 @@ UniqueFEIRExpr ASTBinaryOperatorExpr::Emit2FEExprImpl(std::list } else { return Emit2FEExprLogicOperate(stmts); } - } else { - auto leftFEExpr = leftExpr->Emit2FEExpr(stmts); - auto rightFEExpr = rightExpr->Emit2FEExpr(stmts); - if (FEOptions::GetInstance().IsO2()) { - Ror ror(opcode, leftFEExpr, rightFEExpr); - auto rorExpr = ror.Emit2FEExpr(); - if (rorExpr != nullptr) { - return rorExpr; - } + } + auto leftFEExpr = leftExpr->Emit2FEExpr(stmts); + auto rightFEExpr = rightExpr->Emit2FEExpr(stmts); + if (FEOptions::GetInstance().IsO2()) { + Ror ror(opcode, leftFEExpr, rightFEExpr); + auto rorExpr = ror.Emit2FEExpr(); + if (rorExpr != nullptr) { + return rorExpr; } - UniqueFEIRType feirType = SelectBinaryOperatorType(leftFEExpr, rightFEExpr); - return FEIRBuilder::CreateExprBinary(std::move(feirType), opcode, std::move(leftFEExpr), std::move(rightFEExpr)); } + UniqueFEIRType feirType = SelectBinaryOperatorType(leftFEExpr, rightFEExpr); + return FEIRBuilder::CreateExprBinary(std::move(feirType), opcode, std::move(leftFEExpr), std::move(rightFEExpr)); } } @@ -2137,7 +2609,8 @@ UniqueFEIRExpr ASTParenExpr::Emit2FEExprImpl(std::list &stmts) c // ---------- ASTIntegerLiteral ---------- MIRConst *ASTIntegerLiteral::GenerateMIRConstImpl() const { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst(val, *GlobalTables::GetTypeTable().GetPrimType(PTY_i64)); + return GlobalTables::GetIntConstTable().GetOrCreateIntConst(static_cast(val), + *GlobalTables::GetTypeTable().GetPrimType(PTY_i64)); } UniqueFEIRExpr ASTIntegerLiteral::Emit2FEExprImpl(std::list &stmts) const { @@ -2151,7 +2624,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 +2637,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,28 +2665,31 @@ 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()); } + trueFEIRExpr->SetIsEnhancedChecking(false); + falseFEIRExpr->SetIsEnhancedChecking(false); UniqueFEIRVar tempVar = FEIRBuilder::CreateVarNameForC(varName, *retType); UniqueFEIRVar tempVarCloned1 = tempVar->Clone(); UniqueFEIRVar tempVarCloned2 = tempVar->Clone(); UniqueFEIRStmt retTrueStmt = FEIRBuilder::CreateStmtDAssign(std::move(tempVar), std::move(trueFEIRExpr)); - retTrueStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + retTrueStmt->SetSrcLoc(trueExpr->GetSrcLoc()); trueStmts.emplace_back(std::move(retTrueStmt)); UniqueFEIRStmt retFalseStmt = FEIRBuilder::CreateStmtDAssign(std::move(tempVarCloned1), std::move(falseFEIRExpr)); - retFalseStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + retFalseStmt->SetSrcLoc(falseExpr->GetSrcLoc()); falseStmts.emplace_back(std::move(retFalseStmt)); UniqueFEIRStmt stmtIf = FEIRBuilder::CreateStmtIf(std::move(condFEIRExpr), trueStmts, falseStmts); stmts.emplace_back(std::move(stmtIf)); UniqueFEIRExpr expr = FEIRBuilder::CreateExprDRead(std::move(tempVarCloned2)); + expr->SetIsEnhancedChecking(false); if (!FEOptions::GetInstance().IsNpeCheckDynamic() || !FEOptions::GetInstance().IsBoundaryCheckDynamic()) { expr->SetKind(kExprTernary); } @@ -2257,6 +2733,7 @@ UniqueFEIRExpr ASTImaginaryLiteral::Emit2FEExprImpl(std::list &s // ---------- ASTVAArgExpr ---------- UniqueFEIRExpr ASTVAArgExpr::Emit2FEExprImpl(std::list &stmts) const { CHECK_NULL_FATAL(mirType); + EmitVLASizeExprs(stmts); VaArgInfo info = ProcessValistArgInfo(*mirType); UniqueFEIRExpr readVaList = child->Emit2FEExpr(stmts); // The va_arg_offset temp var is created and assigned from __gr_offs or __vr_offs of va_list @@ -2278,10 +2755,10 @@ UniqueFEIRExpr ASTVAArgExpr::Emit2FEExprImpl(std::list &stmts) c UniqueFEIRStmt condGoTo1 = std::make_unique(cond1->Clone(), OP_brtrue, onStackStr); stmts.emplace_back(std::move(condGoTo1)); // The va_arg set next reg setoff - UniqueFEIRExpr ArgAUnitOffs = FEIRBuilder::CreateExprBinary( + UniqueFEIRExpr argAUnitOffs = FEIRBuilder::CreateExprBinary( OP_add, dreadOffsetVar->Clone(), FEIRBuilder::CreateExprConstI32(info.regOffset)); UniqueFEIRStmt assignArgNextOffs = FEIRBuilder::AssginStmtField( - readVaList->Clone(), std::move(ArgAUnitOffs), info.isGPReg ? 4 : 5); + readVaList->Clone(), std::move(argAUnitOffs), info.isGPReg ? 4 : 5); stmts.emplace_back(std::move(assignArgNextOffs)); UniqueFEIRExpr cond2 = FEIRBuilder::CreateExprBinary( // checking validity: regOffs + next offset > 0, goto on_stack OP_gt, dreadVaListOffset->Clone(), FEIRBuilder::CreateExprConstI32(0)); @@ -2290,7 +2767,7 @@ UniqueFEIRExpr ASTVAArgExpr::Emit2FEExprImpl(std::list &stmts) c // The va_arg will be got from GP or FP/SIMD arg reg MIRType *sizeType = GlobalTables::GetTypeTable().GetPtrType(); UniqueFEIRType sizeFEIRType = std::make_unique(*sizeType); - MIRType *vaArgType = !info.isCopyedMem ? mirType : sizeType; + MIRType *vaArgType = !info.isCopyedMem ? mirType : GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType); MIRType *ptrType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*vaArgType); UniqueFEIRVar vaArgVar = FEIRBuilder::CreateVarNameForC(FEUtils::GetSequentialName("va_arg_"), *ptrType); UniqueFEIRExpr dreadVaArgTop = FEIRBuilder::ReadExprField( @@ -2322,14 +2799,14 @@ UniqueFEIRExpr ASTVAArgExpr::Emit2FEExprImpl(std::list &stmts) c UniqueFEIRStmt endLabelStmt = std::make_unique(endStr); stmts.emplace_back(std::move(endLabelStmt)); UniqueFEIRExpr dreadRetVar = FEIRBuilder::CreateExprDRead(vaArgVar->Clone()); + UniqueFEIRType ptrFEIRType = std::make_unique(*ptrType); if (info.isCopyedMem) { - UniqueFEIRType ptrPtrFEIRType = std::make_unique( - *GlobalTables::GetTypeTable().GetOrCreatePointerType(*ptrType)); - dreadRetVar = FEIRBuilder::CreateExprIRead( - std::move(sizeFEIRType), std::move(ptrPtrFEIRType), std::move(dreadRetVar)); + MIRType *tmpType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType); + UniqueFEIRType tmpFETRType = std::make_unique(*tmpType); + dreadRetVar = FEIRBuilder::CreateExprIRead(tmpFETRType->Clone(), ptrFEIRType->Clone(), std::move(dreadRetVar)); + ptrFEIRType = std::move(tmpFETRType); } UniqueFEIRType baseFEIRType = std::make_unique(*mirType); - UniqueFEIRType ptrFEIRType = std::make_unique(*ptrType); UniqueFEIRExpr retExpr = FEIRBuilder::CreateExprIRead( std::move(baseFEIRType), std::move(ptrFEIRType), std::move(dreadRetVar)); return retExpr; @@ -2468,7 +2945,7 @@ void ASTVAArgExpr::CvtHFA2Struct(const MIRStructType &type, MIRType &fieldType, } UniqueFEIRExpr ireadVaArg = FEIRBuilder::CreateExprIRead(baseType->Clone(), ptrType->Clone(), dreadVaArg->Clone()); UniqueFEIRExpr addrofVar = FEIRBuilder::CreateExprAddrofVar(copyedVar->Clone()); - if(i != 0) { + if (i != 0) { addrofVar = FEIRBuilder::CreateExprBinary( OP_add, std::move(addrofVar), FEIRBuilder::CreateExprConstPtr(static_cast(fieldType.GetSize() * i))); } @@ -2525,19 +3002,47 @@ UniqueFEIRExpr ASTDependentScopeDeclRefExpr::Emit2FEExprImpl(std::list astOpMap = { + {kAtomicOpLoadN, "__atomic_load_n"}, + {kAtomicOpLoad, "__atomic_load"}, + {kAtomicOpStoreN, "__atomic_store_n"}, + {kAtomicOpStore, "__atomic_store"}, + {kAtomicOpExchange, "__atomic_exchange"}, + {kAtomicOpExchangeN, "__atomic_exchange_n"}, + {kAtomicOpAddFetch, "__atomic_add_fetch"}, + {kAtomicOpSubFetch, "__atomic_sub_fetch"}, + {kAtomicOpAndFetch, "__atomic_and_fetch"}, + {kAtomicOpXorFetch, "__atomic_xor_fetch"}, + {kAtomicOpOrFetch, "__atomic_or_fetch"}, + {kAtomicOpFetchAdd, "__atomic_fetch_add"}, + {kAtomicOpFetchSub, "__atomic_fetch_sub"}, + {kAtomicOpFetchAnd, "__atomic_fetch_and"}, + {kAtomicOpFetchXor, "__atomic_fetch_xor"}, + {kAtomicOpFetchOr, "__atomic_fetch_or"}, +}; + // ---------- ASTAtomicExpr ---------- UniqueFEIRExpr ASTAtomicExpr::Emit2FEExprImpl(std::list &stmts) const { auto atomicExpr = std::make_unique(mirType, refType, objExpr->Emit2FEExpr(stmts), atomicOp); if (atomicOp != kAtomicOpLoadN) { + if (firstType != nullptr && secondType != nullptr && firstType->GetSize() != secondType->GetSize()) { + FE_ERR(kLncErr, valExpr1->GetSrcLoc(), "size mismatch in argument 2 of '%s'", astOpMap[atomicOp].c_str()); + } static_cast(atomicExpr.get())->SetVal1Expr(valExpr1->Emit2FEExpr(stmts)); static_cast(atomicExpr.get())->SetVal1Type(val1Type); - } - if (atomicOp == kAtomicOpExchange) { - static_cast(atomicExpr.get())->SetVal2Expr(valExpr2->Emit2FEExpr(stmts)); - static_cast(atomicExpr.get())->SetVal2Type(val2Type); + if (atomicOp == kAtomicOpExchange) { + if (firstType != nullptr && secondType != nullptr && + firstType->GetSize() == secondType->GetSize() && firstType->GetSize() != thirdType->GetSize()) { + FE_ERR(kLncErr, valExpr1->GetSrcLoc(), "size mismatch in argument 3 of '__atomic_exchange'"); + } + static_cast(atomicExpr.get())->SetVal2Expr(valExpr2->Emit2FEExpr(stmts)); + static_cast(atomicExpr.get())->SetVal2Type(val2Type); + } + } else { + static_cast(atomicExpr.get())->SetVal1Type(val1Type); } static_cast(atomicExpr.get())->SetOrderExpr(orderExpr->Emit2FEExpr(stmts)); - auto var = FEIRBuilder::CreateVarNameForC(FEUtils::GetSequentialName("ret.var."), *refType, false, false); + auto var = FEIRBuilder::CreateVarNameForC(GetRetVarName(), *refType, false, false); atomicExpr->SetValVar(var->Clone()); if (!isFromStmt) { auto stmt = std::make_unique(std::move(atomicExpr)); @@ -2549,29 +3054,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..08baa5a6599e56da0ef657a361ed2a60406cbf76 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_function.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_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. @@ -40,11 +40,8 @@ bool ASTFunction::GenerateAliasVars(const std::string &phaseName) { bool ASTFunction::EmitToFEIRStmt(const std::string &phaseName) { phaseResult.RegisterPhaseNameAndStart(phaseName); std::list feirStmts = astFunc.EmitASTStmtToFEIR(); - if ((astFunc.GetSize() <= FEOptions::GetInstance().GetFuncInlineSize() && - !astFunc.GetGenericAttrs().GetAttr(GENATTR_noinline)) || astFunc.GetGenericAttrs().GetAttr(GENATTR_static)) { - FEManager::GetModule().AddOptFuncs(&mirFunction); - } AppendFEIRStmts(feirStmts); + AppendFEIRStmts(vlaCleanupStmts); return phaseResult.Finish(true); } @@ -58,6 +55,10 @@ void ASTFunction::SetMIRFunctionInfo() { mirFunction.PushbackIsString(true); } +void ASTFunction::AddVLACleanupStmts(std::list &stmts) { + vlaCleanupStmts.splice(vlaCleanupStmts.end(), stmts); +} + bool ASTFunction::ProcessImpl() { FE_INFO_LEVEL(FEOptions::kDumpLevelInfoDetail, "ASTFunction::Process() for %s", astFunc.GetName().c_str()); bool success = true; @@ -76,6 +77,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..d9ba04e7569adfe270bb27d1db04aaac798cfb86 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_parser.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_parser.cpp @@ -13,6 +13,7 @@ * See the Mulan PSL v2 for more details. */ #include "ast_parser.h" +#include "driver_options.h" #include "mpl_logging.h" #include "mir_module.h" #include "mpl_logging.h" @@ -24,12 +25,17 @@ #include "ast_input.h" #include "fe_manager.h" #include "enhance_c_checker.h" +#include "fe_macros.h" namespace maple { std::map ASTDeclsBuilder::declesTable; -bool ASTParser::OpenFile() { - astFile = std::make_unique(recordDecles); +const std::string kBuiltinAlloca = "__builtin_alloca"; +const std::string kAlloca = "alloca"; +const std::string kBuiltinAllocaWithAlign = "__builtin_alloca_with_align"; + +bool ASTParser::OpenFile(MapleAllocator &allocator) { + astFile = allocator.GetMemPool()->New(allocator, recordDecles, globalEnumDecles); bool res = astFile->Open(fileName, 0, 0); if (!res) { return false; @@ -38,11 +44,18 @@ bool ASTParser::OpenFile() { return true; } +bool ASTParser::Release() const { + astFile->DisposeTranslationUnit(); + ASTDeclsBuilder::Clear(); + return true; +} + bool ASTParser::Verify() const { return true; } -ASTBinaryOperatorExpr *ASTParser::AllocBinaryOperatorExpr(MapleAllocator &allocator, const clang::BinaryOperator &bo) { +ASTBinaryOperatorExpr *ASTParser::AllocBinaryOperatorExpr(MapleAllocator &allocator, + const clang::BinaryOperator &bo) const { if (bo.isAssignmentOp() && !bo.isCompoundAssignmentOp()) { return ASTDeclsBuilder::ASTExprBuilder(allocator); } @@ -54,6 +67,7 @@ ASTBinaryOperatorExpr *ASTParser::AllocBinaryOperatorExpr(MapleAllocator &alloca return ASTDeclsBuilder::ASTExprBuilder(allocator); } MIRType *lhTy = astFile->CvtType(bo.getLHS()->getType()); + ASSERT_NOT_NULL(lhTy); auto opcode = bo.getOpcode(); if (bo.isCompoundAssignmentOp()) { opcode = clang::BinaryOperator::getOpForCompoundAssignment(bo.getOpcode()); @@ -73,12 +87,16 @@ 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; + bool isCallAlloca = false; for (it = cpdStmt.body_begin(); it != cpdStmt.body_end(); ++it) { childStmt = ProcessStmt(allocator, **it); if (childStmt != nullptr) { astCompoundStmt->SetASTStmt(childStmt); + isCallAlloca = isCallAlloca || childStmt->IsCallAlloca(); + astCompoundStmt->SetCallAlloca(isCallAlloca); } else { continue; } @@ -87,13 +105,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 +122,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 +163,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 +173,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; @@ -166,6 +187,7 @@ ASTStmt *ASTParser::ProcessStmtOffsetOfExpr(MapleAllocator &allocator, const cla if (astExpr == nullptr) { return nullptr; } + astStmt->SetCallAlloca(astExpr->IsCallAlloca()); astStmt->SetASTExpr(astExpr); return astStmt; } @@ -178,6 +200,7 @@ ASTStmt *ASTParser::ProcessStmtGenericSelectionExpr(MapleAllocator &allocator, if (astExpr == nullptr) { return nullptr; } + astStmt->SetCallAlloca(astExpr->IsCallAlloca()); astStmt->SetASTExpr(astExpr); return astStmt; } @@ -189,6 +212,7 @@ ASTStmt *ASTParser::ProcessStmtUnaryOperator(MapleAllocator &allocator, const cl if (astExpr == nullptr) { return nullptr; } + astUOStmt->SetCallAlloca(astExpr->IsCallAlloca()); astUOStmt->SetASTExpr(astExpr); return astUOStmt; } @@ -200,17 +224,20 @@ ASTStmt *ASTParser::ProcessStmtBinaryOperator(MapleAllocator &allocator, const c if (astExpr == nullptr) { return nullptr; } + astBOStmt->SetCallAlloca(astExpr->IsCallAlloca()); astBOStmt->SetASTExpr(astExpr); return astBOStmt; } 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->SetCallAlloca(astExpr != nullptr && astExpr->IsCallAlloca()); astCallExprStmt->SetASTExpr(astExpr); return astCallExprStmt; } @@ -224,6 +251,7 @@ ASTStmt *ASTParser::ProcessStmtImplicitCastExpr(MapleAllocator &allocator, if (astExpr == nullptr) { return nullptr; } + astImplicitCastExprStmt->SetCallAlloca(astExpr->IsCallAlloca()); astImplicitCastExprStmt->SetASTExpr(astExpr); return astImplicitCastExprStmt; } @@ -235,6 +263,7 @@ ASTStmt *ASTParser::ProcessStmtParenExpr(MapleAllocator &allocator, const clang: if (astExpr == nullptr) { return nullptr; } + astParenExprStmt->SetCallAlloca(astExpr->IsCallAlloca()); astParenExprStmt->SetASTExpr(astExpr); return astParenExprStmt; } @@ -246,6 +275,7 @@ ASTStmt *ASTParser::ProcessStmtIntegerLiteral(MapleAllocator &allocator, const c if (astExpr == nullptr) { return nullptr; } + astIntegerLiteralStmt->SetCallAlloca(astExpr->IsCallAlloca()); astIntegerLiteralStmt->SetASTExpr(astExpr); return astIntegerLiteralStmt; } @@ -258,6 +288,7 @@ ASTStmt *ASTParser::ProcessStmtFloatingLiteral(MapleAllocator &allocator, if (astExpr == nullptr) { return nullptr; } + astFloatingLiteralStmt->SetCallAlloca(astExpr->IsCallAlloca()); astFloatingLiteralStmt->SetASTExpr(astExpr); return astFloatingLiteralStmt; } @@ -269,6 +300,7 @@ ASTStmt *ASTParser::ProcessStmtVAArgExpr(MapleAllocator &allocator, const clang: if (astExpr == nullptr) { return nullptr; } + astVAArgExprStmt->SetCallAlloca(astExpr->IsCallAlloca()); astVAArgExprStmt->SetASTExpr(astExpr); return astVAArgExprStmt; } @@ -282,6 +314,7 @@ ASTStmt *ASTParser::ProcessStmtConditionalOperator(MapleAllocator &allocator, if (astExpr == nullptr) { return nullptr; } + astConditionalOperatorStmt->SetCallAlloca(astExpr->IsCallAlloca()); astConditionalOperatorStmt->SetASTExpr(astExpr); return astConditionalOperatorStmt; } @@ -295,6 +328,7 @@ ASTStmt *ASTParser::ProcessStmtCharacterLiteral(MapleAllocator &allocator, if (astExpr == nullptr) { return nullptr; } + astCharacterLiteralStmt->SetCallAlloca(astExpr->IsCallAlloca()); astCharacterLiteralStmt->SetASTExpr(astExpr); return astCharacterLiteralStmt; } @@ -306,13 +340,43 @@ ASTStmt *ASTParser::ProcessStmtCStyleCastExpr(MapleAllocator &allocator, const c if (astExpr == nullptr) { return nullptr; } + astCStyleCastExprStmt->SetCallAlloca(astExpr->IsCallAlloca()); astCStyleCastExprStmt->SetASTExpr(astExpr); return astCStyleCastExprStmt; } +bool ASTParser::CheckIncContinueStmtExpr(const clang::Stmt &bodyStmt) const { + bool hasNestContinueLabel = false; + if (bodyStmt.getStmtClass() == clang::Stmt::ForStmtClass) { + const auto *subExpr = llvm::cast(bodyStmt).getInc(); + if (subExpr == nullptr || subExpr->getStmtClass() != clang::Expr::StmtExprClass) { + return hasNestContinueLabel; + } + const auto *subStmtExpr = llvm::cast(subExpr); + const clang::CompoundStmt *cpdStmt = llvm::dyn_cast(subStmtExpr->getSubStmt()); + clang::CompoundStmt::const_body_iterator it; + for (it = cpdStmt->body_begin(); it != cpdStmt->body_end(); ++it) { + const auto *subStmt = llvm::dyn_cast(*it); + if (subStmt->getStmtClass() == clang::Stmt::ContinueStmtClass) { + hasNestContinueLabel = true; + break; + } + } + } + return hasNestContinueLabel; +} + ASTStmt *ASTParser::ProcessStmtStmtExpr(MapleAllocator &allocator, const clang::StmtExpr &stmtExpr) { ASTStmtExprStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); const clang::CompoundStmt *cpdStmt = stmtExpr.getSubStmt(); + clang::CompoundStmt::const_body_iterator it; + for (it = cpdStmt->body_begin(); it != cpdStmt->body_end(); ++it) { + const auto *bodyStmt = llvm::dyn_cast(*it); + if (bodyStmt->getStmtClass() == clang::Stmt::CaseStmtClass || + bodyStmt->getStmtClass() == clang::Stmt::DefaultStmtClass) { + FE_ERR(kLncErr, astFile->GetLOC(bodyStmt->getBeginLoc()), "Unsupported StmtExpr in switch-case"); + } + } ASTStmt *astCompoundStmt = ProcessStmt(allocator, *cpdStmt); astStmt->SetBodyStmt(astCompoundStmt); return astStmt; @@ -326,6 +390,7 @@ ASTStmt *ASTParser::ProcessStmtCompoundAssignOperator(MapleAllocator &allocator, if (astExpr == nullptr) { return nullptr; } + astCAOStmt->SetCallAlloca(astExpr->IsCallAlloca()); astCAOStmt->SetASTExpr(astExpr); return astCAOStmt; } @@ -338,6 +403,7 @@ ASTStmt *ASTParser::ProcessStmtAtomicExpr(MapleAllocator &allocator, const clang return nullptr; } static_cast(astExpr)->SetFromStmt(true); + astAtomicExprStmt->SetCallAlloca(astExpr->IsCallAlloca()); astAtomicExprStmt->SetASTExpr(astExpr); return astAtomicExprStmt; } @@ -346,6 +412,7 @@ ASTStmt *ASTParser::ProcessStmtReturnStmt(MapleAllocator &allocator, const clang ASTReturnStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); ASTExpr *astExpr = ProcessExpr(allocator, retStmt.getRetValue()); + astStmt->SetCallAlloca(astExpr != nullptr && astExpr->IsCallAlloca()); astStmt->SetASTExpr(astExpr); return astStmt; } @@ -382,6 +449,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) { @@ -394,6 +462,7 @@ ASTStmt *ASTParser::ProcessStmtForStmt(MapleAllocator &allocator, const clang::F if (condExpr == nullptr) { return nullptr; } + astStmt->SetCallAlloca(condExpr->IsCallAlloca()); astStmt->SetCondExpr(condExpr); } if (forStmt.getInc() != nullptr) { @@ -401,6 +470,7 @@ ASTStmt *ASTParser::ProcessStmtForStmt(MapleAllocator &allocator, const clang::F if (incExpr == nullptr) { return nullptr; } + astStmt->SetCallAlloca(incExpr->IsCallAlloca()); astStmt->SetIncExpr(incExpr); } ASTStmt *bodyStmt = nullptr; @@ -421,7 +491,24 @@ ASTStmt *ASTParser::ProcessStmtWhileStmt(MapleAllocator &allocator, const clang: if (condExpr == nullptr) { return nullptr; } + astStmt->SetCallAlloca(condExpr->IsCallAlloca()); astStmt->SetCondExpr(condExpr); + const clang::CompoundStmt *cpdStmt = llvm::dyn_cast(whileStmt.getBody()); + if (cpdStmt != nullptr) { + clang::CompoundStmt::const_body_iterator it; + for (it = cpdStmt->body_begin(); it != cpdStmt->body_end(); ++it) { + const auto *subStmt = llvm::dyn_cast(*it); + if (CheckIncContinueStmtExpr(*subStmt)) { + astStmt->SetNestContinueLabel(true); + break; + } + } + } else { + const auto *subStmt = whileStmt.getBody(); + if (CheckIncContinueStmtExpr(*subStmt)) { + astStmt->SetNestContinueLabel(true); + } + } ASTStmt *bodyStmt = ProcessStmt(allocator, *whileStmt.getBody()); astStmt->SetBodyStmt(bodyStmt); return astStmt; @@ -430,14 +517,18 @@ 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()); + ASSERT_NOT_NULL(gotoStmt.getLabel()); + ASTDecl *astDecl = ProcessDecl(allocator, *gotoStmt.getLabel()); + astStmt->SetLabelName(astDecl->GetName()); return astStmt; } ASTStmt *ASTParser::ProcessStmtIndirectGotoStmt(MapleAllocator &allocator, const clang::IndirectGotoStmt &iGotoStmt) { ASTIndirectGotoStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); - astStmt->SetASTExpr(ProcessExpr(allocator, iGotoStmt.getTarget())); + ASTExpr *astExpr = ProcessExpr(allocator, iGotoStmt.getTarget()); + astStmt->SetCallAlloca(astExpr != nullptr && astExpr->IsCallAlloca()); + astStmt->SetASTExpr(astExpr); return astStmt; } @@ -450,12 +541,16 @@ ASTStmt *ASTParser::ProcessStmtGCCAsmStmt(MapleAllocator &allocator, const clang bool isPlusConstraint = asmStmt.isOutputPlusConstraint(i); astStmt->InsertOutput(std::make_tuple(asmStmt.getOutputName(i).str(), asmStmt.getOutputConstraint(i).str(), isPlusConstraint)); - astStmt->SetASTExpr(ProcessExpr(allocator, asmStmt.getOutputExpr(i))); + ASTExpr *astExpr = ProcessExpr(allocator, asmStmt.getOutputExpr(i)); + astStmt->SetCallAlloca(astExpr != nullptr && astExpr->IsCallAlloca()); + astStmt->SetASTExpr(astExpr); } // set input for (unsigned i = 0; i < asmStmt.getNumInputs(); ++i) { astStmt->InsertInput(std::make_pair(asmStmt.getInputName(i).str(), asmStmt.getInputConstraint(i).str())); - astStmt->SetASTExpr(ProcessExpr(allocator, asmStmt.getInputExpr(i))); + ASTExpr *astExpr = ProcessExpr(allocator, asmStmt.getInputExpr(i)); + astStmt->SetCallAlloca(astExpr != nullptr && astExpr->IsCallAlloca()); + astStmt->SetASTExpr(astExpr); } // set clobbers for (unsigned i = 0; i < asmStmt.getNumClobbers(); ++i) { @@ -482,20 +577,32 @@ 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; + } + } else if (llvm::isa(stmt)) { + const auto *ifStmt = llvm::cast(&stmt); + if (HasDefault(*ifStmt->getThen())) { + return true; + } + if (ifStmt->hasElseStorage() && HasDefault(*ifStmt->getElse())) { + return true; + } } return false; } @@ -512,6 +619,7 @@ ASTStmt *ASTParser::ProcessStmtSwitchStmt(MapleAllocator &allocator, const clang if (condExpr != nullptr) { astStmt->SetCondType(astFile->CvtType(switchStmt.getCond()->getType())); } + astStmt->SetCallAlloca(condExpr != nullptr && condExpr->IsCallAlloca()); astStmt->SetCondExpr(condExpr); // switch body stmt ASTStmt *bodyStmt = switchStmt.getBody() == nullptr ? nullptr : @@ -528,6 +636,7 @@ ASTStmt *ASTParser::ProcessStmtDoStmt(MapleAllocator &allocator, const clang::Do if (condExpr == nullptr) { return nullptr; } + astStmt->SetCallAlloca(condExpr->IsCallAlloca()); astStmt->SetCondExpr(condExpr); ASTStmt *bodyStmt = ProcessStmt(allocator, *doStmt.getBody()); astStmt->SetBodyStmt(bodyStmt); @@ -544,10 +653,31 @@ 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) { + ASTExpr *astExpr = astSubStmt->GetExprs().back(); + astStmt->SetCallAlloca(astExpr != nullptr && astExpr->IsCallAlloca()); + astStmt->SetASTExpr(astExpr); + } + 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->SetCallAlloca(astExpr->IsCallAlloca()); + astStmt->SetASTExpr(astExpr); return astStmt; } @@ -596,47 +726,76 @@ ASTStmt *ASTParser::ProcessStmtContinueStmt(MapleAllocator &allocator, const cla ASTStmt *ASTParser::ProcessStmtDeclStmt(MapleAllocator &allocator, const clang::DeclStmt &declStmt) { ASTDeclStmt *astStmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); CHECK_FATAL(astStmt != nullptr, "astStmt is nullptr"); + std::list decls; if (declStmt.isSingleDecl()) { const clang::Decl *decl = declStmt.getSingleDecl(); if (decl != nullptr) { - ASTDecl *ad = ProcessDecl(allocator, *decl); - if (decl->getKind() == clang::Decl::Var) { - const clang::VarDecl *varDecl = llvm::cast(decl); - ASTExpr *expr = ProcessExprInType(allocator, varDecl->getType()); - if (expr != nullptr) { - astStmt->SetASTExpr(expr); - } - } - // extern func decl in function - if (decl->getKind() == clang::Decl::Function) { - astFuncs.emplace_back(static_cast(ad)); - } - if (ad != nullptr) { - astStmt->SetSubDecl(ad); - } + (void)decls.emplace_back(decl); } } else { // multiple decls clang::DeclGroupRef declGroupRef = declStmt.getDeclGroup(); clang::DeclGroupRef::const_iterator it; for (it = declGroupRef.begin(); it != declGroupRef.end(); ++it) { - ASTDecl *ad = ProcessDecl(allocator, **it); - if ((*it)->getKind() == clang::Decl::Var) { - const clang::VarDecl *varDecl = llvm::cast(*it); - ASTExpr *expr = ProcessExprInType(allocator, varDecl->getType()); - if (expr != nullptr) { - astStmt->SetASTExpr(expr); - } - } - if (ad != nullptr) { - astStmt->SetSubDecl(ad); + (void)decls.emplace_back(*it); + } + } + bool isCallAlloca = false; + for (auto decl : std::as_const(decls)) { + // save vla size expr + MapleList astExprs(allocator.Adapter()); + if (decl->getKind() == clang::Decl::Var) { + const clang::VarDecl *varDecl = llvm::cast(decl); + SaveVLASizeExpr(allocator, *(varDecl->getType().getCanonicalType().getTypePtr()), astExprs); + } else if (decl->getKind() == clang::Decl::Typedef) { + clang::QualType underType = llvm::cast(decl)->getUnderlyingType(); + SaveVLASizeExpr(allocator, *(underType.getCanonicalType().getTypePtr()), astExprs); + } + for (auto expr : std::as_const(astExprs)) { + astStmt->SetVLASizeExpr(expr); + } + ASTDecl *ad = ProcessDecl(allocator, *decl); + // extern func decl in function + if (decl->getKind() == clang::Decl::Function) { + const clang::FunctionDecl *funcDecl = llvm::cast(decl); + if (!funcDecl->isDefined()) { + astFuncs.emplace_back(static_cast(ad)); } } + if (ad != nullptr) { + astStmt->SetSubDecl(ad); + isCallAlloca = isCallAlloca || ad->IsCallAlloca(); + } + } + astStmt->SetCallAlloca(isCallAlloca); + 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->SetCallAlloca(astExpr->IsCallAlloca()); + 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->SetCallAlloca(astExpr->IsCallAlloca()); + astStmt->SetASTExpr(astExpr); return astStmt; } ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, const clang::Expr *expr) const { + ASSERT_NOT_NULL(expr); ASTValue *astValue = nullptr; clang::Expr::EvalResult result; if (expr->getStmtClass() == clang::Stmt::StringLiteralClass && @@ -648,6 +807,7 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, return TranslateLValue2ASTValue(allocator, result, expr); } auto *constMirType = astFile->CvtType(expr->getType().getCanonicalType()); + ASSERT_NOT_NULL(constMirType); if (result.Val.isInt()) { astValue = AllocASTValue(allocator); switch (constMirType->GetPrimType()) { @@ -684,6 +844,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 +875,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,20 +905,30 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, break; case llvm::APFloat::S_IEEEquad: case llvm::APFloat::S_PPCDoubleDouble: - case llvm::APFloat::S_x87DoubleExtended: - bool LosesInfo; + 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(), - llvm::APFloatBase::rmNearestTiesToAway, - &LosesInfo); + llvm::APFloatBase::rmNearestTiesToAway, + &losesInfo); astValue->val.f64 = fValue.convertToDouble(); } else { (void)fValue.convert(llvm::APFloat::IEEEsingle(), llvm::APFloatBase::rmNearestTiesToAway, - &LosesInfo); + &losesInfo); astValue->val.f32 = fValue.convertToFloat(); } break; + } default: CHECK_FATAL(false, "unsupported semantics"); } @@ -764,6 +948,7 @@ ASTValue *ASTParser::TranslateConstantValue2ASTValue(MapleAllocator &allocator, ASTValue *ASTParser::TranslateLValue2ASTValue( MapleAllocator &allocator, const clang::Expr::EvalResult &result, const clang::Expr *expr) const { + ASSERT_NOT_NULL(expr); ASTValue *astValue = nullptr; const clang::APValue::LValueBase &lvBase = result.Val.getLValueBase(); if (lvBase.is()) { @@ -783,6 +968,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,53 +1029,84 @@ 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; \ } ASTExpr *ASTParser::EvaluateExprAsConst(MapleAllocator &allocator, const clang::Expr *expr) { + ASSERT_NOT_NULL(expr); clang::Expr::EvalResult constResult; if (!expr->EvaluateAsConstantExpr(constResult, *astFile->GetNonConstAstContext())) { 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; - (void)floatVal.convert(llvm::APFloat::IEEEdouble(), - llvm::APFloatBase::rmNearestTiesToAway, - &losesInfo); + (void)floatVal.convert(llvm::APFloat::IEEEdouble(), 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) { + ASSERT_NOT_NULL(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; @@ -939,16 +1162,8 @@ ASTExpr *ASTParser::ProcessExpr(MapleAllocator &allocator, const clang::Expr *ex } } -ASTExpr *ASTParser::ProcessExprInType(MapleAllocator &allocator, const clang::QualType &qualType) { - const clang::Type *type = qualType.getCanonicalType().getTypePtr(); - if (type->isVariableArrayType()) { - const clang::VariableArrayType *vAType = llvm::cast(type); - return ProcessExpr(allocator, vAType->getSizeExpr()); - } - return nullptr; -} - -ASTUnaryOperatorExpr *ASTParser::AllocUnaryOperatorExpr(MapleAllocator &allocator, const clang::UnaryOperator &expr) { +ASTUnaryOperatorExpr *ASTParser::AllocUnaryOperatorExpr(MapleAllocator &allocator, + const clang::UnaryOperator &expr) const { clang::UnaryOperator::Opcode clangOpCode = expr.getOpcode(); switch (clangOpCode) { case clang::UO_Minus: // "-" @@ -988,7 +1203,7 @@ ASTValue *ASTParser::AllocASTValue(const MapleAllocator &allocator) const { return allocator.GetMemPool()->New(); } -const clang::Expr *ASTParser::PeelParen(const clang::Expr &expr) { +const clang::Expr *ASTParser::PeelParen(const clang::Expr &expr) const { const clang::Expr *exprPtr = &expr; while (llvm::isa(exprPtr) || (llvm::isa(exprPtr) && @@ -1006,7 +1221,7 @@ const clang::Expr *ASTParser::PeelParen(const clang::Expr &expr) { return exprPtr; } -const clang::Expr *ASTParser::PeelParen2(const clang::Expr &expr) { +const clang::Expr *ASTParser::PeelParen2(const clang::Expr &expr) const { const clang::Expr *exprPtr = &expr; while (llvm::isa(exprPtr) || (llvm::isa(exprPtr) && @@ -1039,17 +1254,25 @@ ASTExpr *ASTParser::ProcessExprUnaryOperator(MapleAllocator &allocator, const cl if (subType->GetPrimType() == PTY_ptr) { int64 len; const clang::QualType qualType = subExpr->getType()->getPointeeType(); - if (astFile->CvtType(qualType)->GetPrimType() == PTY_ptr) { - MIRType *pointeeType = GlobalTables::GetTypeTable().GetPtr(); + const clang::QualType desugaredType = qualType.getDesugaredType(*(astFile->GetContext())); + MIRType *pointeeType = GlobalTables::GetTypeTable().GetPtr(); + MIRType *mirType = astFile->CvtType(qualType); + if (mirType != nullptr && mirType->GetPrimType() == PTY_ptr && !qualType->isVariableArrayType()) { len = static_cast(pointeeType->GetSize()); + astUOExpr->SetPointeeLen(len); + } else if (qualType->isVariableArrayType()) { + astUOExpr->SetisVariableArrayType(true); + ASTExpr *vlaTypeSizeExpr = BuildExprToComputeSizeFromVLA(allocator, desugaredType); + astUOExpr->SetVariableArrayExpr(vlaTypeSizeExpr); } else { const clang::QualType desugaredType = qualType.getDesugaredType(*(astFile->GetContext())); len = astFile->GetContext()->getTypeSizeInChars(desugaredType).getQuantity(); + astUOExpr->SetPointeeLen(len); } - astUOExpr->SetPointeeLen(len); } } if (clangOpCode == clang::UO_Imag || clangOpCode == clang::UO_Real) { + CHECK_FATAL(uo.getSubExpr()->getType().getCanonicalType()->isAnyComplexType(), "Unsupported complex value in MIR"); clang::QualType elementType = llvm::cast( uo.getSubExpr()->getType().getCanonicalType())->getElementType(); MIRType *elementMirType = astFile->CvtType(elementType); @@ -1063,6 +1286,12 @@ ASTExpr *ASTParser::ProcessExprUnaryOperator(MapleAllocator &allocator, const cl if (astExpr == nullptr) { return nullptr; } + astUOExpr->SetCallAlloca(astExpr->IsCallAlloca()); + /* vla as a pointer and typedef is no need to be addrof */ + if (clangOpCode == clang::UO_AddrOf && subExpr->getType()->isVariableArrayType() && + llvm::isa(subExpr->getType())) { + return astExpr; + } astUOExpr->SetASTDecl(astExpr->GetASTDecl()); astUOExpr->SetUOExpr(astExpr); return astUOExpr; @@ -1071,8 +1300,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; } @@ -1093,6 +1323,7 @@ ASTExpr *ASTParser::ProcessExprPredefinedExpr(MapleAllocator &allocator, const c if (astExpr == nullptr) { return nullptr; } + astPredefinedExpr->SetCallAlloca(astExpr->IsCallAlloca()); astPredefinedExpr->SetASTExpr(astExpr); return astPredefinedExpr; } @@ -1104,6 +1335,7 @@ ASTExpr *ASTParser::ProcessExprOpaqueValueExpr(MapleAllocator &allocator, const if (astExpr == nullptr) { return nullptr; } + astOpaqueValueExpr->SetCallAlloca(astExpr->IsCallAlloca()); astOpaqueValueExpr->SetASTExpr(astExpr); return astOpaqueValueExpr; } @@ -1127,36 +1359,54 @@ ASTExpr *ASTParser::ProcessExprBinaryConditionalOperator(MapleAllocator &allocat return astBinaryConditionalOperator; } +ASTExpr *ASTParser::ProcessTypeofExpr(MapleAllocator &allocator, clang::QualType type) { + ASTExpr *astExpr = nullptr; + const clang::TypeOfExprType *typeofType = llvm::cast(type); + if (typeofType->isArrayType() || typeofType->isPointerType()) { + astExpr = ProcessExpr(allocator, typeofType->getUnderlyingExpr()); + } + return astExpr; +} + ASTExpr *ASTParser::ProcessExprCompoundLiteralExpr(MapleAllocator &allocator, const clang::CompoundLiteralExpr &expr) { ASTCompoundLiteralExpr *astCompoundLiteralExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); CHECK_FATAL(astCompoundLiteralExpr != nullptr, "astCompoundLiteralExpr is nullptr"); + clang::QualType type = expr.getType(); + ASTExpr *astExpr = nullptr; + if (type.getTypePtr()->getTypeClass() == clang::Type::TypeOfExpr) { + astExpr = ProcessTypeofExpr(allocator, type); + } + if (astExpr != nullptr) { + astCompoundLiteralExpr->SetVariableArrayExpr(astExpr); + } const clang::Expr *initExpr = expr.getInitializer(); 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 = ProcessExpr(allocator, initExpr); if (astExpr == nullptr) { return nullptr; } - static uint32 unNamedCount = 0; - auto initListName = astFile->GetOrCreateCompoundLiteralExprInitName(unNamedCount++); - astCompoundLiteralExpr->SetInitName(initListName); + astCompoundLiteralExpr->SetCallAlloca(astExpr->IsCallAlloca()); astCompoundLiteralExpr->SetASTExpr(astExpr); return astCompoundLiteralExpr; } +void ASTParser::ParserExprVLASizeExpr(MapleAllocator &allocator, const clang::Type &type, ASTExpr &expr) { + MapleList vlaExprs(allocator.Adapter()); + SaveVLASizeExpr(allocator, type, vlaExprs); + expr.SetVLASizeExprs(std::move(vlaExprs)); +} + ASTExpr *ASTParser::ProcessExprInitListExpr(MapleAllocator &allocator, const clang::InitListExpr &expr) { ASTInitListExpr *astInitListExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); CHECK_FATAL(astInitListExpr != nullptr, "ASTInitListExpr is nullptr"); - MIRType *initListType = astFile->CvtType(expr.getType()); + const clang::Type *type = nullptr; + MIRType *initListType = astFile->CvtType(expr.getType(), false, &type); + if (type != nullptr) { + ParserExprVLASizeExpr(allocator, *type, *astInitListExpr); + } clang::QualType aggType = expr.getType().getCanonicalType(); astInitListExpr->SetInitListType(initListType); const clang::FieldDecl *fieldDecl = expr.getInitializedFieldInUnion(); @@ -1165,12 +1415,14 @@ 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(); ASTDecl *astDecl = ProcessDecl(allocator, *recordDecl); CHECK_FATAL(astDecl != nullptr && astDecl->GetDeclKind() == kASTStruct, "Undefined record type"); uint i = 0; + bool isCallAlloca = false; for (const auto field : static_cast(astDecl)->GetFields()) { if (field->IsAnonymousField() && fieldDecl == nullptr && n != static_cast(astDecl)->GetFields().size()) { @@ -1180,14 +1432,18 @@ ASTExpr *ASTParser::ProcessExprInitListExpr(MapleAllocator &allocator, const cla const clang::Expr *eExpr = le[i]; ASTExpr *astExpr = ProcessExpr(allocator, eExpr); CHECK_FATAL(astExpr != nullptr, "Invalid InitListExpr"); + (void)evaluatedFlags.insert(astExpr->GetEvaluatedFlag()); + isCallAlloca = astExpr->IsCallAlloca() || isCallAlloca; astInitListExpr->SetInitExprs(astExpr); i++; } } } + astInitListExpr->SetCallAlloca(isCallAlloca); } else { if (expr.hasArrayFiller()) { auto *astFilterExpr = ProcessExpr(allocator, expr.getArrayFiller()); + astInitListExpr->SetCallAlloca(astFilterExpr != nullptr && astFilterExpr->IsCallAlloca()); astInitListExpr->SetArrayFiller(astFilterExpr); astInitListExpr->SetHasArrayFiller(true); } @@ -1201,14 +1457,23 @@ ASTExpr *ASTParser::ProcessExprInitListExpr(MapleAllocator &allocator, const cla astInitListExpr->SetTransparent(true); } } + bool isCallAlloca = false; for (uint32 i = 0; i < n; ++i) { const clang::Expr *eExpr = le[i]; ASTExpr *astExpr = ProcessExpr(allocator, eExpr); if (astExpr == nullptr) { return nullptr; } + isCallAlloca = isCallAlloca || astExpr->IsCallAlloca(); + (void)evaluatedFlags.insert(astExpr->GetEvaluatedFlag()); astInitListExpr->SetInitExprs(astExpr); } + astInitListExpr->SetCallAlloca(isCallAlloca); + } + if (evaluatedFlags.count(kNotEvaluated) > 0 || evaluatedFlags.count(kEvaluatedAsNonZero) > 0) { + astInitListExpr->SetEvaluatedFlag(kEvaluatedAsNonZero); + } else { + astInitListExpr->SetEvaluatedFlag(kEvaluatedAsZero); } return astInitListExpr; } @@ -1236,6 +1501,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); @@ -1293,8 +1559,13 @@ ASTExpr *ASTParser::ProcessExprVAArgExpr(MapleAllocator &allocator, const clang: if (astExpr == nullptr) { return nullptr; } + astVAArgExpr->SetCallAlloca(astExpr->IsCallAlloca()); astVAArgExpr->SetASTExpr(astExpr); - astVAArgExpr->SetType(astFile->CvtType(expr.getType())); + const clang::Type *type = nullptr; + astVAArgExpr->SetType(astFile->CvtType(expr.getType(), false, &type)); + if (type != nullptr) { + ParserExprVLASizeExpr(allocator, *type, *astVAArgExpr); + } return astVAArgExpr; } @@ -1303,6 +1574,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 +1583,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; } @@ -1327,29 +1602,33 @@ ASTExpr *ASTParser::ProcessExprArraySubscriptExpr(MapleAllocator &allocator, con base = PeelParen2(*base); ASTExpr *idxExpr = ProcessExpr(allocator, expr.getIdx()); astArraySubscriptExpr->SetIdxExpr(idxExpr); - + astArraySubscriptExpr->SetCallAlloca(idxExpr != nullptr && idxExpr->IsCallAlloca()); clang::QualType arrayQualType = base->getType().getCanonicalType(); if (base->getStmtClass() == clang::Stmt::ImplicitCastExprClass && !static_cast(base)->isPartOfExplicitCast()) { arrayQualType = static_cast(base)->getSubExpr()->getType().getCanonicalType(); } + + CHECK_FATAL(!arrayQualType->isVectorType(), "Unsupported vector type in astArraySubscriptExpr"); + auto arrayMirType = astFile->CvtType(arrayQualType); 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->SetCallAlloca(astBaseExpr != nullptr && astBaseExpr->IsCallAlloca()); astArraySubscriptExpr->SetBaseExpr(astBaseExpr); auto *mirType = astFile->CvtType(exprType); astArraySubscriptExpr->SetType(mirType); return astArraySubscriptExpr; } -uint32 ASTParser::GetSizeFromQualType(const clang::QualType qualType) { +uint32 ASTParser::GetSizeFromQualType(const clang::QualType qualType) const { const clang::QualType desugaredType = qualType.getDesugaredType(*astFile->GetContext()); return astFile->GetContext()->getTypeSizeInChars(desugaredType).getQuantity(); } @@ -1374,7 +1653,7 @@ ASTExpr *ASTParser::GetTypeSizeFromQualType(MapleAllocator &allocator, const cla } } -uint32_t ASTParser::GetAlignOfType(const clang::QualType currQualType, clang::UnaryExprOrTypeTrait exprKind) { +uint32_t ASTParser::GetAlignOfType(const clang::QualType currQualType, clang::UnaryExprOrTypeTrait exprKind) const { clang::QualType qualType = currQualType; clang::CharUnits alignInCharUnits = clang::CharUnits::Zero(); if (const auto *ref = currQualType->getAs()) { @@ -1394,7 +1673,7 @@ uint32_t ASTParser::GetAlignOfType(const clang::QualType currQualType, clang::Un return static_cast(alignInCharUnits.getQuantity()); } -uint32_t ASTParser::GetAlignOfExpr(const clang::Expr &expr, clang::UnaryExprOrTypeTrait exprKind) { +uint32_t ASTParser::GetAlignOfExpr(const clang::Expr &expr, clang::UnaryExprOrTypeTrait exprKind) const { clang::CharUnits alignInCharUnits = clang::CharUnits::Zero(); const clang::Expr *exprNoParens = expr.IgnoreParens(); if (const auto *declRefExpr = clang::dyn_cast(exprNoParens)) { @@ -1407,15 +1686,15 @@ uint32_t ASTParser::GetAlignOfExpr(const clang::Expr &expr, clang::UnaryExprOrTy return static_cast(alignInCharUnits.getQuantity()); } -ASTExpr *ASTParser::GetAddrShiftExpr(MapleAllocator &allocator, ASTExpr *expr, uint32 typeSize) { +ASTExpr *ASTParser::GetAddrShiftExpr(MapleAllocator &allocator, ASTExpr &expr, uint32 typeSize) { MIRType *retType = nullptr; - if (IsSignedInteger(expr->GetType()->GetPrimType())) { + if (IsSignedInteger(expr.GetType()->GetPrimType())) { retType = GlobalTables::GetTypeTable().GetInt64(); } else { retType = GlobalTables::GetTypeTable().GetPtr(); } - if (expr->GetASTOp() == kASTIntegerLiteral) { - auto intExpr = static_cast(expr); + if (expr.GetASTOp() == kASTIntegerLiteral) { + auto intExpr = static_cast(&expr); auto retExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); retExpr->SetVal(intExpr->GetVal() * typeSize); retExpr->SetType(retType); @@ -1425,11 +1704,29 @@ ASTExpr *ASTParser::GetAddrShiftExpr(MapleAllocator &allocator, ASTExpr *expr, u ptrSizeExpr->SetVal(typeSize); ptrSizeExpr->SetType(retType); auto shiftExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); - shiftExpr->SetLeftExpr(expr); + shiftExpr->SetLeftExpr(&expr); shiftExpr->SetRightExpr(ptrSizeExpr); 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; } @@ -1438,8 +1735,16 @@ ASTExpr *ASTParser::BuildExprToComputeSizeFromVLA(MapleAllocator &allocator, con ASTExpr *lhs = BuildExprToComputeSizeFromVLA(allocator, llvm::cast(qualType)->getElementType()); ASTExpr *rhs = nullptr; CHECK_FATAL(llvm::isa(qualType), "the type must be array type"); + clang::Expr *sizeExpr = nullptr; if (llvm::isa(qualType)) { - clang::Expr *sizeExpr = llvm::cast(qualType)->getSizeExpr(); + sizeExpr = llvm::cast(qualType)->getSizeExpr(); + if (sizeExpr == nullptr) { + return nullptr; + } + MapleMap::const_iterator iter = vlaSizeMap.find(sizeExpr); + if (iter != vlaSizeMap.cend()) { + return iter->second; + } rhs = ProcessExpr(allocator, sizeExpr); CHECK_FATAL(sizeExpr->getType()->isIntegerType(), "the type should be integer"); } else if (llvm::isa(qualType)) { @@ -1468,6 +1773,52 @@ ASTExpr *ASTParser::BuildExprToComputeSizeFromVLA(MapleAllocator &allocator, con return integerExpr; } +ASTExpr *ASTParser::GetSizeOfExpr(MapleAllocator &allocator, const clang::UnaryExprOrTypeTraitExpr &expr, + clang::QualType qualType) { + auto *astExprUnaryExprOrTypeTraitExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + CHECK_FATAL(astExprUnaryExprOrTypeTraitExpr != nullptr, "astExprUnaryExprOrTypeTraitExpr is nullptr"); + ASTExpr *astExpr = ProcessExpr(allocator, expr.getArgumentExpr()); + if (astExpr == nullptr) { + return nullptr; + } + astExprUnaryExprOrTypeTraitExpr->SetIdxExpr(astExpr); + ASTExpr *rhs = nullptr; + ASTExpr *lhs = BuildExprToComputeSizeFromVLA(allocator, llvm::cast(qualType)->getElementType()); + clang::Expr *sizeExpr = llvm::cast(qualType)->getSizeExpr(); + if (sizeExpr == nullptr) { + return nullptr; + } + MapleMap::const_iterator iter = vlaSizeMap.find(sizeExpr); + if (iter != vlaSizeMap.cend()) { + astExprUnaryExprOrTypeTraitExpr->SetSizeExpr(iter->second); + return astExprUnaryExprOrTypeTraitExpr; + } + rhs = ProcessExpr(allocator, sizeExpr); + auto *astBOExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + astBOExpr->SetRetType(GlobalTables::GetTypeTable().GetPrimType(PTY_u64)); + astBOExpr->SetOpcode(OP_mul); + astBOExpr->SetLeftExpr(lhs); + astBOExpr->SetRightExpr(rhs); + astExprUnaryExprOrTypeTraitExpr->SetSizeExpr(astBOExpr); + return astExprUnaryExprOrTypeTraitExpr; +} + +ASTExpr *ASTParser::GetSizeOfType(MapleAllocator &allocator, const clang::QualType &qualType) { + auto *astExprUnaryExprOrTypeTraitExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + CHECK_FATAL(astExprUnaryExprOrTypeTraitExpr != nullptr, "astExprUnaryExprOrTypeTraitExpr is nullptr"); + if (llvm::isa(qualType)) { + ASTExpr *vlaSizeExpr = BuildExprToComputeSizeFromVLA(allocator, qualType); + astExprUnaryExprOrTypeTraitExpr->SetSizeExpr(vlaSizeExpr); + return astExprUnaryExprOrTypeTraitExpr; + } + uint32 size = GetSizeFromQualType(qualType); + auto sizeExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + sizeExpr->SetType(GlobalTables::GetTypeTable().GetUInt64()); + sizeExpr->SetVal(size); + astExprUnaryExprOrTypeTraitExpr->SetSizeExpr(sizeExpr); + return astExprUnaryExprOrTypeTraitExpr; +} + ASTExpr *ASTParser::ProcessExprUnaryExprOrTypeTraitExpr(MapleAllocator &allocator, const clang::UnaryExprOrTypeTraitExpr &expr) { auto *astExprUnaryExprOrTypeTraitExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); @@ -1476,14 +1827,11 @@ ASTExpr *ASTParser::ProcessExprUnaryExprOrTypeTraitExpr(MapleAllocator &allocato case clang::UETT_SizeOf: { clang::QualType qualType = expr.isArgumentType() ? expr.getArgumentType().getCanonicalType() : expr.getArgumentExpr()->getType().getCanonicalType(); - if (llvm::isa(qualType)) { - return BuildExprToComputeSizeFromVLA(allocator, qualType); + if (expr.isArgumentType()) { + return GetSizeOfType(allocator, qualType); + } else { + return GetSizeOfExpr(allocator, expr, qualType); } - uint32 size = GetSizeFromQualType(qualType); - auto integerExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); - integerExpr->SetType(GlobalTables::GetTypeTable().GetUInt64()); - integerExpr->SetVal(size); - return integerExpr; } case clang::UETT_PreferredAlignOf: case clang::UETT_AlignOf: { @@ -1520,8 +1868,7 @@ ASTExpr *ASTParser::ProcessExprMemberExpr(MapleAllocator &allocator, const clang astMemberExpr->SetBaseType(astFile->CvtType(expr.getBase()->getType())); auto memberName = expr.getMemberDecl()->getNameAsString(); if (memberName.empty()) { - uint32 id = expr.getMemberDecl()->getLocation().getRawEncoding(); - memberName = astFile->GetOrCreateMappedUnnamedName(id); + memberName = astFile->GetOrCreateMappedUnnamedName(*expr.getMemberDecl()); } astMemberExpr->SetMemberName(memberName); astMemberExpr->SetMemberType(astFile->CvtType(expr.getMemberDecl()->getType())); @@ -1565,16 +1912,19 @@ ASTExpr *ASTParser::ProcessExprConditionalOperator(MapleAllocator &allocator, co if (astExpr == nullptr) { return nullptr; } + astConditionalOperator->SetCallAlloca(astExpr->IsCallAlloca()); astConditionalOperator->SetCondExpr(astExpr); ASTExpr *astTrueExpr = ProcessExpr(allocator, expr.getTrueExpr()); if (astTrueExpr == nullptr) { return nullptr; } + astConditionalOperator->SetCallAlloca(astTrueExpr->IsCallAlloca()); astConditionalOperator->SetTrueExpr(astTrueExpr); ASTExpr *astFalseExpr = ProcessExpr(allocator, expr.getFalseExpr()); if (astFalseExpr == nullptr) { return nullptr; } + astConditionalOperator->SetCallAlloca(astFalseExpr->IsCallAlloca()); astConditionalOperator->SetFalseExpr(astFalseExpr); astConditionalOperator->SetType(astFile->CvtType(expr.getType())); return astConditionalOperator; @@ -1631,6 +1981,7 @@ ASTExpr *ASTParser::ProcessExprConstantExpr(MapleAllocator &allocator, const cla if (astExpr == nullptr) { return nullptr; } + astConstantExpr->SetCallAlloca(astExpr->IsCallAlloca()); astConstantExpr->SetASTExpr(astExpr); return astConstantExpr; } @@ -1649,6 +2000,7 @@ ASTExpr *ASTParser::ProcessExprImaginaryLiteral(MapleAllocator &allocator, const if (astExpr == nullptr) { return nullptr; } + astImaginaryLiteral->SetCallAlloca(astExpr->IsCallAlloca()); astImaginaryLiteral->SetASTExpr(astExpr); return astImaginaryLiteral; } @@ -1656,6 +2008,11 @@ ASTExpr *ASTParser::ProcessExprImaginaryLiteral(MapleAllocator &allocator, const std::map ASTParser::builtingFuncPtrMap = ASTParser::InitBuiltinFuncPtrMap(); +bool ASTParser::IsNeedGetPointeeType(const clang::FunctionDecl &funcDecl) const { + std::string funcNameStr = funcDecl.getNameAsString(); + return (funcNameStr.find("__sync") != std::string::npos || funcNameStr.find("__atomic") != std::string::npos); +} + ASTExpr *ASTParser::ProcessExprCallExpr(MapleAllocator &allocator, const clang::CallExpr &expr) { ASTCallExpr *astCallExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); ASSERT(astCallExpr != nullptr, "astCallExpr is nullptr"); @@ -1666,19 +2023,26 @@ ASTExpr *ASTParser::ProcessExprCallExpr(MapleAllocator &allocator, const clang:: } astCallExpr->SetCalleeExpr(astCallee); // return - MIRType *retType = astFile->CvtType(expr.getCallReturnType(*astFile->GetAstContext())); - astCallExpr->SetRetType(retType); + astCallExpr->SetType(astFile->CvtType(expr.getType())); + // return var attrs + GenericAttrs returnVarAttrs; + astFile->CollectFuncReturnVarAttrs(expr, returnVarAttrs); + astCallExpr->SetReturnVarAttrs(returnVarAttrs); // args - std::vector args; + MapleVector args(allocator.Adapter()); + const clang::FunctionDecl *funcDecl = expr.getDirectCallee(); for (uint32_t i = 0; i < expr.getNumArgs(); ++i) { const clang::Expr *subExpr = expr.getArg(i); ASTExpr *arg = ProcessExpr(allocator, subExpr); - arg->SetType(astFile->CvtType(subExpr->getType())); + clang::QualType type = subExpr->getType(); + if (funcDecl != nullptr && IsNeedGetPointeeType(*funcDecl)) { + type = GetPointeeType(*subExpr); + } + arg->SetType(astFile->CvtType(type)); args.push_back(arg); } astCallExpr->SetArgs(args); // Obtain the function name directly - const clang::FunctionDecl *funcDecl = expr.getDirectCallee(); if (funcDecl != nullptr) { std::string funcName = astFile->GetMangledName(*funcDecl); funcName = astCallExpr->CvtBuiltInFuncName(funcName); @@ -1697,23 +2061,19 @@ ASTExpr *ASTParser::ProcessExprCallExpr(MapleAllocator &allocator, const clang:: } funcName = ss.str(); } - - GenericAttrs attrs; - astFile->CollectFuncAttrs(*funcDecl, attrs, kPublic); - // for inline optimize - if (attrs.GetAttr(GENATTR_static) && FEOptions::GetInstance().GetFuncInlineSize() != 0) { - funcName = funcName + astFile->GetAstFileNameHashStr(); + if (funcName == kBuiltinAlloca || funcName == kAlloca || funcName == kBuiltinAllocaWithAlign) { + astCallExpr->SetCallAlloca(true); } + GenericAttrs attrs = SolveFunctionAttributes(*funcDecl, funcName); astCallExpr->SetFuncName(funcName); astCallExpr->SetFuncAttrs(attrs.ConvertToFuncAttrs()); - ASTFunc *astFunc = static_cast(ASTDeclsBuilder::GetASTDecl(funcDecl->getID())); + ASTFunc *astFunc = static_cast(ProcessDecl(allocator, *funcDecl)); if (astFunc != nullptr) { astCallExpr->SetFuncDecl(astFunc); } } else { astCallExpr->SetIcall(true); } - astCallExpr->SetType(astFile->CvtType(expr.getType())); return astCallExpr; } @@ -1724,6 +2084,8 @@ ASTExpr *ASTParser::ProcessExprParenExpr(MapleAllocator &allocator, const clang: if (astExpr == nullptr) { return nullptr; } + astParenExpr->SetEvaluatedFlag(astExpr->GetEvaluatedFlag()); + astParenExpr->SetCallAlloca(astExpr->IsCallAlloca()); astParenExpr->SetASTExpr(astExpr); return astParenExpr; } @@ -1787,11 +2149,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 +2161,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"); @@ -1807,25 +2169,36 @@ ASTExpr *ASTParser::ProcessExprFloatingLiteral(MapleAllocator &allocator, const return astFloatingLiteral; } -ASTExpr *ASTParser::ProcessExprCastExpr(MapleAllocator &allocator, const clang::CastExpr &expr) { +ASTExpr *ASTParser::ProcessExprCastExpr(MapleAllocator &allocator, const clang::CastExpr &expr, + const clang::Type **vlaType) { ASTCastExpr *astCastExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); CHECK_FATAL(astCastExpr != nullptr, "astCastExpr is nullptr"); - MIRType *srcType = astFile->CvtType(expr.getSubExpr()->getType()); - MIRType *toType = astFile->CvtType(expr.getType()); + const clang::Type *type = nullptr; + MIRType *srcType = astFile->CvtType(expr.getSubExpr()->getType(), false, &type); + MIRType *toType = astFile->CvtType(expr.getType(), false, &type); + if (vlaType != nullptr) { + *vlaType = type; + } astCastExpr->SetSrcType(srcType); astCastExpr->SetDstType(toType); - switch (expr.getCastKind()) { case clang::CK_NoOp: case clang::CK_ToVoid: + break; case clang::CK_FunctionToPointerDecay: + astCastExpr->SetIsFunctionToPointerDecay(true); + break; 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 +2256,9 @@ ASTExpr *ASTParser::ProcessExprCastExpr(MapleAllocator &allocator, const clang:: if (astExpr == nullptr) { return nullptr; } + astExpr->SetRValue(astCastExpr->IsRValue()); + astCastExpr->SetEvaluatedFlag(astExpr->GetEvaluatedFlag()); + astCastExpr->SetCallAlloca(astExpr->IsCallAlloca()); astCastExpr->SetASTExpr(astExpr); return astCastExpr; } @@ -1915,7 +2291,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) { @@ -1948,6 +2323,45 @@ ASTExpr *ASTParser::ProcessExprBinaryOperatorComplex(MapleAllocator &allocator, return astBinOpExpr; } +ASTExpr *ASTParser::SolvePointerOffsetOperation(MapleAllocator &allocator, const clang::BinaryOperator &bo, + ASTBinaryOperatorExpr &astBinOpExpr, ASTExpr &astRExpr, + ASTExpr &astLExpr) { + auto boType = bo.getType().getCanonicalType(); + auto lhsType = bo.getLHS()->getType().getCanonicalType(); + auto rhsType = bo.getRHS()->getType().getCanonicalType(); + auto boMirType = astFile->CvtType(boType); + 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. + return astSizeExpr; +} + +ASTExpr *ASTParser::SolvePointerSubPointerOperation(MapleAllocator &allocator, const clang::BinaryOperator &bo, + ASTBinaryOperatorExpr &astBinOpExpr) const { + auto rhsType = bo.getRHS()->getType().getCanonicalType(); + auto ptrSizeExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + ptrSizeExpr->SetType(astBinOpExpr.GetRetType()); + ptrSizeExpr->SetVal(GetSizeFromQualType(rhsType->getPointeeType())); + auto retASTExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + retASTExpr->SetLeftExpr(&astBinOpExpr); + retASTExpr->SetRightExpr(ptrSizeExpr); + retASTExpr->SetOpcode(OP_div); + retASTExpr->SetRetType(astBinOpExpr.GetRetType()); + return retASTExpr; +} + ASTExpr *ASTParser::ProcessExprBinaryOperator(MapleAllocator &allocator, const clang::BinaryOperator &bo) { ASTBinaryOperatorExpr *astBinOpExpr = AllocBinaryOperatorExpr(allocator, bo); CHECK_FATAL(astBinOpExpr != nullptr, "astBinOpExpr is nullptr"); @@ -1960,6 +2374,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))) || @@ -1969,6 +2385,8 @@ ASTExpr *ASTParser::ProcessExprBinaryOperator(MapleAllocator &allocator, const c } ASTExpr *astRExpr = ProcessExpr(allocator, bo.getRHS()); ASTExpr *astLExpr = ProcessExpr(allocator, bo.getLHS()); + ASSERT_NOT_NULL(astRExpr); + ASSERT_NOT_NULL(astLExpr); if (clangOpCode == clang::BO_Div || clangOpCode == clang::BO_Mul || clangOpCode == clang::BO_DivAssign || clangOpCode == clang::BO_MulAssign) { if (astBinOpExpr->GetRetType()->GetPrimType() == PTY_u16 || astBinOpExpr->GetRetType()->GetPrimType() == PTY_u8) { @@ -1979,8 +2397,8 @@ ASTExpr *ASTParser::ProcessExprBinaryOperator(MapleAllocator &allocator, const c } } if ((leftMirType->GetPrimType() != astBinOpExpr->GetRetType()->GetPrimType() || - rightMirType->GetPrimType() != astBinOpExpr->GetRetType()->GetPrimType()) - && (clang::BinaryOperator::isAdditiveOp(clangOpCode) || clang::BinaryOperator::isMultiplicativeOp(clangOpCode))) { + rightMirType->GetPrimType() != astBinOpExpr->GetRetType()->GetPrimType()) && + (clang::BinaryOperator::isAdditiveOp(clangOpCode) || clang::BinaryOperator::isMultiplicativeOp(clangOpCode))) { astBinOpExpr->SetCvtNeeded(true); } // ptr +/- @@ -1988,35 +2406,24 @@ ASTExpr *ASTParser::ProcessExprBinaryOperator(MapleAllocator &allocator, const c ((lhsType->isPointerType() && rhsType->isIntegerType()) || (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 - } + ASTExpr *astSizeExpr = SolvePointerOffsetOperation(allocator, bo, *astBinOpExpr, *astRExpr, *astLExpr); 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); + if (astLExpr != nullptr && astRExpr != nullptr) { + bool isCallAlloc = astLExpr->IsCallAlloca() || astRExpr->IsCallAlloca(); + astBinOpExpr->SetCallAlloca(isCallAlloc); + } // ptr - ptr if (clangOpCode == clang::BO_Sub && rhsType->isPointerType() && lhsType->isPointerType() && !rhsType->isVoidPointerType() && GetSizeFromQualType(rhsType->getPointeeType()) != 1) { - auto ptrSizeExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); - ptrSizeExpr->SetType(astBinOpExpr->GetRetType()); - ptrSizeExpr->SetVal(GetSizeFromQualType(rhsType->getPointeeType())); - auto retASTExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); - retASTExpr->SetLeftExpr(astBinOpExpr); - retASTExpr->SetRightExpr(ptrSizeExpr); - retASTExpr->SetOpcode(OP_div); - retASTExpr->SetRetType(astBinOpExpr->GetRetType()); - astBinOpExpr = retASTExpr; + astBinOpExpr = static_cast(SolvePointerSubPointerOperation(allocator, bo, *astBinOpExpr)); } if (bo.isCompoundAssignmentOp()) { auto assignExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); @@ -2051,7 +2458,14 @@ ASTDecl *ASTParser::GetAstDeclOfDeclRefExpr(MapleAllocator &allocator, const cla } ASTExpr *ASTParser::ProcessExprCStyleCastExpr(MapleAllocator &allocator, const clang::CStyleCastExpr &castExpr) { - return ProcessExprCastExpr(allocator, castExpr); + ASTCastExpr *astCastExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); + CHECK_FATAL(astCastExpr != nullptr, "astCastExpr is nullptr"); + const clang::Type *type = nullptr; + astCastExpr = static_cast(ProcessExprCastExpr(allocator, castExpr, &type)); + if (type != nullptr) { + ParserExprVLASizeExpr(allocator, *type, *astCastExpr); + } + return astCastExpr; } ASTExpr *ASTParser::ProcessExprArrayInitLoopExpr(MapleAllocator &allocator, @@ -2073,6 +2487,65 @@ ASTExpr *ASTParser::ProcessExprArrayInitIndexExpr(MapleAllocator &allocator, return astExpr; } +clang::Expr *ASTParser::GetAtomValExpr(clang::Expr *valExpr) { + clang::Expr *atomValExpr = valExpr; + while (llvm::isa(atomValExpr) || llvm::isa(atomValExpr) || + llvm::isa(atomValExpr)) { + if (llvm::isa(atomValExpr)) { + auto expr = llvm::cast(atomValExpr); + atomValExpr = expr->getSubExpr(); + } else { + auto expr = llvm::cast(atomValExpr); + atomValExpr = expr->getSubExpr(); + } + } + return atomValExpr; +} + +clang::QualType ASTParser::GetPointeeType(const clang::Expr &expr) { + clang::QualType type = expr.getType().getCanonicalType(); + if (type->isPointerType() && !type->getPointeeType()->isRecordType()) { + type = type->getPointeeType(); + } + return type; +} + +void ASTParser::SetAtomExprValType(MapleAllocator &allocator, const clang::AtomicExpr &atomicExpr, + ASTAtomicExpr &astExpr) { + auto val1Expr = atomicExpr.getVal1(); + astExpr.SetValExpr1(ProcessExpr(allocator, val1Expr)); + const clang::QualType val1Type = GetPointeeType(*val1Expr); + astExpr.SetVal1Type(astFile->CvtType(val1Type)); + /* only atomic_load and atomic_store need to save second param type, for second param type is a pointer */ + if (atomicExpr.getOp() == clang::AtomicExpr::AO__atomic_load || + atomicExpr.getOp() == clang::AtomicExpr::AO__atomic_store) { + auto firstType = val1Expr->getType(); + val1Expr = GetAtomValExpr(val1Expr); + auto secondType = val1Expr->getType(); + astExpr.SetFirstParamType(astFile->CvtType(firstType->isPointerType() ? firstType->getPointeeType() : firstType)); + astExpr.SetSecondParamType(astFile->CvtType(secondType->isPointerType() ? + secondType->getPointeeType() : secondType)); + } +} + +void ASTParser::SetAtomExchangeType(MapleAllocator &allocator, const clang::AtomicExpr &atomicExpr, + ASTAtomicExpr &astExpr) { + auto val2Expr = atomicExpr.getVal2(); + auto val1Expr = atomicExpr.getVal1(); + astExpr.SetValExpr2(ProcessExpr(allocator, val2Expr)); + const clang::QualType val2Type = GetPointeeType(*val2Expr); + astExpr.SetVal2Type(astFile->CvtType(val2Type)); + auto firstType = val2Expr->getType(); + val1Expr = GetAtomValExpr(val1Expr); + auto secondType = val1Expr->getType(); + val2Expr = GetAtomValExpr(val2Expr); + auto thirdType = val2Expr->getType(); + + astExpr.SetFirstParamType(astFile->CvtType(firstType->isPointerType() ? firstType->getPointeeType() : firstType)); + astExpr.SetSecondParamType(astFile->CvtType(secondType->isPointerType() ? secondType->getPointeeType() : secondType)); + astExpr.SetThirdParamType(astFile->CvtType(thirdType->isPointerType() ? thirdType->getPointeeType() : thirdType)); +} + ASTExpr *ASTParser::ProcessExprAtomicExpr(MapleAllocator &allocator, const clang::AtomicExpr &atomicExpr) { ASTAtomicExpr *astExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); @@ -2081,12 +2554,13 @@ ASTExpr *ASTParser::ProcessExprAtomicExpr(MapleAllocator &allocator, astExpr->SetType(astFile->CvtType(atomicExpr.getPtr()->getType())); astExpr->SetRefType(astFile->CvtType(atomicExpr.getPtr()->getType()->getPointeeType())); if (atomicExpr.getOp() != clang::AtomicExpr::AO__atomic_load_n) { - astExpr->SetValExpr1(ProcessExpr(allocator, atomicExpr.getVal1())); - astExpr->SetVal1Type(astFile->CvtType(atomicExpr.getVal1()->getType())); - } - if (atomicExpr.getOp() == clang::AtomicExpr::AO__atomic_exchange) { - astExpr->SetValExpr2(ProcessExpr(allocator, atomicExpr.getVal2())); - astExpr->SetVal2Type(astFile->CvtType(atomicExpr.getVal2()->getType())); + SetAtomExprValType(allocator, atomicExpr, *astExpr); + if (atomicExpr.getOp() == clang::AtomicExpr::AO__atomic_exchange) { + SetAtomExchangeType(allocator, atomicExpr, *astExpr); + } + } else { + const clang::QualType valType = GetPointeeType(atomicExpr); + astExpr->SetVal1Type(astFile->CvtType(valType)); } astExpr->SetOrderExpr(ProcessExpr(allocator, atomicExpr.getOrder())); @@ -2110,7 +2584,9 @@ ASTExpr *ASTParser::ProcessExprAtomicExpr(MapleAllocator &allocator, {clang::AtomicExpr::AO__atomic_fetch_or, kAtomicOpFetchOr}, {clang::AtomicExpr::AO__atomic_fetch_nand, kAtomicOpFetchNand}, }; - CHECK(astOpMap.find(atomicExpr.getOp()) != astOpMap.end(), "atomic expr op not supported!"); + ASSERT(astOpMap.find(atomicExpr.getOp()) != astOpMap.end(), "%s:%d error: atomic expr op not supported!", + FEManager::GetModule().GetFileNameFromFileNum(astFile->GetLOC(atomicExpr.getBuiltinLoc()).fileIdx).c_str(), + astFile->GetLOC(atomicExpr.getBuiltinLoc()).line); astExpr->SetAtomicOp(astOpMap[atomicExpr.getOp()]); return astExpr; } @@ -2157,7 +2633,8 @@ ASTExpr *ASTParser::ProcessExprGenericSelectionExpr(MapleAllocator &allocator, c } bool ASTParser::PreProcessAST() { - TraverseDecl(astUnitDecl, [&](clang::Decl *child) { + TraverseDecl(astUnitDecl, [this](clang::Decl *child) { + ASSERT_NOT_NULL(child); switch (child->getKind()) { case clang::Decl::Var: { globalVarDecles.emplace_back(child); @@ -2191,15 +2668,16 @@ 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); \ - } \ + if (astDeclaration->GetSrcFileIdx() == 0) { \ + Loc loc = astFile->GetLOC(decl.getLocation()); \ + astDeclaration->SetSrcLoc(loc); \ + } \ + } \ return astDeclaration; \ } ASTDecl *ASTParser::ProcessDecl(MapleAllocator &allocator, const clang::Decl &decl) { @@ -2223,7 +2701,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 +2722,14 @@ 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); - } else if (FEOptions::GetInstance().GetFuncInlineSize() != 0) { - structName = structName + astFile->GetAstFileNameHashStr(); - } - curStructOrUnion = ASTDeclsBuilder::ASTStructBuilder( - allocator, fileName, structName, std::vector{recType}, attrs, recDecl.getID()); + curStructOrUnion = ASTDeclsBuilder::ASTStructBuilder(allocator, + fileName, + structName, + MapleVector({recType}, allocator.Adapter()), + attrs, + recDecl.getID()); if (recDecl.isUnion()) { curStructOrUnion->SetIsUnion(); } @@ -2285,7 +2760,7 @@ ASTDecl *ASTParser::ProcessDeclRecordDecl(MapleAllocator &allocator, const clang } if (!recDecl.isDefinedOutsideFunctionOrMethod()) { // Record function scope type decl in global with unique suffix identified - auto itor = std::find(astStructs.begin(), astStructs.end(), curStructOrUnion); + auto itor = std::find(astStructs.cbegin(), astStructs.cend(), curStructOrUnion); if (itor == astStructs.end()) { astStructs.emplace_back(curStructOrUnion); } @@ -2294,6 +2769,60 @@ ASTDecl *ASTParser::ProcessDeclRecordDecl(MapleAllocator &allocator, const clang return curStructOrUnion; } +void ASTParser::ParserStmtVLASizeExpr(MapleAllocator &allocator, const clang::Type &type, std::list &stmts) { + MapleList vlaExprs(allocator.Adapter()); + SaveVLASizeExpr(allocator, type, vlaExprs); + ASTStmtDummy *stmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); + stmt->SetVLASizeExprs(std::move(vlaExprs)); + (void)stmts.emplace_back(stmt); +} + +MapleVector ASTParser::SolveFuncParameterDecls(MapleAllocator &allocator, + const clang::FunctionDecl &funcDecl, + MapleVector &typeDescIn, + std::list &stmts) { + MapleVector paramDecls(allocator.Adapter()); + unsigned int numParam = funcDecl.getNumParams(); + for (uint32_t i = 0; i < numParam; ++i) { + const clang::ParmVarDecl *parmDecl = funcDecl.getParamDecl(i); + ParserStmtVLASizeExpr(allocator, *(parmDecl->getOriginalType().getTypePtr()), stmts); + ASTDecl *parmVarDecl = ProcessDecl(allocator, *parmDecl); + ASSERT_NOT_NULL(parmVarDecl); + paramDecls.push_back(parmVarDecl); + typeDescIn.push_back(parmVarDecl->GetTypeDesc().front()); + } + return paramDecls; +} + +GenericAttrs ASTParser::SolveFunctionAttributes(const clang::FunctionDecl &funcDecl, std::string &funcName) const { + GenericAttrs attrs; + astFile->CollectFuncAttrs(funcDecl, attrs, kPublic); + // for inline optimize + if (attrs.GetAttr(GENATTR_static) && FEOptions::GetInstance().GetFuncInlineSize() != 0) { + funcName = funcName + astFile->GetAstFileNameHashStr(); + } + + // set inline functions as weak symbols as it's in C++ + if (opts::inlineAsWeak == true && attrs.GetAttr(GENATTR_inline) && !attrs.GetAttr(GENATTR_static)) { + attrs.SetAttr(GENATTR_weak); + } + + return attrs; +} + +ASTStmt *ASTParser::SolveFunctionBody(MapleAllocator &allocator, + const clang::FunctionDecl &funcDecl, + ASTFunc &astFunc, const std::list &stmts) { + ASTStmt *astCompoundStmt = ProcessStmt(allocator, *llvm::cast(funcDecl.getBody())); + if (astCompoundStmt != nullptr) { + astFunc.SetCompoundStmt(astCompoundStmt); + astFunc.InsertStmtsIntoCompoundStmtAtFront(stmts); + } else { + return nullptr; + } + return astCompoundStmt; +} + ASTDecl *ASTParser::ProcessDeclFunctionDecl(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl) { ASTFunc *astFunc = static_cast(ASTDeclsBuilder::GetASTDecl(funcDecl.getID())); if (astFunc != nullptr) { @@ -2306,7 +2835,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,39 +2844,11 @@ ASTDecl *ASTParser::ProcessDeclFunctionDecl(MapleAllocator &allocator, const cla if (retType == nullptr) { return nullptr; } - std::vector paramDecls; typeDescIn.push_back(retType); - unsigned int numParam = funcDecl.getNumParams(); + std::list implicitStmts; - for (uint32_t i = 0; i < numParam; ++i) { - const clang::ParmVarDecl *parmDecl = funcDecl.getParamDecl(i); - ASTExpr *expr = ProcessExprInType(allocator, parmDecl->getOriginalType()); - if (expr != nullptr) { - ASTStmtDummy *stmt = ASTDeclsBuilder::ASTStmtBuilder(allocator); - stmt->SetASTExpr(expr); - implicitStmts.emplace_back(stmt); - } - ASTDecl *parmVarDecl = ProcessDecl(allocator, *parmDecl); - paramDecls.push_back(parmVarDecl); - typeDescIn.push_back(parmVarDecl->GetTypeDesc().front()); - } - GenericAttrs attrs; - astFile->CollectFuncAttrs(funcDecl, attrs, kPublic); - // for inline optimize - if (attrs.GetAttr(GENATTR_static) && FEOptions::GetInstance().GetFuncInlineSize() != 0) { - funcName = funcName + astFile->GetAstFileNameHashStr(); - } - // one element vector type in rettype - if (LibAstFile::IsOneElementVector(qualType)) { - attrs.SetAttr(GENATTR_oneelem_simd); - } - if (FEOptions::GetInstance().IsEnableSafeRegion()) { - if (funcDecl.getSafeSpecifier() == clang::SS_Unsafe) { - attrs.SetAttr(GENATTR_unsafed); - } else if (funcDecl.getSafeSpecifier() == clang::SS_Safe) { - attrs.SetAttr(GENATTR_safed); - } - } + MapleVector paramDecls = SolveFuncParameterDecls(allocator, funcDecl, typeDescIn, implicitStmts); + GenericAttrs attrs = SolveFunctionAttributes(funcDecl, funcName); astFunc = ASTDeclsBuilder::ASTFuncBuilder( allocator, fileName, funcName, typeDescIn, attrs, paramDecls, funcDecl.getID()); CHECK_FATAL(astFunc != nullptr, "astFunc is nullptr"); @@ -2355,39 +2856,33 @@ ASTDecl *ASTParser::ProcessDeclFunctionDecl(MapleAllocator &allocator, const cla if (sa != nullptr && !sa->isImplicit()) { astFunc->SetSectionAttr(sa->getName().str()); } + /* create typealias for func return type */ + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRType *sourceType = astFile->CvtSourceType(qualType); + astFunc->SetSourceType(sourceType); + } // collect EnhanceC func attr ProcessNonnullFuncAttrs(funcDecl, *astFunc); ProcessBoundaryFuncAttrs(allocator, funcDecl, *astFunc); ProcessBoundaryParamAttrs(allocator, funcDecl, *astFunc); clang::WeakRefAttr *weakrefAttr = funcDecl.getAttr(); if (weakrefAttr != nullptr) { - astFunc->SetWeakrefAttr(std::pair { true, weakrefAttr->getAliasee().str() }); + astFunc->SetWeakrefAttr(std::pair{true, weakrefAttr->getAliasee().str()}); } if (funcDecl.hasBody()) { - ASTStmt *astCompoundStmt = ProcessStmt(allocator, *llvm::cast(funcDecl.getBody())); - if (astCompoundStmt != nullptr) { - astFunc->SetCompoundStmt(astCompoundStmt); - astFunc->InsertStmtsIntoCompoundStmtAtFront(implicitStmts); - } else { + if (SolveFunctionBody(allocator, funcDecl, *astFunc, implicitStmts) == nullptr) { 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)); -#else - astFunc->SetSize(static_cast(static_cast(astCompoundStmt)->GetASTStmtList().size())); -#endif } return astFunc; } -void ASTParser::ProcessNonnullFuncAttrs(const clang::FunctionDecl &funcDecl, ASTFunc &astFunc) { +void ASTParser::ProcessNonnullFuncAttrs(const clang::FunctionDecl &funcDecl, ASTFunc &astFunc) const { if (funcDecl.hasAttr()) { astFunc.SetAttr(GENATTR_nonnull); } for (const auto *nonNull : funcDecl.specific_attrs()) { - if (!nonNull->args_size()) { + if (nonNull->args_size() == 0) { // Lack of attribute parameters means that all of the pointer parameters are // implicitly marked as nonnull. for (auto paramDecl : astFunc.GetParamDecls()) { @@ -2418,8 +2913,7 @@ ASTDecl *ASTParser::ProcessDeclFieldDecl(MapleAllocator &allocator, const clang: bool isAnonymousField = false; if (fieldName.empty()) { isAnonymousField = true; - uint32 id = decl.getLocation().getRawEncoding(); - fieldName = astFile->GetOrCreateMappedUnnamedName(id); + fieldName = astFile->GetOrCreateMappedUnnamedName(decl); } CHECK_FATAL(!fieldName.empty(), "fieldName is empty"); MIRType *fieldType = astFile->CvtType(qualType); @@ -2433,13 +2927,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,12 +2942,69 @@ 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); } + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRType *sourceType = astFile->CvtSourceType(qualType); + fieldDecl->SetSourceType(sourceType); + } return fieldDecl; } +void ASTParser::SetInitExprForASTVar(MapleAllocator &allocator, const clang::VarDecl &varDecl, + const GenericAttrs &attrs, ASTVar &astVar) { + bool isStaticStorageVar = (varDecl.getStorageDuration() == clang::SD_Static || attrs.GetAttr(GENATTR_tls_static)); + astVar.SetSrcLoc(astFile->GetLOC(varDecl.getLocation())); + auto initExpr = varDecl.getInit(); + auto astInitExpr = ProcessExpr(allocator, initExpr); + ASSERT_NOT_NULL(astInitExpr); + if (initExpr->getStmtClass() == clang::Stmt::InitListExprClass && astInitExpr->GetASTOp() == kASTOpInitListExpr) { + static_cast(astInitExpr)->SetInitListVarName(astVar.GenerateUniqueVarName()); + } + 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. + if (!isStaticStorageVar || flag != kEvaluatedAsZero) { + astVar.SetInitExpr(astInitExpr); + } else { + astVar.SetAttr(GENATTR_static_init_zero); // used to distinguish with uninitialized vars + } + astVar.SetCallAlloca(astInitExpr->IsCallAlloca()); +} + +void ASTParser::SetAlignmentForASTVar(const clang::VarDecl &varDecl, ASTVar &astVar) const { + int64 naturalAlignment = astFile->GetContext()->toCharUnitsFromBits( + astFile->GetContext()->getTypeUnadjustedAlign(varDecl.getType())).getQuantity(); + // Get alignment from the decl + uint32 alignmentBits = varDecl.getMaxAlignment(); + if (alignmentBits != 0) { + uint32 alignment = alignmentBits / 8; + if (alignment > naturalAlignment) { + astVar.SetAlign(alignment); + } + } + // Get alignment from the type + alignmentBits = astFile->GetContext()->getTypeAlignIfKnown(varDecl.getType()); + if (alignmentBits != 0) { + uint32 alignment = alignmentBits / 8; + if (alignment > astVar.GetAlign() && alignment > naturalAlignment) { + astVar.SetAlign(alignment); + } + } +} + +void ASTParser::CheckVarNameValid(std::string varName) { + CHECK_FATAL(isalpha(varName[0]) || varName[0] == '_', "%s' varName is invalid", varName.c_str()); + for (size_t i = 1; i < varName.size(); i++) { + /* check valid varName in C, but unsupport Unicode */ + if (varName[i] == '\\' && i + 1 != varName.size()) { + CHECK_FATAL(varName[i + 1] != 'u' && varName[i + 1] != 'U', "%s' varName is invalid", varName.c_str()); + } + } +} + ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::VarDecl &varDecl) { ASTVar *astVar = static_cast(ASTDeclsBuilder::GetASTDecl(varDecl.getID())); if (astVar != nullptr) { @@ -2462,6 +3014,7 @@ ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::V if (varName.empty()) { return nullptr; } + CheckVarNameValid(varName); clang::QualType qualType = varDecl.getType(); MIRType *varType = astFile->CvtType(qualType); if (varType == nullptr) { @@ -2473,15 +3026,17 @@ ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::V if (attrs.GetAttr(GENATTR_static) && FEOptions::GetInstance().GetFuncInlineSize() != 0) { 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); + if (varType->IsMIRIncompleteStructType() && !attrs.GetAttr(GENATTR_extern)) { + FE_ERR(kLncErr, astFile->GetLOC(varDecl.getLocation()), "tentative definition of variable '%s' has incomplete" + " struct type 'struct '%s''", varName.c_str(), varType->GetName().c_str()); } astVar = ASTDeclsBuilder::ASTVarBuilder( - allocator, fileName, varName, std::vector{varType}, attrs, varDecl.getID()); + allocator, fileName, varName, MapleVector({varType}, allocator.Adapter()), attrs, varDecl.getID()); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRType *sourceType = astFile->CvtSourceType(qualType); + astVar->SetSourceType(sourceType); + } + astVar->SetIsMacro(varDecl.getLocation().isMacroID()); clang::SectionAttr *sa = varDecl.getAttr(); if (sa != nullptr && !sa->isImplicit()) { astVar->SetSectionAttr(sa->getName().str()); @@ -2491,42 +3046,25 @@ ASTDecl *ASTParser::ProcessDeclVarDecl(MapleAllocator &allocator, const clang::V astVar->SetAsmAttr(ala->getLabel().str()); } if (varDecl.hasInit()) { - 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); + SetInitExprForASTVar(allocator, varDecl, attrs, *astVar); } - 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())); + ASTExpr *astExpr = nullptr; + if (llvm::isa(qualType.getCanonicalType())) { + astExpr = BuildExprToComputeSizeFromVLA(allocator, qualType.getCanonicalType()); + astVar->SetBoundaryLenExpr(astExpr); + } + if (qualType.getTypePtr()->getTypeClass() == clang::Type::TypeOfExpr) { + astExpr = ProcessTypeofExpr(allocator, qualType); + } + if (astExpr != nullptr) { + astVar->SetVariableArrayExpr(astExpr); } if (!varDecl.getType()->isIncompleteType()) { - int64 naturalAlignment = astFile->GetContext()->toCharUnitsFromBits( - astFile->GetContext()->getTypeUnadjustedAlign(varDecl.getType())).getQuantity(); - - // Get alignment from the decl - if (uint32 alignmentBits = varDecl.getMaxAlignment()) { - uint32 alignment = alignmentBits / 8; - if (alignment > naturalAlignment) { - astVar->SetAlign(alignment); - } - } - - // Get alignment from the type - if (uint32 alignmentBits = astFile->GetContext()->getTypeAlignIfKnown(varDecl.getType())) { - uint32 alignment = alignmentBits / 8; - if (alignment > astVar->GetAlign() && alignment > naturalAlignment) { - astVar->SetAlign(alignment); - } - } + SetAlignmentForASTVar(varDecl, *astVar); } 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,57 +3085,80 @@ 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); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRType *sourceType = astFile->CvtSourceType(parmQualType); + parmVar->SetSourceType(sourceType); + } 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; } -ASTDecl *ASTParser::ProcessDeclEnumDecl(MapleAllocator &allocator, const clang::EnumDecl &enumDecl) { - ASTEnumDecl *localEnumDecl = static_cast(ASTDeclsBuilder::GetASTDecl(enumDecl.getID())); - if (localEnumDecl != nullptr) { - return localEnumDecl; +ASTDecl *ASTParser::ProcessDeclEnumDecl(MapleAllocator &allocator, const clang::EnumDecl &rawEnumDecl) { + const clang::EnumDecl *enumDecl = rawEnumDecl.getDefinition(); + if (enumDecl == nullptr) { + enumDecl = &rawEnumDecl; + } + ASTEnumDecl *astEnum = static_cast(ASTDeclsBuilder::GetASTDecl(enumDecl->getID())); + if (astEnum != nullptr) { + return astEnum; } GenericAttrs attrs; - 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()); - TraverseDecl(&enumDecl, [&](clang::Decl *child) { + astFile->CollectAttrs(*enumDecl, attrs, kNone); + std::string enumName = astFile->GetDeclName(*enumDecl); + MIRType *mirType; + if (enumDecl->getPromotionType().isNull()) { + mirType = GlobalTables::GetTypeTable().GetInt32(); + } else { + mirType = astFile->CvtType(enumDecl->getPromotionType()); + } + astEnum = ASTDeclsBuilder::ASTLocalEnumDeclBuilder(allocator, fileName, enumName, + MapleVector({mirType}, allocator.Adapter()), attrs, enumDecl->getID()); + TraverseDecl(enumDecl, [&astEnum, &allocator, this](clang::Decl *child) { + ASSERT_NOT_NULL(child); CHECK_FATAL(child->getKind() == clang::Decl::EnumConstant, "Unsupported decl kind: %u", child->getKind()); - localEnumDecl->PushConstant(static_cast(ProcessDecl(allocator, *child))); + astEnum->PushConstant(static_cast(ProcessDecl(allocator, *child))); }); - return localEnumDecl; -} - -ASTDecl *ASTParser::ProcessDeclTypedefDecl(MapleAllocator &allocator, const clang::TypedefDecl &typeDefDecl) { - clang::QualType underlyCanonicalTy = typeDefDecl.getCanonicalDecl()->getUnderlyingType().getCanonicalType(); - // For used type completeness - // Only process implicit record type here - if (underlyCanonicalTy->isRecordType()) { - const auto *recordType = llvm::cast(underlyCanonicalTy); - clang::RecordDecl *recordDecl = recordType->getDecl(); - if (recordDecl->isImplicit()) { - return ProcessDecl(allocator, *recordDecl); - } + Loc l = astFile->GetLOC(enumDecl->getLocation()); + astEnum->SetSrcLoc(l); + auto itor = std::find(astEnums.cbegin(), astEnums.cend(), astEnum); + if (itor == astEnums.end()) { + (void)astEnums.emplace_back(astEnum); } - return nullptr; // skip primitive type and explicit declared type + return astEnum; } ASTDecl *ASTParser::ProcessDeclEnumConstantDecl(MapleAllocator &allocator, const clang::EnumConstantDecl &decl) { @@ -2606,24 +3167,67 @@ ASTDecl *ASTParser::ProcessDeclEnumConstantDecl(MapleAllocator &allocator, const return astConst; } GenericAttrs attrs; - 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()); + astFile->CollectAttrs(decl, attrs, kNone); + const std::string &varName = decl.getNameAsString(); + MIRType *mirType = astFile->CvtType(decl.getType()); + CHECK_NULL_FATAL(mirType); astConst = ASTDeclsBuilder::ASTEnumConstBuilder( - allocator, fileName, varName, std::vector{mirType}, attrs, decl.getID()); - - astConst->SetValue(static_cast(clang::dyn_cast(&decl)->getInitVal().getExtValue())); + allocator, fileName, varName, MapleVector({mirType}, allocator.Adapter()), attrs, decl.getID()); + IntVal val(decl.getInitVal().getExtValue(), mirType->GetPrimType()); + astConst->SetValue(val); return astConst; } -ASTDecl *ASTParser::ProcessDeclLabelDecl(MapleAllocator &allocator, const clang::LabelDecl &decl) { - (void)allocator; - (void)decl; +ASTDecl *ASTParser::ProcessDeclTypedefDecl(MapleAllocator &allocator, const clang::TypedefDecl &decl) { + if (FEOptions::GetInstance().IsDbgFriendly()) { + ASTTypedefDecl *astTypedef = static_cast(ASTDeclsBuilder::GetASTDecl(decl.getID())); + if (astTypedef != nullptr) { + return astTypedef; + } + std::string typedefName = astFile->GetDeclName(decl); + GenericAttrs attrs; + astFile->CollectAttrs(decl, attrs, kNone); + clang::QualType underlyTy = decl.getUnderlyingType(); + MIRType *type = astFile->CvtType(underlyTy, true); + CHECK_NULL_FATAL(type); + astTypedef = ASTDeclsBuilder::ASTTypedefBuilder( + allocator, fileName, typedefName, MapleVector({type}, allocator.Adapter()), attrs, decl.getID()); + const clang::TypedefType *underlyingTypedefType = llvm::dyn_cast(underlyTy); + if (underlyingTypedefType != nullptr) { + auto *subTypedeDecl = static_cast(ProcessDecl(allocator, *underlyingTypedefType->getDecl())); + astTypedef->SetSubTypedefDecl(subTypedeDecl); + } + if (decl.isDefinedOutsideFunctionOrMethod()) { + astTypedef->SetGlobal(true); + } + return astTypedef; + } + clang::QualType underlyCanonicalTy = decl.getCanonicalDecl()->getUnderlyingType().getCanonicalType(); + if (underlyCanonicalTy->isRecordType()) { + const auto *recordType = llvm::cast(underlyCanonicalTy); + clang::RecordDecl *recordDecl = recordType->getDecl(); + if (recordDecl->isImplicit()) { + return ProcessDecl(allocator, *recordDecl); + } + } return nullptr; } +ASTDecl *ASTParser::ProcessDeclLabelDecl(MapleAllocator &allocator, const clang::LabelDecl &decl) { + 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) { - for (auto &decl : recordDecles) { + for (auto &decl : std::as_const(recordDecles)) { clang::RecordDecl *recDecl = llvm::cast(decl->getCanonicalDecl()); if (!recDecl->isCompleteDefinition()) { clang::RecordDecl *recDeclDef = recDecl->getDefinition(); @@ -2637,8 +3241,7 @@ bool ASTParser::RetrieveStructs(MapleAllocator &allocator) { if (curStructOrUnion == nullptr) { return false; } - curStructOrUnion->SetGlobal(true); - auto itor = std::find(astStructs.begin(), astStructs.end(), curStructOrUnion); + auto itor = std::find(astStructs.cbegin(), astStructs.cend(), curStructOrUnion); if (itor != astStructs.end()) { } else { astStructs.emplace_back(curStructOrUnion); @@ -2648,22 +3251,20 @@ bool ASTParser::RetrieveStructs(MapleAllocator &allocator) { } bool ASTParser::RetrieveFuncs(MapleAllocator &allocator) { - for (auto &func : funcDecles) { + for (auto &func : std::as_const(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()); - 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, - funcName.c_str()); - } else { - if (funcDecl->getSafeSpecifier() == clang::SS_None) { - funcDecl->setSafeSpecifier(spec); - } + Loc loc = astFile->GetLOC(funcDecl->getLocation()); + FE_ERR(kLncWarn, loc, "The function %s declaration and definition security attributes " + "are inconsistent.", funcName.c_str()); + } else if (funcDecl->getSafeSpecifier() == clang::SS_None) { + funcDecl->setSafeSpecifier(spec); } } } @@ -2679,7 +3280,7 @@ bool ASTParser::RetrieveFuncs(MapleAllocator &allocator) { // seperate MP with astparser bool ASTParser::RetrieveGlobalVars(MapleAllocator &allocator) { - for (auto &decl : globalVarDecles) { + for (auto &decl : std::as_const(globalVarDecles)) { clang::VarDecl *varDecl = llvm::cast(decl); ASTVar *val = static_cast(ProcessDecl(allocator, *varDecl)); if (val == nullptr) { @@ -2691,7 +3292,7 @@ bool ASTParser::RetrieveGlobalVars(MapleAllocator &allocator) { } bool ASTParser::RetrieveFileScopeAsms(MapleAllocator &allocator) { - for (auto &decl : globalFileScopeAsm) { + for (auto &decl : std::as_const(globalFileScopeAsm)) { clang::FileScopeAsmDecl *fileScopeAsmDecl = llvm::cast(decl); ASTFileScopeAsm *asmDecl = static_cast(ProcessDecl(allocator, *fileScopeAsmDecl)); if (asmDecl == nullptr) { @@ -2702,27 +3303,45 @@ bool ASTParser::RetrieveFileScopeAsms(MapleAllocator &allocator) { return true; } -bool ASTParser::ProcessGlobalTypeDef(MapleAllocator &allocator) { - for (auto gTypeDefDecl : globalTypeDefDecles) { +bool ASTParser::RetrieveGlobalTypeDef(MapleAllocator &allocator) { + for (auto &gTypeDefDecl : std::as_const(globalTypeDefDecles)) { + if (gTypeDefDecl->isImplicit()) { + continue; + } (void)ProcessDecl(allocator, *gTypeDefDecl); } return true; } -const std::string &ASTParser::GetSourceFileName() const { - return fileName; +bool ASTParser::RetrieveEnums(MapleAllocator &allocator) { + for (auto &decl : std::as_const(globalEnumDecles)) { + clang::EnumDecl *enumDecl = llvm::cast(decl->getCanonicalDecl()); + ASTEnumDecl *astEnum = static_cast(ProcessDecl(allocator, *enumDecl)); + if (astEnum == nullptr) { + return false; + } + (void)astEnums.emplace_back(astEnum); + } + return true; +} + +const std::string ASTParser::GetSourceFileName() const { + return fileName.c_str() == nullptr ? "" : fileName.c_str(); } const uint32 ASTParser::GetFileIdx() const { return fileIdx; } -void ASTParser::TraverseDecl(const clang::Decl *decl, std::function const &functor) { +void ASTParser::TraverseDecl(const clang::Decl *decl, std::function const &functor) const { if (decl == nullptr) { return; } + ASSERT_NOT_NULL(clang::dyn_cast(decl)); for (auto *child : clang::dyn_cast(decl)->decls()) { - functor(child); + if (child != nullptr) { + functor(child); + } } } } // namespace maple 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..0cce3fac51e93304953de8a3f384ddd9dcd8b140 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 @@ -27,6 +27,7 @@ #include "fe_manager.h" #include "mir_module.h" #include "mpl_logging.h" +#include "fe_macros.h" namespace maple { std::unordered_map ASTCallExpr::InitBuiltinFuncPtrMap() { @@ -39,6 +40,7 @@ std::unordered_map ASTCallExpr::In #define DEF_MIR_INTRINSIC(STR, NAME, INTRN_CLASS, RETURN_TYPE, ...) \ ans["__builtin_mpl_"#STR] = &ASTCallExpr::EmitBuiltin##STR; #include "intrinsic_vector.def" +#include "intrinsic_vector_new.def" #undef DEF_MIR_INTRINSIC return ans; @@ -56,7 +58,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 +67,39 @@ 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) { + (void)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; + } + std::unique_ptr stmt = nullptr; + UniqueFEIRVar retVar = FEIRBuilder::CreateVarNameForC(GetRetVarName(), *mirType, false); + if (!args.empty()) { + UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); + stmt = std::make_unique(argIntrinsicID, std::move(type), retVar->Clone(), + std::move(argExprList)); + } else { + 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,56 +110,27 @@ 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) { - auto argExpr = args[0]->Emit2FEExpr(stmts); - UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*mirType); - UniqueFEIRType ptrType = FEIRTypeHelper::CreateTypeNative( - *GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType)); - isFinish = true; - return FEIRBuilder::CreateExprIRead(std::move(type), std::move(ptrType), std::move(argExpr)); + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { + return EmitBuiltinVectorLoad(stmts, isFinish); } prefix = "__builtin_mpl_vector_store"; - if (funcName.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) { - return EmitBuiltinVectorZip(stmts, isFinish); + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { + return EmitBuiltinVectorStore(stmts, isFinish); } prefix = "__builtin_mpl_vector_shli"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { - isFinish = true; - UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); - auto arg1Expr = args[0]->Emit2FEExpr(stmts); - auto arg2Expr = args[1]->Emit2FEExpr(stmts); - return FEIRBuilder::CreateExprBinary(std::move(type), OP_shl, std::move(arg1Expr), std::move(arg2Expr)); + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { + return EmitBuiltinVectorShli(stmts, isFinish); } prefix = "__builtin_mpl_vector_shri"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { - isFinish = true; - UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); - auto arg1Expr = args[0]->Emit2FEExpr(stmts); - auto arg2Expr = args[1]->Emit2FEExpr(stmts); - return FEIRBuilder::CreateExprBinary(std::move(type), OP_ashr, std::move(arg1Expr), std::move(arg2Expr)); + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { + return EmitBuiltinVectorShri(stmts, isFinish); } prefix = "__builtin_mpl_vector_shru"; - if (funcName.compare(0, prefix.size(), prefix) == 0) { - isFinish = true; - UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); - auto arg1Expr = args[0]->Emit2FEExpr(stmts); - auto arg2Expr = args[1]->Emit2FEExpr(stmts); - return FEIRBuilder::CreateExprBinary(std::move(type), OP_lshr, std::move(arg1Expr), std::move(arg2Expr)); + if (GetFuncName().compare(0, prefix.size(), prefix) == 0) { + return EmitBuiltinVectorShru(stmts, isFinish); } // 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 +138,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, ...) \ @@ -163,37 +161,51 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltin##STR(std::list &stmts) c return std::make_unique(std::move(feType), INTRN_##STR, argOpnds); \ } #include "intrinsic_vector.def" +#include "intrinsic_vector_new.def" #undef DEF_MIR_INTRINSIC -UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorZip(std::list &stmts, bool &isFinish) const { - std::unique_ptr> argExprList = std::make_unique>(); - for (auto arg : args) { - UniqueFEIRExpr expr = arg->Emit2FEExpr(stmts); - argExprList->emplace_back(std::move(expr)); - } - CHECK_NULL_FATAL(retType); - std::string retName = FEUtils::GetSequentialName("vector_zip_retvar_"); - UniqueFEIRVar retVar = FEIRBuilder::CreateVarNameForC(retName, *retType); - -#define VECTOR_INTRINSICCALL_TYPE(OP_NAME, VECTY) \ - if (FEUtils::EndsWith(funcName, #VECTY)) { \ - stmt = std::make_unique( \ - INTRN_vector_##OP_NAME##_##VECTY, nullptr, retVar->Clone(), std::move(argExprList)); \ - } - UniqueFEIRStmt stmt; +UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorLoad(std::list &stmts, bool &isFinish) const { + auto argExpr = args[0]->Emit2FEExpr(stmts); + UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*mirType); + UniqueFEIRType ptrType = FEIRTypeHelper::CreateTypeNative( + *GlobalTables::GetTypeTable().GetOrCreatePointerType(*mirType)); + isFinish = true; + return FEIRBuilder::CreateExprIRead(std::move(type), std::move(ptrType), std::move(argExpr)); +} - VECTOR_INTRINSICCALL_TYPE(zip, v2i32) - else VECTOR_INTRINSICCALL_TYPE(zip, v4i16) - else VECTOR_INTRINSICCALL_TYPE(zip, v8i8) - else VECTOR_INTRINSICCALL_TYPE(zip, v2u32) - else VECTOR_INTRINSICCALL_TYPE(zip, v4u16) - else VECTOR_INTRINSICCALL_TYPE(zip, v8u8) - else VECTOR_INTRINSICCALL_TYPE(zip, v2f32) +UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorStore(std::list &stmts, bool &isFinish) const { + 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)); + (void)stmts.emplace_back(std::move(stmt)); + isFinish = true; + return nullptr; +} - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); - stmts.emplace_back(std::move(stmt)); +UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorShli(std::list &stmts, bool &isFinish) const { + isFinish = true; + UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); + auto arg1Expr = args[0]->Emit2FEExpr(stmts); + auto arg2Expr = args[1]->Emit2FEExpr(stmts); + return FEIRBuilder::CreateExprBinary(std::move(type), OP_shl, std::move(arg1Expr), std::move(arg2Expr)); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorShri(std::list &stmts, bool &isFinish) const { + isFinish = true; + UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); + auto arg1Expr = args[0]->Emit2FEExpr(stmts); + auto arg2Expr = args[1]->Emit2FEExpr(stmts); + return FEIRBuilder::CreateExprBinary(std::move(type), OP_ashr, std::move(arg1Expr), std::move(arg2Expr)); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinVectorShru(std::list &stmts, bool &isFinish) const { isFinish = true; - return FEIRBuilder::CreateExprDRead(std::move(retVar)); + UniqueFEIRType type = FEIRTypeHelper::CreateTypeNative(*args[0]->GetType()); + auto arg1Expr = args[0]->Emit2FEExpr(stmts); + auto arg2Expr = args[1]->Emit2FEExpr(stmts); + return FEIRBuilder::CreateExprBinary(std::move(type), OP_lshr, std::move(arg1Expr), std::move(arg2Expr)); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinVaStart(std::list &stmts) const { @@ -207,7 +219,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 +234,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 +256,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 +345,271 @@ 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::EmitBuiltinObjectSize(std::list &stmts) const { + return CreateIntrinsicCallAssignedForC(stmts, INTRN_C___builtin_object_size); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinReturnAddress(std::list &stmts) const { @@ -432,15 +629,43 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinAlloca(std::list &stmts) UniqueFEIRExpr ASTCallExpr::EmitBuiltinExpect(std::list &stmts) const { ASSERT(args.size() == 2, "__builtin_expect requires two arguments"); - 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; + std::list subStmts; + UniqueFEIRExpr feExpr = CreateIntrinsicopForC(subStmts, INTRN_C___builtin_expect, false); + bool isOptimized = false; + for (auto &stmt : std::as_const(subStmts)) { + // If there are mutiple conditions combined with logical AND '&&' or logical OR '||' in __builtin_expect, generate + // a __builtin_expect intrinsicop for each one condition in mpl + if (stmt->GetKind() == FEIRNodeKind::kStmtCondGoto) { + isOptimized = true; + auto *condGotoStmt = static_cast(stmt.get()); + // skip if condition label name not starts with + if (condGotoStmt->GetLabelName().rfind(FEUtils::kCondGoToStmtLabelNamePrefix, 0) != 0) { + continue; + } + const auto &conditionExpr = condGotoStmt->GetConditionExpr(); + // skip if __builtin_expect intrinsicop has been generated for condition expr + if (conditionExpr->GetKind() == kExprBinary) { + auto &opnd0 = static_cast(conditionExpr.get())->GetOpnd0(); + if (opnd0->GetKind() == FEIRNodeKind::kExprIntrinsicop && + static_cast(opnd0.get())->GetIntrinsicID() == INTRN_C___builtin_expect) { + continue; + } + } + std::vector> argOpnds; + auto &builtInExpectArgs = static_cast(feExpr.get())->GetOpnds(); + auto cvtFeExpr = FEIRBuilder::CreateExprCvtPrim(conditionExpr->Clone(), builtInExpectArgs.front()->GetPrimType()); + argOpnds.push_back(std::move(cvtFeExpr)); + argOpnds.push_back(builtInExpectArgs.back()->Clone()); + auto returnType = std::make_unique(*mirType); + auto builtinExpectExpr = std::make_unique(std::move(returnType), + INTRN_C___builtin_expect, argOpnds); + auto newConditionExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(builtinExpectExpr)); + condGotoStmt->SetCondtionExpr(newConditionExpr); + } + } + stmts.splice(stmts.end(), subStmts); + return isOptimized ? static_cast(feExpr.get())->GetOpnds().front()->Clone() + : feExpr->Clone(); } UniqueFEIRExpr ASTCallExpr::EmitBuiltinAbs(std::list &stmts) const { @@ -516,6 +741,18 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinExpf(std::list &stmts) co return CreateIntrinsicopForC(stmts, INTRN_C_expf); } +UniqueFEIRExpr ASTCallExpr::EmitBuiltinBswap64(std::list &stmts) const { + return CreateIntrinsicopForC(stmts, INTRN_C_bswap64); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinBswap32(std::list &stmts) const { + return CreateIntrinsicopForC(stmts, INTRN_C_bswap32); +} + +UniqueFEIRExpr ASTCallExpr::EmitBuiltinBswap16(std::list &stmts) const { + return CreateIntrinsicopForC(stmts, INTRN_C_bswap16); +} + UniqueFEIRExpr ASTCallExpr::EmitBuiltinFmax(std::list &stmts) const { return CreateBinaryExpr(stmts, OP_max); } @@ -558,7 +795,7 @@ UniqueFEIRExpr ASTCallExpr::EmitBuiltinIslessequal(std::list &st return CreateBinaryExpr(stmts, OP_le); } -UniqueFEIRExpr ASTCallExpr::EmitBuiltinIsgreater (std::list &stmts) const { +UniqueFEIRExpr ASTCallExpr::EmitBuiltinIsgreater(std::list &stmts) const { return CreateBinaryExpr(stmts, OP_gt); } @@ -690,15 +927,18 @@ 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) { - ss << "__isinf"; - } else if (astFile->CvtType(expr.getArg(0)->getType())->GetPrimType() == PTY_f32) { - ss << "__isinff"; - } else { - ASSERT(false, "Unsupported type passed to isinf"); + MIRType *mirType = astFile->CvtType(expr.getArg(0)->getType()); + if (mirType != nullptr) { + PrimType type = mirType->GetPrimType(); + if (type == PTY_f64) { + ss << "__isinf"; + } else if (type == PTY_f32) { + ss << "__isinff"; + } else { + ASSERT(false, "Unsupported type passed to isinf"); + } } return nullptr; } @@ -708,7 +948,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 +958,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 +968,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 +978,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 +988,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 +998,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; } @@ -792,22 +1032,4 @@ ASTExpr *ASTParser::ParseBuiltinCopysignl(MapleAllocator &allocator, const clang std::stringstream &ss) const { return ProcessBuiltinFuncByName(allocator, expr, ss, "copysignl"); } - -ASTExpr *ASTParser::ParseBuiltinObjectsize(MapleAllocator &allocator, const clang::CallExpr &expr, - std::stringstream &ss) const { - (void)ss; - uint32 objSizeType = expr.getArg(1)->EvaluateKnownConstInt(*astFile->GetContext()).getZExtValue(); - // GCC size_t __builtin_object_size(void *ptr, int type) type range is 0 ~ 3 - ASSERT(objSizeType <= 3, "unexpected type"); - uint64 objSize; - bool canEval = expr.getArg(0)->tryEvaluateObjectSize(objSize, *astFile->GetNonConstAstContext(), objSizeType); - if (!canEval) { - // type 0 and 1 need return -1, type 2 and 3 need return 0 - objSize = objSizeType & 2 ? 0 : -1; - } - ASTIntegerLiteral *astIntegerLiteral = ASTDeclsBuilder::ASTExprBuilder(allocator); - astIntegerLiteral->SetVal(static_cast(objSize)); - astIntegerLiteral->SetType(astFile->CvtType(expr.getType())); - return astIntegerLiteral; -} } // namespace maple diff --git a/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp b/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp index 4184cc0e7379fb4c0a807c3feee68ee724f28c71..5e9a00f605183a1481483dd23553db59c7557911 100644 --- a/src/hir2mpl/ast_input/clang/src/ast_stmt.cpp +++ b/src/hir2mpl/ast_input/clang/src/ast_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. @@ -33,6 +33,7 @@ void ASTStmt::SetASTExpr(ASTExpr *astExpr) { // ---------- ASTStmtDummy ---------- std::list ASTStmtDummy::Emit2FEStmtImpl() const { std::list stmts; + EmitVLASizeExprs(stmts); for (auto expr : exprs) { (void)expr->Emit2FEExpr(stmts); } @@ -45,29 +46,45 @@ void ASTCompoundStmt::SetASTStmt(ASTStmt *astStmt) { } void ASTCompoundStmt::InsertASTStmtsAtFront(const std::list &stmts) { - astStmts.insert(astStmts.begin(), stmts.begin(), stmts.end()); + (void)astStmts.insert(astStmts.cbegin(), stmts.cbegin(), stmts.cend()); } -const std::list &ASTCompoundStmt::GetASTStmtList() const { +const MapleList &ASTCompoundStmt::GetASTStmtList() const { return astStmts; } std::list ASTCompoundStmt::Emit2FEStmtImpl() const { std::list stmts; - auto insertStmt = [&](bool flag) { + auto insertStmt = [&stmts, this](bool flag) { 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(FEUtils::CvtLoc2SrcPosition(GetSrcLoc()), FEUtils::CvtLoc2SrcPosition(GetEndLoc())); + } for (auto it : astStmts) { stmts.splice(stmts.end(), it->Emit2FEStmt()); } + if (!hasEmitted2MIRScope) { + UniqueFEIRScope scope = feFunction.PopTopScope(); + scope->ProcessVLAStack(stmts, IsCallAlloca(), GetEndLoc()); + hasEmitted2MIRScope = true; + } insertStmt(true); return stmts; } @@ -80,8 +97,8 @@ std::list ASTReturnStmt::Emit2FEStmtImpl() const { if (astExpr != nullptr && ConditionalOptimize::DeleteRedundantTmpVar(feExpr, stmts)) { return stmts; } + FEIRBuilder::EmitVLACleanupStmts(FEManager::GetCurrentFEFunction(), stmts); UniqueFEIRStmt stmt = std::make_unique(std::move(feExpr)); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); stmts.emplace_back(std::move(stmt)); return stmts; } @@ -99,9 +116,8 @@ std::list ASTIfStmt::Emit2FEStmtImpl() const { } UniqueFEIRExpr condFEExpr = condExpr->Emit2FEExpr(stmts); condFEExpr = FEIRBuilder::CreateExprZeroCompare(OP_ne, std::move(condFEExpr)); - UniqueFEIRStmt ifStmt; - ifStmt = FEIRBuilder::CreateStmtIf(std::move(condFEExpr), thenStmts, elseStmts); - ifStmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + UniqueFEIRStmt ifStmt = FEIRBuilder::CreateStmtIf(std::move(condFEExpr), thenStmts, elseStmts); + ifStmt->SetSrcLoc(loc); stmts.emplace_back(std::move(ifStmt)); return stmts; } @@ -114,6 +130,11 @@ 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(FEUtils::CvtLoc2SrcPosition(GetSrcLoc()), + FEUtils::CvtLoc2SrcPosition(GetEndLoc()), true); + } if (initStmt != nullptr) { std::list feStmts = initStmt->Emit2FEStmt(); stmts.splice(stmts.cend(), feStmts); @@ -143,11 +164,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 feirScope = feFunction.PopTopScope(); + if (feirScope->GetVLASavedStackVar() != nullptr) { + auto stkRestoreStmt = feirScope->GenVLAStackRestoreStmt(); + stkRestoreStmt->SetSrcLoc(endLoc); + (void)stmts.emplace_back(std::move(stkRestoreStmt)); + } + hasEmitted2MIRScope = true; + } AstLoopUtil::Instance().PopCurrentBreak(); AstLoopUtil::Instance().PopCurrentContinue(); return stmts; @@ -161,6 +191,13 @@ std::list ASTWhileStmt::Emit2FEStmtImpl() const { AstLoopUtil::Instance().PushContinue(loopBodyEndLabelName); auto labelBodyEndStmt = std::make_unique(loopBodyEndLabelName); auto labelLoopEndStmt = std::make_unique(loopEndLabelName); + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + if (!hasEmitted2MIRScope) { + feFunction.PushStmtScope(true); + } + if (!AstLoopUtil::Instance().IsCurrentContinueLabelUsed() && hasNestContinueLabel) { + AstLoopUtil::Instance().PushNestContinue(loopBodyEndLabelName); + } std::list bodyFEStmts = bodyStmt->Emit2FEStmt(); std::list condStmts; std::list condPreStmts; @@ -168,11 +205,13 @@ std::list ASTWhileStmt::Emit2FEStmtImpl() const { (void)condExpr->Emit2FEExpr(condPreStmts); if (AstLoopUtil::Instance().IsCurrentContinueLabelUsed()) { bodyFEStmts.emplace_back(std::move(labelBodyEndStmt)); + } else if (hasNestContinueLabel) { + bodyFEStmts.emplace_back(std::move(labelBodyEndStmt)); } 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()) { @@ -180,11 +219,22 @@ std::list ASTWhileStmt::Emit2FEStmtImpl() const { } AstLoopUtil::Instance().PopCurrentBreak(); AstLoopUtil::Instance().PopCurrentContinue(); + if (hasNestContinueLabel) { + AstLoopUtil::Instance().PopNestContinue(); + } + if (!hasEmitted2MIRScope) { + (void)feFunction.PopTopScope(); + hasEmitted2MIRScope = true; + } return stmts; } std::list ASTDoStmt::Emit2FEStmtImpl() const { - std::list stmts; + std::list feStmts; + FEFunction &feFunc = FEManager::GetCurrentFEFunction(); + if (!hasEmitted2MIRScope) { + feFunc.PushStmtScope(true); + } std::string loopBodyEndLabelName = FEUtils::GetSequentialName("dowhile_body_end_"); std::string loopEndLabelName = FEUtils::GetSequentialName("dowhile_end_"); AstLoopUtil::Instance().PushBreak(loopEndLabelName); @@ -204,41 +254,65 @@ 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()); - stmts.emplace_back(std::move(whileStmt)); + whileStmt->SetSrcLoc(loc); + (void)feStmts.emplace_back(std::move(whileStmt)); if (AstLoopUtil::Instance().IsCurrentBreakLabelUsed()) { - stmts.emplace_back(std::move(labelLoopEndStmt)); + (void)feStmts.emplace_back(std::move(labelLoopEndStmt)); } AstLoopUtil::Instance().PopCurrentBreak(); AstLoopUtil::Instance().PopCurrentContinue(); - return stmts; + if (!hasEmitted2MIRScope) { + (void)feFunc.PopTopScope(); + hasEmitted2MIRScope = true; + } + return feStmts; } std::list ASTBreakStmt::Emit2FEStmtImpl() const { - std::list stmts; - auto stmt = std::make_unique(); + std::string breakName; if (!AstLoopUtil::Instance().IsBreakLabelsEmpty()) { - stmt->SetBreakLabelName(AstLoopUtil::Instance().GetCurrentBreak()); + breakName = AstLoopUtil::Instance().GetCurrentBreak(); } - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + std::string vlaLabelName = FEIRBuilder::EmitVLACleanupStmts(FEManager::GetCurrentFEFunction(), breakName, loc); + if (!vlaLabelName.empty()) { + breakName = vlaLabelName; + } + std::list stmts; + auto stmt = std::make_unique(); + stmt->SetBreakLabelName(breakName); + stmt->SetSrcLoc(loc); stmts.emplace_back(std::move(stmt)); return stmts; } std::list ASTLabelStmt::Emit2FEStmtImpl() const { + // collect scopes of label stmt + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + std::map scopes; + for (const auto &scope : feFunction.GetScopeStack()) { + scopes.insert(std::make_pair(scope->GetID(), scope->Clone())); + } + feFunction.SetLabelWithScopes(GetLabelName(), std::move(scopes)); 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; } std::list ASTContinueStmt::Emit2FEStmtImpl() const { + std::string continueName = AstLoopUtil::Instance().GetCurrentContinue(); + if (!AstLoopUtil::Instance().IsNestContinueLabelsEmpty() && !AstLoopUtil::Instance().IsNestContinueLabelUsed()) { + continueName = AstLoopUtil::Instance().GetNestContinue(); + } + std::string vlaLabelName = FEIRBuilder::EmitVLACleanupStmts(FEManager::GetCurrentFEFunction(), continueName, loc); + if (!vlaLabelName.empty()) { + continueName = vlaLabelName; + } std::list stmts; auto stmt = std::make_unique(); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); - stmt->SetLabelName(AstLoopUtil::Instance().GetCurrentContinue()); + stmt->SetLabelName(continueName); stmts.emplace_back(std::move(stmt)); return stmts; } @@ -255,7 +329,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 +337,15 @@ std::list ASTUnaryOperatorStmt::Emit2FEStmtImpl() const { // ---------- ASTGotoStmt ---------- std::list ASTGotoStmt::Emit2FEStmtImpl() const { std::list stmts; - UniqueFEIRStmt stmt = FEIRBuilder::CreateStmtGoto(labelName); - stmt->SetSrcFileInfo(GetSrcFileIdx(), GetSrcFileLineNum()); + auto stmt = std::make_unique(GetLabelName()); + // collect scopes with vla of goto stmt + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + std::vector> vlaSvaedStackVars; + for (const auto &scope : feFunction.GetScopeStack()) { + if (scope->GetVLASavedStackVar() != nullptr) { + stmt->AddVLASvaedStackVars(scope->GetID(), scope->GetVLASavedStackVar()->Clone()); + } + } stmts.emplace_back(std::move(stmt)); return stmts; } @@ -281,6 +361,10 @@ std::list ASTIndirectGotoStmt::Emit2FEStmtImpl() const { // ---------- ASTSwitchStmt ---------- std::list ASTSwitchStmt::Emit2FEStmtImpl() const { std::list stmts; + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + if (!hasEmitted2MIRScope) { + feFunction.PushStmtScope(true); + } UniqueFEIRExpr expr = condExpr->Emit2FEExpr(stmts); std::string exitName = AstSwitchUtil::Instance().CreateEndOrExitLabelName(); AstLoopUtil::Instance().PushBreak(exitName); @@ -291,12 +375,15 @@ 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)); } stmts.emplace_back(std::move(switchStmt)); AstLoopUtil::Instance().PopCurrentBreak(); + if (!hasEmitted2MIRScope) { + (void)feFunction.PopTopScope(); + hasEmitted2MIRScope = true; + } return stmts; } @@ -304,7 +391,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 +403,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)); } @@ -335,27 +420,24 @@ std::list ASTNullStmt::Emit2FEStmtImpl() const { // ---------- ASTDeclStmt ---------- std::list ASTDeclStmt::Emit2FEStmtImpl() const { std::list stmts; - for (auto expr : exprs) { - (void)expr->Emit2FEExpr(stmts); - } - for (auto decl : subDecls) { - InsertBoundaryVar(decl, stmts); - decl->GenerateInitStmt(stmts); + for (auto declInfo : subDeclInfos) { + if (std::holds_alternative(declInfo)) { + ASTExpr *vlaSizeExpr = std::get(declInfo); + if (vlaSizeExpr == nullptr) { + continue; + } + (void)vlaSizeExpr->Emit2FEExpr(stmts); + } else { + ASTDecl *decl = std::get(declInfo); + if (decl == nullptr) { + continue; + } + decl->GenerateInitStmt(stmts); + } } return stmts; } -void ASTDeclStmt::InsertBoundaryVar(ASTDecl *ptrDecl, std::list &stmts) const { - if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || - ptrDecl == nullptr || ptrDecl->GetBoundaryLenExpr() == nullptr) { - return; - } - // GetCurrentFunction need to be optimized when parallel features - MIRFunction *curFunction = FEManager::GetMIRBuilder().GetCurrentFunctionNotNull(); - UniqueFEIRExpr lenFEExpr = ptrDecl->GetBoundaryLenExpr()->Emit2FEExpr(stmts); - ENCChecker::InitBoundaryVar(*curFunction, *ptrDecl, std::move(lenFEExpr), stmts); -} - // ---------- ASTCallExprStmt ---------- std::list ASTCallExprStmt::Emit2FEStmtImpl() const { std::list stmts; @@ -368,7 +450,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 +468,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 +488,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 +501,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 +521,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 +534,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 +553,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 +577,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 +593,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,17 +602,19 @@ 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") { - std::unique_ptr addrOf = std::make_unique(); + std::unique_ptr addrOf = std::make_unique(allocator); addrOf->SetUOExpr(exprs[i + outputs.size()]); expr = addrOf->Emit2FEExpr(stmts); } else { @@ -548,8 +623,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 +639,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 +652,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..444e3d419392e0a9ff1fb67700893f46e010bba4 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; } @@ -95,13 +99,17 @@ MIRStructType *ASTStruct2FEHelper::CreateMIRStructTypeImpl(bool &error) const { ERR(kLncErr, "class name is empty"); return nullptr; } - MIRStructType *type = FEManager::GetTypeManager().GetOrCreateStructType(name); + MIRStructType *type = FEManager::GetTypeManager().GetOrCreateStructType(astStruct.GenerateUniqueVarName()); error = false; if (astStruct.IsUnion()) { type->SetMIRTypeKind(kTypeUnion); } else { type->SetMIRTypeKind(kTypeStruct); } + if (FEOptions::GetInstance().IsDbgFriendly() && type->GetAlias() == nullptr) { + MIRAlias *alias = allocator.GetMemPool()->New(&FEManager::GetModule()); + type->SetAlias(alias); + } return type; } @@ -143,6 +151,14 @@ bool ASTStructField2FEHelper::ProcessDeclWithContainerImpl(MapleAllocator &alloc mirFieldPair.first = idx; mirFieldPair.second.first = fieldType->GetTypeIndex(); mirFieldPair.second.second = attrs; + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRAlias *mirAlias = static_cast(structType).GetAlias(); + CHECK_NULL_FATAL(mirAlias); + TypeAttrs typeAttrs = field.GetGenericAttrs().ConvertToTypeAttrs(); + MIRAliasVars aliasVar = FEUtils::AddAlias(idx, field.GetSourceType(), typeAttrs); + mirAlias->SetAliasVarMap(idx, aliasVar); + } + field.ClearGenericAttrsContentMap(); return true; } @@ -151,7 +167,19 @@ bool ASTGlobalVar2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { (void)allocator; const std::string varName = astVar.GetName(); MIRType *type = astVar.GetTypeDesc().front(); - MIRSymbol *mirSymbol = FEManager::GetMIRBuilder().GetOrCreateGlobalDecl(varName, *type); + TypeAttrs typeAttrs = astVar.GetGenericAttrs().ConvertToTypeAttrs(); + ENCChecker::InsertBoundaryInAtts(typeAttrs, astVar.GetBoundaryInfo()); + MIRSymbol *mirSymbol = FEManager::GetMIRBuilder().GetGlobalDecl(varName); + if (mirSymbol != nullptr) { + // do not allow extern var override global var + if (mirSymbol->GetStorageClass() != MIRStorageClass::kScExtern && typeAttrs.GetAttr(ATTR_extern)) { + typeAttrs.ResetAttr(ATTR_extern); + } else if (mirSymbol->GetStorageClass() == MIRStorageClass::kScExtern && !typeAttrs.GetAttr(ATTR_extern)) { + mirSymbol->SetStorageClass(MIRStorageClass::kScGlobal); + } + } else { + mirSymbol = FEManager::GetMIRBuilder().GetOrCreateGlobalDecl(varName, *type); + } if (mirSymbol == nullptr) { return false; } @@ -160,19 +188,8 @@ 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()); - 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)) { - ASTExpr *initExpr = astVar.GetInitExpr(); - if (initExpr == nullptr) { - return true; - } - MIRConst *cst = initExpr->GenerateMIRConst(); - mirSymbol->SetKonst(cst); - return true; + if (mirSymbol->GetSrcPosition().LineNum() == 0) { + mirSymbol->SetSrcPosition(FEUtils::CvtLoc2SrcPosition(astVar.GetSrcLoc())); } if (typeAttrs.GetAttr(ATTR_extern)) { mirSymbol->SetStorageClass(MIRStorageClass::kScExtern); @@ -183,14 +200,18 @@ 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()); } if (!astVar.GetAsmAttr().empty()) { mirSymbol->SetAsmAttr(GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(astVar.GetAsmAttr())); } - ASTExpr *initExpr = astVar.GetInitExpr(); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRScope *scope = FEManager::GetModule().GetScope(); + FEUtils::AddAliasInMIRScope(*scope, varName, *mirSymbol, astVar.GetSourceType()); + } + const ASTExpr *initExpr = astVar.GetInitExpr(); MIRConst *cst = nullptr; if (initExpr != nullptr) { cst = initExpr->GenerateMIRConst(); @@ -200,12 +221,28 @@ bool ASTGlobalVar2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { return true; } +// ---------- ASTFileScopeAsm2FEHelper --------- bool ASTFileScopeAsm2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { MapleString asmDecl(astAsm.GetAsmStr().c_str(), allocator.GetMemPool()); FEManager::GetModule().GetAsmDecls().emplace_back(asmDecl); return true; } +// ---------- ASTEnum2FEHelper --------- +bool ASTEnum2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { + (void)allocator; + MIREnum *enumType = FEManager::GetTypeManager().GetOrCreateEnum( + astEnum.GenerateUniqueVarName(), astEnum.GetTypeDesc().front()->GetPrimType()); + if (!astEnum.GetEnumConstants().empty() && enumType->GetElements().empty()) { + for (auto elem : astEnum.GetEnumConstants()) { + GStrIdx elemNameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(elem->GetName()); + enumType->NewElement(elemNameIdx, elem->GetValue()); + } + enumType->SetPrimType(astEnum.GetEnumConstants().front()->GetTypeDesc().front()->GetPrimType()); + } + return true; +} + // ---------- ASTFunc2FEHelper ---------- bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { HIR2MPL_PARALLEL_FORBIDDEN(); @@ -217,13 +254,10 @@ bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { } methodNameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(methodShortName); if (!ASTUtil::InsertFuncSet(methodNameIdx)) { + func.ClearGenericAttrsContentMap(); return true; } SolveReturnAndArgTypes(allocator); - FuncAttrs attrs = GetAttrs(); - if (firstArgRet) { - attrs.SetAttr(FUNCATTR_firstarg_return); - } bool isStatic = IsStatic(); bool isVarg = IsVarg(); CHECK_FATAL(retMIRType != nullptr, "function must have return type"); @@ -233,9 +267,12 @@ 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(FEUtils::CvtLoc2SrcPosition(func.GetSrcLoc())); MIRSymbol *funSym = mirFunc->GetFuncSymbol(); + ASSERT_NOT_NULL(funSym); + if (FEOptions::GetInstance().IsDbgFriendly()) { + FEUtils::AddAliasInMIRScope(*mirFunc->GetScope(), mirFunc->GetName(), *funSym, func.GetSourceType()); + } if (!func.GetSectionAttr().empty()) { funSym->sectionAttr = GlobalTables::GetUStrTable().GetOrCreateStrIdxFromName(func.GetSectionAttr()); } @@ -247,45 +284,64 @@ bool ASTFunc2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { } funSym->SetWeakrefAttr(std::pair { true, idx }); } - std::vector paramDecls = func.GetParamDecls(); + SolveFunctionArguments(); + SolveFunctionAttributes(); + func.ClearGenericAttrsContentMap(); + return true; +} + +void ASTFunc2FEHelper::SolveFunctionArguments() const { + 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); + (void)paramDecls.insert(paramDecls.cbegin(), returnParamVar); } for (uint32 i = 0; i < paramDecls.size(); ++i) { MIRSymbol *sym = FEManager::GetMIRBuilder().GetOrCreateDeclInFunc( paramDecls[i]->GetName(), *argMIRTypes[i], *mirFunc); + ASSERT_NOT_NULL(sym); sym->SetStorageClass(kScFormal); sym->SetSKind(kStVar); TypeAttrs typeAttrs = paramDecls[i]->GetGenericAttrs().ConvertToTypeAttrs(); ENCChecker::InsertBoundaryInAtts(typeAttrs, paramDecls[i]->GetBoundaryInfo()); sym->AddAttrs(typeAttrs); mirFunc->AddArgument(sym); + if (FEOptions::GetInstance().IsDbgFriendly() && paramDecls[i]->GetDeclKind() == kASTVar && + (!firstArgRet || i != 0)) { + FEUtils::AddAliasInMIRScope(*mirFunc->GetScope(), paramDecls[i]->GetName(), *sym, + static_cast(paramDecls[i])->GetSourceType()); + } + } +} + +void ASTFunc2FEHelper::SolveFunctionAttributes() { + FuncAttrs attrs = GetAttrs(); + if (firstArgRet) { + attrs.SetAttr(FUNCATTR_firstarg_return); } mirMethodPair.first = mirFunc->GetStIdx(); mirMethodPair.second.first = mirFunc->GetMIRFuncType()->GetTypeIndex(); ENCChecker::InsertBoundaryInAtts(attrs, func.GetBoundaryInfo()); mirMethodPair.second.second = attrs; mirFunc->SetFuncAttrs(attrs); - 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()); + (void)argMIRTypes.insert(argMIRTypes.cbegin(), returnAndArgTypeNames.cbegin() + 2, returnAndArgTypeNames.cend()); if (retMIRType->GetPrimType() == PTY_agg && retMIRType->GetSize() > 16) { firstArgRet = true; MIRType *retPointerType = GlobalTables::GetTypeTable().GetOrCreatePointerType(*retMIRType); - argMIRTypes.insert(argMIRTypes.begin(), retPointerType); + (void)argMIRTypes.insert(argMIRTypes.cbegin(), retPointerType); retMIRType = GlobalTables::GetTypeTable().GetPrimType(PTY_void); } } @@ -331,9 +387,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..680d471f86dbe3ce6e376320c56f44b87aa48a2b 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. @@ -28,6 +28,8 @@ ASTCompilerComponent::ASTCompilerComponent(MIRModule &module) template ASTCompilerComponent::~ASTCompilerComponent() { + astInput.ClearASTMemberVariable(); + ReleaseMemPool(); mp = nullptr; } @@ -47,21 +49,8 @@ bool ASTCompilerComponent::ParseInputImpl() { } success = success && astInput.ReadASTFiles(allocator, inputNames); CHECK_FATAL(success, "ASTCompilerComponent::ParseInput failed. Exit."); - for (auto &astStruct : astInput.GetASTStructs()) { - FEInputStructHelper *structHelper = allocator.GetMemPool()->New(allocator, *astStruct); - structHelpers.emplace_back(structHelper); - } - - 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; - } - } - globalFuncHelpers.emplace_back(funcHelper); - } + ParseInputStructs(); + ParseInputFuncs(); for (auto &astVar : astInput.GetASTVars()) { FEInputGlobalVarHelper *varHelper = allocator.GetMemPool()->New(allocator, *astVar); @@ -73,10 +62,53 @@ bool ASTCompilerComponent::ParseInputImpl() { allocator, *astFileScopeAsm); globalFileScopeAsmHelpers.emplace_back(asmHelper); } + + for (auto &astEnum : astInput.GetASTEnums()) { + ASTEnum2FEHelper *enumHelper = allocator.GetMemPool()->New(allocator, *astEnum); + (void)enumHelpers.emplace_back(enumHelper); + } timer.StopAndDumpTimeMS("ASTCompilerComponent::ParseInput()"); return success; } +template +void ASTCompilerComponent::ParseInputStructs() { + for (auto &astStruct : astInput.GetASTStructs()) { + std::string structName = astStruct->GenerateUniqueVarName(); + // skip same name structs + if (structNameSet.find(structName) != structNameSet.cend()) { + continue; + } + FEInputStructHelper *structHelper = allocator.GetMemPool()->New(allocator, *astStruct); + structHelpers.emplace_back(structHelper); + structNameSet.insert(structName); + } +} + +template +void ASTCompilerComponent::ParseInputFuncs() { + for (auto &astFunc : astInput.GetASTFuncs()) { + auto it = funcNameMap.find(astFunc->GetName()); + if (it != funcNameMap.cend()) { + // save the function with funcbody + if (it->second->HasCode() && !astFunc->HasCode()) { + continue; + } else { + (void)funcNameMap.erase(it); + auto itHelper = std::find_if(std::begin(globalFuncHelpers), std::end(globalFuncHelpers), + [&astFunc](FEInputMethodHelper *s) -> bool { + return (s->GetMethodName(false) == astFunc->GetName()); + }); + CHECK_FATAL(itHelper != globalFuncHelpers.end(), "astFunc not found"); + (void)globalFuncHelpers.erase(itHelper); + } + } + FEInputMethodHelper *funcHelper = allocator.GetMemPool()->New(allocator, *astFunc); + globalFuncHelpers.emplace_back(funcHelper); + funcNameMap.insert(std::make_pair(astFunc->GetName(), funcHelper)); + } +} + template bool ASTCompilerComponent::PreProcessDeclImpl() { FETimer timer; diff --git a/src/hir2mpl/ast_input/common/include/ast_compiler_component.h b/src/hir2mpl/ast_input/common/include/ast_compiler_component.h index 07e6dadc6eaed90b6bf1d3e09b7bde58c0339164..be00e27ab356d0c60bd1e70dfa29084da80d24b6 100644 --- a/src/hir2mpl/ast_input/common/include/ast_compiler_component.h +++ b/src/hir2mpl/ast_input/common/include/ast_compiler_component.h @@ -17,13 +17,14 @@ #include "fe_macros.h" #include "hir2mpl_compiler_component.h" #include "ast_input.h" +#include "ast_input-inl.h" namespace maple { template class ASTCompilerComponent : public HIR2MPLCompilerComponent { public: explicit ASTCompilerComponent(MIRModule &module); - ~ASTCompilerComponent(); + ~ASTCompilerComponent() override; protected: bool ParseInputImpl() override; @@ -48,7 +49,11 @@ class ASTCompilerComponent : public HIR2MPLCompilerComponent { MemPool *mp; MapleAllocator allocator; ASTInput astInput; + std::unordered_set structNameSet; + std::unordered_map funcNameMap; + + void ParseInputStructs(); + void ParseInputFuncs(); }; // class ASTCompilerComponent } // namespace maple -#include "ast_compiler_component-inl.h" #endif // HIR2MPL_AST_INPUT_INCLUDE_AST_COMPILER_COMPONENT_H diff --git a/src/hir2mpl/ast_input/common/include/ast_decl.h b/src/hir2mpl/ast_input/common/include/ast_decl.h index cc66fac4e766940773cb98f350e0f070c81254ed..c0b0acb423bd571c7f0657839b82c6f6fcdbf589 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. @@ -24,7 +24,6 @@ #include "generic_attrs.h" namespace maple { -using Pos = std::pair; enum DeclKind { kUnknownDecl = 0, kASTDecl, @@ -35,6 +34,7 @@ enum DeclKind { kASTEnumConstant, kASTEnumDecl, kASTFileScopeAsm, + kASTTypedefDecl, }; struct BoundaryInfo { @@ -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 = static_cast(flag); + } + } + + uint32 IsMacroID() const { + return isMacroID; + } + void SetAlign(uint32 n) { if (n > align) { align = n; @@ -98,21 +110,24 @@ class ASTDecl { return GenerateInitStmtImpl(stmts); } - void SetDeclPos(const Pos &p) { - pos = p; + void SetSrcLoc(const Loc &l) { + loc = l; } - void SetSrcLOC(uint32 fileIdx, uint32 lineNum) { - srcFileIdx = fileIdx; - srcFileLineNum = lineNum; + 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 +166,26 @@ class ASTDecl { return boundary.isBytedLen; } + void ClearGenericAttrsContentMap() { + genAttrs.ClearContentMap(); + } + + const MIRType *GetSourceType() const { + return sourceType; + } + + void SetSourceType(MIRType *type) { + sourceType = type; + } + + void SetCallAlloca(bool isAlloc) { + isCallAlloca = isAlloc; + } + + bool IsCallAlloca() const { + return isCallAlloca; + } + protected: virtual MIRConst *Translate2MIRConstImpl() const { CHECK_FATAL(false, "Maybe implemented for other ASTDecls"); @@ -160,21 +195,25 @@ 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 }; + uint32 isMacroID = false; DeclKind declKind = kASTDecl; BoundaryInfo boundary; std::string sectionAttr; + MIRType *sourceType = nullptr; + + private: + bool isCallAlloca = false; }; 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,19 +230,19 @@ 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; } - ~ASTFunc() { + ~ASTFunc() override { compound = nullptr; } - void SetCompoundStmt(ASTStmt*); - void InsertStmtsIntoCompoundStmtAtFront(const std::list &stmts); + void SetCompoundStmt(ASTStmt *astCompoundStmt); + void InsertStmtsIntoCompoundStmtAtFront(const std::list &stmts) const; const ASTStmt *GetCompoundStmt() const; - const std::vector &GetParamDecls() const { + const MapleVector &GetParamDecls() const { return paramDecls; } std::vector> GenArgVarList() const; @@ -219,27 +258,26 @@ class ASTFunc : public ASTDecl { return weakrefAttr; } - uint32 GetSize() const { - return bodySize; - } - - void SetSize(uint32 size) { - 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 +289,7 @@ class ASTStruct : public ASTDecl { fields.emplace_back(f); } - const std::list &GetFields() const { + const MapleList &GetFields() const { return fields; } @@ -264,14 +302,16 @@ class ASTStruct : public ASTDecl { } private: + void GenerateInitStmtImpl(std::list &stmts) override; + 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; @@ -283,7 +323,7 @@ class ASTVar : public ASTDecl { initExpr = init; } - ASTExpr *GetInitExpr() const { + const ASTExpr *GetInitExpr() const { return initExpr; } @@ -299,23 +339,33 @@ 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; private: MIRConst *Translate2MIRConstImpl() const override; void GenerateInitStmtImpl(std::list &stmts) override; - void GenerateInitStmt4StringLiteral(ASTExpr *initASTExpr, const UniqueFEIRVar &feirVar, - const UniqueFEIRExpr &initFeirExpr, std::list &stmts); + void GenerateInitStmt4StringLiteral(const ASTExpr *initASTExpr, const UniqueFEIRVar &feirVar, + const UniqueFEIRExpr &initFeirExpr, std::list &stmts) const; 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,28 +384,27 @@ 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; } ~ASTEnumConstant() = default; - void SetValue(int32 val); - int32 GetValue() const; + void SetValue(const IntVal &val); + const IntVal &GetValue() const; private: MIRConst *Translate2MIRConstImpl() const override; - int32 value = 0; + IntVal value; }; -// 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; } @@ -365,8 +414,39 @@ class ASTEnumDecl : public ASTDecl { consts.emplace_back(c); } + const MapleList &GetEnumConstants() const { + return consts; + } + private: - std::list consts; + void GenerateInitStmtImpl(std::list &stmts) override; + + MapleList consts; +}; + +class ASTTypedefDecl : public ASTDecl { + public: + ASTTypedefDecl(const MapleString &srcFile, const MapleString &nameIn, + const MapleVector &typeDescIn, const GenericAttrs &genAttrsIn) + : ASTDecl(srcFile, nameIn, typeDescIn) { + genAttrs = genAttrsIn; + declKind = kASTTypedefDecl; + } + ~ASTTypedefDecl() = default; + + void SetSubTypedefDecl(ASTTypedefDecl *decl) { + subTypedefDecl = decl; + } + + const ASTTypedefDecl *GetSubTypedefDecl() const { + return subTypedefDecl; + } + + private: + void GenerateInitStmtImpl(std::list &stmts) override; + + ASTTypedefDecl* subTypedefDecl = nullptr; + }; } // 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..6b4272f8812a2c3809e767ea93f1c8acc424b8d6 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,114 @@ 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]); } + static ASTTypedefDecl *ASTTypedefBuilder(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, varNameStr, desc, genAttrsIn); + } else if (declesTable[id] == nullptr) { + declesTable[id] = allocator.GetMemPool()->New(srcFile, varNameStr, desc, genAttrsIn); + } + 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..536ea52f6cecde1b36fc866bb0b8f2244455a5eb 100644 --- a/src/hir2mpl/ast_input/common/include/ast_input-inl.h +++ b/src/hir2mpl/ast_input/common/include/ast_input-inl.h @@ -21,31 +21,42 @@ template ASTInput::ASTInput(MIRModule &moduleIn, MapleAllocator &allocatorIn) : module(moduleIn), allocator(allocatorIn), parserMap(allocatorIn.Adapter()), astStructs(allocatorIn.Adapter()), astFuncs(allocatorIn.Adapter()), astVars(allocatorIn.Adapter()), - astFileScopeAsms(allocatorIn.Adapter()) {} + astFileScopeAsms(allocatorIn.Adapter()), astEnums(allocatorIn.Adapter()) {} 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()); + astStructs, astFuncs, astVars, + astFileScopeAsms, astEnums); + 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, + // Some implicit record or enum decl would be retrieved in func body at use, // so we put `RetrieveFuncs` before `RetrieveStructs` TRY_DO(parser->RetrieveFuncs(allocatorIn)); TRY_DO(parser->RetrieveStructs(allocatorIn)); + if (FEOptions::GetInstance().IsDbgFriendly()) { + TRY_DO(parser->RetrieveEnums(allocatorIn)); + TRY_DO(parser->RetrieveGlobalTypeDef(allocatorIn)); + } TRY_DO(parser->RetrieveGlobalVars(allocatorIn)); TRY_DO(parser->RetrieveFileScopeAsms(allocatorIn)); + TRY_DO(parser->Release()); parserMap.emplace(fileName, parser); return true; } template -bool ASTInput::ReadASTFiles(MapleAllocator &mapleAllocator, const std::vector &fileNames) { +bool ASTInput::ReadASTFiles(MapleAllocator &allocatorIn, const std::vector &fileNames) { bool res = true; for (uint32 i = 0; res && i < fileNames.size(); ++i) { - res = res && ReadASTFile(mapleAllocator, i, fileNames[i]); + FETimer timer; + std::stringstream ss; + ss << "ReadASTFile[" << (i + 1) << "/" << fileNames.size() << "]: " << fileNames[i]; + timer.StartAndDump(ss.str()); + res = res && ReadASTFile(allocatorIn, i, fileNames[i]); RegisterFileInfo(fileNames[i]); + timer.StopAndDumpTimeMS(ss.str()); } return res; } diff --git a/src/hir2mpl/ast_input/common/include/ast_input.h b/src/hir2mpl/ast_input/common/include/ast_input.h index 0352be5790db830d89fe4894cca934ebea947f5d..37634ea8e5e7e58307eeeb452c7572336c0f7f46 100644 --- a/src/hir2mpl/ast_input/common/include/ast_input.h +++ b/src/hir2mpl/ast_input/common/include/ast_input.h @@ -70,6 +70,19 @@ class ASTInput { astFileScopeAsms.emplace_back(fileScopeAsm); } + const MapleList &GetASTEnums() const { + return astEnums; + } + + void ClearASTMemberVariable() { + parserMap.clear(); + astStructs.clear(); + astFuncs.clear(); + astVars.clear(); + astFileScopeAsms.clear(); + astEnums.clear(); + } + private: MIRModule &module; MapleAllocator &allocator; @@ -79,7 +92,7 @@ class ASTInput { MapleList astFuncs; MapleList astVars; MapleList astFileScopeAsms; + MapleList astEnums; }; } -#include "ast_input-inl.h" #endif // HIR2MPL_AST_INPUT_INCLUDE_AST_INPUT_H \ No newline at end of file diff --git a/src/hir2mpl/ast_input/common/src/ast_decl.cpp b/src/hir2mpl/ast_input/common/src/ast_decl.cpp index 56c9747695190252267d080b87c74acc1f9def70..27042a952d99482254360ff0ba1fa5276d1669ae 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 != 0) { + // for macro expansion, variable names of same location need to be unique + os << "_" << std::to_string(isMacroID); + } else { + os << "_" << std::to_string(loc.line) << "_" << std::to_string(loc.column); + } + 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; @@ -74,9 +82,9 @@ MIRConst *ASTVar::Translate2MIRConstImpl() const { return initExpr->GenerateMIRConst(); } -void ASTVar::GenerateInitStmt4StringLiteral(ASTExpr *initASTExpr, const UniqueFEIRVar &feirVar, - const UniqueFEIRExpr &initFeirExpr, std::list &stmts) { - if (!static_cast(initASTExpr)->IsArrayToPointerDecay()) { +void ASTVar::GenerateInitStmt4StringLiteral(const ASTExpr *initASTExpr, const UniqueFEIRVar &feirVar, + const UniqueFEIRExpr &initFeirExpr, std::list &stmts) const { + if (!static_cast(initASTExpr)->IsArrayToPointerDecay()) { std::unique_ptr> argExprList = std::make_unique>(); UniqueFEIRExpr dstExpr = FEIRBuilder::CreateExprAddrofVar(feirVar->Clone()); uint32 stringLiteralSize = static_cast(initFeirExpr.get())->GetStringLiteralSize(); @@ -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,18 +136,40 @@ 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.GetTopMIRScope(); + FEUtils::AddAliasInMIRScope(*mirScope, GetName(), *sym, sourceType); + hasAddedInMIRScope = true; + } + if (variableArrayExpr != nullptr) { // vla declaration point + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + if (feFunction.GetTopFEIRScopePtr() != nullptr && + feFunction.GetTopFEIRScopePtr()->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()); + (void)stmts.emplace_back(std::move(stackSaveStmt)); + // push saved stack var into scope + feFunction.GetTopFEIRScopePtr()->SetVLASavedStackVar(std::move(stackVar)); + feFunction.GetTopFEIRScopePtr()->SetVLASavedStackPtr(stmts.back().get()); + } // 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)); - return; + UniqueFEIRStmt allocaStmt = FEIRBuilder::CreateStmtDAssign(feirVar->Clone(), std::move(allocaExpr)); + allocaStmt->SetSrcLoc(feirVar->GetSrcLoc()); + (void)stmts.emplace_back(std::move(allocaStmt)); } + ENCChecker::InsertBoundaryVar(*this, stmts); if (initExpr == nullptr) { return; } @@ -161,11 +193,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 +206,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()) { @@ -190,17 +220,16 @@ MIRSymbol *ASTVar::Translate2MIRSymbol() const { } // ---------- ASTEnumConstant ---------- -void ASTEnumConstant::SetValue(int32 val) { +void ASTEnumConstant::SetValue(const IntVal &val) { value = val; } -int32 ASTEnumConstant::GetValue() const { +const IntVal &ASTEnumConstant::GetValue() const { return value; } MIRConst *ASTEnumConstant::Translate2MIRConstImpl() const { - return GlobalTables::GetIntConstTable().GetOrCreateIntConst( - value, *GlobalTables::GetTypeTable().GetPrimType(PTY_i32)); + return GlobalTables::GetIntConstTable().GetOrCreateIntConst(value, *typeDesc.front()); } // ---------- ASTFunc --------- @@ -208,7 +237,7 @@ void ASTFunc::SetCompoundStmt(ASTStmt *astCompoundStmt) { compound = astCompoundStmt; } -void ASTFunc::InsertStmtsIntoCompoundStmtAtFront(const std::list &stmts) { +void ASTFunc::InsertStmtsIntoCompoundStmtAtFront(const std::list &stmts) const { static_cast(compound)->InsertASTStmtsAtFront(stmts); } @@ -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(FEUtils::CvtLoc2SrcPosition(astCpdStmt->GetSrcLoc()), + FEUtils::CvtLoc2SrcPosition(astCpdStmt->GetEndLoc())); + const MapleList &astStmtList = astCpdStmt->GetASTStmtList(); for (auto stmtNode : astStmtList) { std::list childStmts = stmtNode->Emit2FEStmt(); for (auto &stmt : childStmts) { @@ -236,8 +268,11 @@ std::list ASTFunc::EmitASTStmtToFEIR() const { stmts.emplace_back(std::move(stmt)); } } + UniqueFEIRScope scope = feFunction.PopTopScope(); // 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) { + Loc endLoc = astCpdStmt->GetEndLoc(); + scope->ProcessVLAStack(stmts, astCpdStmt->IsCallAlloca(), endLoc); UniqueFEIRExpr retExpr = nullptr; PrimType retType = typeDesc[1]->GetPrimType(); if (retType != PTY_void) { @@ -247,6 +282,8 @@ std::list ASTFunc::EmitASTStmtToFEIR() const { retExpr = FEIRBuilder::CreateExprConstAnyScalar(retType, static_cast(0)); } UniqueFEIRStmt retStmt = std::make_unique(std::move(retExpr)); + endLoc.column = 0; + retStmt->SetSrcLoc(endLoc); stmts.emplace_back(std::move(retStmt)); } InsertBoundaryCheckingInRet(stmts); @@ -255,6 +292,47 @@ 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(); +} + +void ASTStruct::GenerateInitStmtImpl(std::list &stmts) { + (void)stmts; + if (!FEOptions::GetInstance().IsDbgFriendly()) { + return; + } + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + MIRScope *mirScope = feFunction.GetTopMIRScope(); + mirScope->SetTypeAliasMap(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(GetName()), + typeDesc.front()->GetTypeIndex()); +} + +// ---------- ASTEnumDecl ---------- +void ASTEnumDecl::GenerateInitStmtImpl(std::list &stmts) { + (void)stmts; + if (!FEOptions::GetInstance().IsDbgFriendly()) { + return; + } + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + MIRScope *mirScope = feFunction.GetTopMIRScope(); + MIRTypeByName *type = FEManager::GetTypeManager().GetOrCreateTypeByNameType(GenerateUniqueVarName()); + mirScope->SetTypeAliasMap(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(GetName()), type->GetTypeIndex()); +} + +// ---------- ASTTypedefDecl ---------- +void ASTTypedefDecl::GenerateInitStmtImpl(std::list &stmts) { + (void)stmts; + if (!FEOptions::GetInstance().IsDbgFriendly()) { + return; + } + FEFunction &feFunction = FEManager::GetCurrentFEFunction(); + MIRScope *mirScope = feFunction.GetTopMIRScope(); + const ASTTypedefDecl *astTypedef = this; + while (astTypedef != nullptr && !astTypedef->isGlobalDecl) { + MIRTypeByName *type = FEManager::GetTypeManager().CreateTypedef( + astTypedef->GenerateUniqueVarName(), *astTypedef->GetTypeDesc().front()); + mirScope->SetTypeAliasMap(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName( + astTypedef->GetName()), type->GetTypeIndex()); + astTypedef = astTypedef->GetSubTypedefDecl(); + } } } // namespace maple diff --git a/src/hir2mpl/ast_input/maple/lib/maple_ast_interface.cpp b/src/hir2mpl/ast_input/maple/lib/maple_ast_interface.cpp index 614abb630c74c8a40c351cfe821c7f6d361bb573..678f3c15dc9093543eee615cbcb79cecc9f58dc8 100644 --- a/src/hir2mpl/ast_input/maple/lib/maple_ast_interface.cpp +++ b/src/hir2mpl/ast_input/maple/lib/maple_ast_interface.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. @@ -28,7 +28,7 @@ bool LibMapleAstFile::Open(const std::string &fileName) { maplefe::AstLoad loadAst; maplefe::ModuleNode *mod = loadAst.LoadFromAstBuf(vec); // add mod to the vector - while(mod) { + while (mod) { handler.AddModule(mod); mod = loadAst.Next(); } 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..33b6137e56451963c6d41f254821fdd251ef9c5a 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. @@ -59,8 +59,6 @@ bool MapleASTParser::PreProcessAST() { #define MAPLE_DECL_CASE(CLASS) \ case maplefe::NK_##CLASS: { \ ASTDecl *astDecl = ProcessDecl##CLASS##Node(allocator, static_cast(decl)); \ - if (astDecl != nullptr) { \ - } \ return astDecl; \ } @@ -78,7 +76,6 @@ ASTDecl *MapleASTParser::ProcessDecl(MapleAllocator &allocator, maplefe::TreeNod CHECK_FATAL(false, "ASTDecl NIY"); return nullptr; } - return nullptr; } ASTDecl *MapleASTParser::ProcessDeclIdentifierNode(MapleAllocator &allocator, maplefe::IdentifierNode *identifierDecl) { @@ -97,7 +94,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 +126,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 +134,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); @@ -223,9 +220,6 @@ ASTStmt *MapleASTParser::ProcessStmtReturnNode(MapleAllocator &allocator, maplef #define MAPLE_EXPR_CASE(CLASS) \ case maplefe::NK_##CLASS: { \ ASTExpr *astExpr = ProcessExpr##CLASS##Node(allocator, static_cast(expr)); \ - if (astExpr == nullptr) { \ - return nullptr; \ - } \ return astExpr; \ } diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_attr.h b/src/hir2mpl/bytecode_input/class/include/jbc_attr.h index 59024ee5acae7647254de9a0cb83a172f10fee0f..ea6ccc9f535724d6bab36cea2fb6cd49bb74efcc 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_attr.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_attr.h @@ -86,7 +86,7 @@ class JBCAttrMap { class JBCAttrRaw : public JBCAttr { public: JBCAttrRaw(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrRaw(); + ~JBCAttrRaw() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io, const JBCConstPool &constPool) override; @@ -141,7 +141,7 @@ class JBCAttrLocalVariableInfo { class JBCAttrConstantValue : public JBCAttr { public: JBCAttrConstantValue(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrConstantValue(); + ~JBCAttrConstantValue() override; const JBCConst *GetConstValue() const { return constValue; } @@ -163,7 +163,7 @@ class JBCOp; class JBCAttrCode : public JBCAttr { public: JBCAttrCode(MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrCode(); + ~JBCAttrCode() override; void InitLocalVarInfo(); void SetLoadStoreType() const; const MapleMap &GetInstMap() const { @@ -279,7 +279,7 @@ class JBCAttrInnerClass : public JBCAttr { class JBCAttrEnclosingMethod : public JBCAttr { public: JBCAttrEnclosingMethod(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrEnclosingMethod(); + ~JBCAttrEnclosingMethod() override; const JBCConstClass *GetConstClass() const { return constClass; } @@ -318,7 +318,7 @@ class JBCAttrSynthetic : public JBCAttr { class JBCAttrSignature : public JBCAttr { public: JBCAttrSignature(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrSignature(); + ~JBCAttrSignature() override; const JBCConstUTF8 *GetConstSignatureName() const { return constSignatureName; } @@ -338,7 +338,7 @@ class JBCAttrSignature : public JBCAttr { class JBCAttrSourceFile : public JBCAttr { public: JBCAttrSourceFile(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrSourceFile(); + ~JBCAttrSourceFile() override; const JBCConstUTF8 *GetConstFileName() const { return constFileName; } @@ -358,7 +358,7 @@ class JBCAttrSourceFile : public JBCAttr { class JBCAttrSourceDebugEx : public JBCAttr { public: JBCAttrSourceDebugEx(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrSourceDebugEx(); + ~JBCAttrSourceDebugEx() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io, const JBCConstPool &constPool) override; @@ -491,13 +491,13 @@ class JBCAttrRTParamAnnotations : public JBCAttr { class JBCAttrRTVisParamAnnotations : public JBCAttrRTParamAnnotations { public: JBCAttrRTVisParamAnnotations(MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrRTVisParamAnnotations() {} + ~JBCAttrRTVisParamAnnotations() override {} }; class JBCAttrRTInvisParamAnnotations : public JBCAttrRTParamAnnotations { public: JBCAttrRTInvisParamAnnotations(MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrRTInvisParamAnnotations() {} + ~JBCAttrRTInvisParamAnnotations() override {} }; // RuntimeVisibleTypeAnnotations Attribute @@ -534,7 +534,7 @@ class JBCAttrRTInvisTypeAnnotations : public JBCAttrRTTypeAnnotations { class JBCAttrAnnotationDefault : public JBCAttr { public: JBCAttrAnnotationDefault(const MapleAllocator &allocator, uint16 nameIdx, uint32 length); - ~JBCAttrAnnotationDefault(); + ~JBCAttrAnnotationDefault() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io, const JBCConstPool &constPool) override; diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_attr_item.h b/src/hir2mpl/bytecode_input/class/include/jbc_attr_item.h index 32ef975dd2573b3191d8637ff39791d3d9de1d8c..e94c7d12c58877e5f036c4dc968083bb0cf2e75a 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_attr_item.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_attr_item.h @@ -61,7 +61,7 @@ class JBCAttrItem { class ExceptionTableItem : public JBCAttrItem { public: ExceptionTableItem(); - ~ExceptionTableItem(); + ~ExceptionTableItem() override; uint16 GetStartPC() const { return startPC; } @@ -108,7 +108,7 @@ enum VerificationTypeInfoTag : uint8 { class VerificationTypeInfo : public JBCAttrItem { public: VerificationTypeInfo(); - ~VerificationTypeInfo(); + ~VerificationTypeInfo() override; static std::map InitTagNameMap(); static std::string TagName(VerificationTypeInfoTag t); const JBCConstClass &GetClassInfoRef() const { @@ -172,7 +172,7 @@ class StackMapFrameItemSame : public StackMapFrameItem { class StackMapFrameItemSameLocals1 : public StackMapFrameItem { public: explicit StackMapFrameItemSameLocals1(uint8 frameType); - ~StackMapFrameItemSameLocals1(); + ~StackMapFrameItemSameLocals1() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io) override; @@ -186,7 +186,7 @@ class StackMapFrameItemSameLocals1 : public StackMapFrameItem { class StackMapFrameItemSameLocals1Ex : public StackMapFrameItem { public: explicit StackMapFrameItemSameLocals1Ex(uint8 frameType); - ~StackMapFrameItemSameLocals1Ex(); + ~StackMapFrameItemSameLocals1Ex() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io) override; @@ -264,7 +264,7 @@ class StackMapFrameItemFull : public StackMapFrameItem { class InnerClassItem : public JBCAttrItem { public: InnerClassItem(); - ~InnerClassItem(); + ~InnerClassItem() override; const JBCConstClass *GetConstClassInnerRef() const { return constClassInner; } @@ -321,7 +321,7 @@ class LineNumberTableItem : public JBCAttrItem { class LocalVariableTableItem : public JBCAttrItem { public: LocalVariableTableItem(); - ~LocalVariableTableItem(); + ~LocalVariableTableItem() override; const JBCConstUTF8 *GetConstName() const { return constName; } @@ -373,7 +373,7 @@ class LocalVariableTableItem : public JBCAttrItem { class LocalVariableTypeTableItem : public JBCAttrItem { public: LocalVariableTypeTableItem(); - ~LocalVariableTypeTableItem(); + ~LocalVariableTypeTableItem() override; const JBCConstUTF8 *GetConstName() const { return constName; } @@ -440,7 +440,7 @@ class ElementValueItem : public JBCAttrItem { class ElementValue : public JBCAttrItem { public: ElementValue(); - ~ElementValue(); + ~ElementValue() override; ElementValueKind GetKind() const { return kind; } @@ -459,7 +459,7 @@ class ElementValue : public JBCAttrItem { class ElementValuePair : public JBCAttrItem { public: ElementValuePair(); - ~ElementValuePair(); + ~ElementValuePair() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io) override; @@ -476,7 +476,7 @@ class ElementValuePair : public JBCAttrItem { class Annotation : public JBCAttrItem { public: explicit Annotation(MapleAllocator &allocator); - ~Annotation(); + ~Annotation() override; const JBCConstUTF8 *GetConstTypeName() const { return constTypeName; } @@ -516,7 +516,7 @@ class ParamAnnotationItem : public JBCAttrItem { class BootstrapMethodItem : public JBCAttrItem { public: explicit BootstrapMethodItem(MapleAllocator &allocator); - ~BootstrapMethodItem(); + ~BootstrapMethodItem() override; const JBCConstMethodHandleInfo *GetConstMethodHandleInfo() const { return methodHandle; } @@ -539,7 +539,7 @@ class BootstrapMethodItem : public JBCAttrItem { class MethodParamItem : public JBCAttrItem { public: MethodParamItem(); - ~MethodParamItem(); + ~MethodParamItem() override; const JBCConstUTF8 *GetConstName() const { return constName; } @@ -560,7 +560,7 @@ class ElementValuePair; class ElementValueConst : public ElementValueItem { public: explicit ElementValueConst(uint8 t); - ~ElementValueConst(); + ~ElementValueConst() override; const JBCConst *GetConstValue() const { return constValue; } @@ -578,7 +578,7 @@ class ElementValueConst : public ElementValueItem { class ElementValueEnum : public ElementValueItem { public: ElementValueEnum(); - ~ElementValueEnum(); + ~ElementValueEnum() override; const JBCConstUTF8 *GetConstTypeName() const { return constTypeName; } @@ -602,7 +602,7 @@ class ElementValueEnum : public ElementValueItem { class ElementValueClassInfo : public ElementValueItem { public: ElementValueClassInfo(); - ~ElementValueClassInfo(); + ~ElementValueClassInfo() override; const JBCConstUTF8 *GetConstClassInfo() const { return constClassInfo; } @@ -620,7 +620,7 @@ class ElementValueClassInfo : public ElementValueItem { class ElementValueAnnotation : public ElementValueItem { public: ElementValueAnnotation(); - ~ElementValueAnnotation(); + ~ElementValueAnnotation() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io) override; @@ -891,7 +891,7 @@ class TypePath : public JBCAttrItem { class TypeAnnotationItem : public JBCAttrItem { public: explicit TypeAnnotationItem(MapleAllocator &allocator); - ~TypeAnnotationItem(); + ~TypeAnnotationItem() override; protected: bool ParseFileImpl(MapleAllocator &allocator, BasicIORead &io) override; @@ -909,4 +909,4 @@ class TypeAnnotationItem : public JBCAttrItem { } // namespace attr } // namespace jbc } // namespace maple -#endif // HIR2MPL_INCLUDE_JBC_ATTR_ITEM_H \ No newline at end of file +#endif // HIR2MPL_INCLUDE_JBC_ATTR_ITEM_H diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_bb.h b/src/hir2mpl/bytecode_input/class/include/jbc_bb.h index f3a3985cbc2670008ccdd91bf9da91a69c3dc19f..889e994988a1b7faca88d448e50caa71f3e36059 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_bb.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_bb.h @@ -23,7 +23,7 @@ class JBCBB : public FEIRBB { public: JBCBB(const jbc::JBCConstPool &argConstPool); JBCBB(uint8 argBBKind, const jbc::JBCConstPool &argConstPool); - ~JBCBB() = default; + ~JBCBB() override = default; bool InitForFuncHeader(); bool InitForCatch(); bool UpdateStack(); diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_class_access.h b/src/hir2mpl/bytecode_input/class/include/jbc_class_access.h index 7868663856560b99b799a43ffd2446c0ff11df28..d38ba68c4e20e8760d230b020689f7f367c9510f 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_class_access.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_class_access.h @@ -17,7 +17,7 @@ namespace maple { namespace jbc { -enum JBCClassAccessFlag { +enum JBCClassAccessFlag: uint16 { kAccClassPublic = 0x0001, kAccClassFinal = 0x0010, kAccClassSuper = 0x0020, @@ -40,7 +40,7 @@ enum JBCClassFieldAccessFlag { kAccFieldEnum = 0x4000, }; -enum JBCClassMethodAccessFlag { +enum JBCClassMethodAccessFlag: uint16 { kAccMethodPublic = 0x0001, kAccMethodPrivate = 0x0002, kAccMethodProtected = 0x0004, @@ -74,4 +74,4 @@ enum JBCAccessFlag { }; } // namespace jbc } // namespace maple -#endif // HIR2MPL_INCLUDE_JBC_CLASS_ACCESS_H \ No newline at end of file +#endif // HIR2MPL_INCLUDE_JBC_CLASS_ACCESS_H diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_class_const.h b/src/hir2mpl/bytecode_input/class/include/jbc_class_const.h index e65d6af34dd530c0f78d7dffac85ec82046793b1..e15f6648e1ee93f0f5d8619f4b2d609a0e5e3a37 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_class_const.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_class_const.h @@ -105,7 +105,7 @@ class JBCConst { return PreProcessImpl(constPool); } - SimpleXMLElem *GenXMLElem(MapleAllocator &allocIn, uint32 id) { + SimpleXMLElem *GenXMLElem(MapleAllocator &allocIn, uint32 id) const { return GenXMLElemImpl(allocIn, id); } @@ -215,7 +215,7 @@ class JBCConstClass : public JBCConst { public: JBCConstClass(MapleAllocator &alloc, JBCConstTag t); JBCConstClass(MapleAllocator &alloc, JBCConstTag t, JBCConstPoolIdx argNameIdx); - ~JBCConstClass(); + ~JBCConstClass() override; GStrIdx GetClassNameIdxOrin() const { return strIdxOrin; @@ -289,7 +289,7 @@ class JBCConstNameAndType : public JBCConst { public: JBCConstNameAndType(MapleAllocator &alloc, JBCConstTag t); JBCConstNameAndType(MapleAllocator &alloc, JBCConstTag t, JBCConstPoolIdx argNameIdx, JBCConstPoolIdx argDescIdx); - ~JBCConstNameAndType(); + ~JBCConstNameAndType() override; const std::string GetName() const { CHECK_FATAL(constName != nullptr, "invalid const index"); @@ -320,7 +320,7 @@ class JBCConstRef : public JBCConst { JBCConstRef(MapleAllocator &alloc, JBCConstTag t); JBCConstRef(MapleAllocator &alloc, JBCConstTag t, JBCConstPoolIdx argClassIdx, JBCConstPoolIdx argClassNameAndTypeIdx); - ~JBCConstRef(); + ~JBCConstRef() override; bool PrepareFEStructElemInfo(); const std::string GetName() const; const std::string GetDesc() const; @@ -357,7 +357,7 @@ class JBCConstRef : public JBCConst { class JBCConstMethodHandleInfo : public JBCConst { public: JBCConstMethodHandleInfo(MapleAllocator &alloc, JBCConstTag t); - ~JBCConstMethodHandleInfo(); + ~JBCConstMethodHandleInfo() override; protected: bool ParseFileImpl(BasicIORead &io) override; @@ -375,7 +375,7 @@ class JBCConstMethodHandleInfo : public JBCConst { class JBCConstMethodType : public JBCConst { public: JBCConstMethodType(MapleAllocator &alloc, JBCConstTag t); - ~JBCConstMethodType(); + ~JBCConstMethodType() override; protected: bool ParseFileImpl(BasicIORead &io) override; @@ -392,7 +392,7 @@ class JBCConstMethodType : public JBCConst { class JBCConstInvokeDynamic : public JBCConst { public: JBCConstInvokeDynamic(MapleAllocator &alloc, JBCConstTag t); - ~JBCConstInvokeDynamic(); + ~JBCConstInvokeDynamic() override; bool PrepareFEStructElemInfo(const std::string &ownerClassName); JBCConstPoolIdx GetBSMAttrIdx() const { return rawData.bsmAttrIdx; diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_compiler_component.h b/src/hir2mpl/bytecode_input/class/include/jbc_compiler_component.h index b4ef3d71d0ea12281e1e39583813070382f1d71a..bf8ea0f203e48205b9374c1b913a9c5dac1801af 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_compiler_component.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_compiler_component.h @@ -23,7 +23,7 @@ namespace maple { class JBCCompilerComponent : public HIR2MPLCompilerComponent { public: JBCCompilerComponent(MIRModule &module); - ~JBCCompilerComponent(); + ~JBCCompilerComponent() override; protected: bool ParseInputImpl() override; @@ -41,4 +41,4 @@ class JBCCompilerComponent : public HIR2MPLCompilerComponent { jbc::JBCInput jbcInput; }; // class JBCCompilerComponent } // namespace maple -#endif // HIR2MPL_INCLUDE_JBC_COMPILER_COMPONENT_H \ No newline at end of file +#endif // HIR2MPL_INCLUDE_JBC_COMPILER_COMPONENT_H diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_function.h b/src/hir2mpl/bytecode_input/class/include/jbc_function.h index 7feb231ccb87819c727e18f443b2dc9d2f4df778..7f86e8c492c8efcc8ac25e79d62befe35b07f73c 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_function.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_function.h @@ -35,7 +35,7 @@ class JBCBBPesudoCatchPred : public FEIRBB { static const uint8 kBBKindPesudoCatchPred = FEIRBBKind::kBBKindExt + 1; JBCBBPesudoCatchPred() : FEIRBB(kBBKindPesudoCatchPred) {} - ~JBCBBPesudoCatchPred() = default; + ~JBCBBPesudoCatchPred() override = default; }; // class JBCBBPesudoCatchPred class JBCFunction : public FEFunction { diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_stmt.h b/src/hir2mpl/bytecode_input/class/include/jbc_stmt.h index 127a08b2037c66e64695ce9b677166d242e5254e..bf04c3a2b804545832a8983e32d011255dfbebd6 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_stmt.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_stmt.h @@ -292,7 +292,8 @@ class JBCStmtPesudoTry : public JBCStmt { class JBCStmtPesudoEndTry : public JBCStmt { public: - JBCStmtPesudoEndTry() : JBCStmt(kJBCStmtPesudoEndTry) { + JBCStmtPesudoEndTry() + : JBCStmt(kJBCStmtPesudoEndTry) { isAuxPost = true; } diff --git a/src/hir2mpl/bytecode_input/class/include/jbc_util.h b/src/hir2mpl/bytecode_input/class/include/jbc_util.h index 3626e891300248c201a001f97dff9d087325e91f..a6e1eff00b80e06d0bc4071c85252af91601b487 100644 --- a/src/hir2mpl/bytecode_input/class/include/jbc_util.h +++ b/src/hir2mpl/bytecode_input/class/include/jbc_util.h @@ -23,8 +23,6 @@ namespace jbc { class JBCUtil { public: static std::string ClassInternalNameToFullName(const std::string &name); - static std::vector SolveMethodSignature(const std::string &signature); - static std::string SolveParamName(const std::string &signature); static JBCPrimType GetPrimTypeForName(const std::string &name); private: diff --git a/src/hir2mpl/bytecode_input/class/src/jbc_class2fe_helper.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_class2fe_helper.cpp index 9d4e09cf5b65e8efaeff801864291a80fbdc752e..2f1e3ca1571026ca1b144ff0e9b424f2faf04b44 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_class2fe_helper.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_class2fe_helper.cpp @@ -237,7 +237,7 @@ bool JBCClassMethod2FEHelper::ProcessDeclImpl(MapleAllocator &allocator) { StructElemNameIdx *structElemNameIdx = allocator.GetMemPool()->New( method.GetClassName(), method.GetName(), method.GetDescription()); FEStructElemInfo *elemInfo = FEManager::GetTypeManager().RegisterStructMethodInfo( - *structElemNameIdx, kSrcLangJava, IsStatic()); + *structElemNameIdx, kSrcLangJava, IsStatic()); elemInfo->SetDefined(); elemInfo->SetFromDex(); return FEInputMethodHelper::ProcessDeclImpl(allocator); diff --git a/src/hir2mpl/bytecode_input/class/src/jbc_function.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_function.cpp index 63a92f0870acfb9196587a7c00f20b0fa4e8c63b..806b6a8654280671122aabf054e1a8d802cbc5de 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 @@ -297,7 +297,7 @@ bool JBCFunction::PreBuildJsrInfo(const jbc::JBCAttrCode &code) { jbc::JBCOpcode opcode = op->GetOpcode(); jbc::JBCOpcodeKind kind = op->GetOpcodeKind(); if (kind != jbc::kOpKindJsr) { - continue;; + continue; } uint32 width = (opcode == jbc::kOpJsr ? 3 : 5); // instruction width for jsr is 3, and for jsr_w is 5 uint32 nextPC = pc + width; @@ -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_opcode.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_opcode.cpp index b75ee723df39e7d82a91730698b8438e03011879..2a04f49c15e04b77182a112a42f732dafd516277 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_opcode.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_opcode.cpp @@ -16,6 +16,7 @@ #include "jbc_class_const.h" #include "jbc_class_const_pool.h" #include "jbc_util.h" +#include "fe_utils_java.h" #include "fe_type_manager.h" namespace maple { @@ -1152,7 +1153,7 @@ const std::vector &JBCOpInvoke::GetInputTypesFromStackImpl() const std::vector JBCOpInvoke::GetInputTypesFromStackImpl(const JBCConstPool &constPool) const { std::vector ans; std::string desc = GetMethodDescription(constPool); - std::vector typeNames = JBCUtil::SolveMethodSignature(desc); + std::vector typeNames = FEUtilJava::SolveMethodSignature(desc); CHECK_FATAL(typeNames.size() > 0, "Invalid method description: %s", desc.c_str()); if (op != kOpInvokeStatic && op != kOpInvokeDynamic) { ans.push_back(kTypeRef); @@ -1170,7 +1171,7 @@ JBCPrimType JBCOpInvoke::GetOutputTypesToStackImpl() const { JBCPrimType JBCOpInvoke::GetOutputTypesToStackImpl(const JBCConstPool &constPool) const { std::string desc = GetMethodDescription(constPool); - std::vector typeNames = JBCUtil::SolveMethodSignature(desc); + std::vector typeNames = FEUtilJava::SolveMethodSignature(desc); CHECK_FATAL(typeNames.size() > 0, "Invalid method description: %s", desc.c_str()); return JBCUtil::GetPrimTypeForName(typeNames[0]); } diff --git a/src/hir2mpl/bytecode_input/class/src/jbc_opcode_helper.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_opcode_helper.cpp index 2a5fec151b45671a3911120112142746b8d55e82..736ba958ef132e9887decdb6dee6a96c47915e8b 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_opcode_helper.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_opcode_helper.cpp @@ -14,7 +14,7 @@ */ #include "jbc_opcode_helper.h" #include "jbc_class_const.h" -#include "jbc_util.h" +#include "fe_utils_java.h" #include "fe_type_manager.h" namespace maple { @@ -104,7 +104,7 @@ std::vector JBCOpcodeHelper::GetBaseTypeNamesForOPInvoke(const jbc: } const jbc::JBCConstRef *constRef = static_cast(constItem); const std::string desc = constRef->GetDesc(); - std::vector typeNames = jbc::JBCUtil::SolveMethodSignature(desc); + std::vector typeNames = FEUtilJava::SolveMethodSignature(desc); for (const std::string &typeName : typeNames) { ans.push_back(FETypeManager::GetBaseTypeName(typeName, false)); } diff --git a/src/hir2mpl/bytecode_input/class/src/jbc_stack2fe_helper.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_stack2fe_helper.cpp index be0dc49fd9c00dddaa0873a900bf94816bf3f1b4..916d2cbe0bfccd369c115ef4397fa2fc351e3afb 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_stack2fe_helper.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_stack2fe_helper.cpp @@ -29,7 +29,7 @@ JBCStack2FEHelper::JBCStack2FEHelper(bool argUseNestExpr) // (mapping to slotNum: nArgs ~ allLocals - 1) // baseLocal + nLocals ~ baseLocal + allLocals - 1: args var // (mapping to slotNum: 0 ~ nArgs - 1) -// + uint32 JBCStack2FEHelper::GetRegNumForSlot(uint32 slotNum) const { uint32 baseLocal = nStacks + nSwaps; uint32 allLocals = nLocals + nArgs; 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/class/src/jbc_util.cpp b/src/hir2mpl/bytecode_input/class/src/jbc_util.cpp index fff2612fecea2fc3f2fd38e5d5b2ed29421cd3cf..951a5eb75e6c25d9b6d23e1d7b3b8351d41fc860 100644 --- a/src/hir2mpl/bytecode_input/class/src/jbc_util.cpp +++ b/src/hir2mpl/bytecode_input/class/src/jbc_util.cpp @@ -25,45 +25,6 @@ std::string JBCUtil::ClassInternalNameToFullName(const std::string &name) { } } -std::vector JBCUtil::SolveMethodSignature(const std::string &signature) { - std::vector ans; - size_t pos1 = signature.find('('); - size_t pos2 = signature.find(')'); - if (pos1 == std::string::npos || pos2 == std::string::npos || pos1 > pos2) { - CHECK_FATAL(false, "invalid method signature %s", signature.c_str()); - } - std::string paramTypeNames = signature.substr(pos1 + 1, pos2 - pos1 - 1); - std::string retTypeName = signature.substr(pos2 + 1); - ans.push_back(retTypeName); - while (paramTypeNames.length() > 0) { - std::string typeName = SolveParamName(paramTypeNames); - ans.push_back(typeName); - paramTypeNames = paramTypeNames.substr(typeName.length()); - } - return ans; -} - -std::string JBCUtil::SolveParamName(const std::string &signature) { - if (signature.empty()) { - return ""; - } - char c = signature[0]; - switch (c) { - case '[': - return "[" + SolveParamName(signature.substr(1)); - case 'L': { - size_t pos = signature.find(';'); - CHECK_FATAL(pos != std::string::npos, "invalid type %s", signature.c_str()); - return signature.substr(0, pos + 1); - } - default: { - std::string ans = ""; - ans.push_back(c); - return ans; - } - } -} - JBCPrimType JBCUtil::GetPrimTypeForName(const std::string &name) { switch (name[0]) { case '[': 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_class.h b/src/hir2mpl/bytecode_input/common/include/bc_class.h index 41ad79f432ac96feb088a19b542fa210ed807255..c7d2422f054c0e1325906306dd3a0e6962cb36a7 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_class.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_class.h @@ -214,7 +214,7 @@ class BCClassMethod : public BCClassElem { return methodMp; } - void ReleaseMempool() { + void ReleaseMempool() const { FEUtils::DeleteMempoolPtr(methodMp); } @@ -366,4 +366,4 @@ class BCClass { }; } } -#endif // HIR2MPL_BC_INPUT_INCLUDE_BC_CLASS_H \ No newline at end of file +#endif // HIR2MPL_BC_INPUT_INCLUDE_BC_CLASS_H diff --git a/src/hir2mpl/bytecode_input/common/include/bc_compiler_component-inl.h b/src/hir2mpl/bytecode_input/common/include/bc_compiler_component-inl.h index 432f850c012cd06f94e84d0f72813643dc10dd5a..4cc8a3fa7c6cd26bd7bd96bede8cc21af1549d75 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_compiler_component-inl.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_compiler_component-inl.h @@ -140,11 +140,11 @@ bool BCCompilerComponent::LoadOnDemandBCClass2FEClass( structHelper->SetIsOnDemandLoad(true); structHelpers.push_back(std::move(structHelper)); } - for (const std::unique_ptr &helper : structHelpers) { + for (std::unique_ptr const &helper : structHelpers) { ASSERT_NOT_NULL(helper); (void)helper->PreProcessDecl(); } - for (const std::unique_ptr &helper : structHelpers) { + for (std::unique_ptr const &helper : structHelpers) { ASSERT_NOT_NULL(helper); (void)helper->ProcessDecl(); helper->ProcessPragma(); diff --git a/src/hir2mpl/bytecode_input/common/include/bc_compiler_component.h b/src/hir2mpl/bytecode_input/common/include/bc_compiler_component.h index fc5fccf2c0d5be13cae642cc10e8179edbb652b4..b243f570e03f64974d57be3663b74416d8b9bfec 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_compiler_component.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_compiler_component.h @@ -24,7 +24,7 @@ template class BCCompilerComponent : public HIR2MPLCompilerComponent { public: explicit BCCompilerComponent(MIRModule &module); - ~BCCompilerComponent(); + ~BCCompilerComponent() override; protected: bool ParseInputImpl() override; @@ -51,4 +51,4 @@ class BCCompilerComponent : public HIR2MPLCompilerComponent { } // namespace bc } // namespace maple #include "bc_compiler_component-inl.h" -#endif // HIR2MPL_BC_INPUT_INCLUDE_BC_COMPILER_COMPONENT_H \ No newline at end of file +#endif // HIR2MPL_BC_INPUT_INCLUDE_BC_COMPILER_COMPONENT_H diff --git a/src/hir2mpl/bytecode_input/common/include/bc_input-inl.h b/src/hir2mpl/bytecode_input/common/include/bc_input-inl.h index 66b37d80476bf8ecc46b4f15ccffff5d4a273d58..8a211e390462fc8ecb5d6ecdb0d55f713e693eb2 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_input-inl.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_input-inl.h @@ -29,14 +29,14 @@ bool BCInput::ReadBCFile(uint32 index, const std::string &fileName, const std } else { CHECK_FATAL(false, "Unsupported BC reader: %s in BCInput", typeid(T).name()); } - if (bcParser->OpenFile() == false) { + if (!bcParser->OpenFile()) { return false; } - if (bcParser->ParseHeader() == false) { + if (!bcParser->ParseHeader()) { ERR(kLncErr, "Parse Header failed in : %s.", fileName.c_str()); return false; } - if (bcParser->Verify() == false) { + if (!bcParser->Verify()) { ERR(kLncErr, "Verify file failed in : %s.", fileName.c_str()); return false; } @@ -111,7 +111,7 @@ bool BCInput::CollectAllDepTypeNamesOnAllBCFiles(std::unordered_set classSet; @@ -130,9 +130,9 @@ bool BCInput::CollectMethodDepTypeNamesOnAllBCFiles(std::unordered_set superClassNames = klass->GetSuperClassNames(); - depSet.insert(superClassNames.begin(), superClassNames.end()); + depSet.insert(superClassNames.cbegin(), superClassNames.cend()); std::vector superInterfaceNames = klass->GetSuperInterfaceNames(); - depSet.insert(superInterfaceNames.begin(), superInterfaceNames.end()); + depSet.insert(superInterfaceNames.cbegin(), superInterfaceNames.cend()); for (const std::unique_ptr &method : klass->GetMethods()) { if (method == nullptr) { continue; @@ -157,7 +157,7 @@ bool BCInput::CollectClassNamesOnAllBCFiles(std::unordered_set & ERR(kLncErr, "Collect all class names failed in : %s.", item.first.c_str()); return false; } - allClassSet.insert(classSet.begin(), classSet.end()); + allClassSet.insert(classSet.cbegin(), classSet.cend()); } return true; } diff --git a/src/hir2mpl/bytecode_input/common/include/bc_instruction.h b/src/hir2mpl/bytecode_input/common/include/bc_instruction.h index 0181dbd1d299454365d90fffa06e73ccf051b2c1..3673af772a73cad84d8084a2cf8de16bf4896d97 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_instruction.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_instruction.h @@ -121,9 +121,12 @@ struct TypeInferItem; struct BCRegTypeItem { BCRegTypeItem(const GStrIdx &idx, bool isIndeterminateIn = false, bool isFromDefIn = false) - : typeNameIdx(idx), isIndeterminate(isIndeterminateIn), isFromDef(isFromDefIn) {} + : typeNameIdx(idx), + isIndeterminate(isIndeterminateIn), + isFromDef(isFromDefIn) {} BCRegTypeItem(const BCRegTypeItem &item) - : typeNameIdx(item.typeNameIdx), isIndeterminate(item.isIndeterminate) {} + : typeNameIdx(item.typeNameIdx), + isIndeterminate(item.isIndeterminate) {} ~BCRegTypeItem() = default; PrimType GetPrimType() const; @@ -181,7 +184,7 @@ class BCRegType { return allocator; } - void SetTypeNameIdx(const GStrIdx &idx) { + void SetTypeNameIdx(const GStrIdx &idx) const { regTypeItem->typeNameIdx = idx; } @@ -189,12 +192,12 @@ class BCRegType { return regTypeItem->isIndeterminate; } - void SetIsIndeterminate(bool flag) { + void SetIsIndeterminate(bool flag) const { regTypeItem->isIndeterminate = flag; } static void InsertUniqueTypeItem(MapleList &itemSet, BCRegTypeItem *item) { - for (auto &elem : itemSet) { + for (auto const &elem : itemSet) { if ((!elem->isIndeterminate && !item->isIndeterminate && (*elem) == (*item)) || elem == item) { return; } @@ -343,7 +346,7 @@ struct TypeInferItem { } bool RegisterInPrevs(TypeInferItem *prev) { - for (auto e : prevs) { + for (auto const e : prevs) { if (e == prev) { return false; } @@ -364,7 +367,7 @@ struct TypeInferItem { currItem->isAlive = true; for (auto type : *types) { bool duplicate = false; - for (auto ty : *(currItem->aliveUsedTypes)) { + for (auto const ty : *(currItem->aliveUsedTypes)) { if (ty == type) { duplicate = true; break; @@ -376,7 +379,7 @@ struct TypeInferItem { } } // insert into its prevs cyclely - for (auto prev : currItem->prevs) { + for (auto const prev : currItem->prevs) { if (end != nullptr && end->reg == prev->reg && end->reg->regType->IsBefore(prev->beginPos, end->beginPos)) { continue; } @@ -405,7 +408,7 @@ struct TypeInferItem { auto currItem = workList[index++]; currItem->isAlive = true; bool duplicate = false; - for (auto ty : *(currItem->aliveUsedTypes)) { + for (auto const ty : *(currItem->aliveUsedTypes)) { if (ty == type) { duplicate = true; break; @@ -416,7 +419,7 @@ struct TypeInferItem { currItem->reg->regType->UpdateFuzzyUsedSet(type); } // insert into its prevs cyclely - for (auto prev : currItem->prevs) { + for (auto prev : std::as_const(currItem->prevs)) { if (end != nullptr && end->reg == prev->reg && end->reg->regType->IsBefore(prev->beginPos, end->beginPos)) { continue; } diff --git a/src/hir2mpl/bytecode_input/common/include/bc_io.h b/src/hir2mpl/bytecode_input/common/include/bc_io.h index 84578e4ab3ff05541ba56a741ed9ee407bf2ea04..e47cc2575371f4306a97e616350b13b9b9e3e5d9 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_io.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_io.h @@ -45,7 +45,7 @@ struct RawData { class BCReader : public BCIO, public BasicIORead { public: explicit BCReader(const std::string &fileName); - virtual ~BCReader(); + ~BCReader() override; bool RetrieveHeader(RawData &data); void SetEndianTag(bool isBigEndian); template diff --git a/src/hir2mpl/bytecode_input/common/include/bc_parser-inl.h b/src/hir2mpl/bytecode_input/common/include/bc_parser-inl.h index f6ecf59e7c51cebdb980489c6bab0119c0a2b386..48938f822d346e8a92dcee22d0996c5cf2ff8a0a 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_parser-inl.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_parser-inl.h @@ -53,7 +53,7 @@ template void MethodProcessSchedular::CallbackThreadMainStart() { std::thread::id tid = std::this_thread::get_id(); if (FEOptions::GetInstance().GetDumpLevel() >= FEOptions::kDumpLevelInfoDebug) { - INFO(kLncInfo, "Start Run Thread (tid=%lx)", tid); + INFO(kLncInfo, "Start Run Thread (tid=%lx)", std::hash{}(tid)); } FEConfigParallel::GetInstance().RegisterRunThreadID(tid); } diff --git a/src/hir2mpl/bytecode_input/common/include/bc_parser.h b/src/hir2mpl/bytecode_input/common/include/bc_parser.h index 92189e8e6803d03cfee5976459bbd916d019724f..25a5eb000594f13583850f8a34797020d3438270 100644 --- a/src/hir2mpl/bytecode_input/common/include/bc_parser.h +++ b/src/hir2mpl/bytecode_input/common/include/bc_parser.h @@ -75,7 +75,7 @@ class MethodProcessSchedular : public MplScheduler { public: MethodProcessSchedular(const std::string &name) : MplScheduler(name) {} - ~MethodProcessSchedular() { + ~MethodProcessSchedular() override { FEConfigParallel::GetInstance().RunThreadIDCleanUp(); } @@ -94,4 +94,4 @@ class MethodProcessSchedular : public MplScheduler { } // namespace bc } // namespace maple #include "bc_parser-inl.h" -#endif // MPL_FE_BC_INPUT_BC_PARSER_H \ No newline at end of file +#endif // MPL_FE_BC_INPUT_BC_PARSER_H diff --git a/src/hir2mpl/bytecode_input/common/include/bc_pragma.h b/src/hir2mpl/bytecode_input/common/include/bc_pragma.h index 28258bd93c246f40d46ae2a3ff611d5252e19004..cb33222911e76a5e5cf1cde05ddf86bda2f0a07e 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,33 @@ * 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 -#endif // HIR2MPL_BC_INPUT_INCLUDE_BC_PRAGMA_H \ No newline at end of file +#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 diff --git a/src/hir2mpl/bytecode_input/common/include/rc_setter.h b/src/hir2mpl/bytecode_input/common/include/rc_setter.h index 9bdaf2a0622eea1d8651fdc1ede6de52f224a05a..85116a18f052fc87a47472c0d1bab45b530f190e 100644 --- a/src/hir2mpl/bytecode_input/common/include/rc_setter.h +++ b/src/hir2mpl/bytecode_input/common/include/rc_setter.h @@ -56,7 +56,8 @@ class RCSetter { void MarkRCAttributes() const; private: - explicit RCSetter(const std::string &whiteListName) : rcFieldAttrWhiteListName(whiteListName) { + explicit RCSetter(const std::string &whiteListName) + : rcFieldAttrWhiteListName(whiteListName) { if (!rcFieldAttrWhiteListName.empty()) { LoadRCFieldAttrWhiteList(rcFieldAttrWhiteListName); } @@ -81,4 +82,4 @@ class RCSetter { }; } // namespace bc } // namespace maple -#endif // BC_INPUT_INCLUDE_RC_SETTER_H \ No newline at end of file +#endif // BC_INPUT_INCLUDE_RC_SETTER_H 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..9c5633b0992ab125b8f2309312418ac7a24c19bd 100644 --- a/src/hir2mpl/bytecode_input/common/src/bc_function.cpp +++ b/src/hir2mpl/bytecode_input/common/src/bc_function.cpp @@ -85,8 +85,10 @@ 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.tyIdx = mirType->GetTypeIndex(); + aliasVar.mplStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(localVar->GetName(*mirType)); + aliasVar.atk = kATKType; + aliasVar.index = mirType->GetTypeIndex().GetIdx(); + aliasVar.isLocal = !localVar->IsGlobal(); if (!std::get<2>(item).empty()) { aliasVar.sigStrIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(std::get<2>(item)); } @@ -147,4 +149,4 @@ bool BCFunction::EmitToMIR(const std::string &phaseName) { return phaseResult.Finish(); } } // namespace bc -} // namespace maple \ No newline at end of file +} // namespace maple diff --git a/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp b/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp index c8ac5512389e0e1d30fb19b106f37a165e543279..3edcf1646e55ea8dced98ceac506c33f0f8d2487 100644 --- a/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp +++ b/src/hir2mpl/bytecode_input/common/src/bc_instruction.cpp @@ -71,7 +71,7 @@ std::list BCInstruction::EmitToFEIRStmts() { if ((instKind & kTarget) || (instKind & kCatch)) { if (instKind & kCatch) { UniqueFEIRStmt stmt = GenCatchStmt(); - stmts.emplace_back(std::move(stmt));; + stmts.emplace_back(std::move(stmt)); } else { UniqueFEIRStmt stmt = GenLabelStmt(); stmts.emplace_back(std::move(stmt)); @@ -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/bytecode_input/dex/include/dex_class.h b/src/hir2mpl/bytecode_input/dex/include/dex_class.h index bf3edbc9ef7825f8f38f4a17487bea1bc4841b9d..98829312fa78fcc81e02109ee55c1ac1ffdc8736 100644 --- a/src/hir2mpl/bytecode_input/dex/include/dex_class.h +++ b/src/hir2mpl/bytecode_input/dex/include/dex_class.h @@ -27,7 +27,9 @@ class DexClassField : public BCClassField { public: DexClassField(const BCClass &klassIn, uint32 itemIdxIn, uint32 idxIn, uint32 acc, const std::string &nameIn, const std::string &descIn) - : BCClassField(klassIn, acc, nameIn, descIn), itemIdx(itemIdxIn), idx(idxIn) {} + : BCClassField(klassIn, acc, nameIn, descIn), + itemIdx(itemIdxIn), + idx(idxIn) {} ~DexClassField() = default; protected: @@ -56,7 +58,9 @@ class DexClassMethod : public BCClassMethod { public: DexClassMethod(const BCClass &klassIn, uint32 itemIdxIn, uint32 idxIn, bool isVirtualIn, uint32 acc, const std::string &nameIn, const std::string &descIn) - : BCClassMethod(klassIn, acc, isVirtualIn, nameIn, descIn), itemIdx(itemIdxIn), idx(idxIn) {} + : BCClassMethod(klassIn, acc, isVirtualIn, nameIn, descIn), + itemIdx(itemIdxIn), + idx(idxIn) {} ~DexClassMethod() = default; protected: diff --git a/src/hir2mpl/bytecode_input/dex/src/dex_class2fe_helper.cpp b/src/hir2mpl/bytecode_input/dex/src/dex_class2fe_helper.cpp index 88e36800463511e016894d434a064095b7f8b914..4e0d39b7b75ed1323aeda397023a530ef3ee196b 100644 --- a/src/hir2mpl/bytecode_input/dex/src/dex_class2fe_helper.cpp +++ b/src/hir2mpl/bytecode_input/dex/src/dex_class2fe_helper.cpp @@ -71,7 +71,7 @@ void DexClass2FEHelper::InitMethodHelpersImpl() { FieldAttrs DexClassField2FEHelper::AccessFlag2AttributeImpl(uint32 accessFlag) const { FieldAttrs attrs; if (accessFlag & DexFileUtil::kDexAccPublic) { - attrs.SetAttr(FLDATTR_public);; + attrs.SetAttr(FLDATTR_public); } if (accessFlag & DexFileUtil::kDexAccPrivate) { attrs.SetAttr(FLDATTR_private); @@ -171,4 +171,4 @@ bool DexClassMethod2FEHelper::IsInit() const { return method->IsInit(); } } // namespace bc -} // namespace maple \ No newline at end of file +} // namespace maple diff --git a/src/hir2mpl/bytecode_input/dex/src/dex_reader.cpp b/src/hir2mpl/bytecode_input/dex/src/dex_reader.cpp index d2d075b6f384997e35d3b71f74825a46caa37192..88d62d251fc24cd62f2c2311eadd01bfdf8909b3 100644 --- a/src/hir2mpl/bytecode_input/dex/src/dex_reader.cpp +++ b/src/hir2mpl/bytecode_input/dex/src/dex_reader.cpp @@ -291,9 +291,9 @@ std::unique_ptr>> DexReader::ConstructBCTry } std::unique_ptr>> DexReader::ConstructBCCatchList( - std::vector &catchHandlerItems) const { + std::vector &catchHandlerItems) const { std::unique_ptr>> catches = - std::make_unique>>(); + std::make_unique>>(); for (const auto catchHandlerItem : catchHandlerItems) { // Use V (void) catch exceptions GStrIdx exceptionNameIdx = catchHandlerItem.IsCatchAllHandlerType() ? BCUtil::GetVoidIdx() : diff --git a/src/hir2mpl/bytecode_input/dex/src/dexfile_libdexfile.cpp b/src/hir2mpl/bytecode_input/dex/src/dexfile_libdexfile.cpp index 0624909889f664fee8f4a5bb06f731c4c8561ff7..4f5d067a1092577503c3f69fe54b814f81f0173e 100644 --- a/src/hir2mpl/bytecode_input/dex/src/dexfile_libdexfile.cpp +++ b/src/hir2mpl/bytecode_input/dex/src/dexfile_libdexfile.cpp @@ -1674,7 +1674,7 @@ const ResolvedCallSiteIdItem *LibDexFile::GetCallSiteIdItem(uint32_t idx) const } const ResolvedMethodHandleItem *LibDexFile::GetMethodHandleItem(uint32_t idx) const { - return ResolvedMethodHandleItem::GetInstance(*this, idx);; + return ResolvedMethodHandleItem::GetInstance(*this, idx); } void LibDexFile::DebugNewLocalCb(void *context, const art::DexFile::LocalInfo &entry) const { 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..a47d1f144c73b1212ec3df888f9f6a0b8cf00c9b 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. @@ -21,7 +21,6 @@ namespace maple { constexpr int64 kUndefValue = 0xdeadbeef; -static const char *kBoundsBuiltFunc = "__builtin_dynamic_bounds_cast"; class ENCChecker { public: ENCChecker() = default; @@ -29,19 +28,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); @@ -52,6 +50,7 @@ class ENCChecker { static std::string GetBoundaryName(const UniqueFEIRExpr &expr); static bool IsGlobalVarInExpr(const UniqueFEIRExpr &expr); static std::pair InsertBoundaryVar(MIRBuilder &mirBuilder, const UniqueFEIRExpr &expr); + static void InsertBoundaryVar(const ASTDecl &ptrDecl, std::list &stmts); static bool IsConstantIndex(const UniqueFEIRExpr &expr); static void PeelNestedBoundaryChecking(std::list &stmts, const UniqueFEIRExpr &baseExpr); static void ReduceBoundaryChecking(std::list &stmts, 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,16 +70,16 @@ 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 void ReplaceBoundaryErr(const MIRBuilder &mirBuilder, const FEIRStmtNary *stmt); static UniqueFEIRExpr GetBoundaryLenExprCache(uint32 hash); static UniqueFEIRExpr GetBoundaryLenExprCache(const TypeAttrs &attr); static UniqueFEIRExpr GetBoundaryLenExprCache(const FieldAttrs &attr); @@ -90,6 +89,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..f7ce0726405cbef407b21347befef998de75395b 100644 --- a/src/hir2mpl/common/include/fe_file_type.h +++ b/src/hir2mpl/common/include/fe_file_type.h @@ -42,8 +42,8 @@ class FEFileType { FileType GetFileTypeByMagicNumber(uint32 magic) const; void Reset(); void LoadDefault(); - void RegisterExtName(FileType fileType, const std::string &extName); - void RegisterMagicNumber(FileType fileType, uint32 magicNumber); + void RegisterExtName(FileType argFileType, const std::string &extName); + void RegisterMagicNumber(FileType argFileType, uint32 magicNumber); static std::string GetPath(const std::string &pathName); static std::string GetName(const std::string &pathName, bool withExt = true); static std::string GetExtName(const std::string &pathName); @@ -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..d7c2d2c29edc38379f280802d7d66530f1b5333b 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,22 +25,23 @@ #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) \ - A.PushbackMIRInfo(MIRInfoPair(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(B), C)); \ - A.PushbackIsString(D) +#define SET_FUNC_INFO_PAIR(A, B, C, D) \ + do { \ + (A).PushbackMIRInfo(MIRInfoPair(GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(B), C)); \ + (A).PushbackIsString(D); \ + } while (0) \ 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 +51,28 @@ 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, bool isControllScope = false); + void PushStmtScope(bool isControllScope); + UniqueFEIRScope PopTopScope(); + FEIRScope *GetTopFEIRScopePtr() const; + MIRScope *GetTopMIRScope() const; + virtual void AddVLACleanupStmts(std::list &stmts); 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(); } @@ -98,6 +116,18 @@ class FEFunction { return safeRegionFlag; } + const std::deque &GetScopeStack() const { + return scopeStack; + } + + void SetLabelWithScopes(std::string labelName, std::map scopes) { + labelWithScopes.insert(std::make_pair(labelName, std::move(scopes))); + } + + const std::unordered_map> &GetLabelWithScopes() const { + return labelWithScopes; + } + LLT_PROTECTED: // run phase routines virtual bool GenerateGeneralStmt(const std::string &phaseName) = 0; @@ -112,6 +142,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 +168,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); + void PhaseTimerStart(FETimerNS &timer) const; + void PhaseTimerStopAndDump(FETimerNS &timer, const std::string &label) const; virtual void DumpFEIRCFGGraphForDFGEdge(std::ofstream &file); virtual bool HasThis() = 0; virtual bool IsNative() = 0; @@ -155,11 +184,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; @@ -172,11 +201,11 @@ class FEFunction { MIRFunction &mirFunction; LLT_PRIVATE: - void OutputStmts(); + void OutputStmts() const; bool SetupFEIRStmtGoto(FEIRStmtGoto &stmt); bool SetupFEIRStmtSwitch(FEIRStmtSwitch &stmt); - const FEIRStmtPesudoLOC *GetLOCForStmt(const FEIRStmt &feStmt) const; - void AddLocForStmt(const FEIRStmt &feIRStmt, std::list &mirStmts) const; + const FEIRStmtPesudoLOC *GetLOCForStmt(const FEIRStmt &feIRStmt) const; + void AddLocForStmt(const FEIRStmt &stmt, std::list &mirStmts) const; void LabelFEIRStmts(); // label fe ir stmts FEIRBB *NewFEIRBB(uint32 &id); bool IsBBEnd(const FEIRStmt &stmt) const; @@ -188,7 +217,7 @@ class FEFunction { void LinkSwitchBBAndItsTargets(FEIRBB &bb, const FEIRStmt &stmtTail); void LinkBB(FEIRBB &predBB, FEIRBB &succBB); FEIRBB &GetFEIRBBByStmt(const FEIRStmt &stmt); - bool CheckBBsStmtNoAuxTail(const FEIRBB &bb); + bool CheckBBsStmtNoAuxTail(const FEIRBB &bb) const; void ProcessCheckPoints(); void InsertCheckPointForBBs(); void InsertCheckPointForTrys(); @@ -213,6 +242,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 +254,9 @@ class FEFunction { std::map defVarTypeScatterStmtMap; std::unordered_map> boundaryMap; // EnhanceC boundary var std::stack safeRegionFlag; // EnhanceC saferegion(true: safe, false: unsafe) + std::deque scopeStack; // an element of the stack represents the scope + uint32 scopeID = 0; + std::unordered_map> labelWithScopes; }; } // 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..edb5a9bb71e1eecc22ef583156a2f96dfa0e20b1 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() { @@ -91,9 +91,27 @@ class FEInputFileScopeAsmHelper { virtual bool ProcessDeclImpl(MapleAllocator &allocator) = 0; }; +class FEInputEnumHelper { + public: + explicit FEInputEnumHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn) {} + virtual ~FEInputEnumHelper() = default; + + bool ProcessDecl() { + return ProcessDecl(allocator); + } + + bool ProcessDecl(MapleAllocator &allocatorIn) { + return ProcessDeclImpl(allocatorIn); + } + + protected: + MapleAllocator &allocator; + virtual bool ProcessDeclImpl(MapleAllocator &allocator) = 0; +}; + class FEInputFieldHelper { public: - FEInputFieldHelper(MapleAllocator &allocator) {} + explicit FEInputFieldHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn) {} virtual ~FEInputFieldHelper() = default; const FieldPair &GetMIRFieldPair() const { return mirFieldPair; @@ -103,12 +121,16 @@ class FEInputFieldHelper { return mirFieldPair.second.second.GetAttr(FLDATTR_static); } - bool ProcessDecl(MapleAllocator &allocator) { - return ProcessDeclImpl(allocator); + bool ProcessDecl() { + return ProcessDecl(allocator); + } + + bool ProcessDecl(MapleAllocator &alloc) { + return ProcessDeclImpl(alloc); } - bool ProcessDeclWithContainer(MapleAllocator &allocator) { - return ProcessDeclWithContainerImpl(allocator); + bool ProcessDeclWithContainer(MapleAllocator &alloc) { + return ProcessDeclWithContainerImpl(alloc); } static void SetFieldAttribute(const std::string &name, FieldAttrs &attr) { @@ -126,12 +148,14 @@ class FEInputFieldHelper { protected: virtual bool ProcessDeclImpl(MapleAllocator &allocator) = 0; virtual bool ProcessDeclWithContainerImpl(MapleAllocator &allocator) = 0; + + MapleAllocator &allocator; FieldPair mirFieldPair; }; class FEInputMethodHelper { public: - FEInputMethodHelper(MapleAllocator &allocatorIn) + explicit FEInputMethodHelper(MapleAllocator &allocatorIn) : allocator(allocatorIn), srcLang(kSrcLangUnknown), feFunc(nullptr), @@ -218,7 +242,7 @@ class FEInputMethodHelper { } protected: - virtual bool ProcessDeclImpl(MapleAllocator &allocator); + virtual bool ProcessDeclImpl(MapleAllocator &allocatorIn); virtual void SolveReturnAndArgTypesImpl(MapleAllocator &allocator) = 0; virtual std::string GetMethodNameImpl(bool inMpl, bool full) const = 0; virtual FuncAttrs GetAttrsImpl() const = 0; @@ -256,7 +280,7 @@ class FEInputStructHelper : public FEInputContainer { isSkipped(false), srcLang(kSrcLangJava) {} - virtual ~FEInputStructHelper() { + ~FEInputStructHelper() override { mirStructType = nullptr; mirSymbol = nullptr; pragmaHelper = nullptr; @@ -363,7 +387,7 @@ class FEInputStructHelper : public FEInputContainer { void ProcessPragma(); protected: - MIRStructType *GetContainerImpl(); + MIRStructType *GetContainerImpl() override; virtual bool PreProcessDeclImpl(); virtual bool ProcessDeclImpl(); virtual std::string GetStructNameOrinImpl() const = 0; diff --git a/src/hir2mpl/common/include/fe_java_string_manager.h b/src/hir2mpl/common/include/fe_java_string_manager.h index 9b372074bb8b5f07ce017f8de10222304dcc58e7..870c65bdb46baa7d94b4bc699647f211c1e04054 100644 --- a/src/hir2mpl/common/include/fe_java_string_manager.h +++ b/src/hir2mpl/common/include/fe_java_string_manager.h @@ -32,8 +32,8 @@ class FEJavaStringManager { MIRSymbol *GetLiteralPtrVar(const std::string &str) const; MIRSymbol *GetLiteralPtrVar(const std::u16string &strU16) const; // methods for string - MIRSymbol *CreateLiteralVar(MIRBuilder &mirBuilder, const std::string &str, bool isFieldValue); - MIRSymbol *CreateLiteralVar(MIRBuilder &mirBuilder, const std::u16string &strU16, bool isFieldValue); + MIRSymbol *CreateLiteralVar(MIRBuilder &mirBuilderIn, const std::string &str, bool isFieldValue); + MIRSymbol *CreateLiteralVar(MIRBuilder &mirBuilderIn, const std::u16string &strU16, bool isFieldValue); MIRSymbol *GetLiteralVar(const std::string &str) const; MIRSymbol *GetLiteralVar(const std::u16string &strU16) const; static std::string GetLiteralGlobalName(const std::u16string &strU16); @@ -47,7 +47,7 @@ class FEJavaStringManager { }; MIRArrayType *ConstructArrayType4Str(const std::u16string &strU16, bool compressible) const; - MIRAggConst *CreateByteArrayConst(const std::u16string &str, MIRArrayType &byteArrayType, bool compressible) const; + MIRAggConst *CreateByteArrayConst(const std::u16string &strU16, MIRArrayType &byteArrayType, bool compressible) const; static std::vector SwapBytes(const std::u16string &strU16); static uint16 ExchangeBytesPosition(uint16 input); template diff --git a/src/hir2mpl/common/include/fe_macros.h b/src/hir2mpl/common/include/fe_macros.h index 37b0f9cb265a1131e9573ee50e23642090a569ff..c607f79fd4ec0fabebcc2948845c4508ff833eec 100644 --- a/src/hir2mpl/common/include/fe_macros.h +++ b/src/hir2mpl/common/include/fe_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. @@ -15,11 +15,9 @@ #ifndef HIR2MPL_INCLUDE_FE_MACROS_H #define HIR2MPL_INCLUDE_FE_MACROS_H #include -#include -#include #include #include -#include +#include #include "fe_options.h" #include "mpl_logging.h" @@ -63,8 +61,22 @@ CHECK_FATAL(run, "%s", #run); \ } while (0) -#define FE_ERR(num, fmt, ...) do { \ - ERR(num, fmt, ##__VA_ARGS__); \ - FEManager::GetDiagManager().IncErrNum(); \ +// for user +#define FE_ERR(num, loc, fmt, ...) do { \ + if (PRINT_LEVEL_USER <= kLlErr) { \ + std::ostringstream ss; \ + ss << FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx) << ":" << loc.line << " error: " << fmt; \ + logInfo.InsertUserErrorMessage( \ + loc, logInfo.EmitLogToStringForUser(num, kLlErr, ss.str().c_str(), ##__VA_ARGS__)); \ + } \ +} while (0) + +#define FE_WARN(num, loc, fmt, ...) do { \ + if (PRINT_LEVEL_USER <= kLlWarn) { \ + std::ostringstream ss; \ + ss << FEManager::GetModule().GetFileNameFromFileNum(loc.fileIdx) << ":" << loc.line << " warning: " << fmt; \ + logInfo.InsertUserWarnMessage( \ + loc, logInfo.EmitLogToStringForUser(num, kLlWarn, ss.str().c_str(), ##__VA_ARGS__)); \ + } \ } while (0) #endif // ~HIR2MPL_INCLUDE_FE_MACROS_H \ No newline at end of file diff --git a/src/hir2mpl/common/include/fe_manager.h b/src/hir2mpl/common/include/fe_manager.h index ba96fb4755a00d2949f734d22da117524c1aecd7..3ca99cecc49af3490beade5533e018cf14cdc338 100644 --- a/src/hir2mpl/common/include/fe_manager.h +++ b/src/hir2mpl/common/include/fe_manager.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. @@ -19,7 +19,6 @@ #include "mir_builder.h" #include "fe_type_manager.h" #include "fe_java_string_manager.h" -#include "fe_diag_manager.h" #include "fe_function.h" namespace maple { @@ -40,11 +39,6 @@ class FEManager { return manager->javaStringManager; } - static FEDiagManager &GetDiagManager() { - ASSERT(manager != nullptr, "manager is not initialize"); - return manager->diagManager; - } - static MIRBuilder &GetMIRBuilder() { ASSERT(manager != nullptr, "manager is not initialize"); return manager->builder; @@ -113,7 +107,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 { @@ -140,7 +134,6 @@ class FEManager { static FEManager *manager; MIRModule &module; FETypeManager typeManager; - FEDiagManager diagManager; MIRBuilder builder; FEFunction *curFEFunction = nullptr; FEJavaStringManager javaStringManager; diff --git a/src/hir2mpl/common/include/fe_options.h b/src/hir2mpl/common/include/fe_options.h index e00a26ba3251d267a2fd4050fbaac58ed3ef39cc..d115838d32ead18bc749980137f21384201710eb 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; + void SetIsDumpFEIRBB(bool flag) { + isDumpBB = flag; } - bool IsDumpJBCBB() const { - return isDumpJBCBB; + bool IsDumpFEIRBB() const { + return isDumpBB; } - void SetIsDumpFEIRCFGGraph(bool flag) { - isDumpGenCFGGraph = flag; + void AddFuncNameForDumpCFGGraph(const std::string &funcName) { + funcNamesForDumpCFGGraph.insert(funcName); } - bool IsDumpFEIRCFGGraph() const { - return isDumpGenCFGGraph; - } - - 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) { @@ -440,6 +443,17 @@ class FEOptions { return isEnableSafeRegion; } + void SetDefaultSafe(bool flag) { + isDefaultSafe = flag; + } + + bool IsDefaultSafe() const { + if (IsEnableSafeRegion()) { + return isDefaultSafe; + } + return false; + } + void SetO2(bool flag) { isO2 = flag; } @@ -472,6 +486,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 +526,7 @@ class FEOptions { bool isDumpTime; bool isDumpComment = false; bool isDumpLOC = true; + bool isDbgFriendly = false; bool isDumpPhaseTime = false; bool isDumpPhaseTimeDetail = false; @@ -512,7 +535,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 +552,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; @@ -547,8 +569,10 @@ class FEOptions { bool isNpeCheckDynamic = false; bool isBoundaryCheckDynamic = false; bool isEnableSafeRegion = false; + bool isDefaultSafe = 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..98130125bf7be4f71acfb1b953f26f8b5c01a008 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); @@ -132,7 +134,7 @@ class FEStructFieldInfo : public FEStructElemInfo { public: FEStructFieldInfo(MapleAllocator &allocatorIn, const StructElemNameIdx &argStructElemNameIdx, MIRSrcLang argSrcLang, bool argIsStatic); - ~FEStructFieldInfo() { + ~FEStructFieldInfo() override { fieldType = nullptr; } GStrIdx GetFieldNameIdx() const { @@ -178,7 +180,7 @@ class FEStructMethodInfo : public FEStructElemInfo { public: FEStructMethodInfo(MapleAllocator &allocatorIn, const StructElemNameIdx &argStructElemNameIdx, MIRSrcLang argSrcLang, bool argIsStatic); - ~FEStructMethodInfo(); + ~FEStructMethodInfo() override; PUIdx GetPuIdx() const; bool IsConstructor() const { return isConstructor; 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_type_manager.h b/src/hir2mpl/common/include/fe_type_manager.h index d489ba0a9feeade19f0c4e10b8e13773b152f7dc..546e695b8baa3b460d8adec5d478fceefd5c785d 100644 --- a/src/hir2mpl/common/include/fe_type_manager.h +++ b/src/hir2mpl/common/include/fe_type_manager.h @@ -112,6 +112,14 @@ class FETypeManager { MIRStructType *GetOrCreateStructType(const std::string &name); MIRStructType *CreateStructType(const std::string &name); + MIRTypeByName *CreateTypeByNameType(const std::string &name); + MIRTypeByName *GetOrCreateTypeByNameType(const std::string &name); + MIRTypeByName *GetTypeByNameType(const std::string &name); + MIRTypeByName *GetTypeByNameType(const GStrIdx &nameIdx); + MIRTypeByName *CreateTypedef(const std::string &name, const MIRType &type); + MIREnum *CreateEnum(const std::string &name, PrimType primType); + MIREnum *GetOrCreateEnum(const std::string &name, PrimType primType = PTY_i32); + size_t GetEnumIdx(const std::string &name); MIRType *GetOrCreateComplexStructType(const MIRType &elemType); MIRStructType *GetOrCreateClassOrInterfaceType(const GStrIdx &nameIdx, bool isInterface, FETypeFlag typeFlag, bool &isCreate); @@ -259,6 +267,7 @@ class FETypeManager { void UpdateNameFuncMapFromTypeTable(); void UpdateDupTypes(const GStrIdx &nameIdx, bool isInterface, const std::unordered_map::iterator &importedTypeIt); + void ReleaseMIRFuncCodeMempool(std::unordered_map &map); // MCC function void InitFuncMCCGetOrInsertLiteral(); @@ -297,6 +306,10 @@ class FETypeManager { std::unordered_map nameMCCFuncMap; MIRFunction *funcMCCGetOrInsertLiteral; + // ---------- ast C ---------- + std::unordered_map nameTypeMap; + std::unordered_map enumNameMap; + // ---------- Enhance C ---------- std::unordered_map boundaryLenExprHashMap; std::unordered_set ownedNonnullFieldStructSet; diff --git a/src/hir2mpl/common/include/fe_utils.h b/src/hir2mpl/common/include/fe_utils.h index 92184fce85df2d9e457fc6b1668af32833ab43d4..ba3146e016961e80bf8299328067e5d1145bd790 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. @@ -23,8 +23,17 @@ #include "global_tables.h" #include "mempool.h" #include "mir_nodes.h" +#include "mir_scope.h" namespace maple { + +enum FEErrno : int { + kNoError = 0, + kCmdParseError = 1, + kNoValidInput = 2, + kFEError = 3, +}; + class FEUtils { public: FEUtils() = default; @@ -39,18 +48,25 @@ 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); - static MIRType *GetStructFieldType(const MIRStructType *type, FieldID feildID); + static MIRType *GetStructFieldType(const MIRStructType *type, FieldID fieldID); static const MIRFuncType *GetFuncPtrType(const MIRType &type); static MIRConst *CreateImplicitConst(MIRType *type); static PrimType GetVectorElementPrimType(PrimType vectorPrimType); static bool EndsWith(const std::string &value, const std::string &ending); static MIRConst *TraverseToMIRConst(MIRAggConst *aggConst, const MIRStructType &structType, FieldID &fieldID); + static Loc GetSrcLocationForMIRSymbol(const MIRSymbol &symbol); + static MIRAliasVars AddAlias(const GStrIdx &mplNameIdx, const MIRType *sourceType, const TypeAttrs &attrs, + bool isLocal = true); + static void AddAliasInMIRScope(MIRScope &scope, const std::string &srcVarName, const MIRSymbol &symbol, + const MIRType *sourceType); + static SrcPosition CvtLoc2SrcPosition(const Loc &loc); static const std::string kBoolean; static const std::string kByte; @@ -82,6 +98,8 @@ class FEUtils { static const std::string kMCCStaticFieldSetDouble; static const std::string kMCCStaticFieldSetObject; + static const std::string kCondGoToStmtLabelNamePrefix; + static inline MemPool *NewMempool(const std::string &name, bool isLocalPool) { return memPoolCtrler.NewMemPool(name, isLocalPool); } @@ -248,6 +266,8 @@ class FEUtils { return mccStaticFieldSetObjectIdx; } + static void InitPrimTypeFuncNameIdxMap(std::map &primTypeFuncNameIdxMap); + private: static bool LogicXOR(bool v1, bool v2) { return (v1 && !v2) || (!v1 && v2); @@ -262,6 +282,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; } @@ -337,14 +358,18 @@ class AstLoopUtil { } ~AstLoopUtil() = default; - void PushBreak(std::string labelPair); + void PushBreak(std::string label); std::string GetCurrentBreak(); void PopCurrentBreak(); bool IsBreakLabelsEmpty() const; + bool IsNestContinueLabelsEmpty() const; void PushContinue(std::string label); + void PushNestContinue(std::string label); std::string GetCurrentContinue(); + std::string GetNestContinue(); bool IsContinueLabelsEmpty() const; void PopCurrentContinue(); + void PopNestContinue(); bool IsCurrentBreakLabelUsed() { return breakLabels.top().second; @@ -354,10 +379,14 @@ class AstLoopUtil { return continueLabels.top().second; } + bool IsNestContinueLabelUsed() { + return nestContinueLabels.top().second; + } private: AstLoopUtil() = default; std::stack> breakLabels = std::stack>(); std::stack> continueLabels = std::stack>(); + std::stack> nestContinueLabels = std::stack>(); }; } // namespace maple #endif // HIR2MPL_INCLUDE_FE_UTILS_H 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..9a22390c4d43467bf2ec1ac6282d91261977203c 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_builder.h b/src/hir2mpl/common/include/feir_builder.h index bdf4f1b8b8fe854846bfef8993d203565c13b0a6..48feebcb33785fcc42110069458ae0c468e71649 100644 --- a/src/hir2mpl/common/include/feir_builder.h +++ b/src/hir2mpl/common/include/feir_builder.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. @@ -19,6 +19,7 @@ #include "mpl_logging.h" #include "feir_var.h" #include "feir_stmt.h" +#include "fe_function.h" namespace maple { class FEIRBuilder { @@ -117,7 +118,7 @@ class FEIRBuilder { static UniqueFEIRStmt CreateStmtJavaInstanceOf(UniqueFEIRVar dstVar, UniqueFEIRVar srcVar, UniqueFEIRType type); static UniqueFEIRStmt CreateStmtJavaInstanceOf(UniqueFEIRVar dstVar, UniqueFEIRVar srcVar, UniqueFEIRType type, uint32 argTypeID); - static UniqueFEIRStmt CreateStmtJavaFillArrayData(UniqueFEIRVar argVar, const int8 *arrayData, + static UniqueFEIRStmt CreateStmtJavaFillArrayData(UniqueFEIRVar srcVar, const int8 *arrayData, uint32 size, const std::string &arrayName); static std::list CreateStmtArrayStore(UniqueFEIRVar varElem, UniqueFEIRVar varArray, UniqueFEIRVar varIndex); @@ -142,6 +143,9 @@ class FEIRBuilder { static UniqueFEIRExpr ReadExprField(UniqueFEIRExpr expr, FieldID fieldID, UniqueFEIRType fieldType); static UniqueFEIRStmt AssginStmtField(const UniqueFEIRExpr &addrExpr, UniqueFEIRExpr srcExpr, FieldID fieldID); static bool IsZeroConstExpr(const UniqueFEIRExpr &expr); + static UniqueFEIRStmt CreateVLAStackRestore(const UniqueFEIRVar &vlaSavedStackVar); + static std::string EmitVLACleanupStmts(FEFunction &feFunction, const std::string &labelName, const Loc &loc); + static void EmitVLACleanupStmts(const FEFunction &feFunction, std::list &stmts); }; // class FEIRBuilder } // namespace maple #endif // HIR2MPL_INCLUDE_COMMON_FEIR_BUILDER_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..5988a29c938e74686aef686bd66d55a3ca2ea626 --- /dev/null +++ b/src/hir2mpl/common/include/feir_scope.h @@ -0,0 +1,98 @@ +/* + * 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_FEIR_SCOPE_H +#define HIR2MPL_COMMON_INCLUDE_FEIR_SCOPE_H +#include "mir_scope.h" +#include "mpl_logging.h" +#include "src_position.h" +#include "feir_var.h" +#include "feir_stmt.h" + +namespace maple { +class FEIRScope; +using UniqueFEIRScope = std::unique_ptr; + +class FEIRScope { + public: + explicit FEIRScope(uint32 currID) : id(currID) {} + FEIRScope(uint32 currID, MIRScope *scope) : id(currID), mirScope(scope) {} + FEIRScope(uint32 currID, bool isControll) : id(currID), isControllScope(isControll) {} + virtual ~FEIRScope() = default; + + uint32 GetID() const { + return id; + } + + void SetMIRScope(MIRScope *scope) { + mirScope = scope; + } + + MIRScope *GetMIRScope() { + return mirScope; + } + + const MIRScope *GetMIRScope() const { + return mirScope; + } + + void SetVLASavedStackVar(UniqueFEIRVar var) { + vlaSavedStackVar = std::move(var); + } + + const UniqueFEIRVar &GetVLASavedStackVar() const { + return vlaSavedStackVar; + } + + void SetVLASavedStackPtr(FEIRStmt *stmt) { + feirStmt = stmt; + } + + FEIRStmt *GetVLASavedStackPtr() const { + return feirStmt; + } + + void SetIsControllScope(bool flag) { + isControllScope = flag; + } + + bool IsControllScope() const { + return isControllScope; + } + + UniqueFEIRStmt GenVLAStackRestoreStmt() const; + UniqueFEIRScope Clone() const; + + void ProcessVLAStack(std::list &stmts, bool isCallAlloca, Loc endLoc) { + FEIRStmt *feirStmt = GetVLASavedStackPtr(); + if (feirStmt != nullptr) { + if (isCallAlloca) { + feirStmt->SetIsNeedGenMir(false); + } else { + auto stackRestoreStmt = GenVLAStackRestoreStmt(); + stackRestoreStmt->SetSrcLoc(endLoc); + (void)stmts.emplace_back(std::move(stackRestoreStmt)); + } + } + } + + private: + uint32 id; + MIRScope *mirScope = nullptr; // one func, compoundstmt or forstmt scope includes decls + UniqueFEIRVar vlaSavedStackVar = nullptr; + bool isControllScope = false; // The controlling scope in a if/switch/while/for statement + FEIRStmt *feirStmt = 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..3dd6d5fcc61cfa67500bffb4868205c63eff3956 --- 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. @@ -50,6 +50,8 @@ constexpr uint32 kOpHashShift = 24; constexpr uint32 kTypeHashShift = 8; constexpr uint32 kOtherShift = 16; constexpr uint32 kRandomNum = 0x9e3779b9; +constexpr uint32 kSeedLeftShift = 6; +constexpr uint32 kSeedRightShift = 2; // ---------- FEIRNode ---------- class FEIRNode { @@ -124,9 +126,12 @@ class FEIRStmt : public FELinkListNode { } std::list GenMIRStmts(MIRBuilder &mirBuilder) const { - std::list stmts = GenMIRStmtsImpl(mirBuilder); - SetMIRStmtSrcPos(stmts); - return stmts; + if (isNeedGenMir) { + std::list stmts = GenMIRStmtsImpl(mirBuilder); + SetMIRStmtSrcPos(stmts); + return stmts; + } + return std::list(); } FEIRNodeKind GetKind() const { @@ -138,17 +143,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 +190,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 +221,28 @@ 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; + } + + uint32 GetSrcFileColumn() const { + return loc.column; } bool HasSetLOCInfo() const { - return (srcFileLineNum != 0 || srcFileIndex != 0); + return (loc.fileIdx != 0 || loc.line != 0); } bool IsDummy() const { @@ -261,6 +261,10 @@ class FEIRStmt : public FELinkListNode { return DumpImpl(prefix); } + void SetIsNeedGenMir(bool needGen) { + isNeedGenMir = needGen; + } + protected: virtual std::string DumpDotStringImpl() const; virtual void DumpImpl(const std::string &prefix) const; @@ -277,7 +281,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 +306,27 @@ 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; + bool isEnhancedChecking = true; + std::vector extraPreds; + std::vector extraSuccs; + + private: + bool isNeedGenMir = true; }; using UniqueFEIRStmt = std::unique_ptr; @@ -328,7 +337,7 @@ class FEIRStmtCheckPoint : public FEIRStmt { FEIRStmtCheckPoint() : FEIRStmt(FEIRNodeKind::kStmtCheckPoint), firstVisibleStmt(nullptr) {} - ~FEIRStmtCheckPoint() { + ~FEIRStmtCheckPoint() override { firstVisibleStmt = nullptr; } @@ -409,6 +418,14 @@ class FEIRExpr { return isBoundaryChecking; } + void SetIsEnhancedChecking(bool flag) { + isEnhancedChecking = flag; + } + + bool IsEnhancedChecking() const { + return isEnhancedChecking; + } + void SetType(std::unique_ptr argType) { SetTypeImpl(std::move(argType)); } @@ -457,6 +474,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; @@ -511,7 +540,9 @@ class FEIRExpr { bool isAddrof : 1; bool hasException : 1; bool isBoundaryChecking : 1; + bool isEnhancedChecking : 1; std::unique_ptr type; + Loc loc = {0, 0, 0}; }; // class FEIRExpr using UniqueFEIRExpr = std::unique_ptr; @@ -668,12 +699,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)); } @@ -698,7 +731,7 @@ class FEIRExprAddrofConstArray : public FEIRExpr { } std::size_t seed = array.size(); for (uint32 elem : array) { - seed ^= elem + kRandomNum + (seed << 6) + (seed >> 2); + seed ^= elem + kRandomNum + (seed << kSeedLeftShift) + (seed >> kSeedRightShift); } hash += static_cast(seed); if (elemType != nullptr) { @@ -711,6 +744,7 @@ class FEIRExprAddrofConstArray : public FEIRExpr { std::string arrayName; std::vector array; MIRType *elemType = nullptr; + std::string str; }; // ---------- FEIRExprAddrOfLabel ---------- @@ -861,7 +895,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,9 +928,9 @@ 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); + seed ^= idx->Hash() + kRandomNum + (seed << kSeedLeftShift) + (seed >> kSeedRightShift); } } return hash + static_cast(seed); @@ -924,10 +958,10 @@ class FEIRExprUnary : public FEIRExpr { } protected: - virtual std::unique_ptr CloneImpl() const override; + std::unique_ptr CloneImpl() const override; void RegisterDFGNodes2CheckPointImpl(FEIRStmtCheckPoint &checkPoint) override; bool CalculateDefs4AllUsesImpl(FEIRStmtCheckPoint &checkPoint, FEIRUseDefChain &udChain) override; - virtual BaseNode *GenMIRNodeImpl(MIRBuilder &mirBuilder) const override; + BaseNode *GenMIRNodeImpl(MIRBuilder &mirBuilder) const override; std::vector GetVarUsesImpl() const override; uint32 HashImpl() const override { @@ -971,16 +1005,13 @@ class FEIRExprTypeCvt : public FEIRExprUnary { using FuncPtrGenMIRNode = BaseNode* (FEIRExprTypeCvt::*)(MIRBuilder &mirBuilder) const; static std::map InitFuncPtrMapForParseExpr(); - // GenMIRNodeMode1: - // MIR: op () + // MIR: op () BaseNode *GenMIRNodeMode1(MIRBuilder &mirBuilder) const; - // GenMIRNodeMode2: - // MIR: op () + // MIR: op () BaseNode *GenMIRNodeMode2(MIRBuilder &mirBuilder) const; - // GenMIRNodeMode3: - // MIR: retype () + // MIR: retype () BaseNode *GenMIRNodeMode3(MIRBuilder &mirBuilder) const; static std::map mapOpNestable; @@ -1011,7 +1042,7 @@ class FEIRExprExtractBits : public FEIRExprUnary { BaseNode *GenMIRNodeImpl(MIRBuilder &mirBuilder) const override; uint32 HashImpl() const override { - return FEIRExprUnary::HashImpl() + (static_cast(bitOffset) << 16) + static_cast(bitSize); + return FEIRExprUnary::HashImpl() + (static_cast(bitOffset) << kOtherShift) + static_cast(bitSize); } private: @@ -1040,6 +1071,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(); } @@ -1104,7 +1140,7 @@ class FEIRExprBinary : public FEIRExpr { uint32 HashImpl() const override { return (static_cast(kind) << kOpHashShift) + (type->Hash() << kTypeHashShift) + - (static_cast(op) << kOtherShift) + (opnd0->Hash() << 8) + opnd1->Hash(); + (static_cast(op) << kOtherShift) + (opnd0->Hash() << kTypeHashShift) + opnd1->Hash(); } private: @@ -1146,7 +1182,8 @@ class FEIRExprTernary : public FEIRExpr { uint32 HashImpl() const override { return (static_cast(kind) << kOpHashShift) + (type->Hash() << kTypeHashShift) + - (static_cast(op) << kOtherShift) + (opnd0->Hash() << 8) + (opnd1->Hash() << 16) + opnd1->Hash(); + (static_cast(op) << kOtherShift) + + (opnd0->Hash() << kTypeHashShift) + (opnd1->Hash() << kOtherShift) + opnd2->Hash(); } private: @@ -1166,6 +1203,9 @@ class FEIRExprNary : public FEIRExpr { void AddOpnd(std::unique_ptr argOpnd); void AddOpnds(const std::vector> &argOpnds); void ResetOpnd(); + const std::vector> &GetOpnds() const { + return opnds; + } protected: void RegisterDFGNodes2CheckPointImpl(FEIRStmtCheckPoint &checkPoint) override; @@ -1177,7 +1217,7 @@ class FEIRExprNary : public FEIRExpr { (static_cast(op) << kOtherShift); std::size_t seed = opnds.size(); for (auto &opnd : opnds) { - seed ^= opnd->Hash() + kRandomNum + (seed << 6) + (seed >> 2); + seed ^= opnd->Hash() + kRandomNum + (seed << kSeedLeftShift) + (seed >> kSeedRightShift); } hash += static_cast(seed); return hash; @@ -1247,6 +1287,10 @@ class FEIRExprIntrinsicopForC : public FEIRExprNary { const std::vector> &argOpnds); ~FEIRExprIntrinsicopForC() = default; + MIRIntrinsicID GetIntrinsicID() const { + return intrinsicID; + } + protected: std::unique_ptr CloneImpl() const override; BaseNode *GenMIRNodeImpl(MIRBuilder &mirBuilder) const override; @@ -1324,7 +1368,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); @@ -1465,6 +1509,7 @@ class FEIRExprAtomic : public FEIRExpr { protected: std::unique_ptr CloneImpl() const override; BaseNode *GenMIRNodeImpl(MIRBuilder &mirBuilder) const override; + TyIdx GetTyIdx(MIRBuilder &mirBuilder) const; private: MIRType *mirType = nullptr; @@ -1682,8 +1727,8 @@ class FEIRStmtJavaFillArrayData : public FEIRStmtAssign { LLT_PRIVATE: PrimType ProcessArrayElemPrimType() const; - MIRSymbol *ProcessArrayElemData(MIRBuilder &mirBuilder, PrimType elemPrimType) const; - MIRAggConst *FillArrayElem(MIRBuilder &mirBuilder, PrimType elemPrimType, MIRType &arrayTypeWithSize, + MIRSymbol *ProcessArrayElemData(const MIRBuilder &mirBuilder, PrimType elemPrimType) const; + MIRAggConst *FillArrayElem(const MIRBuilder &mirBuilder, PrimType elemPrimType, MIRType &arrayTypeWithSize, uint32 elemSize) const; std::unique_ptr arrayExpr; @@ -1855,9 +1900,9 @@ class FEIRStmtReturn : public FEIRStmtUseOnly { // ---------- FEIRStmtPesudoLabel ---------- class FEIRStmtPesudoLabel : public FEIRStmt { public: - FEIRStmtPesudoLabel(uint32 argLabelIdx); + explicit FEIRStmtPesudoLabel(uint32 argLabelIdx); ~FEIRStmtPesudoLabel() = default; - void GenerateLabelIdx(MIRBuilder &mirBuilder); + void GenerateLabelIdx(const MIRBuilder &mirBuilder); uint32 GetLabelIdx() const { return labelIdx; @@ -1884,7 +1929,7 @@ class FEIRStmtPesudoLabel2 : public FEIRStmt { : FEIRStmt(FEIRNodeKind::kStmtPesudoLabel), labelIdxOuter(qIdx0), labelIdxInner(qIdx1) {} ~FEIRStmtPesudoLabel2() = default; - static LabelIdx GenMirLabelIdx(MIRBuilder &mirBuilder, uint32 qIdx0, uint32 qIdx1); + static LabelIdx GenMirLabelIdx(const MIRBuilder &mirBuilder, uint32 qIdx0, uint32 qIdx1); std::pair GetLabelIdx() const; uint32 GetPos() const { return labelIdxInner; @@ -1904,7 +1949,7 @@ class FEIRStmtPesudoLabel2 : public FEIRStmt { class FEIRStmtGoto : public FEIRStmt { public: explicit FEIRStmtGoto(uint32 argLabelIdx); - virtual ~FEIRStmtGoto(); + ~FEIRStmtGoto() override; void SetLabelIdx(uint32 argLabelIdx) { labelIdx = argLabelIdx; } @@ -1975,7 +2020,7 @@ class FEIRStmtGoto2 : public FEIRStmt { // ---------- FEIRStmtGoto ---------- class FEIRStmtGotoForC : public FEIRStmt { public: - explicit FEIRStmtGotoForC(const std::string &labelName); + explicit FEIRStmtGotoForC(const std::string &name); virtual ~FEIRStmtGotoForC() = default; void SetLabelName(const std::string &name) { labelName = name; @@ -1985,6 +2030,10 @@ class FEIRStmtGotoForC : public FEIRStmt { return labelName; } + void AddVLASvaedStackVars(uint32 scopeID, UniqueFEIRVar vlaSavedStackVar) { + vlaSvaedStackVars.emplace_back(std::make_pair(scopeID, std::move(vlaSavedStackVar))); + } + protected: bool IsFallThroughImpl() const override { return false; @@ -1996,7 +2045,12 @@ class FEIRStmtGotoForC : public FEIRStmt { std::string DumpDotStringImpl() const override; std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const override; + + private: + void GenVLACleanup(MIRBuilder &mirBuilder, std::list &ans) const; + std::string labelName; + std::vector> vlaSvaedStackVars; }; // ---------- FEIRStmtIGoto ---------- @@ -2023,7 +2077,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; @@ -2033,11 +2087,15 @@ class FEIRStmtCondGotoForC : public FEIRStmt { return labelName; } - protected: - bool IsFallThroughImpl() const override { - return false; + const UniqueFEIRExpr &GetConditionExpr() const { + return expr; + } + + void SetCondtionExpr(UniqueFEIRExpr &exprIn) { + expr = std::move(exprIn); } + protected: bool IsBranchImpl() const override { return true; } @@ -2112,7 +2170,7 @@ class FEIRStmtCondGoto2 : public FEIRStmtGoto2 { class FEIRStmtSwitch : public FEIRStmt { public: explicit FEIRStmtSwitch(UniqueFEIRExpr argExpr); - ~FEIRStmtSwitch(); + ~FEIRStmtSwitch() override; void SetDefaultLabelIdx(uint32 labelIdx) { defaultLabelIdx = labelIdx; } @@ -2151,14 +2209,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; @@ -2176,7 +2231,7 @@ class FEIRStmtSwitch : public FEIRStmt { class FEIRStmtSwitch2 : public FEIRStmt { public: explicit FEIRStmtSwitch2(uint32 outerIdxIn, UniqueFEIRExpr argExpr); - ~FEIRStmtSwitch2(); + ~FEIRStmtSwitch2() override; void SetDefaultLabelIdx(uint32 labelIdx) { defaultLabelIdx = labelIdx; } @@ -2215,14 +2270,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 +2325,7 @@ class FEIRStmtSwitchForC : public FEIRStmt { // ---------- FEIRStmtCaseForC ---------- class FEIRStmtCaseForC : public FEIRStmt { public: - FEIRStmtCaseForC(int64 lCaseLabel); + explicit FEIRStmtCaseForC(int64 label); void AddCaseTag2CaseVec(int64 lCaseTag, int64 rCaseTag); ~FEIRStmtCaseForC() = default; void AddFeirStmt(UniqueFEIRStmt stmt) { @@ -2335,7 +2387,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 +2438,6 @@ 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; std::list GenMIRStmtsImplForStatic(MIRBuilder &mirBuilder) const; std::list GenMIRStmtsImplForNonStatic(MIRBuilder &mirBuilder) const; @@ -2461,6 +2512,10 @@ class FEIRStmtICallAssign : public FEIRStmtAssign { FEIRStmtICallAssign(); ~FEIRStmtICallAssign() = default; + void SetPrototype(UniqueFEIRType type) { + prototype = std::move(type); + } + protected: std::list GenMIRStmtsImpl(MIRBuilder &mirBuilder) const override; std::string DumpDotStringImpl() const override; @@ -2470,6 +2525,8 @@ class FEIRStmtICallAssign : public FEIRStmtAssign { private: void InsertNonnullCheckingInArgs(MIRBuilder &mirBuilder, std::list &ans) const; void InsertNonnullInRetVar(MIRSymbol &retVarSym) const; + + UniqueFEIRType prototype = nullptr; }; // ---------- FEIRStmtIntrinsicCallAssign ---------- @@ -2494,7 +2551,10 @@ class FEIRStmtIntrinsicCallAssign : public FEIRStmtAssign { private: void ConstructArgsForInvokePolyMorphic(MIRBuilder &mirBuilder, MapleVector &intrnCallargs) const; + std::list GenMIRStmtsForIntrnC(MIRBuilder &mirBuilder, TyIdx tyIdx = TyIdx(0)) const; + std::list GenMIRStmtsForFillNewArray(MIRBuilder &mirBuilder) const; std::list GenMIRStmtsForInvokePolyMorphic(MIRBuilder &mirBuilder) const; + std::list GenMIRStmtsForClintCheck(MIRBuilder &mirBuilder) const; MIRIntrinsicID intrinsicId; UniqueFEIRType type; @@ -2552,7 +2612,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 +2683,7 @@ class FEIRStmtPesudoCatch2 : public FEIRStmtPesudoLabel2 { class FEIRStmtPesudoSafe : public FEIRStmt { public: - FEIRStmtPesudoSafe(bool isEnd); + explicit FEIRStmtPesudoSafe(bool isEnd); ~FEIRStmtPesudoSafe() = default; protected: @@ -2634,7 +2694,7 @@ class FEIRStmtPesudoSafe : public FEIRStmt { class FEIRStmtPesudoUnsafe : public FEIRStmt { public: - FEIRStmtPesudoUnsafe(bool isEnd); + explicit FEIRStmtPesudoUnsafe(bool isEnd); ~FEIRStmtPesudoUnsafe() = default; protected: @@ -2702,6 +2762,10 @@ class FEIRStmtIf : public FEIRStmt { condExpr = std::move(argCondExpr); } + const UniqueFEIRExpr &GetCondExpr() const { + return condExpr; + } + void SetHasElse(bool argHasElse) { hasElse = argHasElse; } @@ -2725,10 +2789,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 +2811,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: @@ -2788,7 +2862,7 @@ class FEIRStmtContinue : public FEIRStmt { FEIRStmtContinue(): FEIRStmt(FEIRNodeKind::kStmtContinue) {} ~FEIRStmtContinue() = default; - void SetLabelName(std::string name){ + void SetLabelName(std::string name) { labelName = std::move(name); } @@ -2807,6 +2881,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 +2898,7 @@ class FEIRStmtLabel : public FEIRStmt { class FEIRStmtAtomic : public FEIRStmt { public: - FEIRStmtAtomic(UniqueFEIRExpr expr); + explicit FEIRStmtAtomic(UniqueFEIRExpr expr); ~FEIRStmtAtomic() = default; protected: @@ -2860,7 +2938,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_type.h b/src/hir2mpl/common/include/feir_type.h index 9f64fe67496879b44f8ccf8c0f294907841b48fa..7daf3670c114570076153c7e7068d6e128414015 100644 --- a/src/hir2mpl/common/include/feir_type.h +++ b/src/hir2mpl/common/include/feir_type.h @@ -80,6 +80,7 @@ class FEIRType { } MIRType *GenerateMIRType(MIRSrcLang argSrcLang, bool usePtr) const { + (void)argSrcLang; return GenerateMIRType(usePtr); } @@ -328,7 +329,7 @@ class FEIRTypeNative : public FEIRType { class FEIRTypePointer : public FEIRType { public: explicit FEIRTypePointer(std::unique_ptr argBaseType, PrimType argPrimType = PTY_ref); - ~FEIRTypePointer() = default; + ~FEIRTypePointer() override = default; FEIRTypePointer(const FEIRTypePointer&) = delete; FEIRTypePointer &operator=(const FEIRTypePointer&) = delete; const UniqueFEIRType &GetBaseType() const { @@ -348,21 +349,21 @@ class FEIRTypePointer : public FEIRType { bool IsScalarImpl() const override; TypeDim ArrayIncrDimImpl(TypeDim delta) override; TypeDim ArrayDecrDimImpl(TypeDim delta) override; - virtual PrimType GetPrimTypeImpl() const override; - virtual void SetPrimTypeImpl(PrimType pt) override; - virtual bool IsRefImpl() const override { + PrimType GetPrimTypeImpl() const override; + void SetPrimTypeImpl(PrimType pt) override; + bool IsRefImpl() const override { return true; // pointer type is ref } - virtual bool IsArrayImpl() const override { + bool IsArrayImpl() const override { return baseType->IsArray(); } - virtual bool IsPreciseImpl() const override { + bool IsPreciseImpl() const override { return baseType->IsPrecise(); } - virtual bool IsValidImpl() const override { + bool IsValidImpl() const override { return baseType->IsValid(); } diff --git a/src/hir2mpl/common/include/feir_var.h b/src/hir2mpl/common/include/feir_var.h index 98322da484ba4986b15d0db8fbfbc530d03e3ad1..8bcb328e14de2a7163f61006d29aa59edafc35d8 100644 --- a/src/hir2mpl/common/include/feir_var.h +++ b/src/hir2mpl/common/include/feir_var.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. @@ -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,17 @@ class FEIRVar { MIRSymbol *GenerateGlobalMIRSymbol(MIRBuilder &builder) const { MIRSymbol *mirSym = GenerateGlobalMIRSymbolImpl(builder); - mirSym->GetSrcPosition().SetFileNum(static_cast(srcFileIdx)); - mirSym->GetSrcPosition().SetLineNum(srcFileLineNum); - builder.GetMirModule().InsertInlineGlobal(mirSym->GetStIdx().Idx()); + if (mirSym->GetSrcPosition().LineNum() == 0) { + mirSym->SetSrcPosition(FEUtils::CvtLoc2SrcPosition(loc)); + } 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(FEUtils::CvtLoc2SrcPosition(loc)); + } return mirSym; } @@ -147,10 +149,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 +165,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 +201,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..6b7406d30dd1516e305de461292c3369d429bb86 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 }; +constexpr uint32 kMaxATTRNum = 128; class GenericAttrs { public: @@ -44,6 +45,10 @@ class GenericAttrs { attrFlag.set(x); } + void ResetAttr(GenericAttrKind x) { + attrFlag.reset(x); + } + bool GetAttr(GenericAttrKind x) const { return attrFlag[x]; } @@ -56,21 +61,49 @@ class GenericAttrs { return !(*this == tA); } + void InitContentMap() { + contentMap.resize(kMaxATTRNum); + 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..423e67f82d95349ed2e18fb1ac23ad05f0010c1a 100644 --- a/src/hir2mpl/common/include/hir2mpl_compiler.h +++ b/src/hir2mpl/common/include/hir2mpl_compiler.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,11 +26,11 @@ #include "ark_annotation_processor.h" #include "dex_reader.h" #include "ast_compiler_component.h" +#include "ast_compiler_component-inl.h" #include "ast_parser.h" #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 +70,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..3e9040f0995b45669455bf44dad327450090daca 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); @@ -137,6 +136,7 @@ class HIR2MPLCompilerComponent { std::list globalFuncHelpers; std::list globalVarHelpers; std::list globalFileScopeAsmHelpers; + std::list enumHelpers; std::unique_ptr phaseResultTotal; std::set compileFailedFEFunctions; }; diff --git a/src/hir2mpl/common/include/hir2mpl_option.h b/src/hir2mpl/common/include/hir2mpl_option.h new file mode 100644 index 0000000000000000000000000000000000000000..f26aeb0f2ec3c60cc4dbbb0e33ebf698466c7264 --- /dev/null +++ b/src/hir2mpl/common/include/hir2mpl_option.h @@ -0,0 +1,65 @@ +/* + * 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 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 defaultSafe; +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..fcc4b4b78df8d68df9850464397f8da387a1647e 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,21 +17,20 @@ #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; return options; } - void Init(); + void Init() const; 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; @@ -40,88 +39,91 @@ class HIR2MPLOptions : public maple::MapleDriverOptionBase { static std::list SplitByComma(const std::string &s); // non-option process - void ProcessInputFiles(const std::vector &inputs); + void ProcessInputFiles(const std::vector &inputs) const; 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 &) const; + bool ProcessVersion(const maplecl::OptionInterface &) const; // 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) const; + bool ProcessInJar(const maplecl::OptionInterface &mpltApk) const; + bool ProcessInDex(const maplecl::OptionInterface &inDex) const; + bool ProcessInAST(const maplecl::OptionInterface &inAst) const; + bool ProcessInMAST(const maplecl::OptionInterface &inMast) const; + bool ProcessInputMplt(const maplecl::OptionInterface &mplt) const; + bool ProcessInputMpltFromSys(const maplecl::OptionInterface &mpltSys) const; + bool ProcessInputMpltFromApk(const maplecl::OptionInterface &mpltApk) const; // 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) const; + bool ProcessOutputName(const maplecl::OptionInterface &outputName) const; + bool ProcessGenMpltOnly(const maplecl::OptionInterface &) const; + bool ProcessGenAsciiMplt(const maplecl::OptionInterface &) const; + bool ProcessDumpInstComment(const maplecl::OptionInterface &) const; + bool ProcessNoMplFile(const maplecl::OptionInterface &) const; // 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) const; + bool ProcessDumpTime(const maplecl::OptionInterface &) const; + bool ProcessDumpComment(const maplecl::OptionInterface &) const; + bool ProcessDumpLOC(const maplecl::OptionInterface &) const; + bool ProcessDbgFriendly(const maplecl::OptionInterface &) const; + bool ProcessDumpPhaseTime(const maplecl::OptionInterface &) const; + bool ProcessDumpPhaseTimeDetail(const maplecl::OptionInterface &) const; // 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) const; + bool ProcessJBCInfoUsePathName(const maplecl::OptionInterface &) const; + bool ProcessDumpJBCStmt(const maplecl::OptionInterface &) const; + bool ProcessDumpJBCAll(const maplecl::OptionInterface &) const; + bool ProcessDumpJBCErrorOnly(const maplecl::OptionInterface &) const; + bool ProcessDumpJBCFuncName(const maplecl::OptionInterface &opt) const; + bool ProcessEmitJBCLocalVarInfo(const maplecl::OptionInterface &) const; // 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 &) const; + bool ProcessNoBarrier(const maplecl::OptionInterface &) const; + bool ProcessO2(const maplecl::OptionInterface &) const; + bool ProcessSimplifyShortCircuit(const maplecl::OptionInterface &) const; + bool ProcessEnableVariableArray(const maplecl::OptionInterface &) const; + bool ProcessFuncInlineSize(const maplecl::OptionInterface &funcInliceSize) const; + bool ProcessWPAA(const maplecl::OptionInterface &) const; // ast compiler options - bool ProcessUseSignedChar(const mapleOption::Option &opt); - bool ProcessBigEndian(const mapleOption::Option &opt); + bool ProcessUseSignedChar(const maplecl::OptionInterface &) const; + bool ProcessBigEndian() const; - // general stmt/bb/cfg debug options - bool ProcessDumpFEIRCFGGraph(const mapleOption::Option &opt); + // general stmt/bb/cfg options + bool ProcessDumpFEIRBB(const maplecl::OptionInterface &) const; + bool ProcessDumpFEIRCFGGraph(const maplecl::OptionInterface &opt) const; // 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) const; + bool ProcessDumpThreadTime(const maplecl::OptionInterface &) const; // 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) const; + bool ProcessClassLoaderContext(const maplecl::OptionInterface &classloadercontext) const; + bool ProcessCollectDepTypes(const maplecl::OptionInterface &dep) const; + bool ProcessDepSameNamePolicy(const maplecl::OptionInterface &depsamename) const; // EnhanceC - bool ProcessNpeCheckDynamic(const mapleOption::Option &opt); - bool ProcessBoundaryCheckDynamic(const mapleOption::Option &opt); - bool ProcessSafeRegion(const mapleOption::Option &opt); + bool ProcessNpeCheckDynamic(const maplecl::OptionInterface &) const; + bool ProcessBoundaryCheckDynamic(const maplecl::OptionInterface &) const; + bool ProcessSafeRegion(const maplecl::OptionInterface &) const; + bool ProcessDefaultSafe(const maplecl::OptionInterface &) const; // symbol resolve - bool ProcessAOT(const mapleOption::Option &opt); + bool ProcessAOT(const maplecl::OptionInterface &) const; }; // 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..c6ad931e9189e200c68d60cc48ef18d339a4530c 100644 --- a/src/hir2mpl/common/include/simple_zip.h +++ b/src/hir2mpl/common/include/simple_zip.h @@ -22,10 +22,6 @@ #include "basic_io.h" namespace maple { -static const uint32 kZipSigLocalFile = 0x04034B50; -static const uint32 kZipSigDataDescriptor = 0x08074B50; -static const uint32 kZipSigCentralDir = 0x02014B50; - class ZipLocalFileHeader { public: ZipLocalFileHeader() = default; @@ -115,8 +111,8 @@ class ZipLocalFile { class SimpleZip : public BasicIORead { public: - SimpleZip(BasicIOMapFile &file); - ~SimpleZip(); + explicit SimpleZip(BasicIOMapFile &file); + ~SimpleZip() override; void ParseFile(); const std::list> &GetFiles() const { 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..178142ec79e7ac710d8b1d43c0d8d8f62e5bce90 100644 --- a/src/hir2mpl/common/src/basic_io.cpp +++ b/src/hir2mpl/common/src/basic_io.cpp @@ -14,13 +14,13 @@ */ #include "basic_io.h" #include -#include #include #include #include #include #include #include "mpl_logging.h" +#include "file_utils.h" namespace maple { BasicIOMapFile::BasicIOMapFile(const std::string &name) @@ -36,7 +36,8 @@ BasicIOMapFile::~BasicIOMapFile() { bool BasicIOMapFile::OpenAndMapImpl() { fd = -1; - fd = open(fileName.c_str(), O_RDONLY); + std::string realPath = FileUtils::GetRealPath(fileName); + fd = open(realPath.c_str(), O_RDONLY); if (fd < 0) { ERR(kLncErr, "Unable to open %s.\nError %d in open()", fileName.c_str(), errno); return false; diff --git a/src/hir2mpl/common/src/enhance_c_checker.cpp b/src/hir2mpl/common/src/enhance_c_checker.cpp old mode 100755 new mode 100644 index beecaa10fabf90be7d88f71156771d3ce6e44eca..eaadc191191588dad972b7143d831dc92bf471c3 --- 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,9 @@ #include "fe_macros.h" namespace maple { -void ASTParser::ProcessNonnullFuncPtrAttrs(const clang::ValueDecl &valueDecl, ASTDecl &astVar) { +const std::string kBoundsBuiltFunc = "__builtin_dynamic_bounds_cast"; +void ASTParser::ProcessNonnullFuncPtrAttrs(MapleAllocator &allocator, const clang::ValueDecl &valueDecl, + ASTDecl &astVar) { const MIRFuncType *funcType = FEUtils::GetFuncPtrType(*astVar.GetTypeDesc().front()); if (funcType == nullptr) { return; @@ -31,7 +33,7 @@ void ASTParser::ProcessNonnullFuncPtrAttrs(const clang::ValueDecl &valueDecl, AS TypeAttrs retAttr = funcType->GetRetAttrs(); // nonnull with args in function type pointers need marking nonnull arg for (const auto *nonNull : valueDecl.specific_attrs()) { - if (!nonNull->args_size()) { + if (nonNull->args_size() == 0) { continue; } for (const clang::ParamIdx ¶mIdx : nonNull->args()) { @@ -48,8 +50,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) { @@ -95,24 +97,29 @@ bool ENCChecker::HasNullExpr(const UniqueFEIRExpr &expr) { } void ENCChecker::CheckNonnullGlobalVarInit(const MIRSymbol &sym, const MIRConst *cst) { - if (!FEOptions::GetInstance().IsNpeCheckDynamic() || !sym.GetAttr(ATTR_nonnull)) { - return; - } - if (cst == nullptr) { - FE_ERR(kLncErr, "%s:%d error: nonnull parameter is uninitialized when defined", - FEManager::GetModule().GetFileNameFromFileNum(sym.GetSrcPosition().FileNum()).c_str(), - sym.GetSrcPosition().LineNum()); + if (!FEOptions::GetInstance().IsNpeCheckDynamic()) { return; } - if (cst->IsZero()) { - FE_ERR(kLncErr, "%s:%d error: null assignment of nonnull pointer", - FEManager::GetModule().GetFileNameFromFileNum(sym.GetSrcPosition().FileNum()).c_str(), - sym.GetSrcPosition().LineNum()); - return; + if (sym.GetAttr(ATTR_nonnull)) { + if ((cst != nullptr && cst->IsZero()) || (cst == nullptr && sym.GetAttr(ATTR_static_init_zero))) { + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), "null assignment of nonnull pointer"); + } else if (cst == nullptr) { + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), "nonnull parameter is uninitialized when defined"); + } + } else if (sym.GetAttr(ATTR_static_init_zero) && HasNonnullFieldInStruct(*sym.GetType())) { + auto *structType = static_cast(sym.GetType()); + for (size_t i = 0; i < structType->GetFieldsSize(); ++i) { + if (!structType->GetFieldsElemt(i).second.second.GetAttr(FLDATTR_nonnull)) { + continue; + } + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), + "null assignment of nonnull field pointer. [field name: %s]", + GlobalTables::GetStrTable().GetStringFromStrIdx(structType->GetFieldsElemt(i).first).c_str()); + } } } -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; } @@ -123,23 +130,31 @@ void ENCChecker::CheckNullFieldInGlobalStruct(MIRType &type, MIRAggConst &cst, c } size_t idx = structType.GetKind() == kTypeUnion ? 0 : i; // union only is one element if (idx < cst.GetConstVec().size() && cst.GetConstVecItem(idx) != nullptr && cst.GetConstVecItem(idx)->IsZero()) { - FE_ERR(kLncErr, "%s:%d error: null assignment of nonnull field pointer. [field name: %s]", - FEManager::GetModule().GetFileNameFromFileNum(initExprs[idx]->GetSrcFileIdx()).c_str(), - initExprs[idx]->GetSrcFileLineNum(), + FE_ERR(kLncErr, initExprs[idx]->GetSrcLoc(), "null assignment of nonnull field pointer. [field name: %s]", GlobalTables::GetStrTable().GetStringFromStrIdx(structType.GetFieldsElemt(i).first).c_str()); } } } void ENCChecker::CheckNonnullLocalVarInit(const MIRSymbol &sym, const ASTExpr *initExpr) { - if (!FEOptions::GetInstance().IsNpeCheckDynamic() || !sym.GetAttr(ATTR_nonnull)) { + if (!FEOptions::GetInstance().IsNpeCheckDynamic() || initExpr != nullptr) { return; } - if (initExpr == nullptr) { - FE_ERR(kLncErr, "%s:%d error: nonnull parameter is uninitialized when defined", - FEManager::GetModule().GetFileNameFromFileNum(sym.GetSrcPosition().FileNum()).c_str(), - sym.GetSrcPosition().LineNum()); - return; + if (sym.GetAttr(ATTR_nonnull)) { + if (sym.GetAttr(ATTR_static_init_zero)) { + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), "null assignment of nonnull pointer"); + } else { + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), + "error: nonnull parameter is uninitialized when defined"); + } + } else if (sym.GetAttr(ATTR_static_init_zero) && HasNonnullFieldInStruct(*sym.GetType())) { + auto *structType = static_cast(sym.GetType()); + for (size_t i = 0; i < structType->GetFieldsSize(); ++i) { + if (structType->GetFieldsElemt(i).second.second.GetAttr(FLDATTR_nonnull)) { + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), + "null assignment of nonnull field pointer. [field name: %s]", + GlobalTables::GetStrTable().GetStringFromStrIdx(structType->GetFieldsElemt(i).first).c_str());} + } } } @@ -149,14 +164,12 @@ void ENCChecker::CheckNonnullLocalVarInit(const MIRSymbol &sym, const UniqueFEIR return; } if (HasNullExpr(initFEExpr)) { - FE_ERR(kLncErr, "%s:%d error: null assignment of nonnull pointer", - FEManager::GetModule().GetFileNameFromFileNum(sym.GetSrcPosition().FileNum()).c_str(), - sym.GetSrcPosition().LineNum()); + FE_ERR(kLncErr, FEUtils::GetSrcLocationForMIRSymbol(sym), "null assignment of nonnull pointer"); return; } if (initFEExpr->GetPrimType() == PTY_ptr) { UniqueFEIRStmt stmt = std::make_unique(OP_assignassertnonnull, initFEExpr->Clone()); - stmt->SetSrcFileInfo(sym.GetSrcPosition().FileNum(), sym.GetSrcPosition().LineNum()); + stmt->SetSrcLoc(FEUtils::GetSrcLocationForMIRSymbol(sym)); stmts.emplace_back(std::move(stmt)); } } @@ -189,8 +202,8 @@ std::string ENCChecker::PrintParamIdx(const std::list &idxs) { } void ENCChecker::CheckNonnullArgsAndRetForFuncPtr(const MIRType &dstType, const UniqueFEIRExpr &srcExpr, - uint32 fileNum, uint32 fileLine) { - if (!FEOptions::GetInstance().IsNpeCheckDynamic()) { + const Loc &loc) { + if (!FEOptions::GetInstance().IsNpeCheckDynamic() || !srcExpr->IsEnhancedChecking()) { return; } const MIRFuncType *funcType = FEUtils::GetFuncPtrType(dstType); @@ -209,13 +222,12 @@ 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, loc, "function pointer and assigned function %s are mismatched " + "for the %s argument of nonnull attributes", 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); + FE_ERR(kLncErr, loc, "function pointer and target function's nonnull attributes are mismatched for " + "the return value"); } } const MIRFuncType *srcFuncType = FEUtils::GetFuncPtrType(*srcExpr->GetType()->GenerateMIRTypeAuto()); @@ -228,12 +240,11 @@ 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()); + FE_ERR(kLncErr, loc, "function pointer's nonnull attributes are mismatched for the %s argument", + 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); + FE_ERR(kLncErr, loc, "function pointer's nonnull attributes are mismatched for the return value"); } } } @@ -246,7 +257,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 +265,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 +291,35 @@ 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)) { - 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()); - } + 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, loc, "null assignment of nonnull structure field pointer in %s", 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)) { - FE_ERR(kLncErr, "%s:%d error: null assignment risk of nonnull field pointer", - FEManager::GetModule().GetFileNameFromFileNum(srcFileIdx).c_str(), srcFileLineNum); + if (ENCChecker::HasNonnullFieldInPtrStruct(dst)) { + FE_ERR(kLncErr, loc, "null assignment risk of nonnull field pointer"); } } @@ -328,7 +345,7 @@ void ASTParser::ProcessBoundaryFuncAttrs(MapleAllocator &allocator, const clang: if (lenExpr == nullptr) { continue; } - if (!countAttr->index_size()) { + if (countAttr->index_size() == 0) { // Lack of attribute index parameters means that only one pointer parameter is // implicitly marked as boundary var in func. for (unsigned int i = 0; i < astFunc.GetParamDecls().size(); ++i) { @@ -367,7 +384,7 @@ void ASTParser::ProcessByteBoundaryFuncAttrs(MapleAllocator &allocator, const cl if (lenExpr == nullptr) { continue; } - if (!countAttr->index_size()) { + if (countAttr->index_size() == 0) { // Lack of attribute index parameters means that only one pointer parameter is // implicitly marked as boundary var in func. for (unsigned int i = 0; i < astFunc.GetParamDecls().size(); ++i) { @@ -432,7 +449,7 @@ void ASTParser::ProcessBoundaryParamAttrs(MapleAllocator &allocator, const clang } for (const auto *countAttr : parmDecl->specific_attrs()) { clang::Expr *expr = countAttr->getLenExpr(); - if (countAttr->index_size()) { + if (countAttr->index_size() > 0) { continue; // boundary attrs with index args are only marked function pointers } ASTExpr *lenExpr = ProcessExpr(allocator, expr); @@ -443,7 +460,7 @@ void ASTParser::ProcessBoundaryParamAttrs(MapleAllocator &allocator, const clang } for (const auto *byteCountAttr : parmDecl->specific_attrs()) { clang::Expr *expr = byteCountAttr->getLenExpr(); - if (byteCountAttr->index_size()) { + if (byteCountAttr->index_size() > 0) { continue; // boundary attrs with index args are only marked function pointers } ASTExpr *lenExpr = ProcessExpr(allocator, expr); @@ -464,14 +481,14 @@ void ASTParser::ProcessBoundaryParamAttrsByIndex(MapleAllocator &allocator, cons for (unsigned int i = 0; i < funcDecl.getNumParams(); ++i) { const clang::ParmVarDecl *parmDecl = funcDecl.getParamDecl(i); for (const auto *countIndexAttr : parmDecl->specific_attrs()) { - if (countIndexAttr->index_size()) { + if (countIndexAttr->index_size() > 0) { continue; // boundary attrs with index args are only marked function pointers } unsigned int lenIdx = countIndexAttr->getLenVarIndex().getASTIndex(); ProcessBoundaryLenExprInFunc(allocator, funcDecl, i, astFunc, lenIdx, true); } for (const auto *byteCountIndexAttr : parmDecl->specific_attrs()) { - if (byteCountIndexAttr->index_size()) { + if (byteCountIndexAttr->index_size() > 0) { continue; // boundary attrs with index args are only marked function pointers } unsigned int lenIdx = byteCountIndexAttr->getLenVarIndex().getASTIndex(); @@ -490,7 +507,7 @@ void ASTParser::ProcessBoundaryVarAttrs(MapleAllocator &allocator, const clang:: if (lenExpr == nullptr) { continue; } - if (countAttr->index_size()) { + if (countAttr->index_size() > 0) { continue; // boundary attrs with index args are only marked function pointers } ProcessBoundaryLenExprInVar(allocator, astVar, varDecl, lenExpr, true); @@ -501,7 +518,7 @@ void ASTParser::ProcessBoundaryVarAttrs(MapleAllocator &allocator, const clang:: if (lenExpr == nullptr) { continue; } - if (byteCountAttr->index_size()) { + if (byteCountAttr->index_size() > 0) { continue; // boundary attrs with index args are only marked function pointers } ProcessBoundaryLenExprInVar(allocator, astVar, varDecl, lenExpr, false); @@ -552,10 +569,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 @@ -565,7 +582,7 @@ bool ASTParser::ProcessBoundaryFuncPtrAttrsForParams(T *attr, MapleAllocator &al bool isUpdated = false; clang::Expr *expr = attr->getLenExpr(); ASTExpr *lenExpr = ProcessExpr(allocator, expr); - if (!attr->index_size() || lenExpr == nullptr) { + if (attr->index_size() == 0 || lenExpr == nullptr) { return isUpdated; } std::vector typesVec = funcType.GetParamTypeList(); @@ -575,8 +592,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 +611,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,25 +648,24 @@ 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(); - if (!attr->index_size() || lenIdx >= typesVec.size()) { + if (attr->index_size() == 0 || lenIdx >= typesVec.size()) { return isUpdated; } MIRType *lenType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(typesVec[lenIdx]); if (lenType == nullptr || !FEUtils::IsInteger(lenType->GetPrimType())) { - FE_ERR(kLncErr, "%s:%d error: The boundary length var by the %s argument is not an integer type", - FEManager::GetModule().GetFileNameFromFileNum(astDecl.GetSrcFileIdx()).c_str(), - astDecl.GetSrcFileLineNum(), ENCChecker::GetNthStr(lenIdx).c_str()); + FE_ERR(kLncErr, astDecl.GetSrcLoc(), "The boundary length var by the %s argument is not an integer type", + ENCChecker::GetNthStr(lenIdx).c_str()); return isUpdated; } for (const clang::ParamIdx ¶mIdx : attr->index()) { @@ -693,7 +709,7 @@ void ASTParser::ProcessBoundaryFieldAttrs(MapleAllocator &allocator, const ASTSt if (lenExpr == nullptr) { continue; } - if (!countAttr->index_size()) { + if (countAttr->index_size() == 0) { ProcessBoundaryLenExprInField(allocator, *astField, structDecl, fieldDecl->getType(), lenExpr, true); } } @@ -703,7 +719,7 @@ void ASTParser::ProcessBoundaryFieldAttrs(MapleAllocator &allocator, const ASTSt if (lenExpr == nullptr) { continue; } - if (!byteCountAttr->index_size()) { + if (byteCountAttr->index_size() == 0) { ProcessBoundaryLenExprInField(allocator, *astField, structDecl, fieldDecl->getType(), lenExpr, false); } } @@ -717,9 +733,7 @@ void ASTParser::ProcessBoundaryLenExpr(MapleAllocator &allocator, ASTDecl &ptrDe const std::function &getLenExprFromStringLiteral, ASTExpr *lenExpr, bool isSize) { if (!qualType->isPointerType()) { - FE_ERR(kLncErr, "%s:%d error: The variable modified by the boundary attribute should be a pointer type", - FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The variable modified by the boundary attribute should be a pointer type"); return; } // Check lenExpr kind from: length stringLiteral or constant value/var expression @@ -730,9 +744,7 @@ void ASTParser::ProcessBoundaryLenExpr(MapleAllocator &allocator, ASTDecl &ptrDe return; } } else if (lenExpr->GetType() == nullptr || !FEUtils::IsInteger(lenExpr->GetType()->GetPrimType())) { - FE_ERR(kLncErr, "%s:%d error: The boundary length expr is not an integer type", - FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The boundary length expr is not an integer type"); return; } if (isSize) { @@ -743,12 +755,28 @@ void ASTParser::ProcessBoundaryLenExpr(MapleAllocator &allocator, ASTDecl &ptrDe if (pointedType->GetPrimType() == PTY_f64) { lenSize = 8; // 8 is f64 byte num, because now f128 also cvt to f64 } - lenExpr = GetAddrShiftExpr(allocator, lenExpr, lenSize); + lenExpr = GetAddrShiftExpr(allocator, *lenExpr, lenSize); } ptrDecl.SetBoundaryLenExpr(lenExpr); 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, lenExpr.GetSrcLoc(), "The boundary length expr containing statement is invalid"); + break; + } + } +} + void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, unsigned int idx, ASTFunc &astFunc, ASTExpr *lenExpr, bool isSize) { ASTDecl *ptrDecl = nullptr; @@ -760,13 +788,12 @@ void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const cl ptrDecl = astFunc.GetParamDecls()[idx]; qualType = funcDecl.getParamDecl(idx)->getType(); } else { - FE_ERR(kLncErr, "%s:%d error: The parameter annotated boundary attr [the %s argument] is not found" - "in the function [%s]", FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum(), ENCChecker::GetNthStr(idx).c_str(), astFunc.GetName().c_str()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The parameter annotated boundary attr [the %s argument] is not found" + "in the function [%s]", ENCChecker::GetNthStr(idx).c_str(), astFunc.GetName().c_str()); return; } // parameter stringLiteral -> real parameter decl - auto getLenExprFromStringLiteral = [&]() -> ASTExpr* { + auto getLenExprFromStringLiteral = [&allocator, &astFunc, lenExpr, ptrDecl]() -> ASTExpr* { ASTStringLiteral *strExpr = static_cast(lenExpr); std::string lenName(strExpr->GetCodeUnits().begin(), strExpr->GetCodeUnits().end()); for (size_t i = 0; i < astFunc.GetParamDecls().size(); ++i) { @@ -775,9 +802,8 @@ void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const cl } MIRType *lenType = astFunc.GetParamDecls()[i]->GetTypeDesc().front(); if (lenType == nullptr || !FEUtils::IsInteger(lenType->GetPrimType())) { - FE_ERR(kLncErr, "%s:%d error: The parameter [%s] specified as boundary length var is not an integer type " - "in the function [%s]", FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum(), lenName.c_str(), astFunc.GetName().c_str()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The parameter [%s] specified as boundary length var is not an integer " + "type in the function [%s]", lenName.c_str(), astFunc.GetName().c_str()); return nullptr; } ASTDeclRefExpr *lenRefExpr = ASTDeclsBuilder::ASTExprBuilder(allocator); @@ -786,9 +812,8 @@ void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const cl ptrDecl->SetBoundaryLenParamIdx(static_cast(i)); return lenRefExpr; } - FE_ERR(kLncErr, "%s:%d error: The parameter [%s] specified as boundary length var is not found " - "in the function [%s]", FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum(), lenName.c_str(), astFunc.GetName().c_str()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The parameter [%s] specified as boundary length var is not found " + "in the function [%s]", lenName.c_str(), astFunc.GetName().c_str()); return nullptr; }; ProcessBoundaryLenExpr(allocator, *ptrDecl, qualType, getLenExprFromStringLiteral, lenExpr, isSize); @@ -797,14 +822,14 @@ void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const cl void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const clang::FunctionDecl &funcDecl, unsigned int idx, ASTFunc &astFunc, unsigned int lenIdx, bool isSize) { if (lenIdx > astFunc.GetParamDecls().size()) { - FE_ERR(kLncErr, "error: The %s parameter specified as boundary length var is not found " + FE_ERR(kLncErr, astFunc.GetSrcLoc(), "The %s parameter specified as boundary length var is not found " "in the function [%s]", ENCChecker::GetNthStr(lenIdx).c_str(), astFunc.GetName().c_str()); return; } ASTDecl *lenDecl = astFunc.GetParamDecls()[lenIdx]; MIRType *lenType = lenDecl->GetTypeDesc().front(); if (lenType == nullptr || !FEUtils::IsInteger(lenType->GetPrimType())) { - FE_ERR(kLncErr, "error: The %s parameter specified as boundary length var is not an integer type " + FE_ERR(kLncErr, astFunc.GetSrcLoc(), "The %s parameter specified as boundary length var is not an integer type " "in the function [%s]", ENCChecker::GetNthStr(lenIdx).c_str(), astFunc.GetName().c_str()); return; } @@ -818,7 +843,7 @@ void ASTParser::ProcessBoundaryLenExprInFunc(MapleAllocator &allocator, const cl } else if (idx < astFunc.GetParamDecls().size()) { ptrDecl = astFunc.GetParamDecls()[idx]; } else { - FE_ERR(kLncErr, "error: The %s parameter annotated boundary attr is not found in the function [%s]", + FE_ERR(kLncErr, astFunc.GetSrcLoc(), "The %s parameter annotated boundary attr is not found in the function [%s]", ENCChecker::GetNthStr(idx).c_str(), astFunc.GetName().c_str()); return; } @@ -840,10 +865,8 @@ void ASTParser::ProcessBoundaryLenExprInVar(MapleAllocator &allocator, ASTDecl & void ASTParser::ProcessBoundaryLenExprInVar(MapleAllocator &allocator, ASTDecl &ptrDecl, const clang::QualType &qualType, ASTExpr *lenExpr, bool isSize) { // The StringLiteral is not allowed to use as boundary length of var - auto getLenExprFromStringLiteral = [&]() -> ASTExpr* { - FE_ERR(kLncErr, "%s:%d error: The StringLiteral is not allowed to use as boundary length of var", - FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum()); + auto getLenExprFromStringLiteral = [lenExpr]() -> ASTExpr* { + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The StringLiteral is not allowed to use as boundary length of var"); return nullptr; }; ProcessBoundaryLenExpr(allocator, ptrDecl, qualType, getLenExprFromStringLiteral, lenExpr, isSize); @@ -852,7 +875,7 @@ void ASTParser::ProcessBoundaryLenExprInVar(MapleAllocator &allocator, ASTDecl & void ASTParser::ProcessBoundaryLenExprInField(MapleAllocator &allocator, ASTDecl &ptrDecl, const ASTStruct &structDecl, const clang::QualType &qualType, ASTExpr *lenExpr, bool isSize) { // boundary length stringLiteral in field -> real field decl - auto getLenExprFromStringLiteral = [&]() -> ASTExpr* { + auto getLenExprFromStringLiteral = [&allocator, &structDecl, lenExpr]() -> ASTExpr* { ASTStringLiteral *strExpr = static_cast(lenExpr); std::string lenName(strExpr->GetCodeUnits().begin(), strExpr->GetCodeUnits().end()); for (ASTField *fieldDecl: structDecl.GetFields()) { @@ -861,9 +884,8 @@ void ASTParser::ProcessBoundaryLenExprInField(MapleAllocator &allocator, ASTDecl } MIRType *lenType = fieldDecl->GetTypeDesc().front(); if (lenType == nullptr || !FEUtils::IsInteger(lenType->GetPrimType())) { - FE_ERR(kLncErr, "%s:%d error: The field [%s] specified as boundary length var is not an integer type " - "in the struct [%s]", FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum(), lenName.c_str(), structDecl.GetName().c_str()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The field [%s] specified as boundary length var is not an integer type " + "in the struct [%s]", lenName.c_str(), structDecl.GetName().c_str()); return nullptr; } fieldDecl->SetAttr(GENATTR_final_boundary_size); @@ -872,9 +894,8 @@ void ASTParser::ProcessBoundaryLenExprInField(MapleAllocator &allocator, ASTDecl lenRefExpr->SetType(fieldDecl->GetTypeDesc().front()); return lenRefExpr; } - FE_ERR(kLncErr, "%s:%d error: The StringLiteral [%s] as boundary length var is not found " - "in the struct [%s]", FEManager::GetModule().GetFileNameFromFileNum(lenExpr->GetSrcFileIdx()).c_str(), - lenExpr->GetSrcFileLineNum(), lenName.c_str(), structDecl.GetName().c_str()); + FE_ERR(kLncErr, lenExpr->GetSrcLoc(), "The StringLiteral [%s] as boundary length var is not found " + "in the struct [%s]", lenName.c_str(), structDecl.GetName().c_str()); return nullptr; }; ProcessBoundaryLenExpr(allocator, ptrDecl, qualType, getLenExprFromStringLiteral, lenExpr, isSize); @@ -953,7 +974,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 +995,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) { @@ -999,21 +1020,21 @@ MIRConst *ENCChecker::GetMIRConstFromExpr(const UniqueFEIRExpr &expr) { } else if (expr->GetKind() == kExprAddrofArray) { FEIRExprAddrofArray *arrExpr = static_cast(expr.get()); MIRConst *cst = GetMIRConstFromExpr(arrExpr->GetExprArray()); - if (cst != nullptr && cst->GetKind() == kConstAggConst) { - for (const auto & idxExpr : arrExpr->GetExprIndexs()) { - MIRAggConst *aggConst = static_cast(cst); - if (idxExpr->GetKind() != kExprConst) { - return nullptr; - } - uint64 idx = static_cast(idxExpr.get())->GetValue().u64; - if (idx >= aggConst->GetConstVec().size()) { - return nullptr; - } - cst = aggConst->GetConstVecItem(idx); + if (cst == nullptr || cst->GetKind() != kConstAggConst) { + return nullptr; + } + for (const auto &idxExpr : arrExpr->GetExprIndexs()) { + MIRAggConst *aggConst = static_cast(cst); + if (idxExpr->GetKind() != kExprConst) { + return nullptr; } - return cst; + uint64 idx = static_cast(idxExpr.get())->GetValue().u64; + if (idx >= aggConst->GetConstVec().size()) { + return nullptr; + } + cst = aggConst->GetConstVecItem(idx); } - return nullptr; + return cst; } return nullptr; } @@ -1047,15 +1068,13 @@ void ENCChecker::AssignBoundaryVar(MIRBuilder &mirBuilder, const UniqueFEIRExpr auto lIt = curFEFunction.GetBoundaryMap().find(dstExpr->Hash()); if (lIt != curFEFunction.GetBoundaryMap().end()) { // The boundary var exists on the l-value lBoundaryVarStIdx = lIt->second; - } else { - if (lRealLenExpr != nullptr) { // init boundary in func body if a field/global var l-value with boundary attr - std::list stmts; - lBoundaryVarStIdx = InitBoundaryVar(*curFunction, dstExpr, lRealLenExpr->Clone(), stmts); - for (const auto &stmt : stmts) { - std::list stmtNodes = stmt->GenMIRStmts(mirBuilder); - for (auto stmtNode : stmtNodes) { - curFunction->GetBody()->InsertFirst(stmtNode); - } + } else if (lRealLenExpr != nullptr) { // init boundary in func body if a field/global var l-value with boundary attr + std::list stmts; + lBoundaryVarStIdx = InitBoundaryVar(*curFunction, dstExpr, lRealLenExpr->Clone(), stmts); + for (const auto &stmt : stmts) { + std::list stmtNodes = stmt->GenMIRStmts(mirBuilder); + for (auto stmtNode : stmtNodes) { + curFunction->GetBody()->InsertFirst(stmtNode); } } } @@ -1158,6 +1177,17 @@ std::pair ENCChecker::InsertBoundaryVar(MIRBuilder &mirBuilder, co return boundaryVarStIdx; } +void ENCChecker::InsertBoundaryVar(const ASTDecl &ptrDecl, std::list &stmts) { + if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || + ptrDecl.GetBoundaryLenExpr() == nullptr) { + return; + } + // GetCurrentFunction need to be optimized when parallel features + MIRFunction *curFunction = FEManager::GetMIRBuilder().GetCurrentFunctionNotNull(); + UniqueFEIRExpr lenFEExpr = ptrDecl.GetBoundaryLenExpr()->Emit2FEExpr(stmts); + ENCChecker::InitBoundaryVar(*curFunction, ptrDecl, std::move(lenFEExpr), stmts); +} + std::string ENCChecker::GetBoundaryName(const UniqueFEIRExpr &expr) { std::string boundaryName; if (expr == 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()) && @@ -1393,7 +1424,8 @@ UniqueFEIRExpr ENCChecker::GetRealBoundaryLenExprInFuncByIndex(const TypeAttrs & CHECK_FATAL(type.IsMIRPtrType(), "Must be ptr type!"); size_t lenSize = static_cast(type).GetPointedType()->GetSize(); MapleAllocator &allocator = FEManager::GetModule().GetMPAllocator(); - astLenExpr = ASTParser::GetAddrShiftExpr(allocator, astCallExpr.GetArgsExpr()[idx], static_cast(lenSize)); + astLenExpr = ASTParser::GetAddrShiftExpr(allocator, *(astCallExpr.GetArgsExpr()[idx]), + static_cast(lenSize)); } std::list nullStmts; return astLenExpr->Emit2FEExpr(nullStmts); @@ -1432,6 +1464,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 +1587,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()); - stmts.insert(--stmts.end(), std::move(stmt)); + stmt->SetSrcLoc(stmts.back()->GetSrcLoc()); + stmts.insert(--stmts.cend(), 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 +1610,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 +1618,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 +1666,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 +1721,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,9 +1750,9 @@ 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()); + ans.insert(ans.cend(), stmtnodes.cbegin(), stmtnodes.cend()); } } ENCChecker::AssignBoundaryVar(mirBuilder, dstExpr, expr, lenExpr, ans); @@ -1721,7 +1763,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,16 +1781,16 @@ 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()); + ans.insert(ans.cend(), stmtnodes.cbegin(), stmtnodes.cend()); } } ENCChecker::AssignBoundaryVar(mirBuilder, dstExpr, baseExpr, lenExpr, ans); } 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; } @@ -1762,24 +1804,22 @@ void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const Uniqu if (fieldID == 0) { MIRSymbol *dstSym = var->GenerateMIRSymbol(mirBuilder); 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); + FE_WARN(kLncWarn, loc, "this var specified as the global or field boundary length is " + "assigned or token address. [Use __Unsafe__ to eliminate the warning]"); } } else { FieldID tmpID = fieldID; MIRStructType *structType = static_cast(var->GetType()->GenerateMIRTypeAuto()); FieldPair fieldPair = structType->TraverseToFieldRef(tmpID); 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); + FE_WARN(kLncWarn, loc, "this field specified as the global or field boundary length is " + "assigned or token address. [Use __Unsafe__ to eliminate the warning]"); } } } 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; @@ -1795,23 +1835,21 @@ void ENCChecker::CheckBoundaryLenFinalAssign(MIRBuilder &mirBuilder, const Uniqu FieldID tmpID = fieldID; FieldPair fieldPair = static_cast(baseType)->TraverseToFieldRef(tmpID); 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); + FE_WARN(kLncWarn, loc, "this field specified as the global or field boundary length is " + "assigned or token address. [Use __Unsafe__ to eliminate the warning]"); } } -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); } } @@ -1858,30 +1896,7 @@ MapleVector ENCChecker::ReplaceBoundaryChecking(MIRBuilder &mirBuilde } rightNode = rightExpr->GenMIRNode(mirBuilder); } else { - if (ENCChecker::IsUnsafeRegion(mirBuilder)) { - return args; - } - if (op == OP_callassertle) { - auto callAssert = static_cast(stmt); - FE_ERR(kLncErr, "%s:%d error: boundaryless pointer passed to %s that requires a boundary pointer for the %s" - " argument", FEManager::GetModule().GetFileNameFromFileNum(stmt->GetSrcFileIdx()).c_str(), - stmt->GetSrcFileLineNum(), callAssert->GetFuncName().c_str(), - ENCChecker::GetNthStr(callAssert->GetParamIndex()).c_str()); - } else if (op == OP_returnassertle) { - if (curFunction->GetName().compare(kBoundsBuiltFunc) != 0) { - FE_ERR(kLncErr, "%s:%d error: boundaryless pointer returned from %s that requires a boundary pointer", - FEManager::GetModule().GetFileNameFromFileNum(stmt->GetSrcFileIdx()).c_str(), - stmt->GetSrcFileLineNum(), curFunction->GetName().c_str()); - } - } else if (op == OP_assignassertle) { - FE_ERR(kLncErr, "%s:%d error: r-value requires a boundary pointer", - FEManager::GetModule().GetFileNameFromFileNum(stmt->GetSrcFileIdx()).c_str(), stmt->GetSrcFileLineNum()); - } else if (ENCChecker::IsSafeRegion(mirBuilder) && - (op == OP_calcassertge || - (op == OP_assertge && static_cast(stmt)->IsComputable()))) { - FE_ERR(kLncErr, "%s:%d error: calculation with pointer requires bounds in safe region", - FEManager::GetModule().GetFileNameFromFileNum(stmt->GetSrcFileIdx()).c_str(), stmt->GetSrcFileLineNum()); - } + ReplaceBoundaryErr(mirBuilder, stmt); return args; } } @@ -1892,15 +1907,38 @@ MapleVector ENCChecker::ReplaceBoundaryChecking(MIRBuilder &mirBuilde return args; } +void ENCChecker::ReplaceBoundaryErr(const MIRBuilder &mirBuilder, const FEIRStmtNary *stmt) { + if (ENCChecker::IsUnsafeRegion(mirBuilder)) { + return; + } + Opcode op = stmt->GetOP(); + if (op == OP_callassertle) { + auto callAssert = static_cast(stmt); + FE_ERR(kLncErr, stmt->GetSrcLoc(), "boundaryless pointer passed to %s that requires a boundary pointer for " + "the %s argument", callAssert->GetFuncName().c_str(), + ENCChecker::GetNthStr(callAssert->GetParamIndex()).c_str()); + } else if (op == OP_returnassertle) { + MIRFunction *curFunction = mirBuilder.GetCurrentFunctionNotNull(); + if (curFunction->GetName() != kBoundsBuiltFunc) { + FE_ERR(kLncErr, stmt->GetSrcLoc(), "boundaryless pointer returned from %s that requires a boundary pointer", + curFunction->GetName().c_str()); + } + } else if (op == OP_assignassertle) { + FE_ERR(kLncErr, stmt->GetSrcLoc(), "r-value requires a boundary pointer"); + } else if (ENCChecker::IsSafeRegion(mirBuilder) && + (op == OP_calcassertge || + (op == OP_assertge && static_cast(stmt)->IsComputable()))) { + FE_ERR(kLncErr, stmt->GetSrcLoc(), "calculation with pointer requires bounds in safe region"); + } +} + bool ASTArraySubscriptExpr::InsertBoundaryChecking(std::list &stmts, UniqueFEIRExpr indexExpr, UniqueFEIRExpr baseAddrFEExpr) const { if (!FEOptions::GetInstance().IsBoundaryCheckDynamic()) { 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(), *mirType, std::move(realLenExpr), stmts); } bool ENCChecker::IsSameBoundary(const AttrBoundary &arg1, const AttrBoundary &arg2) { @@ -2100,7 +2138,10 @@ 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) { + if (!FEOptions::GetInstance().IsBoundaryCheckDynamic() || !srcExpr->IsEnhancedChecking()) { + return; + } const MIRFuncType *funcType = FEUtils::GetFuncPtrType(dstType); if (funcType == nullptr) { return; @@ -2118,13 +2159,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, - PrintParamIdx(errIdxs).c_str()); + FE_ERR(kLncErr, loc, "function pointer and target function's boundary attributes are mismatched " + "for the %s argument", 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); + FE_ERR(kLncErr, loc, "function pointer and target function's boundary attributes are mismatched " + "for the return value"); } } const MIRFuncType *srcFuncType = FEUtils::GetFuncPtrType(*srcExpr->GetType()->GenerateMIRTypeAuto()); @@ -2137,12 +2177,11 @@ 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()); + FE_ERR(kLncErr, loc, "function pointer's boundary attributes are mismatched for the %s argument", + 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); + FE_ERR(kLncErr, loc, "function pointer's boundary attributes are mismatched for the return value"); } } } @@ -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_config_parallel.cpp b/src/hir2mpl/common/src/fe_config_parallel.cpp index 889adda306f987ab124843def932a89249401633..980373dda4920b96f39474ce315c371d8bc3dbe1 100644 --- a/src/hir2mpl/common/src/fe_config_parallel.cpp +++ b/src/hir2mpl/common/src/fe_config_parallel.cpp @@ -13,7 +13,6 @@ * See the Mulan PSL v2 for more details. */ #include "fe_config_parallel.h" -#include "mpl_logging.h" namespace maple { FEConfigParallel FEConfigParallel::instance; diff --git a/src/hir2mpl/common/src/fe_function.cpp b/src/hir2mpl/common/src/fe_function.cpp index 22e4a3a8921bc1fc7a13a17397e60d4ca40ec685..2e55bb4b07110de0ee7fc69a394272a4d94da0a0 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) { @@ -261,14 +208,14 @@ std::string FEFunction::GetGeneralFuncName() const { return mirFunction.GetName(); } -void FEFunction::PhaseTimerStart(FETimerNS &timer) { +void FEFunction::PhaseTimerStart(FETimerNS &timer) const { if (!FEOptions::GetInstance().IsDumpPhaseTime()) { return; } timer.Start(); } -void FEFunction::PhaseTimerStopAndDump(FETimerNS &timer, const std::string &label) { +void FEFunction::PhaseTimerStopAndDump(FETimerNS &timer, const std::string &label) const { if (!FEOptions::GetInstance().IsDumpPhaseTime()) { return; } @@ -279,14 +226,12 @@ void FEFunction::PhaseTimerStopAndDump(FETimerNS &timer, const std::string &labe bool FEFunction::UpdateFormal(const std::string &phaseName) { phaseResult.RegisterPhaseNameAndStart(phaseName); HIR2MPL_PARALLEL_FORBIDDEN(); - uint32 idx = 0; mirFunction.ClearFormals(); FEManager::GetMIRBuilder().SetCurrentFunction(mirFunction); for (const std::unique_ptr &argVar : argVarList) { MIRSymbol *sym = argVar->GenerateMIRSymbol(FEManager::GetMIRBuilder()); sym->SetStorageClass(kScFormal); mirFunction.AddArgument(sym); - idx++; } return phaseResult.Finish(); } @@ -399,7 +344,7 @@ bool FEFunction::SetupFEIRStmtJavaTry(const std::string &phaseName) { FEIRStmtPesudoJavaTry *stmtJavaTry = static_cast(stmt); for (uint32 labelIdx : stmtJavaTry->GetCatchLabelIdxVec()) { auto it = mapLabelStmt.find(labelIdx); - CHECK_FATAL(it != mapLabelStmt.end(), "label is not found"); + CHECK_FATAL(it != mapLabelStmt.cend(), "label is not found"); stmtJavaTry->AddCatchTarget(*(it->second)); } } @@ -433,7 +378,7 @@ bool FEFunction::SetupFEIRStmtBranch(const std::string &phaseName) { bool FEFunction::SetupFEIRStmtGoto(FEIRStmtGoto &stmt) { auto it = mapLabelStmt.find(stmt.GetLabelIdx()); - if (it == mapLabelStmt.end()) { + if (it == mapLabelStmt.cend()) { ERR(kLncErr, "target not found for stmt goto"); return false; } @@ -444,7 +389,7 @@ bool FEFunction::SetupFEIRStmtGoto(FEIRStmtGoto &stmt) { bool FEFunction::SetupFEIRStmtSwitch(FEIRStmtSwitch &stmt) { // default target auto itDefault = mapLabelStmt.find(stmt.GetDefaultLabelIdx()); - if (itDefault == mapLabelStmt.end()) { + if (itDefault == mapLabelStmt.cend()) { ERR(kLncErr, "target not found for stmt goto"); return false; } @@ -453,7 +398,7 @@ bool FEFunction::SetupFEIRStmtSwitch(FEIRStmtSwitch &stmt) { // value targets for (const auto &itItem : stmt.GetMapValueLabelIdx()) { auto itTarget = mapLabelStmt.find(itItem.second); - if (itTarget == mapLabelStmt.end()) { + if (itTarget == mapLabelStmt.cend()) { ERR(kLncErr, "target not found for stmt goto"); return false; } @@ -485,7 +430,7 @@ bool FEFunction::UpdateRegNum2This(const std::string &phaseName) { return success; } -void FEFunction::OutputStmts() { +void FEFunction::OutputStmts() const { FELinkListNode *node = feirStmtHead->GetNext(); while (node != feirStmtTail) { FEIRStmt *currStmt = static_cast(node); @@ -538,7 +483,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 +511,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; @@ -612,7 +555,7 @@ FEIRBB &FEFunction::GetFEIRBBByStmt(const FEIRStmt &stmt) { return *(it->second); } -bool FEFunction::CheckBBsStmtNoAuxTail(const FEIRBB &bb) { +bool FEFunction::CheckBBsStmtNoAuxTail(const FEIRBB &bb) const { bool bbHasStmtNoAuxTail = (bb.GetStmtNoAuxTail() != nullptr); CHECK_FATAL(bbHasStmtNoAuxTail, "Error accured in BuildFEIRBB phase, bb.GetStmtNoAuxTail() should not be nullptr"); return true; @@ -845,4 +788,69 @@ 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(scopeID++); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRScope *mirScope = mirFunction.GetScope(); + mirScope->SetRange(startOfScope, endOfScope); + feirScope->SetMIRScope(mirScope); + } + scopeStack.push_front(std::move(feirScope)); +} + +void FEFunction::PushStmtScope(const SrcPosition &startOfScope, const SrcPosition &endOfScope, bool isControllScope) { + UniqueFEIRScope feirScope = std::make_unique(scopeID++); + if (FEOptions::GetInstance().IsDbgFriendly()) { + MIRScope *parentMIRScope = GetTopMIRScope(); + CHECK_NULL_FATAL(parentMIRScope); + MIRScope *mirScope = mirFunction.GetModule()->GetMemPool()->New(mirFunction.GetModule()); + mirScope->SetRange(startOfScope, endOfScope); + (void)parentMIRScope->AddScope(mirScope); + feirScope->SetMIRScope(mirScope); + } + feirScope->SetIsControllScope(isControllScope); + scopeStack.push_front(std::move(feirScope)); +} + +void FEFunction::PushStmtScope(bool isControllScope) { + UniqueFEIRScope feirScope = std::make_unique(scopeID++, isControllScope); + scopeStack.push_front(std::move(feirScope)); +} + +FEIRScope *FEFunction::GetTopFEIRScopePtr() const { + if (!scopeStack.empty()) { + return scopeStack.front().get(); + } + CHECK_FATAL(false, "scope stack is empty"); + return nullptr; +} + +MIRScope *FEFunction::GetTopMIRScope() const { + if (scopeStack.empty()) { + CHECK_FATAL(false, "scope stack is empty"); + return nullptr; + } + for (const auto &feirScope : scopeStack) { + if (feirScope->GetMIRScope() != nullptr) { + return feirScope->GetMIRScope(); + } + } + return nullptr; +} + +UniqueFEIRScope FEFunction::PopTopScope() { + if (!scopeStack.empty()) { + UniqueFEIRScope scope = std::move(scopeStack.front()); + scopeStack.pop_front(); + return scope; + } + CHECK_FATAL(false, "scope stack is empty"); + return nullptr; +} + +void FEFunction::AddVLACleanupStmts(std::list &stmts) { + (void)stmts; + CHECK_FATAL(false, "AddVLACleanupStmts only support astfunction"); +}; } // namespace maple diff --git a/src/hir2mpl/common/src/fe_function_phase_result.cpp b/src/hir2mpl/common/src/fe_function_phase_result.cpp index bb11b77f15f6cc0680034cc8c9dbb687980990bb..16ce9e51bbf2048c9a7733a635e0cbb49b69feee 100644 --- a/src/hir2mpl/common/src/fe_function_phase_result.cpp +++ b/src/hir2mpl/common/src/fe_function_phase_result.cpp @@ -34,7 +34,7 @@ void FEFunctionPhaseResult::Combine(const FEFunctionPhaseResult &result) { void FEFunctionPhaseResult::Dump() { for (const std::string &name :phaseNames) { auto it = phaseTimes.find(name); - CHECK_FATAL(it != phaseTimes.end(), "phase time is undefined for %s", name.c_str()); + CHECK_FATAL(it != phaseTimes.cend(), "phase time is undefined for %s", name.c_str()); INFO(kLncInfo, "[PhaseTime] %s: %lld ns", name.c_str(), it->second); } } @@ -42,7 +42,7 @@ void FEFunctionPhaseResult::Dump() { void FEFunctionPhaseResult::DumpMS() { for (const std::string &name :phaseNames) { auto it = phaseTimes.find(name); - CHECK_FATAL(it != phaseTimes.end(), "phase time is undefined for %s", name.c_str()); + CHECK_FATAL(it != phaseTimes.cend(), "phase time is undefined for %s", name.c_str()); INFO(kLncInfo, "[PhaseTime] %s: %.2lf ms", name.c_str(), it->second / 1000000.0); // 1ms = 1000000 ns } } diff --git a/src/hir2mpl/common/src/fe_input_helper.cpp b/src/hir2mpl/common/src/fe_input_helper.cpp index 71d21bb6534058abc0da97975d4d9508b31e2b4c..2dcefcd3a12d6aaac05b3e4ef506e7b2adc22b4a 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"; @@ -300,7 +302,7 @@ void FEInputStructHelper::ProcessExtraFields() { } } // insert at the beginning - structType->GetFields().insert(structType->GetFields().begin(), + structType->GetFields().insert(structType->GetFields().cbegin(), FieldPair(fieldStrIdx, TyIdxFieldAttrPair(fieldType->GetTypeIndex(), typeAttrs))); } } diff --git a/src/hir2mpl/common/src/fe_java_string_manager.cpp b/src/hir2mpl/common/src/fe_java_string_manager.cpp index 9a1f5c6817a5fcd9edb7bcd10f49713a88cd62e5..666404ce1e790ed9be4269bf50c25cba749a7146 100644 --- a/src/hir2mpl/common/src/fe_java_string_manager.cpp +++ b/src/hir2mpl/common/src/fe_java_string_manager.cpp @@ -197,7 +197,7 @@ MIRAggConst *FEJavaStringManager::CreateByteArrayConst(const std::u16string &str #endif // JAVA_OBJ_IN_MFILE // @count - uint32 strCount = strU16.length() ? static_cast((strU16.length() * 2) | compressible) : 0; + uint32 strCount = (strU16.length() > 0) ? static_cast((strU16.length() * 2) | compressible) : 0; AddDataIntoByteArray(*newconst, *mp, currData, strCount, *uInt64); // @hash 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..7f879fc929f5721e2be5ab6a3f3b5215d67d3897 100644 --- a/src/hir2mpl/common/src/fe_type_manager.cpp +++ b/src/hir2mpl/common/src/fe_type_manager.cpp @@ -80,7 +80,17 @@ FETypeManager::~FETypeManager() { funcMCCStaticFieldSetObject = nullptr; } +void FETypeManager::ReleaseMIRFuncCodeMempool(std::unordered_map &map) { + for (auto it = map.begin(); it != map.end(); ++it) { + it->second->ReleaseCodeMemory(); + } +} + void FETypeManager::ReleaseMemPool() { + ReleaseMIRFuncCodeMempool(nameFuncMap); + ReleaseMIRFuncCodeMempool(nameStaticFuncMap); + ReleaseMIRFuncCodeMempool(mpltNameFuncMap); + ReleaseMIRFuncCodeMempool(mpltNameStaticFuncMap); FEUtils::DeleteMempoolPtr(mp); } @@ -121,22 +131,23 @@ void FETypeManager::UpdateStructNameTypeMapFromTypeTable(const std::string &mplt bool sameNameUseLastest = sameNamePolicy.IsUseLastest(); GStrIdx mpltNameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(mpltName); for (MIRType *type : GlobalTables::GetTypeTable().GetTypeTable()) { - 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) { - // type is existed - structSameNameSrcList.push_back(std::make_pair(structType->GetNameStrIdx(), - structNameSrcMap[structType->GetNameStrIdx()])); - structSameNameSrcList.push_back(std::make_pair(structType->GetNameStrIdx(), mpltNameIdx)); - if (sameNameUseLastest) { - structNameTypeMap[structType->GetNameStrIdx()] = std::make_pair(structType, flag); - structNameSrcMap[structType->GetNameStrIdx()] = mpltNameIdx; - } - } else { - // type is not existed + if ((type == nullptr) || !IsStructType(*type)) { + continue; + } + MIRStructType *structType = static_cast(type); + auto it = structNameTypeMap.insert(std::make_pair(structType->GetNameStrIdx(), std::make_pair(structType, flag))); + if (!it.second) { + // type is existed + structSameNameSrcList.push_back(std::make_pair(structType->GetNameStrIdx(), + structNameSrcMap[structType->GetNameStrIdx()])); + structSameNameSrcList.push_back(std::make_pair(structType->GetNameStrIdx(), mpltNameIdx)); + if (sameNameUseLastest) { + structNameTypeMap[structType->GetNameStrIdx()] = std::make_pair(structType, flag); structNameSrcMap[structType->GetNameStrIdx()] = mpltNameIdx; } + } else { + // type is not existed + structNameSrcMap[structType->GetNameStrIdx()] = mpltNameIdx; } } } @@ -213,6 +224,76 @@ MIRStructType *FETypeManager::GetOrCreateStructType(const std::string &name) { return structType; } +MIRTypeByName *FETypeManager::CreateTypeByNameType(const std::string &name) { + GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + MIRTypeByName nameType(strIdx); + TyIdx tyIdx = GlobalTables::GetTypeTable().GetOrCreateMIRType(&nameType); + MIRTypeByName *type = static_cast(GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx.GetIdx())); + nameTypeMap[strIdx] = type; + return type; +} + +MIRTypeByName *FETypeManager::GetOrCreateTypeByNameType(const std::string &name) { + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + const auto &it = nameTypeMap.find(nameIdx); + if (it != nameTypeMap.cend()) { + return it->second; + } + MIRTypeByName *nameType = CreateTypeByNameType(name); + return nameType; +} + +MIRTypeByName *FETypeManager::GetTypeByNameType(const std::string &name) { + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + return GetTypeByNameType(nameIdx); +} + +MIRTypeByName *FETypeManager::GetTypeByNameType(const GStrIdx &nameIdx) { + const auto &it = nameTypeMap.find(nameIdx); + if (it != nameTypeMap.cend()) { + return it->second; + } + return nullptr; +} + +MIRTypeByName *FETypeManager::CreateTypedef(const std::string &name, const MIRType &type) { + MIRTypeByName *typdefType = GetOrCreateTypeByNameType(name); + if (!module.GetScope()->GetTypeAlias()->Exist(typdefType->GetNameStrIdx())) { + module.GetScope()->SetTypeAliasMap(typdefType->GetNameStrIdx(), type.GetTypeIndex()); + } + return typdefType; +} + +MIREnum *FETypeManager::CreateEnum(const std::string &name, PrimType primType) { + GStrIdx strIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + MIREnum *enumType = new MIREnum(primType, strIdx); + enumNameMap[strIdx] = GlobalTables::GetEnumTable().enumTable.size(); + GlobalTables::GetEnumTable().enumTable.push_back(enumType); + return enumType; +} + +MIREnum *FETypeManager::GetOrCreateEnum(const std::string &name, PrimType primType) { + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + const auto &it = enumNameMap.find(nameIdx); + if (it != enumNameMap.cend()) { + CHECK_FATAL(it->second < GlobalTables::GetEnumTable().enumTable.size(), "enumTable out of bounds"); + MIREnum *enumType = GlobalTables::GetEnumTable().enumTable[it->second]; + return enumType; + } + MIREnum *enumType = CreateEnum(name, primType); + return enumType; +} + +size_t FETypeManager::GetEnumIdx(const std::string &name) { + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + const auto &it = enumNameMap.find(nameIdx); + if (it != enumNameMap.cend()) { + return it->second; + } + CHECK_FATAL(false, "The enum was not found, %s", name.c_str()); + return 0; +} + /* * create MIRStructType for complex number, e.g. * type $Complex|F second; - auto const &it = thisDexClassNameTypeIDMap.find(mplClassName); + const auto &thisDexClassNameTypeIDMap = itMap->second; + const auto &it = thisDexClassNameTypeIDMap.find(mplClassName); if (it != thisDexClassNameTypeIDMap.end()) { return it->second; } @@ -418,8 +499,8 @@ MIRType *FETypeManager::GetOrCreateArrayType(MIRType &elemType, uint8 dim, PrimT } } -MIRType *FETypeManager::GetOrCreateJArrayType(MIRType &elem, uint8 dim, PrimType ptyPtr) { - MIRType *type = &elem; +MIRType *FETypeManager::GetOrCreateJArrayType(MIRType &elemType, uint8 dim, PrimType ptyPtr) { + MIRType *type = &elemType; for (uint8 i = 0; i < dim; i++) { type = GlobalTables::GetTypeTable().GetOrCreateJarrayType(*type); CHECK_NULL_FATAL(type); @@ -437,27 +518,27 @@ void FETypeManager::AddClassToModule(const MIRStructType &structType) { } FEStructElemInfo *FETypeManager::RegisterStructFieldInfo( - const StructElemNameIdx &structElemNameIdx, MIRSrcLang argSrcLang, bool isStatic) { + const StructElemNameIdx &argStructElemNameIdx, MIRSrcLang argSrcLang, bool isStatic) { std::lock_guard lk(feTypeManagerMtx); - FEStructElemInfo *ptrInfo = GetStructElemInfo(structElemNameIdx.full); + FEStructElemInfo *ptrInfo = GetStructElemInfo(argStructElemNameIdx.full); if (ptrInfo != nullptr) { return ptrInfo; } - ptrInfo = allocator.GetMemPool()->New(allocator, structElemNameIdx, argSrcLang, isStatic); - CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(structElemNameIdx.full, ptrInfo)).second == true, + ptrInfo = allocator.GetMemPool()->New(allocator, argStructElemNameIdx, argSrcLang, isStatic); + CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(argStructElemNameIdx.full, ptrInfo)).second, "register struct elem info failed"); return ptrInfo; } FEStructElemInfo *FETypeManager::RegisterStructMethodInfo( - const StructElemNameIdx &structElemNameIdx, MIRSrcLang argSrcLang, bool isStatic) { + const StructElemNameIdx &argStructElemNameIdx, MIRSrcLang argSrcLang, bool isStatic) { std::lock_guard lk(feTypeManagerMtx); - FEStructElemInfo *ptrInfo = GetStructElemInfo(structElemNameIdx.full); + FEStructElemInfo *ptrInfo = GetStructElemInfo(argStructElemNameIdx.full); if (ptrInfo != nullptr) { return ptrInfo; } - ptrInfo = allocator.GetMemPool()->New(allocator, structElemNameIdx, argSrcLang, isStatic); - CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(structElemNameIdx.full, ptrInfo)).second == true, + ptrInfo = allocator.GetMemPool()->New(allocator, argStructElemNameIdx, argSrcLang, isStatic); + CHECK_FATAL(mapStructElemInfo.insert(std::make_pair(argStructElemNameIdx.full, ptrInfo)).second, "register struct elem info failed"); return ptrInfo; } @@ -470,7 +551,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 +562,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; @@ -727,10 +808,7 @@ MIRFunction *FETypeManager::GetMCCFunction(const std::string &funcName) const { MIRFunction *FETypeManager::GetMCCFunction(const GStrIdx &funcNameIdx) const { auto it = nameMCCFuncMap.find(funcNameIdx); - if (it == nameMCCFuncMap.end()) { - return nullptr; - } else { - return it->second; - } + CHECK_FATAL(it != nameMCCFuncMap.cend(), "The specified MCCFunc was not found"); + return it->second; } } // namespace maple diff --git a/src/hir2mpl/common/src/fe_utils.cpp b/src/hir2mpl/common/src/fe_utils.cpp index 772620e1c45cc9108da4a73c7b5d1d9e9bf90172..9b56ec667fea73d2903b51b3bb9027c6c82694cb 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. @@ -50,6 +50,8 @@ const std::string FEUtils::kMCCStaticFieldSetFloat = "MCC_StaticFieldSetFloat"; const std::string FEUtils::kMCCStaticFieldSetDouble = "MCC_StaticFieldSetDouble"; const std::string FEUtils::kMCCStaticFieldSetObject = "MCC_StaticFieldSetObject"; +const std::string FEUtils::kCondGoToStmtLabelNamePrefix = "shortCircuit_"; + std::vector FEUtils::Split(const std::string &str, char delim) { std::vector ans; std::stringstream ss; @@ -105,14 +107,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 +125,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 +193,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 +208,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) { @@ -229,7 +239,7 @@ bool FEUtils::TraverseToNamedField(MIRStructType &structType, const GStrIdx &nam FieldID FEUtils::GetStructFieldID(MIRStructType *base, const std::string &fieldName) { MIRStructType *type = base; - std::vector fieldNames = FEUtils::Split(fieldName, '.'); + std::vector fieldNames = FEUtils::Split(fieldName, '$'); std::reverse(fieldNames.begin(), fieldNames.end()); FieldID fieldID = 0; for (const auto &f: fieldNames) { @@ -320,10 +330,17 @@ MIRConst *FEUtils::CreateImplicitConst(MIRType *type) { if (type->IsStructType()) { auto structType = static_cast(type); FieldID fieldID = 0; - for (auto &f:structType->GetFields()) { + if (type->GetKind() == kTypeUnion) { fieldID++; + auto &f = structType->GetFields().front(); auto fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(f.second.first); aggConst->AddItem(CreateImplicitConst(fieldType), fieldID); + } else { + for (auto &f : structType->GetFields()) { + fieldID++; + auto fieldType = GlobalTables::GetTypeTable().GetTypeFromTyIdx(f.second.first); + aggConst->AddItem(CreateImplicitConst(fieldType), fieldID); + } } } else if (type->GetKind() == kTypeArray) { auto arrayType = static_cast(type); @@ -394,7 +411,7 @@ bool FEUtils::EndsWith(const std::string &value, const std::string &ending) { // in the search, curfieldid is being decremented until it reaches 1 MIRConst *FEUtils::TraverseToMIRConst(MIRAggConst *aggConst, const MIRStructType &structType, FieldID &fieldID) { - if (aggConst == nullptr || !aggConst->GetConstVec().size()) { + if (aggConst == nullptr || aggConst->GetConstVec().size() == 0) { return nullptr; } uint32 fieldIdx = 0; @@ -424,6 +441,54 @@ MIRConst *FEUtils::TraverseToMIRConst(MIRAggConst *aggConst, const MIRStructType return curConst; } +Loc FEUtils::GetSrcLocationForMIRSymbol(const MIRSymbol &symbol) { + return Loc(symbol.GetSrcPosition().FileNum(), symbol.GetSrcPosition().LineNum(), symbol.GetSrcPosition().Column()); +} + +void FEUtils::InitPrimTypeFuncNameIdxMap(std::map &primTypeFuncNameIdxMap) { + primTypeFuncNameIdxMap = { + { PTY_u1, GetMCCStaticFieldSetBoolIdx() }, + { PTY_i8, GetMCCStaticFieldSetByteIdx() }, + { PTY_i16, GetMCCStaticFieldSetShortIdx() }, + { PTY_u16, GetMCCStaticFieldSetCharIdx() }, + { PTY_i32, GetMCCStaticFieldSetIntIdx() }, + { PTY_i64, GetMCCStaticFieldSetLongIdx() }, + { PTY_f32, GetMCCStaticFieldSetFloatIdx() }, + { PTY_f64, GetMCCStaticFieldSetDoubleIdx() }, + { PTY_ref, GetMCCStaticFieldSetObjectIdx() }, + }; +} + +MIRAliasVars FEUtils::AddAlias(const GStrIdx &mplNameIdx, const MIRType *sourceType, const TypeAttrs &attrs, + bool isLocal) { + MIRAliasVars aliasVar; + aliasVar.mplStrIdx = mplNameIdx; + aliasVar.isLocal = isLocal; + aliasVar.attrs = attrs; + if (sourceType != nullptr) { + aliasVar.atk = kATKType; + aliasVar.index = sourceType->GetTypeIndex(); + } else { + CHECK_FATAL(false, "unknown source type of %s", + GlobalTables::GetStrTable().GetStringFromStrIdx(mplNameIdx).c_str()); + } + return aliasVar; +}; + +void FEUtils::AddAliasInMIRScope(MIRScope &scope, const std::string &srcVarName, const MIRSymbol &symbol, + const MIRType *sourceType) { + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(srcVarName); + MIRAliasVars aliasVar = FEUtils::AddAlias(symbol.GetNameStrIdx(), sourceType, symbol.GetAttrs(), symbol.IsLocal()); + scope.SetAliasVarMap(nameIdx, aliasVar); +}; + +SrcPosition FEUtils::CvtLoc2SrcPosition(const Loc &loc) { + SrcPosition srcPos; + srcPos.SetFileNum(static_cast(loc.fileIdx)); + srcPos.SetLineNum(loc.line); + srcPos.SetColumn(static_cast(loc.column)); + return srcPos; +} // ---------- FELinkListNode ---------- FELinkListNode::FELinkListNode() : prev(nullptr), next(nullptr) {} @@ -465,6 +530,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"; @@ -528,6 +603,10 @@ bool AstLoopUtil::IsBreakLabelsEmpty() const { return breakLabels.empty(); } +bool AstLoopUtil::IsNestContinueLabelsEmpty() const { + return nestContinueLabels.empty(); +} + void AstLoopUtil::PopCurrentBreak() { breakLabels.pop(); } @@ -536,11 +615,20 @@ void AstLoopUtil::PushContinue(std::string label) { continueLabels.push(std::make_pair(label, false)); } +void AstLoopUtil::PushNestContinue(std::string label) { + nestContinueLabels.push(std::make_pair(label, false)); +} + std::string AstLoopUtil::GetCurrentContinue() { continueLabels.top().second = true; return continueLabels.top().first; } +std::string AstLoopUtil::GetNestContinue() { + nestContinueLabels.top().second = true; + return nestContinueLabels.top().first; +} + bool AstLoopUtil::IsContinueLabelsEmpty() const { return continueLabels.empty(); } @@ -548,4 +636,8 @@ bool AstLoopUtil::IsContinueLabelsEmpty() const { void AstLoopUtil::PopCurrentContinue() { continueLabels.pop(); } + +void AstLoopUtil::PopNestContinue() { + nestContinueLabels.pop(); +} } // namespace maple diff --git a/src/hir2mpl/common/src/fe_utils_java.cpp b/src/hir2mpl/common/src/fe_utils_java.cpp index 4b363d9453e0697c49804f452aaa3fa188168759..5ac307d9701c84459fba7fb92187bffcb9838601 100644 --- a/src/hir2mpl/common/src/fe_utils_java.cpp +++ b/src/hir2mpl/common/src/fe_utils_java.cpp @@ -23,7 +23,7 @@ std::vector FEUtilJava::SolveMethodSignature(const std::string &sig if (pos1 == std::string::npos || pos2 == std::string::npos || pos1 > pos2) { CHECK_FATAL(false, "invalid method signature %s", signature.c_str()); } - std::string paramTypeNames = signature.substr(pos1 + 1, pos2 - pos1 - 1); + std::string paramTypeNames = signature.substr(pos1 + 1, (pos2 - pos1) - 1); std::string retTypeName = signature.substr(pos2 + 1); ans.push_back(retTypeName); while (paramTypeNames.length() > 0) { diff --git a/src/hir2mpl/common/src/feir_builder.cpp b/src/hir2mpl/common/src/feir_builder.cpp index fc9890620a63a6c9641e646df55a117a4189c8e8..c0e09da9961f41eeaa4a3cafde6483994d32bfc2 100644 --- a/src/hir2mpl/common/src/feir_builder.cpp +++ b/src/hir2mpl/common/src/feir_builder.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. @@ -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)); } @@ -364,6 +364,9 @@ UniqueFEIRExpr FEIRBuilder::CreateExprCastPrim(UniqueFEIRExpr srcExpr, PrimType // Handle the case separately for future optimization and deletion. // bool u1 if (srcExpr->GetPrimType() == PTY_u1) { + if (FEUtils::IsInteger(dstType)) { + return CreateExprCvtPrim(std::move(srcExpr), dstType); + } if (IsPrimitiveFloat(dstType)) { return CreateExprCvtPrim(std::move(srcExpr), PTY_u32, dstType); } @@ -375,7 +378,7 @@ UniqueFEIRExpr FEIRBuilder::CreateExprCastPrim(UniqueFEIRExpr srcExpr, PrimType } // Integer to Integer : 8, 16, 32, 64 bits Integer - auto createExprExt = [&]() { + auto createExprExt = [&srcExpr, &dstType]() { if (FEUtils::IsUnsignedInteger(dstType)) { return CreateExprZExt(std::move(srcExpr), dstType); } else { @@ -676,7 +679,6 @@ UniqueFEIRStmt FEIRBuilder::CreateStmtRetype(UniqueFEIRVar varDst, const UniqueF UniqueFEIRExpr expr = std::make_unique(varDst->GetType()->Clone(), OP_cvt, std::move(dreadExpr)); return FEIRBuilder::CreateStmtDAssign(std::move(varDst), std::move(expr), false); } - return nullptr; // Cannot retype, maybe introduced by redundant phi. } UniqueFEIRStmt FEIRBuilder::CreateStmtComment(const std::string &comment) { @@ -718,4 +720,54 @@ bool FEIRBuilder::IsZeroConstExpr(const std::unique_ptr &expr) { } return false; } + +UniqueFEIRStmt FEIRBuilder::CreateVLAStackRestore(const UniqueFEIRVar &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)); +} + +std::string FEIRBuilder::EmitVLACleanupStmts(FEFunction &feFunction, const std::string &labelName, const Loc &loc) { + std::list stmts; + bool isVlaCleanup = false; + std::string vlaLabelName = ""; + for (const auto &scope : feFunction.GetScopeStack()) { + if (scope->GetVLASavedStackVar() != nullptr) { + if (!isVlaCleanup) { + // label vla_cleanup + vlaLabelName = FEUtils::GetSequentialName("vla_cleanup."); + auto vlaLabelStmt = std::make_unique(vlaLabelName); + (void)stmts.emplace_back(std::move(vlaLabelStmt)); + } + // vla stack restore + isVlaCleanup = true; + auto stackRestoreStmt = scope->GenVLAStackRestoreStmt(); + (void)stmts.emplace_back(std::move(stackRestoreStmt)); + } + if (scope->IsControllScope()) { + break; + } + } + if (isVlaCleanup) { + // goto last label name + auto gotoStmt = FEIRBuilder::CreateStmtGoto(labelName); + stmts.emplace_back(std::move(gotoStmt)); + for (const auto &stmt : stmts) { + stmt->SetSrcLoc(loc); + } + feFunction.AddVLACleanupStmts(stmts); + } + return vlaLabelName; +} + +void FEIRBuilder::EmitVLACleanupStmts(const FEFunction &feFunction, std::list &stmts) { + for (const auto &scope : feFunction.GetScopeStack()) { + if (scope->GetVLASavedStackVar() != nullptr) { + auto stackRestoreStmt = scope->GenVLAStackRestoreStmt(); + (void)stmts.emplace_back(std::move(stackRestoreStmt)); + } + } +} } // namespace maple diff --git a/src/hir2mpl/common/src/feir_scope.cpp b/src/hir2mpl/common/src/feir_scope.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f21e59e2d4c84e1521d629f6f3d812ed41a90fda --- /dev/null +++ b/src/hir2mpl/common/src/feir_scope.cpp @@ -0,0 +1,32 @@ +/* + * 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 { +UniqueFEIRScope FEIRScope::Clone() const { + UniqueFEIRScope scope = std::make_unique(id, mirScope); + scope->SetIsControllScope(isControllScope); + if (vlaSavedStackVar != nullptr) { + scope->SetVLASavedStackVar(vlaSavedStackVar->Clone()); + } + return scope; +} + +UniqueFEIRStmt FEIRScope::GenVLAStackRestoreStmt() const { + CHECK_NULL_FATAL(vlaSavedStackVar); + return FEIRBuilder::CreateVLAStackRestore(vlaSavedStackVar->Clone()); +} +} 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..9a0bdcd0d37add26489b51034d1a6db181f58026 --- 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 ---------- @@ -164,12 +167,12 @@ std::set &FEIRStmtCheckPoint::CalcuDef(UniqueFEIRVar &use) { CHECK_NULL_FATAL(use); auto itLocal = localUD.find(&use); // search localUD - if (itLocal != localUD.end()) { + if (itLocal != localUD.cend()) { return itLocal->second; } // search cacheUD auto itCache = cacheUD.find(FEIRDFGNode(use)); - if (itCache != cacheUD.end()) { + if (itCache != cacheUD.cend()) { return itCache->second; } // search by DFS @@ -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,23 @@ 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); + FE_ERR(kLncErr, loc, "null assignment of nonnull pointer"); return; } UniqueFEIRStmt stmt = std::make_unique(OP_assignassertnonnull, expr->Clone()); @@ -515,7 +529,7 @@ std::list FEIRStmtJavaFillArrayData::GenMIRStmtsImpl(MIRBuilder &mirB args.push_back(nodeAddrof); uint64 elemPrimTypeSize = GetPrimTypeSize(elemPrimType); uint64 val = elemPrimTypeSize * size; - BaseNode *nodebytes = mirBuilder.CreateIntConst(static_cast(val), PTY_i32); + BaseNode *nodebytes = mirBuilder.CreateIntConst(val, PTY_i32); args.push_back(nodebytes); StmtNode *stmt = mirBuilder.CreateStmtIntrinsicCallAssigned(INTRN_JAVA_ARRAY_FILL, std::move(args), nullptr); ans.push_back(stmt); @@ -531,7 +545,7 @@ PrimType FEIRStmtJavaFillArrayData::ProcessArrayElemPrimType() const { return elemPrimType; } -MIRSymbol *FEIRStmtJavaFillArrayData::ProcessArrayElemData(MIRBuilder &mirBuilder, PrimType elemPrimType) const { +MIRSymbol *FEIRStmtJavaFillArrayData::ProcessArrayElemData(const MIRBuilder &mirBuilder, PrimType elemPrimType) const { // specify size for const array uint32 sizeIn = size; MIRType *arrayTypeWithSize = GlobalTables::GetTypeTable().GetOrCreateArrayType( @@ -544,7 +558,7 @@ MIRSymbol *FEIRStmtJavaFillArrayData::ProcessArrayElemData(MIRBuilder &mirBuilde return arrayVar; } -MIRAggConst *FEIRStmtJavaFillArrayData::FillArrayElem(MIRBuilder &mirBuilder, PrimType elemPrimType, +MIRAggConst *FEIRStmtJavaFillArrayData::FillArrayElem(const MIRBuilder &mirBuilder, PrimType elemPrimType, MIRType &arrayTypeWithSize, uint32 elemSize) const { MemPool *mp = mirBuilder.GetMirModule().GetMemPool(); MIRModule &module = mirBuilder.GetMirModule(); @@ -651,7 +665,7 @@ std::list FEIRStmtJavaMultiANewArray::GenMIRStmtsImpl(MIRBuilder &mir // const class FEIRStmtJavaConstClass feStmtConstClass(GetVarClass()->Clone(), elemType->Clone()); std::list stmtsConstClass = feStmtConstClass.GenMIRStmts(mirBuilder); - (void)ans.insert(ans.end(), stmtsConstClass.begin(), stmtsConstClass.end()); + (void)ans.insert(ans.cend(), stmtsConstClass.cbegin(), stmtsConstClass.cend()); // invoke newInstance UniqueFEIRVar varRetCall = var->Clone(); varRetCall->SetType(FETypeManager::kFEIRTypeJavaObject->Clone()); @@ -666,7 +680,7 @@ std::list FEIRStmtJavaMultiANewArray::GenMIRStmtsImpl(MIRBuilder &mir FEIRStmtJavaTypeCheck feStmtCheck(var->Clone(), std::move(expr), arrayType->Clone(), FEIRStmtJavaTypeCheck::kCheckCast); std::list stmtsCheck = feStmtCheck.GenMIRStmts(mirBuilder); - (void)ans.insert(ans.end(), stmtsCheck.begin(), stmtsCheck.end()); + (void)ans.insert(ans.cend(), stmtsCheck.cbegin(), stmtsCheck.cend()); return ans; } @@ -706,10 +720,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 +847,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 +866,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 +879,19 @@ 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, - mirBuilder.GetCurrentFunction()->GetName().c_str()); + FE_ERR(kLncErr, loc, "%s return nonnull but got null pointer", 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); } @@ -925,12 +943,39 @@ FEIRStmtGotoForC::FEIRStmtGotoForC(const std::string &name) std::list FEIRStmtGotoForC::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { std::list ans; + GenVLACleanup(mirBuilder, ans); LabelIdx label = mirBuilder.GetOrCreateMIRLabel(labelName); GotoNode *gotoNode = mirBuilder.CreateStmtGoto(OP_goto, label); ans.push_back(gotoNode); return ans; } +void FEIRStmtGotoForC::GenVLACleanup(MIRBuilder &mirBuilder, std::list &ans) const { + if (vlaSvaedStackVars.empty()) { + return; + } + const auto &labelWithScopes = FEManager::GetCurrentFEFunction().GetLabelWithScopes(); + const auto &iter = labelWithScopes.find(labelName); + if (iter == labelWithScopes.cend()) { + return; + } + const std::map &scopes = iter->second; + for (const auto &pair : vlaSvaedStackVars) { + // The current scope is the same, and the parent scope is also the same between goto stmt and label stmt + const auto &pIter = scopes.find(pair.first); + if (pIter != scopes.cend()) { + CHECK_NULL_FATAL(pIter->second); + const UniqueFEIRVar &vlaStackVar = pIter->second->GetVLASavedStackVar(); + if (vlaStackVar != nullptr) { + break; + } + } + // emit vla stack restore stmt + auto vlaStmt = FEIRBuilder::CreateVLAStackRestore(pair.second->Clone())->GenMIRStmts(mirBuilder); + (void)ans.insert(ans.cend(), vlaStmt.cbegin(), vlaStmt.cend()); + } +} + std::string FEIRStmtGotoForC::DumpDotStringImpl() const { std::stringstream ss; ss << " " << id << ": " << GetFEIRNodeKindDescription(kind); @@ -1026,6 +1071,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 +1111,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 +1160,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 +1176,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 +1534,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,26 +1544,13 @@ 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 { - primTypeFuncNameIdxMap = { - { PTY_u1, FEUtils::GetMCCStaticFieldSetBoolIdx() }, - { PTY_i8, FEUtils::GetMCCStaticFieldSetByteIdx() }, - { PTY_i16, FEUtils::GetMCCStaticFieldSetShortIdx() }, - { PTY_u16, FEUtils::GetMCCStaticFieldSetCharIdx() }, - { PTY_i32, FEUtils::GetMCCStaticFieldSetIntIdx() }, - { PTY_i64, FEUtils::GetMCCStaticFieldSetLongIdx() }, - { PTY_f32, FEUtils::GetMCCStaticFieldSetFloatIdx() }, - { PTY_f64, FEUtils::GetMCCStaticFieldSetDoubleIdx() }, - { PTY_ref, FEUtils::GetMCCStaticFieldSetObjectIdx() }, - }; -} std::list FEIRStmtFieldStore::GenMIRStmtsImplForStatic(MIRBuilder &mirBuilder) const { CHECK_FATAL(fieldInfo.GetFieldNameIdx() != 0, "invalid name idx"); std::list mirStmts; @@ -1522,15 +1575,15 @@ std::list FEIRStmtFieldStore::GenMIRStmtsImplForStatic(MIRBuilder &mi if (FEOptions::GetInstance().IsAOT()) { needMCCForStatic = NeedMCCForStatic(typeID); if (!needMCCForStatic) { - BaseNode *argNumExpr = mirBuilder.CreateIntConst(static_cast(typeID), PTY_i32); + BaseNode *argNumExpr = mirBuilder.CreateIntConst(typeID, PTY_i32); args.push_back(argNumExpr); } else { const auto &pt = fieldInfo.GetType()->GetPrimType(); std::map primTypeFuncNameIdxMap; - InitPrimTypeFuncNameIdxMap(primTypeFuncNameIdxMap); + FEUtils::InitPrimTypeFuncNameIdxMap(primTypeFuncNameIdxMap); const auto &itorFunc = primTypeFuncNameIdxMap.find(pt); - CHECK_FATAL(itorFunc != primTypeFuncNameIdxMap.end(), "java type not support %d", pt); - args.push_back(mirBuilder.CreateIntConst(static_cast(fieldInfo.GetFieldID()), PTY_i32)); + CHECK_FATAL(itorFunc != primTypeFuncNameIdxMap.cend(), "java type not support %d", pt); + args.push_back(mirBuilder.CreateIntConst(fieldInfo.GetFieldID(), PTY_i32)); BaseNode *nodeSrc = mirBuilder.CreateExprDread(*symSrc); args.push_back(nodeSrc); MIRSymbol *retVarSym = nullptr; @@ -1564,9 +1617,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 +1699,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 +1715,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; } } @@ -1680,24 +1735,15 @@ std::list FEIRStmtFieldLoad::GenMIRStmtsImplForStatic(MIRBuilder &mir uint32 typeID = UINT32_MAX; needMCCForStatic = NeedMCCForStatic(typeID); if (!needMCCForStatic) { - BaseNode *argNumExpr = mirBuilder.CreateIntConst(static_cast(typeID), PTY_i32); + BaseNode *argNumExpr = mirBuilder.CreateIntConst(typeID, PTY_i32); args.push_back(argNumExpr); } else { auto pt = fieldInfo.GetType()->GetPrimType(); - std::map primTypeFuncNameIdxMap = { - { PTY_u1, FEUtils::GetMCCStaticFieldGetBoolIdx() }, - { PTY_i8, FEUtils::GetMCCStaticFieldGetByteIdx() }, - { PTY_i16, FEUtils::GetMCCStaticFieldGetShortIdx() }, - { PTY_u16, FEUtils::GetMCCStaticFieldGetCharIdx() }, - { PTY_i32, FEUtils::GetMCCStaticFieldGetIntIdx() }, - { PTY_i64, FEUtils::GetMCCStaticFieldGetLongIdx() }, - { PTY_f32, FEUtils::GetMCCStaticFieldGetFloatIdx() }, - { PTY_f64, FEUtils::GetMCCStaticFieldGetDoubleIdx() }, - { PTY_ref, FEUtils::GetMCCStaticFieldGetObjectIdx() }, - }; + std::map primTypeFuncNameIdxMap; + FEUtils::InitPrimTypeFuncNameIdxMap(primTypeFuncNameIdxMap); auto itorFunc = primTypeFuncNameIdxMap.find(pt); - CHECK_FATAL(itorFunc != primTypeFuncNameIdxMap.end(), "java type not support %d", pt); - args.push_back(mirBuilder.CreateIntConst(static_cast(fieldInfo.GetFieldID()), PTY_i32)); + CHECK_FATAL(itorFunc != primTypeFuncNameIdxMap.cend(), "java type not support %d", pt); + args.push_back(mirBuilder.CreateIntConst(fieldInfo.GetFieldID(), PTY_i32)); MIRSymbol *retVarSym = nullptr; retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); StmtNode *stmtMCC = mirBuilder.CreateStmtCallAssigned( @@ -1820,26 +1866,20 @@ 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); } - PUIdx puIdx = methodInfo.GetPuIdx(); - // for inline optimize - if (FEManager::GetModule().IsOptFunc(mirBuilder.GetCurrentFunction()) || - mirBuilder.GetCurrentFunction()->GetAttr(FUNCATTR_static)) { - FEManager::GetModule().InsertInlineGlobal(puIdx); - } MIRSymbol *retVarSym = nullptr; if (!methodInfo.IsReturnVoid() && var != nullptr) { retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); InsertNonnullInRetVar(*retVarSym); } if (retVarSym == nullptr) { - stmtCall = mirBuilder.CreateStmtCall(puIdx, std::move(args), mirOp); + stmtCall = mirBuilder.CreateStmtCall(methodInfo.GetPuIdx(), std::move(args), mirOp); } else { - stmtCall = mirBuilder.CreateStmtCallAssigned(puIdx, std::move(args), retVarSym, mirOp); + stmtCall = mirBuilder.CreateStmtCallAssigned(methodInfo.GetPuIdx(), std::move(args), retVarSym, mirOp); } ans.push_back(stmtCall); return ans; @@ -1862,18 +1902,21 @@ 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, + FE_ERR(kLncErr, loc, "null passed to a callee that requires a nonnull argument[the %s argument]", 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); } @@ -1921,12 +1964,12 @@ std::list FEIRStmtCallAssign::GenMIRStmtsUseZeroReturn(MIRBuilder &mi Opcode FEIRStmtCallAssign::AdjustMIROp() const { if (methodInfo.IsReturnVoid()) { auto it = mapOpAssignToOp.find(mirOp); - if (it != mapOpAssignToOp.end()) { + if (it != mapOpAssignToOp.cend()) { return it->second; } } else { auto it = mapOpToOpAssign.find(mirOp); - if (it != mapOpToOpAssign.end()) { + if (it != mapOpToOpAssign.cend()) { return it->second; } } @@ -1976,18 +2019,24 @@ 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, + FE_ERR(kLncErr, loc, "null passed to a callee that requires a nonnull argument[the %s argument]", 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,18 +2065,26 @@ 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); - MIRSymbol *retVarSym = nullptr; + bool isC = FEManager::GetModule().IsCModule(); + MIRType *pMIRType = nullptr; + if (isC) { + CHECK_FATAL(prototype != nullptr, "cannot find prototype for icall"); + pMIRType = prototype->GenerateMIRTypeAuto(); + CHECK_NULL_FATAL(pMIRType); + } if (var != nullptr) { - retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + MIRSymbol *retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); InsertNonnullInRetVar(*retVarSym); - stmtICall = mirBuilder.CreateStmtIcallAssigned(std::move(args), *retVarSym); + stmtICall = isC ? mirBuilder.CreateStmtIcallprotoAssigned(std::move(args), *retVarSym, pMIRType->GetTypeIndex()) : + mirBuilder.CreateStmtIcallAssigned(std::move(args), *retVarSym); } else { - stmtICall = mirBuilder.CreateStmtIcall(std::move(args)); + stmtICall = isC ? mirBuilder.CreateStmtIcallproto(std::move(args), pMIRType->GetTypeIndex()) : + mirBuilder.CreateStmtIcall(std::move(args)); } ans.push_back(stmtICall); return ans; @@ -2104,35 +2161,47 @@ void FEIRStmtIntrinsicCallAssign::RegisterDFGNodes2CheckPointImpl(FEIRStmtCheckP } std::list FEIRStmtIntrinsicCallAssign::GenMIRStmtsImpl(MIRBuilder &mirBuilder) const { - std::list ans; - StmtNode *stmtCall = nullptr; - if (intrinsicId == INTRN_JAVA_CLINIT_CHECK) { - MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); - if (FEOptions::GetInstance().IsAOT()) { - BaseNode *argNumExpr = mirBuilder.CreateIntConst(static_cast(typeID), PTY_i32); - args.push_back(argNumExpr); + switch (intrinsicId) { + case INTRN_JAVA_CLINIT_CHECK: { + return GenMIRStmtsForClintCheck(mirBuilder); } - stmtCall = mirBuilder.CreateStmtIntrinsicCall(INTRN_JAVA_CLINIT_CHECK, std::move(args), - type->GenerateMIRType()->GetTypeIndex()); - } else if (intrinsicId == INTRN_JAVA_FILL_NEW_ARRAY) { - MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); - if (exprList != nullptr) { - for (const auto &expr : *exprList) { - BaseNode *node = expr->GenMIRNode(mirBuilder); - args.push_back(node); + case INTRN_JAVA_FILL_NEW_ARRAY: { + return GenMIRStmtsForFillNewArray(mirBuilder); + } + case INTRN_JAVA_POLYMORPHIC_CALL: { + return GenMIRStmtsForInvokePolyMorphic(mirBuilder); + } + CASE_INTRN_C_SYNC: { + if (type != nullptr) { + return GenMIRStmtsForIntrnC(mirBuilder, type->GenerateMIRType()->GetTypeIndex()); } + break; } - MIRSymbol *retVarSym = nullptr; - if ((var != nullptr) && (var.get() != nullptr)) { - retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + default: { + break; } - stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(INTRN_JAVA_FILL_NEW_ARRAY, std::move(args), retVarSym, - type->GenerateMIRType(true)->GetTypeIndex()); - } else if (intrinsicId == INTRN_JAVA_POLYMORPHIC_CALL) { - return GenMIRStmtsForInvokePolyMorphic(mirBuilder); - } else if (intrinsicId == INTRN_C_va_start || intrinsicId == INTRN_C_memcpy) { - MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); - if (exprList != nullptr) { + } + return GenMIRStmtsForIntrnC(mirBuilder); +} + +std::list FEIRStmtIntrinsicCallAssign::GenMIRStmtsForClintCheck(MIRBuilder &mirBuilder) const { + std::list ans; + MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); + if (FEOptions::GetInstance().IsAOT()) { + BaseNode *argNumExpr = mirBuilder.CreateIntConst(typeID, PTY_i32); + args.push_back(argNumExpr); + } + IntrinsiccallNode *stmtCall = mirBuilder.CreateStmtIntrinsicCall(INTRN_JAVA_CLINIT_CHECK, std::move(args), + type->GenerateMIRType()->GetTypeIndex()); + (void)ans.emplace_back(stmtCall); + return ans; +} + +std::list FEIRStmtIntrinsicCallAssign::GenMIRStmtsForIntrnC(MIRBuilder &mirBuilder, TyIdx returnTyIdx) const { + std::list ans; + MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); + if (exprList != nullptr) { + if (intrinsicId == INTRN_C_va_start || intrinsicId == INTRN_C_memcpy) { for (const auto &expr : *exprList) { BaseNode *node = expr->GenMIRNode(mirBuilder); if (expr->IsAddrof()) { @@ -2140,33 +2209,42 @@ 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); - } - } - stmtCall = mirBuilder.CreateStmtIntrinsicCall(INTRN_C_memset, std::move(args), TyIdx(0)); - } else if (intrinsicId >= INTRN_vector_zip_v2i32 && intrinsicId <= INTRN_vector_zip_v2f32) { - MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); - if (exprList != nullptr) { + } else { for (const auto &expr : *exprList) { BaseNode *node = expr->GenMIRNode(mirBuilder); args.push_back(node); } } - MIRSymbol *retVarSym = nullptr; - if ((var != nullptr) && (var.get() != nullptr)) { - retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + } + MIRSymbol *retVarSym = nullptr; + IntrinsiccallNode *stmtCall = nullptr; + if (var != nullptr) { + retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicId, std::move(args), retVarSym, returnTyIdx); + } else { + stmtCall = mirBuilder.CreateStmtIntrinsicCall(intrinsicId, std::move(args), TyIdx(0)); + } + + (void)ans.emplace_back(stmtCall); + return ans; +} + +std::list FEIRStmtIntrinsicCallAssign::GenMIRStmtsForFillNewArray(MIRBuilder &mirBuilder) const { + std::list ans; + MapleVector args(mirBuilder.GetCurrentFuncCodeMpAllocator()->Adapter()); + if (exprList != nullptr) { + for (const auto &expr : *exprList) { + BaseNode *node = expr->GenMIRNode(mirBuilder); + args.push_back(node); } - stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicId, std::move(args), retVarSym); } - // other intrinsic call should be implemented - ans.emplace_back(stmtCall); + MIRSymbol *retVarSym = nullptr; + if ((var != nullptr) && (var.get() != nullptr)) { + retVarSym = var->GenerateLocalMIRSymbol(mirBuilder); + } + auto *stmtCall = mirBuilder.CreateStmtIntrinsicCallAssigned(INTRN_JAVA_FILL_NEW_ARRAY, std::move(args), retVarSym, + type->GenerateMIRType(true)->GetTypeIndex()); + (void)ans.emplace_back(stmtCall); return ans; } @@ -2221,7 +2299,7 @@ void FEIRStmtIntrinsicCallAssign::ConstructArgsForInvokePolyMorphic(MIRBuilder & dreadExprProtoName->SetPrimType(PTY_ptr); intrnCallargs.push_back(dreadExprProtoName); - BaseNode *argNumExpr = mirBuilder.CreateIntConst(static_cast(polyArgs->size() - 1), PTY_i32); + BaseNode *argNumExpr = mirBuilder.CreateIntConst(static_cast(polyArgs->size() - 1), PTY_i32); intrnCallargs.push_back(argNumExpr); bool isAfterMethodHandle = true; @@ -2229,7 +2307,7 @@ void FEIRStmtIntrinsicCallAssign::ConstructArgsForInvokePolyMorphic(MIRBuilder & intrnCallargs.push_back(mirBuilder.CreateExprDread(*(arg->GenerateMIRSymbol(mirBuilder)))); if (FEOptions::GetInstance().IsAOT() && isAfterMethodHandle) { if (isInStaticFunc) { - intrnCallargs.push_back(mirBuilder.CreateIntConst(static_cast(callerClassTypeID), PTY_i32)); + intrnCallargs.push_back(mirBuilder.CreateIntConst(callerClassTypeID, PTY_i32)); } else { std::unique_ptr varThisAsLocalVar = std::make_unique(FEUtils::GetThisIdx(), FEIRTypeDefault(PTY_ref).Clone()); @@ -2246,7 +2324,8 @@ FEIRExpr::FEIRExpr(FEIRNodeKind argKind) isNestable(true), isAddrof(false), hasException(false), - isBoundaryChecking(false) { + isBoundaryChecking(false), + isEnhancedChecking(true) { type = std::make_unique(); } @@ -2255,9 +2334,9 @@ FEIRExpr::FEIRExpr(FEIRNodeKind argKind, std::unique_ptr argType) isNestable(true), isAddrof(false), hasException(false), - isBoundaryChecking(false) { - SetType(std::move(argType)); -} + isBoundaryChecking(false), + isEnhancedChecking(true), + type(std::move(argType)) {} std::unique_ptr FEIRExpr::Clone() { auto expr = CloneImpl(); @@ -2265,6 +2344,8 @@ std::unique_ptr FEIRExpr::Clone() { expr->isAddrof = IsAddrof(); expr->hasException = HasException(); expr->isBoundaryChecking = IsBoundaryChecking(); + expr->isEnhancedChecking = IsEnhancedChecking(); + expr->SetLoc(loc); return expr; } @@ -2368,9 +2449,11 @@ 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); + return mirBuilder.CreateIntConst(static_cast(value.i64), primType); case PTY_f32: return mirBuilder.CreateFloatConst(value.f32); case PTY_f64: @@ -2516,27 +2599,33 @@ 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); - FEManager::GetModule().InsertInlineGlobal(arrayVar->GetStIdx().Idx()); MIRModule &module = mirBuilder.GetMirModule(); MIRAggConst *val = module.GetMemPool()->New(module, *arrayTypeWithSize); for (uint32 i = 0; i < array.size(); ++i) { @@ -2623,10 +2712,6 @@ BaseNode *FEIRExprAddrofFunc::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { GStrIdx strIdx = GlobalTables::GetStrTable().GetStrIdxFromName(funcAddr); MIRFunction *mirFunc = FEManager::GetTypeManager().GetMIRFunction(strIdx, false); CHECK_FATAL(mirFunc != nullptr, "can not get MIRFunction"); - if (FEManager::GetModule().IsOptFunc(mirBuilder.GetCurrentFunction()) || - mirBuilder.GetCurrentFunction()->GetAttr(FUNCATTR_static)) { - mirBuilder.GetMirModule().InsertInlineGlobal(mirFunc->GetPuidx()); - } return mirBuilder.CreateExprAddroffunc(mirFunc->GetPuidx(), mirBuilder.GetMirModule().GetMemPool()); } @@ -2799,7 +2884,7 @@ std::unique_ptr FEIRExprTypeCvt::CloneImpl() const { BaseNode *FEIRExprTypeCvt::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { auto ptrFunc = funcPtrMapForParseExpr.find(op); - ASSERT(ptrFunc != funcPtrMapForParseExpr.end(), "unsupported op: %s", kOpcodeInfo.GetName(op).c_str()); + ASSERT(ptrFunc != funcPtrMapForParseExpr.cend(), "unsupported op: %s", kOpcodeInfo.GetName(op).c_str()); return (this->*(ptrFunc->second))(mirBuilder); } @@ -2896,7 +2981,7 @@ std::unique_ptr FEIRExprExtractBits::CloneImpl() const { BaseNode *FEIRExprExtractBits::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { auto ptrFunc = funcPtrMapForParseExpr.find(op); - ASSERT(ptrFunc != funcPtrMapForParseExpr.end(), "unsupported op: %s", kOpcodeInfo.GetName(op).c_str()); + ASSERT(ptrFunc != funcPtrMapForParseExpr.cend(), "unsupported op: %s", kOpcodeInfo.GetName(op).c_str()); return (this->*(ptrFunc->second))(mirBuilder); } @@ -2991,7 +3076,7 @@ std::unique_ptr FEIRExprBinary::CloneImpl() const { BaseNode *FEIRExprBinary::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { auto ptrFunc = funcPtrMapForGenMIRNode.find(op); - ASSERT(ptrFunc != funcPtrMapForGenMIRNode.end(), "unsupported op: %s", kOpcodeInfo.GetName(op).c_str()); + ASSERT(ptrFunc != funcPtrMapForGenMIRNode.cend(), "unsupported op: %s", kOpcodeInfo.GetName(op).c_str()); return (this->*(ptrFunc->second))(mirBuilder); } @@ -3712,13 +3797,13 @@ BaseNode *FEIRExprCStyleCast::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { arrayNode->SetNumOpnds(static_cast(arrayType->GetDim() + 1)); return arrayNode; } - auto isCvtNeeded = [&](const MIRType &fromNode, const MIRType &toNode, const BaseNode &baseNode) { + auto isCvtNeeded = [](const MIRType &fromNode, const MIRType &toNode) { if (fromNode.EqualTo(toNode)) { return false; } return true; }; - if (!isCvtNeeded(*srcType, *destType, *sub)) { + if (!isCvtNeeded(*srcType, *destType)) { return sub; } if (sub != nullptr && srcType != nullptr && destType != nullptr) { @@ -3763,6 +3848,17 @@ std::unique_ptr FEIRExprAtomic::CloneImpl() const { return expr; } +TyIdx FEIRExprAtomic::GetTyIdx(MIRBuilder &mirBuilder) const { + TyIdx typeIndex(0); + if (atomicOp == kAtomicOpExchange) { + typeIndex = val2Type->GetTypeIndex(); + } else { + typeIndex = val1Type->GetTypeIndex(); + } + + return typeIndex; +} + BaseNode *FEIRExprAtomic::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { MIRSymbol *retVar = nullptr; if (atomicOp != kAtomicOpStore) { @@ -3777,43 +3873,35 @@ BaseNode *FEIRExprAtomic::GenMIRNodeImpl(MIRBuilder &mirBuilder) const { if (atomicOp == kAtomicOpExchange) { args.emplace_back(valExpr2->GenMIRNode(mirBuilder)); } - if (atomicOp == kAtomicOpExchangeN || - (atomicOp >= kAtomicOpAddFetch && atomicOp <= kAtomicOpFetchNand)) { - retVoid = false; - } else { - retVoid = true; - } + retVoid = (atomicOp == kAtomicOpExchangeN || + (atomicOp >= kAtomicOpAddFetch && atomicOp <= kAtomicOpFetchNand)) ? false : true; } static std::unordered_map intrinsicIDMap = { - {kAtomicOpLoadN, INTRN_C___atomic_load_n}, - {kAtomicOpLoad, INTRN_C___atomic_load}, - {kAtomicOpStoreN, INTRN_C___atomic_store_n}, - {kAtomicOpStore, INTRN_C___atomic_store}, - {kAtomicOpExchangeN, INTRN_C___atomic_exchange_n}, - {kAtomicOpExchange, INTRN_C___atomic_compare_exchange}, - {kAtomicOpAddFetch, INTRN_C___atomic_add_fetch}, - {kAtomicOpSubFetch, INTRN_C___atomic_sub_fetch}, - {kAtomicOpAndFetch, INTRN_C___atomic_and_fetch}, - {kAtomicOpXorFetch, INTRN_C___atomic_xor_fetch}, - {kAtomicOpOrFetch, INTRN_C___atomic_or_fetch}, - {kAtomicOpNandFetch, INTRN_C___atomic_nand_fetch}, - {kAtomicOpFetchAdd, INTRN_C___atomic_fetch_add}, - {kAtomicOpFetchSub, INTRN_C___atomic_fetch_sub}, - {kAtomicOpFetchAnd, INTRN_C___atomic_fetch_and}, - {kAtomicOpFetchXor, INTRN_C___atomic_fetch_xor}, - {kAtomicOpFetchOr, INTRN_C___atomic_fetch_or}, - {kAtomicOpFetchNand, INTRN_C___atomic_fetch_nand}, + {kAtomicOpLoadN, INTRN_C___atomic_load_n}, + {kAtomicOpLoad, INTRN_C___atomic_load}, + {kAtomicOpStoreN, INTRN_C___atomic_store_n}, + {kAtomicOpStore, INTRN_C___atomic_store}, + {kAtomicOpExchangeN, INTRN_C___atomic_exchange_n}, + {kAtomicOpExchange, INTRN_C___atomic_exchange}, + {kAtomicOpAddFetch, INTRN_C___atomic_add_fetch}, + {kAtomicOpSubFetch, INTRN_C___atomic_sub_fetch}, + {kAtomicOpAndFetch, INTRN_C___atomic_and_fetch}, + {kAtomicOpXorFetch, INTRN_C___atomic_xor_fetch}, + {kAtomicOpOrFetch, INTRN_C___atomic_or_fetch}, + {kAtomicOpNandFetch, INTRN_C___atomic_nand_fetch}, + {kAtomicOpFetchAdd, INTRN_C___atomic_fetch_add}, + {kAtomicOpFetchSub, INTRN_C___atomic_fetch_sub}, + {kAtomicOpFetchAnd, INTRN_C___atomic_fetch_and}, + {kAtomicOpFetchXor, INTRN_C___atomic_fetch_xor}, + {kAtomicOpFetchOr, INTRN_C___atomic_fetch_or}, + {kAtomicOpFetchNand, INTRN_C___atomic_fetch_nand}, }; - CHECK(intrinsicIDMap.find(atomicOp) != intrinsicIDMap.end(), "atomic opcode not yet supported!"); + ASSERT(intrinsicIDMap.find(atomicOp) != intrinsicIDMap.end(), "atomic opcode not yet supported!"); MIRIntrinsicID intrinsicID = intrinsicIDMap[atomicOp]; args.emplace_back(orderExpr->GenMIRNode(mirBuilder)); - StmtNode *stmt = nullptr; - if (!retVoid) { - stmt = mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicID, std::move(args), retVar); - } else { - stmt = mirBuilder.CreateStmtIntrinsicCall(intrinsicID, std::move(args), TyIdx(0)); - } - return stmt; + TyIdx typeIndex = GetTyIdx(mirBuilder); + return (!retVoid) ? mirBuilder.CreateStmtIntrinsicCallAssigned(intrinsicID, std::move(args), retVar, typeIndex) + : mirBuilder.CreateStmtIntrinsicCall(intrinsicID, std::move(args), typeIndex); } // ---------- FEIRStmtPesudoLabel ---------- @@ -3829,7 +3917,7 @@ std::list FEIRStmtPesudoLabel::GenMIRStmtsImpl(MIRBuilder &mirBuilder return ans; } -void FEIRStmtPesudoLabel::GenerateLabelIdx(MIRBuilder &mirBuilder) { +void FEIRStmtPesudoLabel::GenerateLabelIdx(const MIRBuilder &mirBuilder) { std::stringstream ss; ss << "label" << HIR2MPLEnv::GetInstance().GetGlobalLabelIdx(); HIR2MPLEnv::GetInstance().IncrGlobalLabelIdx(); @@ -3843,7 +3931,7 @@ std::string FEIRStmtPesudoLabel::DumpDotStringImpl() const { } // ---------- FEIRStmtPesudoLabel2 ---------- -LabelIdx FEIRStmtPesudoLabel2::GenMirLabelIdx(MIRBuilder &mirBuilder, uint32 qIdx0, uint32 qIdx1) { +LabelIdx FEIRStmtPesudoLabel2::GenMirLabelIdx(const MIRBuilder &mirBuilder, uint32 qIdx0, uint32 qIdx1) { std::string label = "L" + std::to_string(qIdx0) + "_" + std::to_string(qIdx1); return mirBuilder.GetOrCreateMIRLabel(label); } @@ -3863,7 +3951,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 +4079,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 +4208,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 +4220,12 @@ 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); + FE_ERR(kLncErr, loc, "null assignment of nonnull pointer"); return; } UniqueFEIRStmt stmt = std::make_unique(OP_assignassertnonnull, baseExpr->Clone()); @@ -4144,6 +4235,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 +4292,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 nodes = stmt->GenMIRStmts(mirBuilder); + initStmts.splice(initStmts.end(), nodes); + } + 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 +4324,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 +4395,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_type.cpp b/src/hir2mpl/common/src/feir_type.cpp index d9af32cf7a3bd62fc9dccfdab873e0e891337a07..9052fa4f9de3fbfaf32df7652b7cdafd84a2d65c 100644 --- a/src/hir2mpl/common/src/feir_type.cpp +++ b/src/hir2mpl/common/src/feir_type.cpp @@ -71,7 +71,7 @@ MIRType *FEIRType::GenerateMIRTypeAuto(MIRSrcLang argSrcLang) const { MIRType *FEIRType::GenerateMIRTypeAutoImpl(MIRSrcLang argSrcLang) const { HIR2MPL_PARALLEL_FORBIDDEN(); auto it = langConfig.find(argSrcLang); - if (it == langConfig.end()) { + if (it == langConfig.cend()) { CHECK_FATAL(false, "unsupported language"); return nullptr; } @@ -444,9 +444,9 @@ void FEIRTypePointer::SetPrimTypeImpl(PrimType pt) { } // ---------- FEIRTypeNative ---------- -FEIRTypeNative::FEIRTypeNative(MIRType &argMIRtype) +FEIRTypeNative::FEIRTypeNative(MIRType &argMIRType) : FEIRType(kFEIRTypeNative), - mirType(argMIRtype) { + mirType(argMIRType) { kind = kFEIRTypeNative; // Right now, FEIRTypeNative is only used for c-language. srcLang = kSrcLangC; diff --git a/src/hir2mpl/common/src/feir_var.cpp b/src/hir2mpl/common/src/feir_var.cpp index cd26cc9bd52a112f96ac39fcc2892fb79e830806..082030b15ee2deda6beefc25efdd2c3dcc773125 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); } @@ -111,14 +123,15 @@ MIRSymbol *FEIRVar::GenerateGlobalMIRSymbolImpl(MIRBuilder &builder) const { HIR2MPL_PARALLEL_FORBIDDEN(); MIRType *mirType = type->GenerateMIRTypeAuto(); 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)) { - return gSymbol; + MIRSymbol *gSymbol = builder.GetGlobalDecl(name); + if (gSymbol != nullptr && attrs.GetAttr(ATTR_extern)) { + return gSymbol; } + GStrIdx nameIdx = GlobalTables::GetStrTable().GetOrCreateStrIdxFromName(name); + gSymbol = builder.GetOrCreateGlobalDecl(name, *mirType); // Set global var attr once std::size_t pos = name.find("_7C"); if (pos != std::string::npos) { @@ -163,7 +176,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/feir_var_reg.cpp b/src/hir2mpl/common/src/feir_var_reg.cpp index 42f937f1aaae6f65f79b0329c8ce880c6c60417d..c21a9ce99e42b9430cab5c80abca668499ee0fe5 100644 --- a/src/hir2mpl/common/src/feir_var_reg.cpp +++ b/src/hir2mpl/common/src/feir_var_reg.cpp @@ -13,10 +13,10 @@ * See the Mulan PSL v2 for more details. */ #include "feir_var_reg.h" -#include "fe_options.h" #include #include #include "mir_type.h" +#include "fe_options.h" namespace maple { std::string FEIRVarReg::GetNameImpl(const MIRType &mirType) const { diff --git a/src/hir2mpl/common/src/generic_attrs.cpp b/src/hir2mpl/common/src/generic_attrs.cpp index 65a94a8f5a21e42c85d7148fb19e718415052c8e..de7ccba767bcca2de929cc927b4fde5d1efeb615 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 < kMaxATTRNum; ++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 < kMaxATTRNum; ++i) { if (attrFlag[i] == 0) { continue; } @@ -63,17 +64,15 @@ 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)); - attr.SetAliasFuncName(name); - } - if (iter->first == GENATTR_constructor_priority) { - attr.SetConstructorPriority(std::get(iter->second)); - } - if (iter->first == GENATTR_destructor_priority) { - attr.SetDestructorPriority(std::get(iter->second)); - } + if (GetContentFlag(GENATTR_alias)) { + std::string name = GlobalTables::GetStrTable().GetStringFromStrIdx(std::get(contentMap[GENATTR_alias])); + attr.SetAliasFuncName(name); + } + if (GetContentFlag(GENATTR_constructor_priority)) { + attr.SetConstructorPriority(std::get(contentMap[GENATTR_constructor_priority])); + } + 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..b7b2febb18e4afcb4fc061560e5563ae9dd15600 100644 --- a/src/hir2mpl/common/src/hir2mpl.cpp +++ b/src/hir2mpl/common/src/hir2mpl.cpp @@ -12,24 +12,24 @@ * FIT FOR A PARTICULAR PURPOSE. * See the Mulan PSL v2 for more details. */ -#include "hir2mpl_compiler.h" #include "fe_utils.h" +#include "hir2mpl_compiler.h" +#include "mpl_sighandler.h" using namespace maple; int main(int argc, char **argv) { + SigHandler::EnableAll(); + 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..ecb6b851a68c6b410da757463820e6643ccff7d0 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,10 @@ #include "fe_manager.h" #include "fe_file_type.h" #include "fe_timer.h" +#include "inline_mplt.h" +#ifndef ONLY_C #include "rc_setter.h" +#endif namespace maple { HIR2MPLCompiler::HIR2MPLCompiler(MIRModule &argModule) @@ -34,9 +37,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,16 +66,22 @@ 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(); ExportMplFile(); - int res = FEManager::GetDiagManager().GetDiagRes(); + logInfo.PrintUserWarnMessages(); + logInfo.PrintUserErrorMessages(); + int res = logInfo.GetUserErrorsNum() > 0 ? FEErrno::kFEError : FEErrno::kNoError; HIR2MPLEnv::GetInstance().Finish(); Release(); return res; @@ -155,14 +166,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 +225,12 @@ 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()) { + std::unique_ptr modInline = std::make_unique(module); + bool isInlineNeeded = modInline->CollectInlineInfo(FEOptions::GetInstance().GetFuncInlineSize()); + if (isInlineNeeded) { + modInline->DumpInlineCandidateToFile(outNameWithoutType + ".mplt_inline"); + } } timer.StopAndDumpTimeMS("Output mpl"); } @@ -293,12 +306,11 @@ void HIR2MPLCompiler::ProcessFunctions() { funcSize += comp->GetFunctionsSize(); if (!success) { const std::set &failedFEFunctions = comp->GetCompileFailedFEFunctions(); - compileFailedFEFunctions.insert(failedFEFunctions.begin(), failedFEFunctions.end()); + compileFailedFEFunctions.insert(failedFEFunctions.cbegin(), failedFEFunctions.cend()); } if (FEOptions::GetInstance().IsDumpPhaseTime()) { comp->DumpPhaseTimeTotal(); } - comp->ReleaseMemPool(); } FEManager::GetTypeManager().MarkExternStructType(); module.SetNumFuncs(funcSize); @@ -308,6 +320,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 +332,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_compiler_component.cpp b/src/hir2mpl/common/src/hir2mpl_compiler_component.cpp index 6aa4e58f5c44a2ce9a6969575900b782f9b2e239..ff7abd5bb0ef6257f9a299b6296ef9c69fba5fe7 100644 --- a/src/hir2mpl/common/src/hir2mpl_compiler_component.cpp +++ b/src/hir2mpl/common/src/hir2mpl_compiler_component.cpp @@ -100,6 +100,12 @@ bool HIR2MPLCompilerComponent::ProcessDeclImpl() { ASSERT_NOT_NULL(helper); success = helper->ProcessDecl() ? success : false; } + if (FEOptions::GetInstance().IsDbgFriendly()) { + for (FEInputEnumHelper *helper : enumHelpers) { + ASSERT_NOT_NULL(helper); + success = helper->ProcessDecl() ? success : false; + } + } timer.StopAndDumpTimeMS("HIR2MPLCompilerComponent::ProcessDecl()"); return success; } diff --git a/src/hir2mpl/common/src/hir2mpl_option.cpp b/src/hir2mpl/common/src/hir2mpl_option.cpp new file mode 100644 index 0000000000000000000000000000000000000000..960504109c02b16f1bf641e46b04dd89e834b674 --- /dev/null +++ b/src/hir2mpl/common/src/hir2mpl_option.cpp @@ -0,0 +1,206 @@ +/* + * 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 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 defaultSafe({"-defaultSafe", "--defaultSafe"}, + " --defaultSafe : treat unmarked function or blocks as safe region by default", + {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..766ca307ed04e7765b56f95965f5cf76c2eb84fa 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. @@ -13,589 +13,365 @@ * See the Mulan PSL v2 for more details. */ #include "hir2mpl_options.h" +#include +#include #include #include +#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 "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", {} }, - - // 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", {} } -}; HIR2MPLOptions::HIR2MPLOptions() { - CreateUsages(kUsage); Init(); } -void HIR2MPLOptions::Init() { +void HIR2MPLOptions::Init() const { FEOptions::GetInstance().Init(); bool success = InitFactory(); CHECK_FATAL(success, "InitFactory failed. Exit."); } 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::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