diff --git a/.github/workflows/clang-tests.yml b/.github/workflows/clang-tests.yml new file mode 100644 index 0000000000000..cd7aefc437b39 --- /dev/null +++ b/.github/workflows/clang-tests.yml @@ -0,0 +1,43 @@ +name: Clang Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - '.github/workflows/clang-tests.yml' + pull_request: + paths: + - 'clang/**' + - 'llvm/**' + - '.github/workflows/clang-tests.yml' + +jobs: + build_clang: + name: clang check-all + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # - windows-latest + # - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Test clang + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release + build_target: check-clang diff --git a/.github/workflows/libclang-abi-tests.yml b/.github/workflows/libclang-abi-tests.yml new file mode 100644 index 0000000000000..ed54c4a1e54de --- /dev/null +++ b/.github/workflows/libclang-abi-tests.yml @@ -0,0 +1,152 @@ +name: libclang ABI Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - '.github/workflows/libclang-abi-tests.yml' + pull_request: + paths: + - 'clang/**' + - '.github/workflows/libclang-abi-tests.yml' + +jobs: + abi-dump-setup: + runs-on: ubuntu-latest + outputs: + BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} + ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} + ABI_LIBS: ${{ steps.vars.outputs.ABI_LIBS }} + BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} + BASELINE_VERSION_MINOR: ${{ steps.vars.outputs.BASELINE_VERSION_MINOR }} + LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} + LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} + steps: + - name: Checkout source + uses: actions/checkout@v1 + with: + fetch-depth: 250 + + - name: Get LLVM version + id: version + uses: llvm/actions/get-llvm-version@main + + - name: Setup Variables + id: vars + run: | + minor_version=0 + remote_repo='https://github.com/llvm/llvm-project' + if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 -o ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then + major_version=$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) + baseline_ref="$major_version.0.0" + + # If there is a minor release, we want to use that as the base line. + minor_ref=`git ls-remote --refs -t $remote_repo llvmorg-$major_version.[1-9].[0-9] | tail -n1 | grep -o 'llvmorg-.\+' || true` + if [ -n "$minor_ref" ]; then + baseline_ref=$minor_ref + else + # Check if we have a release candidate + rc_ref=`git ls-remote --refs -t $remote_repo llvmorg-$major_version.[1-9].[0-9]-rc* | tail -n1 | grep -o 'llvmorg-.\+' || true` + if [ -n "$rc_ref" ]; then + baseline_ref=$rc_ref + fi + fi + echo ::set-output name=BASELINE_VERSION_MAJOR::$major_version + echo ::set-output name=BASELINE_REF::$baseline_ref + echo ::set-output name=ABI_HEADERS::clang-c + echo ::set-output name=ABI_LIBS::libclang.so + else + echo ::set-output name=BASELINE_VERSION_MAJOR::${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + echo ::set-output name=BASELINE_REF::${{ steps.version.outputs.LLVM_VERSION_MAJOR }}.0.0 + echo ::set-output name=ABI_HEADERS::. + echo ::set-output name=ABI_LIBS::libclang.so libclang-cpp.so + fi + + + abi-dump: + needs: abi-dump-setup + runs-on: ubuntu-latest + strategy: + matrix: + name: + - build-baseline + - build-latest + include: + - name: build-baseline + llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} + ref: ${{ needs.abi-dump-setup.outputs.BASELINE_REF }} + repo: llvm/llvm-project + - name: build-latest + llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} + ref: ${{ github.sha }} + repo: ${{ github.repository }} + steps: + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - name: Install abi-compliance-checker + run: | + sudo apt-get install abi-dumper autoconf pkg-config + - name: Install universal-ctags + run: | + git clone https://github.com/universal-ctags/ctags.git + cd ctags + ./autogen.sh + ./configure + sudo make install + - name: Download source code + uses: llvm/actions/get-llvm-project-src@main + with: + ref: ${{ matrix.ref }} + repo: ${{ matrix.repo }} + - name: Configure + run: | + mkdir install + cmake -B build -S llvm -G Ninja -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g -Og" -DCMAKE_INSTALL_PREFIX=`pwd`/install llvm + - name: Build + run: ninja -C build/ ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} install-clang-headers + - name: Dump ABI + run: | + parallel abi-dumper -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o {}-${{ matrix.ref }}.abi ./build/lib/{} ::: ${{ needs.abi-dump-setup.outputs.ABI_LIBS }} + for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do + # Remove symbol versioning from dumps, so we can compare across major versions. + sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' $lib-${{ matrix.ref }}.abi + tar -czf $lib-${{ matrix.ref }}.abi.tar.gz $lib-${{ matrix.ref }}.abi + done + - name: Upload ABI file + uses: actions/upload-artifact@v2 + with: + name: ${{ matrix.name }} + path: "*${{ matrix.ref }}.abi.tar.gz" + + abi-compare: + runs-on: ubuntu-latest + needs: + - abi-dump-setup + - abi-dump + steps: + - name: Download baseline + uses: actions/download-artifact@v1 + with: + name: build-baseline + - name: Download latest + uses: actions/download-artifact@v1 + with: + name: build-latest + + - name: Install abi-compliance-checker + run: sudo apt-get install abi-compliance-checker + - name: Compare ABI + run: | + for lib in ${{ needs.abi-dump-setup.outputs.ABI_LIBS }}; do + abi-compliance-checker -lib $lib -old build-baseline/$lib*.abi.tar.gz -new build-latest/$lib*.abi.tar.gz + done + - name: Upload ABI Comparison + if: always() + uses: actions/upload-artifact@v2 + with: + name: compat-report-${{ github.sha }} + path: compat_reports/ + diff --git a/.github/workflows/libclc-tests.yml b/.github/workflows/libclc-tests.yml new file mode 100644 index 0000000000000..e99d919a45bef --- /dev/null +++ b/.github/workflows/libclc-tests.yml @@ -0,0 +1,53 @@ +name: libclc Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - 'libclc/**' + - '.github/workflows/libclc-tests.yml' + pull_request: + paths: + - 'clang/**' + - 'llvm/**' + - 'libclc/**' + - '.github/workflows/libclc-tests.yml' + +jobs: + build_libclc: + name: libclc test + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # Disable build on windows, because I can't figure out where llvm-config is. + #- windows-latest + # - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Build clang + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="clang" -DCMAKE_BUILD_TYPE=Release + build_target: "" + - name: Build and test libclc + # spirv targets require llvm-spirv, so skip building them until we figure out + # how to install this tool. + run: | + cmake -G Ninja -S libclc -B libclc-build -DLLVM_CONFIG=`pwd`/build/bin/llvm-config -DLIBCLC_TARGETS_TO_BUILD="amdgcn--;amdgcn--amdhsa;r600--;nvptx--;nvptx64--;nvptx--nvidiacl;nvptx64--nvidiacl" + ninja -C libclc-build + ninja -C libclc-build test diff --git a/.github/workflows/lld-tests.yml b/.github/workflows/lld-tests.yml new file mode 100644 index 0000000000000..ffa7e873d80de --- /dev/null +++ b/.github/workflows/lld-tests.yml @@ -0,0 +1,43 @@ +name: LLD Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'lld/**' + - 'llvm/**' + - '.github/workflows/lld-tests.yml' + pull_request: + paths: + - 'lld/**' + - 'llvm/**' + - '.github/workflows/lld-tests.yml' + +jobs: + build_lld: + name: lld check-all + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # - windows-latest + # - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Test lld + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="lld" -DCMAKE_BUILD_TYPE=Release + build_target: check-lld diff --git a/.github/workflows/lldb-tests.yml b/.github/workflows/lldb-tests.yml new file mode 100644 index 0000000000000..fb4310d048475 --- /dev/null +++ b/.github/workflows/lldb-tests.yml @@ -0,0 +1,50 @@ +name: lldb Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'clang/**' + - 'llvm/**' + - 'lldb/**' + - '.github/workflows/lldb-tests.yml' + pull_request: + paths: + - 'clang/**' + - 'llvm/**' + - 'lldb/**' + - '.github/workflows/lldb-tests.yml' + +jobs: + build_lldb: + name: lldb build + runs-on: ${{ matrix.os }} + # Workaround for build faliure on Mac OS X: llvm.org/PR46190, https://github.com/actions/virtual-environments/issues/2274 + env: + CPLUS_INCLUDE_PATH: /usr/local/opt/llvm/include/c++/v1:/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # - windows-latest + # - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Build lldb + uses: llvm/actions/build-test-llvm-project@main + with: + # Mac OS requries that libcxx is enabled for lldb tests, so we need to disable them. + cmake_args: -G Ninja -DLLVM_ENABLE_PROJECTS="clang;lldb" -DCMAKE_BUILD_TYPE=Release -DLLDB_INCLUDE_TESTS=OFF + # check-lldb is not consistent, so we only build lldb. + build_target: "" diff --git a/.github/workflows/llvm-tests.yml b/.github/workflows/llvm-tests.yml new file mode 100644 index 0000000000000..c72c54b81ffdd --- /dev/null +++ b/.github/workflows/llvm-tests.yml @@ -0,0 +1,176 @@ +name: LLVM Tests + +on: + push: + branches: + - 'release/**' + paths: + - 'llvm/**' + - '.github/workflows/llvm-tests.yml' + pull_request: + paths: + - 'llvm/**' + - '.github/workflows/llvm-tests.yml' + +jobs: + build_llvm: + name: llvm check-all + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + # - windows-latest + # - macOS-latest + steps: + - name: Setup Windows + if: startsWith(matrix.os, 'windows') + uses: llvm/actions/setup-windows@main + with: + arch: amd64 + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - uses: actions/checkout@v1 + with: + fetch-depth: 250 + - name: Test llvm + uses: llvm/actions/build-test-llvm-project@main + with: + cmake_args: -G Ninja -DCMAKE_BUILD_TYPE=Release + + abi-dump-setup: + runs-on: ubuntu-latest + outputs: + BASELINE_REF: ${{ steps.vars.outputs.BASELINE_REF }} + ABI_HEADERS: ${{ steps.vars.outputs.ABI_HEADERS }} + BASELINE_VERSION_MAJOR: ${{ steps.vars.outputs.BASELINE_VERSION_MAJOR }} + LLVM_VERSION_MAJOR: ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + LLVM_VERSION_MINOR: ${{ steps.version.outputs.LLVM_VERSION_MINOR }} + LLVM_VERSION_PATCH: ${{ steps.version.outputs.LLVM_VERSION_PATCH }} + steps: + - name: Checkout source + uses: actions/checkout@v1 + with: + fetch-depth: 250 + + - name: Get LLVM version + id: version + uses: llvm/actions/get-llvm-version@main + + - name: Setup Variables + id: vars + run: | + if [ ${{ steps.version.outputs.LLVM_VERSION_MINOR }} -ne 0 -o ${{ steps.version.outputs.LLVM_VERSION_PATCH }} -eq 0 ]; then + echo ::set-output name=BASELINE_VERSION_MAJOR::$(( ${{ steps.version.outputs.LLVM_VERSION_MAJOR }} - 1)) + echo ::set-output name=ABI_HEADERS::llvm-c + else + echo ::set-output name=BASELINE_VERSION_MAJOR::${{ steps.version.outputs.LLVM_VERSION_MAJOR }} + echo ::set-output name=ABI_HEADERS::. + fi + + abi-dump: + needs: abi-dump-setup + runs-on: ubuntu-latest + strategy: + matrix: + name: + - build-baseline + - build-latest + include: + - name: build-baseline + llvm_version_major: ${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }} + ref: llvmorg-${{ needs.abi-dump-setup.outputs.BASELINE_VERSION_MAJOR }}.0.0 + repo: llvm/llvm-project + - name: build-latest + llvm_version_major: ${{ needs.abi-dump-setup.outputs.LLVM_VERSION_MAJOR }} + ref: ${{ github.sha }} + repo: ${{ github.repository }} + steps: + - name: Install Ninja + uses: llvm/actions/install-ninja@main + - name: Install abi-compliance-checker + run: | + sudo apt-get install abi-dumper autoconf pkg-config + - name: Install universal-ctags + run: | + git clone https://github.com/universal-ctags/ctags.git + cd ctags + ./autogen.sh + ./configure + sudo make install + - name: Download source code + uses: llvm/actions/get-llvm-project-src@main + with: + ref: ${{ matrix.ref }} + repo: ${{ matrix.repo }} + - name: Configure + run: | + mkdir install + cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD="" -DLLVM_BUILD_LLVM_DYLIB=ON -DCMAKE_C_FLAGS_DEBUG="-g -Og" -DCMAKE_CXX_FLAGS_DEBUG="-g -Og" -DCMAKE_INSTALL_PREFIX=`pwd`/install llvm + - name: Build + # Need to run install-LLVM twice to ensure the symlink is installed (this is a bug). + run: | + ninja -C build install-LLVM + ninja -C build install-LLVM + ninja -C build install-llvm-headers + - name: Dump ABI + run: | + if [ "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" ]; then + nm ./install/lib/libLLVM.so | awk "/T _LLVM/ || /T LLVM/ { print $3 }" | sort -u | sed -e "s/^_//g" | cut -d ' ' -f 3 > llvm.symbols + # Even though the -symbols-list option doesn't seem to filter out the symbols, I believe it speeds up processing, so I'm leaving it in. + export EXTRA_ARGS="-symbols-list llvm.symbols" + else + touch llvm.symbols + fi + abi-dumper $EXTRA_ARGS -lver ${{ matrix.ref }} -skip-cxx -public-headers ./install/include/${{ needs.abi-dump-setup.outputs.ABI_HEADERS }} -o ${{ matrix.ref }}.abi ./install/lib/libLLVM.so + # Remove symbol versioning from dumps, so we can compare across major versions. + sed -i 's/LLVM_${{ matrix.llvm_version_major }}/LLVM_NOVERSION/' ${{ matrix.ref }}.abi + tar -czf ${{ matrix.ref }}.abi.tar.gz ${{ matrix.ref }}.abi + - name: Upload ABI file + uses: actions/upload-artifact@v1 + with: + name: ${{ matrix.name }} + path: ${{ matrix.ref }}.abi.tar.gz + + - name: Upload symbol list file + if: matrix.name == 'build-baseline' + uses: actions/upload-artifact@v1 + with: + name: symbol-list + path: llvm.symbols + + abi-compare: + runs-on: ubuntu-latest + needs: + - abi-dump-setup + - abi-dump + steps: + - name: Download baseline + uses: actions/download-artifact@v1 + with: + name: build-baseline + - name: Download latest + uses: actions/download-artifact@v1 + with: + name: build-latest + - name: Download symbol list + uses: actions/download-artifact@v1 + with: + name: symbol-list + + - name: Install abi-compliance-checker + run: sudo apt-get install abi-compliance-checker + - name: Compare ABI + run: | + if [ -s symbol-list/llvm.symbols ]; then + # This option doesn't seem to work with the ABI dumper, so passing it here. + export EXTRA_ARGS="-symbols-list symbol-list/llvm.symbols" + fi + abi-compliance-checker $EXTRA_ARGS -l libLLVM.so -old build-baseline/*.tar.gz -new build-latest/*.tar.gz || test "${{ needs.abi-dump-setup.outputs.ABI_HEADERS }}" = "llvm-c" + - name: Upload ABI Comparison + if: always() + uses: actions/upload-artifact@v1 + with: + name: compat-report-${{ github.sha }} + path: compat_reports/ diff --git a/.github/workflows/main-branch-sync.yml b/.github/workflows/main-branch-sync.yml deleted file mode 100644 index 5ea360e281d61..0000000000000 --- a/.github/workflows/main-branch-sync.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: main branch sync - -on: - push: - branches: - - 'main' - -jobs: - branch_sync: - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v2 - with: - # persist-credentials: false allows us to use our own credentials for - # pushing to the repository. Otherwise, the default github actions token - # is used. - persist-credentials: false - fetch-depth: 0 - - - name: Update branch - env: - LLVMBOT_TOKEN: ${{ secrets.LLVMBOT_MAIN_SYNC }} - run: | - git push https://$LLVMBOT_TOKEN@github.com/${{ github.repository }} HEAD:master diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index a9f5b3e0c15bc..39c2c552eb73e 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -13,7 +13,6 @@ add_clang_library(clangTidyCppCoreGuidelinesModule NarrowingConversionsCheck.cpp NoMallocCheck.cpp OwningMemoryCheck.cpp - PreferMemberInitializerCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp ProBoundsConstantArrayIndexCheck.cpp ProBoundsPointerArithmeticCheck.cpp diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index bf613109f0ebd..4cb5022888d3d 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -22,7 +22,6 @@ #include "NarrowingConversionsCheck.h" #include "NoMallocCheck.h" #include "OwningMemoryCheck.h" -#include "PreferMemberInitializerCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" #include "ProBoundsConstantArrayIndexCheck.h" #include "ProBoundsPointerArithmeticCheck.h" @@ -67,8 +66,6 @@ class CppCoreGuidelinesModule : public ClangTidyModule { "cppcoreguidelines-non-private-member-variables-in-classes"); CheckFactories.registerCheck( "cppcoreguidelines-owning-memory"); - CheckFactories.registerCheck( - "cppcoreguidelines-prefer-member-initializer"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); CheckFactories.registerCheck( diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp deleted file mode 100644 index 2d75009438601..0000000000000 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.cpp +++ /dev/null @@ -1,246 +0,0 @@ -//===--- PreferMemberInitializerCheck.cpp - clang-tidy -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "PreferMemberInitializerCheck.h" -#include "clang/AST/ASTContext.h" -#include "clang/ASTMatchers/ASTMatchFinder.h" -#include "clang/Lex/Lexer.h" - -using namespace clang::ast_matchers; - -namespace clang { -namespace tidy { -namespace cppcoreguidelines { - -static bool isControlStatement(const Stmt *S) { - return isa(S); -} - -static bool isNoReturnCallStatement(const Stmt *S) { - const auto *Call = dyn_cast(S); - if (!Call) - return false; - - const FunctionDecl *Func = Call->getDirectCallee(); - if (!Func) - return false; - - return Func->isNoReturn(); -} - -static bool isLiteral(const Expr *E) { - return isa(E); -} - -static bool isUnaryExprOfLiteral(const Expr *E) { - if (const auto *UnOp = dyn_cast(E)) - return isLiteral(UnOp->getSubExpr()); - return false; -} - -static bool shouldBeDefaultMemberInitializer(const Expr *Value) { - if (isLiteral(Value) || isUnaryExprOfLiteral(Value)) - return true; - - if (const auto *DRE = dyn_cast(Value)) - return isa(DRE->getDecl()); - - return false; -} - -static const std::pair -isAssignmentToMemberOf(const RecordDecl *Rec, const Stmt *S) { - if (const auto *BO = dyn_cast(S)) { - if (BO->getOpcode() != BO_Assign) - return std::make_pair(nullptr, nullptr); - - const auto *ME = dyn_cast(BO->getLHS()->IgnoreParenImpCasts()); - if (!ME) - return std::make_pair(nullptr, nullptr); - - const auto *Field = dyn_cast(ME->getMemberDecl()); - if (!Field) - return std::make_pair(nullptr, nullptr); - - if (isa(ME->getBase())) - return std::make_pair(Field, BO->getRHS()->IgnoreParenImpCasts()); - } else if (const auto *COCE = dyn_cast(S)) { - if (COCE->getOperator() != OO_Equal) - return std::make_pair(nullptr, nullptr); - - const auto *ME = - dyn_cast(COCE->getArg(0)->IgnoreParenImpCasts()); - if (!ME) - return std::make_pair(nullptr, nullptr); - - const auto *Field = dyn_cast(ME->getMemberDecl()); - if (!Field) - return std::make_pair(nullptr, nullptr); - - if (isa(ME->getBase())) - return std::make_pair(Field, COCE->getArg(1)->IgnoreParenImpCasts()); - } - - return std::make_pair(nullptr, nullptr); -} - -PreferMemberInitializerCheck::PreferMemberInitializerCheck( - StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), - IsUseDefaultMemberInitEnabled( - Context->isCheckEnabled("modernize-use-default-member-init")), - UseAssignment(OptionsView("modernize-use-default-member-init", - Context->getOptions().CheckOptions, Context) - .get("UseAssignment", false)) {} - -void PreferMemberInitializerCheck::storeOptions( - ClangTidyOptions::OptionMap &Opts) { - Options.store(Opts, "UseAssignment", UseAssignment); -} - -void PreferMemberInitializerCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher( - cxxConstructorDecl(hasBody(compoundStmt()), unless(isInstantiated())) - .bind("ctor"), - this); -} - -void PreferMemberInitializerCheck::check( - const MatchFinder::MatchResult &Result) { - const auto *Ctor = Result.Nodes.getNodeAs("ctor"); - const auto *Body = cast(Ctor->getBody()); - - const CXXRecordDecl *Class = Ctor->getParent(); - SourceLocation InsertPos; - bool FirstToCtorInits = true; - - for (const Stmt *S : Body->body()) { - if (S->getBeginLoc().isMacroID()) { - StringRef MacroName = - Lexer::getImmediateMacroName(S->getBeginLoc(), *Result.SourceManager, - getLangOpts()); - if (MacroName.contains_lower("assert")) - return; - } - if (isControlStatement(S)) - return; - - if (isNoReturnCallStatement(S)) - return; - - if (const auto *CondOp = dyn_cast(S)) { - if (isNoReturnCallStatement(CondOp->getLHS()) || - isNoReturnCallStatement(CondOp->getRHS())) - return; - } - - const FieldDecl *Field; - const Expr *InitValue; - std::tie(Field, InitValue) = isAssignmentToMemberOf(Class, S); - if (Field) { - if (IsUseDefaultMemberInitEnabled && getLangOpts().CPlusPlus11 && - Ctor->isDefaultConstructor() && - (getLangOpts().CPlusPlus20 || !Field->isBitField()) && - (!isa(Class->getDeclContext()) || - !cast(Class->getDeclContext())->isUnion()) && - shouldBeDefaultMemberInitializer(InitValue)) { - auto Diag = - diag(S->getBeginLoc(), "%0 should be initialized in an in-class" - " default member initializer") - << Field; - - SourceLocation FieldEnd = - Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0, - *Result.SourceManager, getLangOpts()); - Diag << FixItHint::CreateInsertion(FieldEnd, - UseAssignment ? " = " : "{") - << FixItHint::CreateInsertionFromRange( - FieldEnd, - CharSourceRange(InitValue->getSourceRange(), true)) - << FixItHint::CreateInsertion(FieldEnd, UseAssignment ? "" : "}"); - - SourceLocation SemiColonEnd = - Lexer::findNextToken(S->getEndLoc(), *Result.SourceManager, - getLangOpts()) - ->getEndLoc(); - CharSourceRange StmtRange = - CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd); - - Diag << FixItHint::CreateRemoval(StmtRange); - } else { - auto Diag = - diag(S->getBeginLoc(), "%0 should be initialized in a member" - " initializer of the constructor") - << Field; - - bool AddComma = false; - if (!Ctor->getNumCtorInitializers() && FirstToCtorInits) { - SourceLocation BodyPos = Ctor->getBody()->getBeginLoc(); - SourceLocation NextPos = Ctor->getBeginLoc(); - do { - InsertPos = NextPos; - NextPos = Lexer::findNextToken(NextPos, *Result.SourceManager, - getLangOpts()) - ->getLocation(); - } while (NextPos != BodyPos); - InsertPos = Lexer::getLocForEndOfToken( - InsertPos, 0, *Result.SourceManager, getLangOpts()); - - Diag << FixItHint::CreateInsertion(InsertPos, " : "); - } else { - bool Found = false; - for (const auto *Init : Ctor->inits()) { - if (Init->isMemberInitializer()) { - if (Result.SourceManager->isBeforeInTranslationUnit( - Field->getLocation(), Init->getMember()->getLocation())) { - InsertPos = Init->getSourceLocation(); - Found = true; - break; - } - } - } - - if (!Found) { - if (Ctor->getNumCtorInitializers()) { - InsertPos = Lexer::getLocForEndOfToken( - (*Ctor->init_rbegin())->getSourceRange().getEnd(), 0, - *Result.SourceManager, getLangOpts()); - } - Diag << FixItHint::CreateInsertion(InsertPos, ", "); - } else { - AddComma = true; - } - } - Diag << FixItHint::CreateInsertion(InsertPos, Field->getName()) - << FixItHint::CreateInsertion(InsertPos, "(") - << FixItHint::CreateInsertionFromRange( - InsertPos, - CharSourceRange(InitValue->getSourceRange(), true)) - << FixItHint::CreateInsertion(InsertPos, ")"); - if (AddComma) - Diag << FixItHint::CreateInsertion(InsertPos, ", "); - - SourceLocation SemiColonEnd = - Lexer::findNextToken(S->getEndLoc(), *Result.SourceManager, - getLangOpts()) - ->getEndLoc(); - CharSourceRange StmtRange = - CharSourceRange::getCharRange(S->getBeginLoc(), SemiColonEnd); - - Diag << FixItHint::CreateRemoval(StmtRange); - FirstToCtorInits = false; - } - } - } -} - -} // namespace cppcoreguidelines -} // namespace tidy -} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h deleted file mode 100644 index dbef7c98d8e35..0000000000000 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/PreferMemberInitializerCheck.h +++ /dev/null @@ -1,41 +0,0 @@ -//===--- PreferMemberInitializerCheck.h - clang-tidy ------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERMEMBERINITIALIZERCHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERMEMBERINITIALIZERCHECK_H - -#include "../ClangTidyCheck.h" - -namespace clang { -namespace tidy { -namespace cppcoreguidelines { - -/// Finds member initializations in the constructor body which can be placed -/// into the initialization list instead. -/// -/// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.html -class PreferMemberInitializerCheck : public ClangTidyCheck { -public: - PreferMemberInitializerCheck(StringRef Name, ClangTidyContext *Context); - bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { - return LangOpts.CPlusPlus; - } - void storeOptions(ClangTidyOptions::OptionMap &Opts) override; - void registerMatchers(ast_matchers::MatchFinder *Finder) override; - void check(const ast_matchers::MatchFinder::MatchResult &Result) override; - - const bool IsUseDefaultMemberInitEnabled; - const bool UseAssignment; -}; - -} // namespace cppcoreguidelines -} // namespace tidy -} // namespace clang - -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PREFERMEMBERINITIALIZERCHECK_H diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp index d33040a00e150..867b074ca6dbd 100644 --- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp @@ -352,6 +352,10 @@ static bool isParamInMainLikeFunction(const ParmVarDecl &ParmDecl, return false; if (FDecl->getAccess() != AS_public && FDecl->getAccess() != AS_none) return false; + // If the function doesn't have a name thats an identifier, can occur of the + // function is an operator overload, bail out early. + if (!FDecl->getDeclName().isIdentifier()) + return false; enum MainType { None, Main, WMain }; auto IsCharPtrPtr = [](QualType QType) -> MainType { if (QType.isNull()) diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp index dc89ebd59fe25..35aed2166f038 100644 --- a/clang-tools-extra/clangd/ClangdLSPServer.cpp +++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp @@ -510,6 +510,11 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params, "semanticTokens request, choosing the latter (no notifications)."); Opts.TheiaSemanticHighlighting = false; } + if (Opts.TheiaSemanticHighlighting) { + log("Using legacy semanticHighlights notification, which will be removed " + "in clangd 13. Clients should use the standard semanticTokens " + "request instead."); + } if (Params.rootUri && *Params.rootUri) Opts.WorkspaceRoot = std::string(Params.rootUri->file()); diff --git a/clang-tools-extra/clangd/Config.h b/clang-tools-extra/clangd/Config.h index 44ca283b6a0e2..391632cb086ac 100644 --- a/clang-tools-extra/clangd/Config.h +++ b/clang-tools-extra/clangd/Config.h @@ -90,6 +90,13 @@ struct Config { struct { bool SuppressAll = false; llvm::StringSet<> Suppress; + + /// Configures what clang-tidy checks to run and options to use with them. + struct { + // A comma-seperated list of globs specify which clang-tidy checks to run. + std::string Checks; + llvm::StringMap CheckOptions; + } ClangTidy; } Diagnostics; /// Style of the codebase. @@ -99,14 +106,6 @@ struct Config { // ::). All nested namespaces are affected as well. std::vector FullyQualifiedNamespaces; } Style; - - /// Configures what clang-tidy checks to run and options to use with them. - struct { - // A comma-seperated list of globs to specify which clang-tidy checks to - // run. - std::string Checks; - llvm::StringMap CheckOptions; - } ClangTidy; }; } // namespace clangd diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp index e82c6e159421c..dadc578c3a81d 100644 --- a/clang-tools-extra/clangd/ConfigCompile.cpp +++ b/clang-tools-extra/clangd/ConfigCompile.cpp @@ -31,6 +31,7 @@ #include "Features.inc" #include "TidyProvider.h" #include "support/Logger.h" +#include "support/Path.h" #include "support/Trace.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -101,9 +102,11 @@ struct FragmentCompiler { // Normalized Fragment::SourceInfo::Directory. std::string FragmentDirectory; - llvm::Optional compileRegex(const Located &Text) { + llvm::Optional + compileRegex(const Located &Text, + llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags) { std::string Anchored = "^(" + *Text + ")$"; - llvm::Regex Result(Anchored); + llvm::Regex Result(Anchored, Flags); std::string RegexError; if (!Result.isValid(RegexError)) { diag(Error, "Invalid regex " + Anchored + ": " + RegexError, Text.Range); @@ -189,16 +192,21 @@ struct FragmentCompiler { compile(std::move(F.CompileFlags)); compile(std::move(F.Index)); compile(std::move(F.Diagnostics)); - compile(std::move(F.ClangTidy)); } void compile(Fragment::IfBlock &&F) { if (F.HasUnrecognizedCondition) Out.Conditions.push_back([&](const Params &) { return false; }); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + llvm::Regex::RegexFlags Flags = llvm::Regex::IgnoreCase; +#else + llvm::Regex::RegexFlags Flags = llvm::Regex::NoFlags; +#endif + auto PathMatch = std::make_unique>(); for (auto &Entry : F.PathMatch) { - if (auto RE = compileRegex(Entry)) + if (auto RE = compileRegex(Entry, Flags)) PathMatch->push_back(std::move(*RE)); } if (!PathMatch->empty()) { @@ -219,7 +227,7 @@ struct FragmentCompiler { auto PathExclude = std::make_unique>(); for (auto &Entry : F.PathExclude) { - if (auto RE = compileRegex(Entry)) + if (auto RE = compileRegex(Entry, Flags)) PathExclude->push_back(std::move(*RE)); } if (!PathExclude->empty()) { @@ -350,7 +358,8 @@ struct FragmentCompiler { return; Spec.MountPoint = std::move(*AbsPath); Out.Apply.push_back([Spec(std::move(Spec))](const Params &P, Config &C) { - if (!P.Path.startswith(Spec.MountPoint)) + if (P.Path.empty() || !pathStartsWith(Spec.MountPoint, P.Path, + llvm::sys::path::Style::posix)) return; C.Index.External = Spec; // Disable background indexing for the files under the mountpoint. @@ -379,6 +388,8 @@ struct FragmentCompiler { for (llvm::StringRef N : Normalized) C.Diagnostics.Suppress.insert(N); }); + + compile(std::move(F.ClangTidy)); } void compile(Fragment::StyleBlock &&F) { @@ -422,7 +433,7 @@ struct FragmentCompiler { CurSpec += Str; } - void compile(Fragment::ClangTidyBlock &&F) { + void compile(Fragment::DiagnosticsBlock::ClangTidyBlock &&F) { std::string Checks; for (auto &CheckGlob : F.Add) appendTidyCheckSpec(Checks, CheckGlob, true); @@ -433,8 +444,9 @@ struct FragmentCompiler { if (!Checks.empty()) Out.Apply.push_back( [Checks = std::move(Checks)](const Params &, Config &C) { - C.ClangTidy.Checks.append( - Checks, C.ClangTidy.Checks.empty() ? /*skip comma*/ 1 : 0, + C.Diagnostics.ClangTidy.Checks.append( + Checks, + C.Diagnostics.ClangTidy.Checks.empty() ? /*skip comma*/ 1 : 0, std::string::npos); }); if (!F.CheckOptions.empty()) { @@ -445,8 +457,8 @@ struct FragmentCompiler { Out.Apply.push_back( [CheckOptions = std::move(CheckOptions)](const Params &, Config &C) { for (auto &StringPair : CheckOptions) - C.ClangTidy.CheckOptions.insert_or_assign(StringPair.first, - StringPair.second); + C.Diagnostics.ClangTidy.CheckOptions.insert_or_assign( + StringPair.first, StringPair.second); }); } } diff --git a/clang-tools-extra/clangd/ConfigFragment.h b/clang-tools-extra/clangd/ConfigFragment.h index 5b67c49fe1546..c36b07f5e8e22 100644 --- a/clang-tools-extra/clangd/ConfigFragment.h +++ b/clang-tools-extra/clangd/ConfigFragment.h @@ -203,6 +203,29 @@ struct Fragment { /// (e.g. by disabling a clang-tidy check, or the -Wunused compile flag). /// This often has other advantages, such as skipping some analysis. std::vector> Suppress; + + /// Controls how clang-tidy will run over the code base. + /// + /// The settings are merged with any settings found in .clang-tidy + /// configiration files with these ones taking precedence. + struct ClangTidyBlock { + std::vector> Add; + /// List of checks to disable. + /// Takes precedence over Add. To enable all llvm checks except include + /// order: + /// Add: llvm-* + /// Remove: llvm-include-onder + std::vector> Remove; + + /// A Key-Value pair list of options to pass to clang-tidy checks + /// These take precedence over options specified in clang-tidy + /// configuration files. Example: + /// CheckOptions: + /// readability-braces-around-statements.ShortStatementLines: 2 + std::vector, Located>> + CheckOptions; + }; + ClangTidyBlock ClangTidy; }; DiagnosticsBlock Diagnostics; @@ -215,30 +238,6 @@ struct Fragment { std::vector> FullyQualifiedNamespaces; }; StyleBlock Style; - - /// Controls how clang-tidy will run over the code base. - /// - /// The settings are merged with any settings found in .clang-tidy - /// configiration files with these ones taking precedence. - // FIXME: move this to Diagnostics.Tidy. - struct ClangTidyBlock { - std::vector> Add; - /// List of checks to disable. - /// Takes precedence over Add. To enable all llvm checks except include - /// order: - /// Add: llvm-* - /// Remove: llvm-include-onder - std::vector> Remove; - - /// A Key-Value pair list of options to pass to clang-tidy checks - /// These take precedence over options specified in clang-tidy configuration - /// files. Example: - /// CheckOptions: - /// readability-braces-around-statements.ShortStatementLines: 2 - std::vector, Located>> - CheckOptions; - }; - ClangTidyBlock ClangTidy; }; } // namespace config diff --git a/clang-tools-extra/clangd/ConfigYAML.cpp b/clang-tools-extra/clangd/ConfigYAML.cpp index 7aaff55654974..348ee9dd1f75f 100644 --- a/clang-tools-extra/clangd/ConfigYAML.cpp +++ b/clang-tools-extra/clangd/ConfigYAML.cpp @@ -62,7 +62,7 @@ class Parser { Dict.handle("CompileFlags", [&](Node &N) { parse(F.CompileFlags, N); }); Dict.handle("Index", [&](Node &N) { parse(F.Index, N); }); Dict.handle("Style", [&](Node &N) { parse(F.Style, N); }); - Dict.handle("ClangTidy", [&](Node &N) { parse(F.ClangTidy, N); }); + Dict.handle("Diagnostics", [&](Node &N) { parse(F.Diagnostics, N); }); Dict.parse(N); return !(N.failed() || HadError); } @@ -110,7 +110,17 @@ class Parser { Dict.parse(N); } - void parse(Fragment::ClangTidyBlock &F, Node &N) { + void parse(Fragment::DiagnosticsBlock &F, Node &N) { + DictParser Dict("Diagnostics", this); + Dict.handle("Suppress", [&](Node &N) { + if (auto Values = scalarValues(N)) + F.Suppress = std::move(*Values); + }); + Dict.handle("ClangTidy", [&](Node &N) { parse(F.ClangTidy, N); }); + Dict.parse(N); + } + + void parse(Fragment::DiagnosticsBlock::ClangTidyBlock &F, Node &N) { DictParser Dict("ClangTidy", this); Dict.handle("Add", [&](Node &N) { if (auto Values = scalarValues(N)) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 1a5379acfe7d7..a38c8a57d1613 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -395,20 +396,6 @@ DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const { return None; } -// For platforms where paths are case-insensitive (but case-preserving), -// we need to do case-insensitive comparisons and use lowercase keys. -// FIXME: Make Path a real class with desired semantics instead. -// This class is not the only place this problem exists. -// FIXME: Mac filesystems default to case-insensitive, but may be sensitive. - -static std::string maybeCaseFoldPath(PathRef Path) { -#if defined(_WIN32) || defined(__APPLE__) - return Path.lower(); -#else - return std::string(Path); -#endif -} - std::vector DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches( llvm::ArrayRef Dirs) const { @@ -567,7 +554,10 @@ class DirectoryBasedGlobalCompilationDatabase::BroadcastThread { } ~BroadcastThread() { - ShouldStop.store(true, std::memory_order_release); + { + std::lock_guard Lock(Mu); + ShouldStop.store(true, std::memory_order_release); + } CV.notify_all(); Thread.join(); } diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp index 403d3fe3e64f5..1020282f5ee89 100644 --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -316,8 +316,8 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs, Check->registerMatchers(&CTFinder); } - ASTDiags.setLevelAdjuster([&, &Cfg(Config::current())]( - DiagnosticsEngine::Level DiagLevel, + const Config& Cfg = Config::current(); + ASTDiags.setLevelAdjuster([&](DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) { if (Cfg.Diagnostics.SuppressAll || isBuiltinDiagnosticSuppressed(Info.getID(), Cfg.Diagnostics.Suppress)) diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp index 78110dc0de603..76cf813e68083 100644 --- a/clang-tools-extra/clangd/Protocol.cpp +++ b/clang-tools-extra/clangd/Protocol.cpp @@ -27,6 +27,21 @@ namespace clang { namespace clangd { +namespace { + +// Helper that doesn't treat `null` and absent fields as failures. +template +bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop, + T &Out, llvm::json::Path P) { + auto *O = Params.getAsObject(); + assert(O); + auto *V = O->get(Prop); + // Field is missing or null. + if (!V || V->getAsNull().hasValue()) + return true; + return fromJSON(*V, Out, P.field(Prop)); +} +} // namespace char LSPError::ID; @@ -490,7 +505,7 @@ bool fromJSON(const llvm::json::Value &Params, DidChangeTextDocumentParams &R, return O && O.map("textDocument", R.textDocument) && O.map("contentChanges", R.contentChanges) && O.map("wantDiagnostics", R.wantDiagnostics) && - O.mapOptional("forceRebuild", R.forceRebuild); + mapOptOrNull(Params, "forceRebuild", R.forceRebuild, P); } bool fromJSON(const llvm::json::Value &E, FileChangeType &Out, @@ -580,10 +595,10 @@ bool fromJSON(const llvm::json::Value &Params, Diagnostic &R, llvm::json::Path P) { llvm::json::ObjectMapper O(Params, P); return O && O.map("range", R.range) && O.map("message", R.message) && - O.mapOptional("severity", R.severity) && - O.mapOptional("category", R.category) && - O.mapOptional("code", R.code) && O.mapOptional("source", R.source); - return true; + mapOptOrNull(Params, "severity", R.severity, P) && + mapOptOrNull(Params, "category", R.category, P) && + mapOptOrNull(Params, "code", R.code, P) && + mapOptOrNull(Params, "source", R.source, P); } llvm::json::Value toJSON(const PublishDiagnosticsParams &PDP) { @@ -818,7 +833,7 @@ bool fromJSON(const llvm::json::Value &Params, CompletionContext &R, llvm::json::ObjectMapper O(Params, P); int TriggerKind; if (!O || !O.map("triggerKind", TriggerKind) || - !O.mapOptional("triggerCharacter", R.triggerCharacter)) + !mapOptOrNull(Params, "triggerCharacter", R.triggerCharacter, P)) return false; R.triggerKind = static_cast(TriggerKind); return true; @@ -1121,8 +1136,8 @@ bool fromJSON(const llvm::json::Value &Params, ConfigurationSettings &S, llvm::json::ObjectMapper O(Params, P); if (!O) return true; // 'any' type in LSP. - return O.mapOptional("compilationDatabaseChanges", - S.compilationDatabaseChanges); + return mapOptOrNull(Params, "compilationDatabaseChanges", + S.compilationDatabaseChanges, P); } bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts, @@ -1133,8 +1148,8 @@ bool fromJSON(const llvm::json::Value &Params, InitializationOptions &Opts, return fromJSON(Params, Opts.ConfigSettings, P) && O.map("compilationDatabasePath", Opts.compilationDatabasePath) && - O.mapOptional("fallbackFlags", Opts.fallbackFlags) && - O.mapOptional("clangdFileStatus", Opts.FileStatus); + mapOptOrNull(Params, "fallbackFlags", Opts.fallbackFlags, P) && + mapOptOrNull(Params, "clangdFileStatus", Opts.FileStatus, P); } bool fromJSON(const llvm::json::Value &E, TypeHierarchyDirection &Out, @@ -1190,10 +1205,11 @@ bool fromJSON(const llvm::json::Value &Params, TypeHierarchyItem &I, return O && O.map("name", I.name) && O.map("kind", I.kind) && O.map("uri", I.uri) && O.map("range", I.range) && O.map("selectionRange", I.selectionRange) && - O.mapOptional("detail", I.detail) && - O.mapOptional("deprecated", I.deprecated) && - O.mapOptional("parents", I.parents) && - O.mapOptional("children", I.children) && O.mapOptional("data", I.data); + mapOptOrNull(Params, "detail", I.detail, P) && + mapOptOrNull(Params, "deprecated", I.deprecated, P) && + mapOptOrNull(Params, "parents", I.parents, P) && + mapOptOrNull(Params, "children", I.children, P) && + mapOptOrNull(Params, "data", I.data, P); } bool fromJSON(const llvm::json::Value &Params, @@ -1238,7 +1254,7 @@ bool fromJSON(const llvm::json::Value &Params, CallHierarchyItem &I, return O && O.map("name", I.name) && O.map("kind", I.kind) && O.map("uri", I.uri) && O.map("range", I.range) && O.map("selectionRange", I.selectionRange) && - O.mapOptional("data", I.data); + mapOptOrNull(Params, "data", I.data, P); } bool fromJSON(const llvm::json::Value &Params, diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp index 0a9f12221287b..bcf1cd5a6183a 100644 --- a/clang-tools-extra/clangd/TidyProvider.cpp +++ b/clang-tools-extra/clangd/TidyProvider.cpp @@ -106,7 +106,7 @@ class DotClangTidyTree { llvm::SmallVector Caches; { std::lock_guard Lock(Mu); - for (auto I = path::begin(Parent), E = path::end(Parent); I != E; ++I) { + for (auto I = path::rbegin(Parent), E = path::rend(Parent); I != E; ++I) { assert(I->end() >= Parent.begin() && I->end() <= Parent.end() && "Canonical path components should be substrings"); llvm::StringRef Ancestor(Parent.begin(), I->end() - Parent.begin()); @@ -255,7 +255,7 @@ TidyProvider disableUnusableChecks(llvm::ArrayRef ExtraBadChecks) { TidyProviderRef provideClangdConfig() { return [](tidy::ClangTidyOptions &Opts, llvm::StringRef) { - const auto &CurTidyConfig = Config::current().ClangTidy; + const auto &CurTidyConfig = Config::current().Diagnostics.ClangTidy; if (!CurTidyConfig.Checks.empty()) mergeCheckList(Opts.Checks, CurTidyConfig.Checks); diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index d3c7da96a441f..a857b34798715 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -68,7 +68,7 @@ llvm::Optional getOtherRefFile(const Decl &D, StringRef MainFile, if (OtherFile) return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { - if (*RefFilePath != MainFile) + if (!pathEqual(*RefFilePath, MainFile)) OtherFile = *RefFilePath; } }); @@ -474,7 +474,7 @@ findOccurrencesOutsideFile(const NamedDecl &RenameDecl, if ((R.Kind & RefKind::Spelled) == RefKind::Unknown) return; if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) { - if (*RefFilePath != MainFile) + if (!pathEqual(*RefFilePath, MainFile)) AffectedFiles[*RefFilePath].push_back(toRange(R.Location)); } }); diff --git a/clang-tools-extra/clangd/support/CMakeLists.txt b/clang-tools-extra/clangd/support/CMakeLists.txt index f0fe073eb1361..fc7d7a28117b1 100644 --- a/clang-tools-extra/clangd/support/CMakeLists.txt +++ b/clang-tools-extra/clangd/support/CMakeLists.txt @@ -23,6 +23,7 @@ add_clang_library(clangdSupport Logger.cpp Markup.cpp MemoryTree.cpp + Path.cpp Shutdown.cpp Threading.cpp ThreadsafeFS.cpp diff --git a/clang-tools-extra/clangd/support/Function.h b/clang-tools-extra/clangd/support/Function.h index 2cac1b1e7f67e..936800d569857 100644 --- a/clang-tools-extra/clangd/support/Function.h +++ b/clang-tools-extra/clangd/support/Function.h @@ -51,7 +51,7 @@ template class Event { Subscription &operator=(Subscription &&Other) { // If *this is active, unsubscribe. if (Parent) { - std::lock_guard(Parent->ListenersMu); + std::lock_guard Lock(Parent->ListenersMu); llvm::erase_if(Parent->Listeners, [&](const std::pair &P) { return P.second == ListenerID; diff --git a/clang-tools-extra/clangd/support/Path.cpp b/clang-tools-extra/clangd/support/Path.cpp new file mode 100644 index 0000000000000..a7907cffe60c7 --- /dev/null +++ b/clang-tools-extra/clangd/support/Path.cpp @@ -0,0 +1,39 @@ +//===--- Path.cpp -------------------------------------------*- C++-*------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "support/Path.h" +#include "llvm/Support/Path.h" +namespace clang { +namespace clangd { + +#ifdef CLANGD_PATH_CASE_INSENSITIVE +std::string maybeCaseFoldPath(PathRef Path) { return Path.lower(); } +bool pathEqual(PathRef A, PathRef B) { return A.equals_lower(B); } +#else // NOT CLANGD_PATH_CASE_INSENSITIVE +std::string maybeCaseFoldPath(PathRef Path) { return Path.str(); } +bool pathEqual(PathRef A, PathRef B) { return A == B; } +#endif // CLANGD_PATH_CASE_INSENSITIVE + +bool pathStartsWith(PathRef Ancestor, PathRef Path, + llvm::sys::path::Style Style) { + assert(llvm::sys::path::is_absolute(Ancestor) && + llvm::sys::path::is_absolute(Path)); + // If ancestor ends with a separator drop that, so that we can match /foo/ as + // a parent of /foo. + if (llvm::sys::path::is_separator(Ancestor.back(), Style)) + Ancestor = Ancestor.drop_back(); + // Ensure Path starts with Ancestor. + if (!pathEqual(Ancestor, Path.take_front(Ancestor.size()))) + return false; + Path = Path.drop_front(Ancestor.size()); + // Then make sure either two paths are equal or Path has a separator + // afterwards. + return Path.empty() || llvm::sys::path::is_separator(Path.front(), Style); +} +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/support/Path.h b/clang-tools-extra/clangd/support/Path.h index 4d4ad7f490473..938d7d7e99c9a 100644 --- a/clang-tools-extra/clangd/support/Path.h +++ b/clang-tools-extra/clangd/support/Path.h @@ -10,8 +10,14 @@ #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_PATH_H #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Path.h" #include +/// Whether current platform treats paths case insensitively. +#if defined(_WIN32) || defined(__APPLE__) +#define CLANGD_PATH_CASE_INSENSITIVE +#endif + namespace clang { namespace clangd { @@ -22,6 +28,18 @@ using Path = std::string; /// signatures. using PathRef = llvm::StringRef; +// For platforms where paths are case-insensitive (but case-preserving), +// we need to do case-insensitive comparisons and use lowercase keys. +// FIXME: Make Path a real class with desired semantics instead. +std::string maybeCaseFoldPath(PathRef Path); +bool pathEqual(PathRef, PathRef); + +/// Checks if \p Ancestor is a proper ancestor of \p Path. This is just a +/// smarter lexical prefix match, e.g: foo/bar/baz doesn't start with foo/./bar. +/// Both \p Ancestor and \p Path must be absolute. +bool pathStartsWith( + PathRef Ancestor, PathRef Path, + llvm::sys::path::Style Style = llvm::sys::path::Style::native); } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/unittests/CMakeLists.txt b/clang-tools-extra/clangd/unittests/CMakeLists.txt index adf4ac827cce3..c396c6f5873b5 100644 --- a/clang-tools-extra/clangd/unittests/CMakeLists.txt +++ b/clang-tools-extra/clangd/unittests/CMakeLists.txt @@ -93,6 +93,7 @@ add_unittest(ClangdUnitTests ClangdTests TestIndex.cpp TestTU.cpp TestWorkspace.cpp + TidyProviderTests.cpp TypeHierarchyTests.cpp URITests.cpp XRefsTests.cpp @@ -103,6 +104,7 @@ add_unittest(ClangdUnitTests ClangdTests support/FunctionTests.cpp support/MarkupTests.cpp support/MemoryTreeTests.cpp + support/PathTests.cpp support/ThreadingTests.cpp support/TestTracer.cpp support/TraceTests.cpp diff --git a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp index ef24b5d8417f5..d9aa171f31029 100644 --- a/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigCompileTests.cpp @@ -99,6 +99,25 @@ TEST_F(ConfigCompileTests, Condition) { Frag.If.PathMatch.emplace_back("ba*r"); EXPECT_FALSE(compileAndApply()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); + + // Only matches case-insensitively. + Frag = {}; + Frag.If.PathMatch.emplace_back("B.*R"); + EXPECT_THAT(Diags.Diagnostics, IsEmpty()); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + EXPECT_TRUE(compileAndApply()); +#else + EXPECT_FALSE(compileAndApply()); +#endif + + Frag = {}; + Frag.If.PathExclude.emplace_back("B.*R"); + EXPECT_THAT(Diags.Diagnostics, IsEmpty()); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + EXPECT_FALSE(compileAndApply()); +#else + EXPECT_TRUE(compileAndApply()); +#endif } TEST_F(ConfigCompileTests, CompileCommands) { @@ -259,32 +278,36 @@ TEST_F(ConfigCompileTests, DiagnosticSuppression) { } TEST_F(ConfigCompileTests, Tidy) { - Frag.ClangTidy.Add.emplace_back("bugprone-use-after-move"); - Frag.ClangTidy.Add.emplace_back("llvm-*"); - Frag.ClangTidy.Remove.emplace_back("llvm-include-order"); - Frag.ClangTidy.Remove.emplace_back("readability-*"); - Frag.ClangTidy.CheckOptions.emplace_back( + auto &Tidy = Frag.Diagnostics.ClangTidy; + Tidy.Add.emplace_back("bugprone-use-after-move"); + Tidy.Add.emplace_back("llvm-*"); + Tidy.Remove.emplace_back("llvm-include-order"); + Tidy.Remove.emplace_back("readability-*"); + Tidy.CheckOptions.emplace_back( std::make_pair(std::string("StrictMode"), std::string("true"))); - Frag.ClangTidy.CheckOptions.emplace_back(std::make_pair( + Tidy.CheckOptions.emplace_back(std::make_pair( std::string("example-check.ExampleOption"), std::string("0"))); EXPECT_TRUE(compileAndApply()); EXPECT_EQ( - Conf.ClangTidy.Checks, + Conf.Diagnostics.ClangTidy.Checks, "bugprone-use-after-move,llvm-*,-llvm-include-order,-readability-*"); - EXPECT_EQ(Conf.ClangTidy.CheckOptions.size(), 2U); - EXPECT_EQ(Conf.ClangTidy.CheckOptions.lookup("StrictMode"), "true"); - EXPECT_EQ(Conf.ClangTidy.CheckOptions.lookup("example-check.ExampleOption"), + EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.size(), 2U); + EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup("StrictMode"), + "true"); + EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup( + "example-check.ExampleOption"), "0"); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); } TEST_F(ConfigCompileTests, TidyBadChecks) { - Frag.ClangTidy.Add.emplace_back("unknown-check"); - Frag.ClangTidy.Remove.emplace_back("*"); - Frag.ClangTidy.Remove.emplace_back("llvm-includeorder"); + auto &Tidy = Frag.Diagnostics.ClangTidy; + Tidy.Add.emplace_back("unknown-check"); + Tidy.Remove.emplace_back("*"); + Tidy.Remove.emplace_back("llvm-includeorder"); EXPECT_TRUE(compileAndApply()); // Ensure bad checks are stripped from the glob. - EXPECT_EQ(Conf.ClangTidy.Checks, "-*"); + EXPECT_EQ(Conf.Diagnostics.ClangTidy.Checks, "-*"); EXPECT_THAT( Diags.Diagnostics, ElementsAre( @@ -402,6 +425,23 @@ TEST_F(ConfigCompileTests, ExternalBlockMountPoint) { ASSERT_THAT(Diags.Diagnostics, IsEmpty()); ASSERT_TRUE(Conf.Index.External); EXPECT_THAT(Conf.Index.External->MountPoint, FooPath); + + // Only matches case-insensitively. + BazPath = testPath("fOo/baz.h", llvm::sys::path::Style::posix); + BazPath = llvm::sys::path::convert_to_slash(BazPath); + Parm.Path = BazPath; + + FooPath = testPath("FOO/", llvm::sys::path::Style::posix); + FooPath = llvm::sys::path::convert_to_slash(FooPath); + Frag = GetFrag("", FooPath.c_str()); + compileAndApply(); + ASSERT_THAT(Diags.Diagnostics, IsEmpty()); +#ifdef CLANGD_PATH_CASE_INSENSITIVE + ASSERT_TRUE(Conf.Index.External); + EXPECT_THAT(Conf.Index.External->MountPoint, FooPath); +#else + ASSERT_FALSE(Conf.Index.External); +#endif } } // namespace } // namespace config diff --git a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp index 25d468ba604ab..e1c81344de201 100644 --- a/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp +++ b/clang-tools-extra/clangd/unittests/ConfigYAMLTests.cpp @@ -60,10 +60,11 @@ CompileFlags: { Add: [foo, bar] } Index: Background: Skip --- -ClangTidy: - CheckOptions: - IgnoreMacros: true - example-check.ExampleOption: 0 +Diagnostics: + ClangTidy: + CheckOptions: + IgnoreMacros: true + example-check.ExampleOption: 0 )yaml"; auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback()); EXPECT_THAT(Diags.Diagnostics, IsEmpty()); @@ -77,7 +78,7 @@ CompileFlags: { Add: [foo, bar] } ASSERT_TRUE(Results[2].Index.Background); EXPECT_EQ("Skip", *Results[2].Index.Background.getValue()); - EXPECT_THAT(Results[3].ClangTidy.CheckOptions, + EXPECT_THAT(Results[3].Diagnostics.ClangTidy.CheckOptions, ElementsAre(PairVal("IgnoreMacros", "true"), PairVal("example-check.ExampleOption", "0"))); } diff --git a/clang-tools-extra/clangd/unittests/RenameTests.cpp b/clang-tools-extra/clangd/unittests/RenameTests.cpp index 4bc03796bb2ba..b2c83a1a43038 100644 --- a/clang-tools-extra/clangd/unittests/RenameTests.cpp +++ b/clang-tools-extra/clangd/unittests/RenameTests.cpp @@ -1067,6 +1067,52 @@ TEST(RenameTest, Renameable) { } } +MATCHER_P(newText, T, "") { return arg.newText == T; } + +TEST(RenameTest, IndexMergeMainFile) { + Annotations Code("int ^x();"); + TestTU TU = TestTU::withCode(Code.code()); + TU.Filename = "main.cc"; + auto AST = TU.build(); + + auto Main = testPath("main.cc"); + + auto Rename = [&](const SymbolIndex *Idx) { + auto GetDirtyBuffer = [&](PathRef Path) -> llvm::Optional { + return Code.code().str(); // Every file has the same content. + }; + RenameOptions Opts; + Opts.AllowCrossFile = true; + RenameInputs Inputs{Code.point(), "xPrime", AST, Main, + Idx, Opts, GetDirtyBuffer}; + auto Results = rename(Inputs); + EXPECT_TRUE(bool(Results)) << llvm::toString(Results.takeError()); + return std::move(*Results); + }; + + // We do not expect to see duplicated edits from AST vs index. + auto Results = Rename(TU.index().get()); + EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main)); + EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(), + ElementsAre(newText("xPrime"))); + + // Sanity check: we do expect to see index results! + TU.Filename = "other.cc"; + Results = Rename(TU.index().get()); + EXPECT_THAT(Results.GlobalChanges.keys(), + UnorderedElementsAre(Main, testPath("other.cc"))); + +#ifdef CLANGD_PATH_CASE_INSENSITIVE + // On case-insensitive systems, no duplicates if AST vs index case differs. + // https://github.com/clangd/clangd/issues/665 + TU.Filename = "MAIN.CC"; + Results = Rename(TU.index().get()); + EXPECT_THAT(Results.GlobalChanges.keys(), ElementsAre(Main)); + EXPECT_THAT(Results.GlobalChanges[Main].asTextEdits(), + ElementsAre(newText("xPrime"))); +#endif +} + TEST(RenameTest, MainFileReferencesOnly) { // filter out references not from main file. llvm::StringRef Test = diff --git a/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp b/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp new file mode 100644 index 0000000000000..a16c87456a1a0 --- /dev/null +++ b/clang-tools-extra/clangd/unittests/TidyProviderTests.cpp @@ -0,0 +1,60 @@ +//===-- TidyProviderTests.cpp - Clang tidy configuration provider tests ---===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestFS.h" +#include "TidyProvider.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { + +namespace { + +TEST(TidyProvider, NestedDirectories) { + MockFS FS; + FS.Files[testPath(".clang-tidy")] = R"yaml( + Checks: 'llvm-*' + CheckOptions: + - key: TestKey + value: 1 +)yaml"; + FS.Files[testPath("sub1/.clang-tidy")] = R"yaml( + Checks: 'misc-*' + CheckOptions: + - key: TestKey + value: 2 +)yaml"; + FS.Files[testPath("sub1/sub2/.clang-tidy")] = R"yaml( + Checks: 'bugprone-*' + CheckOptions: + - key: TestKey + value: 3 + InheritParentConfig: true +)yaml"; + + TidyProvider Provider = provideClangTidyFiles(FS); + + auto BaseOptions = getTidyOptionsForFile(Provider, testPath("File.cpp")); + ASSERT_TRUE(BaseOptions.Checks.hasValue()); + EXPECT_EQ(*BaseOptions.Checks, "llvm-*"); + EXPECT_EQ(BaseOptions.CheckOptions.lookup("TestKey").Value, "1"); + + auto Sub1Options = getTidyOptionsForFile(Provider, testPath("sub1/File.cpp")); + ASSERT_TRUE(Sub1Options.Checks.hasValue()); + EXPECT_EQ(*Sub1Options.Checks, "misc-*"); + EXPECT_EQ(Sub1Options.CheckOptions.lookup("TestKey").Value, "2"); + + auto Sub2Options = + getTidyOptionsForFile(Provider, testPath("sub1/sub2/File.cpp")); + ASSERT_TRUE(Sub2Options.Checks.hasValue()); + EXPECT_EQ(*Sub2Options.Checks, "misc-*,bugprone-*"); + EXPECT_EQ(Sub2Options.CheckOptions.lookup("TestKey").Value, "3"); +} +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/support/PathTests.cpp b/clang-tools-extra/clangd/unittests/support/PathTests.cpp new file mode 100644 index 0000000000000..599c76926d30d --- /dev/null +++ b/clang-tools-extra/clangd/unittests/support/PathTests.cpp @@ -0,0 +1,37 @@ +//===-- PathTests.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "TestFS.h" +#include "support/Path.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +namespace clang { +namespace clangd { +namespace { +TEST(PathTests, IsAncestor) { + EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("foo"))); + EXPECT_TRUE(pathStartsWith(testPath("foo/"), testPath("foo"))); + + EXPECT_FALSE(pathStartsWith(testPath("foo"), testPath("fooz"))); + EXPECT_FALSE(pathStartsWith(testPath("foo/"), testPath("fooz"))); + + EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("foo/bar"))); + EXPECT_TRUE(pathStartsWith(testPath("foo/"), testPath("foo/bar"))); + +#ifdef CLANGD_PATH_CASE_INSENSITIVE + EXPECT_TRUE(pathStartsWith(testPath("fOo"), testPath("foo/bar"))); + EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("fOo/bar"))); +#else + EXPECT_FALSE(pathStartsWith(testPath("fOo"), testPath("foo/bar"))); + EXPECT_FALSE(pathStartsWith(testPath("foo"), testPath("fOo/bar"))); +#endif +} +} // namespace +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 2960aad5a5569..29321bb3eb04c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -47,6 +47,9 @@ Major New Features Improvements to clangd ---------------------- +Performance +^^^^^^^^^^^ + - clangd's memory usage is significantly reduced on most Linux systems. In particular, memory usage should not increase dramatically over time. @@ -59,6 +62,172 @@ Improvements to clangd systems can disable this using ``--malloc_trim=0`` or the CMake flag ``-DCLANGD_MALLOC_TRIM=0``. +- Added the `$/memoryUsage request + `_: an LSP extension. + This provides a breakdown of the memory clangd thinks it is using (excluding + malloc overhead etc). The clangd VSCode extension supports showing the memory + usage tree. + +Parsing and selection +^^^^^^^^^^^^^^^^^^^^^ + +- Improved navigation of broken code in C using Recovery AST. (This has been + enabled for C++ since clangd 11). + +- Types are understood more often in broken code. (This is the first release + where Recovery AST preserves speculated types). + +- Heuristic resolution for dependent names in templates. + +Code completion +^^^^^^^^^^^^^^^ + +- Higher priority for symbols that were already used in this file, and symbols + from namespaces mentioned in this file. (Estimated 3% accuracy improvement) + +- Introduced a ranking algorithm trained on snippets from a large C++ codebase. + Use the flag ``--ranking-model=decision_forest`` to try this (Estimated 6% + accuracy improvement). This mode is likely to become the default in future. + + Note: this is a generic model, not specialized for your code. clangd does not + collect any data from your code to train code completion. + +- Signature help works with functions with template-dependent parameter types. + +Go to definition +^^^^^^^^^^^^^^^^ + +- Selecting an ``auto`` or ``decltype`` keyword will attempt to navigate to + a definition of the deduced type. + +- Improved handling of aliases: navigate to the underlying entity more often. + +- Better understanding of declaration vs definition for Objective-C classes and + protocols. + +- Selecting a pure-virtual method shows its overrides. + +Find references +^^^^^^^^^^^^^^^ + +- Indexes are smarter about not returning stale references when code is deleted. + +- References in implementation files are always indexed, so results should be + more complete. + +- Find-references on a virtual method shows references to overridden methods. + +New navigation features +^^^^^^^^^^^^^^^^^^^^^^^ + +- Call hierarchy (``textDocument/callHierarchy``) is supported. + Only incoming calls are available. + +- Go to implementation (``textDocument/implementation``) is supported on + abstract classes, and on virtual methods. + +- Symbol search (``workspace/symbol``) queries may be partially qualified. + That is, typing ``b::Foo`` will match the symbol ``a::b::c::Foo``. + +Refactoring +^^^^^^^^^^^ + +- New refactoring: populate ``switch`` statement with cases. + (This acts as a fix for the ``-Wswitch-enum`` warning). + +- Renaming templates is supported, and many other complex cases were fixed. + +- Attempting to rename to an invalid or conflicting name can produce an error + message rather than broken code. (Not all cases are detected!) + +- The accuracy of many code actions has been improved. + +Hover +^^^^^ + +- Hovers for ``auto`` and ``decltype`` show the type in the same style as other + hovers. ``this`` is also now supported. + +- Displayed type names are more consistent and idiomatic. + +Semantic highlighting +^^^^^^^^^^^^^^^^^^^^^ + +- Inactive preprocessor regions (``#ifdef``) are highlighted as comments. + +- clangd 12 is the last release with support for the non-standard + ``textDocument/semanticHighlights`` notification. Clients sholud migrate to + the ``textDocument/semanticTokens`` request added in LSP 3.16. + +Remote index (alpha) +^^^^^^^^^^^^^^^^^^^^ + +- clangd can now connect to a remote index server instead of building a project + index locally. This saves resources in large codebases that are slow to index. + +- The server program is ``clangd-index-server``, and it consumes index files + produced by ``clangd-indexer``. + +- This feature requires clangd to be built with the CMake flag + ``-DCLANGD_ENABLE_REMOTE=On``, which requires GRPC libraries and is not + enabled by default. Unofficial releases of the remote-index-enabled client + and server tools are at https://github.com/clangd/clangd/releases + +- Large projects can deploy a shared server, and check in a ``.clangd`` file + to enable it (in the ``Index.External`` section). We hope to provide such a + server for ``llvm-project`` itself in the near future. + +Configuration +^^^^^^^^^^^^^ + +- Static and remote indexes can be configured in the ``Index.External`` section. + Different static indexes can now be used for different files. + (Obsoletes the flag ``--index-file``). + +- Diagnostics can be filtered or suppressed in the ``Diagnostics`` section. + +- Clang-tidy checks can be enabled/disabled in the ``Diagnostics.ClangTidy`` + section. (Obsoletes the flag ``--clang-tidy-checks``). + +- The compilation database directory can be configured in the ``CompileFlags`` + section. Different compilation databases can now be specified for different + files. (Obsoletes the flag ``--compile-commands-dir``). + +- Errors in loaded configuration files are published as LSP diagnostics, and so + should be shown in your editor. + +`Full reference of configuration options `_ + +System integration +^^^^^^^^^^^^^^^^^^ + +- Changes to ``compile_commands.json`` and ``compile_flags.txt`` will take + effect the next time a file is parsed, without restarting clangd. + +- ``clangd --check=`` can be run on the command-line to simulate + opening a file without actually using an editor. This can be useful to + reproduce crashes or aother problems. + +- Various fixes to handle filenames correctly (and case-insensitively) on + windows. + +- If incoming LSP messages are malformed, the logs now contain details. + +Miscellaneous +^^^^^^^^^^^^^ + +- "Show AST" request + (`textDocument/ast `_) + added as an LSP extension. This displays a simplified view of the clang AST + for selected code. The clangd VSCode extension supports this. + +- clangd should no longer crash while loading old or corrupt index files. + +- The flags ``--index``, ``--recovery-ast`` and ``-suggest-missing-includes`` + have been retired. These features are now always enabled. + +- Too many stability and correctness fixes to mention. + Improvements to clang-doc ------------------------- @@ -121,12 +290,6 @@ New checks Finds structs that are inefficiently packed or aligned, and recommends packing and/or aligning of said structs as needed. -- New :doc:`cppcoreguidelines-prefer-member-initializer - ` check. - - Finds member initializations in the constructor body which can be placed into - the initialization list instead. - - New :doc:`bugprone-misplaced-pointer-arithmetic-in-alloc ` check. @@ -195,6 +358,16 @@ Changes in existing checks Added `std::basic_string_view` to default list of ``string``-like types. +Deprecated checks +^^^^^^^^^^^^^^^^^ + +- The :doc:`readability-deleted-default + ` check has been deprecated. + + The clang warning `Wdefaulted-function-deleted + `_ + will diagnose the same issues and is enabled by default. + Improvements to include-fixer ----------------------------- diff --git a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst b/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst deleted file mode 100644 index 5a5ee3e57a8cb..0000000000000 --- a/clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-prefer-member-initializer.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. title:: clang-tidy - cppcoreguidelines-prefer-member-initializer - -cppcoreguidelines-prefer-member-initializer -=========================================== - -Finds member initializations in the constructor body which can be converted -into member initializers of the constructor instead. This not only improves -the readability of the code but also positively affects its performance. -Class-member assignments inside a control statement or following the first -control statement are ignored. - -This check implements `C.49 `_ from the CppCoreGuidelines. - -If the language version is `C++ 11` or above, the constructor is the default -constructor of the class, the field is not a bitfield (only in case of earlier -language version than `C++ 20`), furthermore the assigned value is a literal, -negated literal or ``enum`` constant then the preferred place of the -initialization is at the class member declaration. - -This latter rule is `C.48 `_ from CppCoreGuidelines. - -Please note, that this check does not enforce this latter rule for -initializations already implemented as member initializers. For that purpose -see check `modernize-use-default-member-init `_. - -Example 1 ---------- - -.. code-block:: c++ - - class C { - int n; - int m; - public: - C() { - n = 1; // Literal in default constructor - if (dice()) - return; - m = 1; - } - }; - -Here ``n`` can be initialized using a default member initializer, unlike -``m``, as ``m``'s initialization follows a control statement (``if``): - -.. code-block:: c++ - - class C { - int n{1}; - int m; - public: - C() { - if (dice()) - return; - m = 1; - } - -Example 2 ---------- - -.. code-block:: c++ - - class C { - int n; - int m; - public: - C(int nn, int mm) { - n = nn; // Neither default constructor nor literal - if (dice()) - return; - m = mm; - } - }; - -Here ``n`` can be initialized in the constructor initialization list, unlike -``m``, as ``m``'s initialization follows a control statement (``if``): - -.. code-block:: c++ - - C(int nn, int mm) : n(nn) { - if (dice()) - return; - m = mm; - } - -.. option:: UseAssignment - - If this option is set to `true` (default is `false`), the check will initialize - members with an assignment. In this case the fix of the first example looks - like this: - -.. code-block:: c++ - - class C { - int n = 1; - int m; - public: - C() { - if (dice()) - return; - m = 1; - } - }; diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst index 00134eb05484c..5f2083e00061a 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/readability-deleted-default.rst @@ -3,20 +3,6 @@ readability-deleted-default =========================== -Checks that constructors and assignment operators marked as ``= default`` are -not actually deleted by the compiler. - -.. code-block:: c++ - - class Example { - public: - // This constructor is deleted because I is missing a default value. - Example() = default; - // This is fine. - Example(const Example& Other) = default; - // This operator is deleted because I cannot be assigned (it is const). - Example& operator=(const Example& Other) = default; - - private: - const int I; - }; +This check has been deprecated prefer to make use of the `Wdefaulted-function-deleted +`_ +flag. diff --git a/clang-tools-extra/docs/index.rst b/clang-tools-extra/docs/index.rst index d5c00b89a1555..f1eaeb502ab56 100644 --- a/clang-tools-extra/docs/index.rst +++ b/clang-tools-extra/docs/index.rst @@ -24,23 +24,6 @@ Contents clang-doc -Doxygen Documentation -===================== -The Doxygen documentation describes the **internal** software that makes up the -tools of clang-tools-extra, not the **external** use of these tools. The Doxygen -documentation contains no instructions about how to use the tools, only the APIs -that make up the software. For usage instructions, please see the user's guide -or reference manual for each tool. - -* `Doxygen documentation`_ - -.. _`Doxygen documentation`: doxygen/annotated.html - -.. note:: - This documentation is generated directly from the source code with doxygen. - Since the tools of clang-tools-extra are constantly under active - development, what you're about to read is out of date! - Indices and tables ================== diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp deleted file mode 100644 index dc6cb7606a0de..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init-assignment.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer,modernize-use-default-member-init %t -- \ -// RUN: -config="{CheckOptions: [{key: modernize-use-default-member-init.UseAssignment, value: 1}]}" - -class Simple1 { - int n; - // CHECK-FIXES: int n = 0; - double x; - // CHECK-FIXES: double x = 0.0; - -public: - Simple1() { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple1(int nn, double xx) { - // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple1() = default; -}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp deleted file mode 100644 index fe5bb7c3bb989..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer-modernize-use-default-member-init.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer,modernize-use-default-member-init %t - -class Simple1 { - int n; - // CHECK-FIXES: int n{0}; - double x; - // CHECK-FIXES: double x{0.0}; - -public: - Simple1() { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in an in-class default member initializer [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple1(int nn, double xx) { - // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple1() = default; -}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp deleted file mode 100644 index b5c04c32c9fad..0000000000000 --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-prefer-member-initializer.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// RUN: %check_clang_tidy %s cppcoreguidelines-prefer-member-initializer %t -- -- -fcxx-exceptions - -extern void __assert_fail (__const char *__assertion, __const char *__file, - unsigned int __line, __const char *__function) - __attribute__ ((__noreturn__)); -#define assert(expr) \ - ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) - -class Simple1 { - int n; - double x; - -public: - Simple1() { - // CHECK-FIXES: Simple1() : n(0), x(0.0) { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple1(int nn, double xx) { - // CHECK-FIXES: Simple1(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple1() = default; -}; - -class Simple2 { - int n; - double x; - -public: - Simple2() : n(0) { - // CHECK-FIXES: Simple2() : n(0), x(0.0) { - x = 0.0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple2(int nn, double xx) : n(nn) { - // CHECK-FIXES: Simple2(int nn, double xx) : n(nn), x(xx) { - x = xx; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple2() = default; -}; - -class Simple3 { - int n; - double x; - -public: - Simple3() : x(0.0) { - // CHECK-FIXES: Simple3() : n(0), x(0.0) { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - Simple3(int nn, double xx) : x(xx) { - // CHECK-FIXES: Simple3(int nn, double xx) : n(nn), x(xx) { - n = nn; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple3() = default; -}; - -int something_int(); -double something_double(); - -class Simple4 { - int n; - -public: - Simple4() { - // CHECK-FIXES: Simple4() : n(something_int()) { - n = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Simple4() = default; -}; - -static bool dice(); - -class Complex1 { - int n; - int m; - -public: - Complex1() : n(0) { - if (dice()) - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional expression - } - - ~Complex1() = default; -}; - -class Complex2 { - int n; - int m; - -public: - Complex2() : n(0) { - if (!dice()) - return; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional expression - } - - ~Complex2() = default; -}; - -class Complex3 { - int n; - int m; - -public: - Complex3() : n(0) { - while (dice()) - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional loop - } - - ~Complex3() = default; -}; - -class Complex4 { - int n; - int m; - -public: - Complex4() : n(0) { - while (!dice()) - return; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional loop - } - - ~Complex4() = default; -}; - -class Complex5 { - int n; - int m; - -public: - Complex5() : n(0) { - do { - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional loop - } while (dice()); - } - - ~Complex5() = default; -}; - -class Complex6 { - int n; - int m; - -public: - Complex6() : n(0) { - do { - return; - } while (!dice()); - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional loop - } - - ~Complex6() = default; -}; - -class Complex7 { - int n; - int m; - -public: - Complex7() : n(0) { - for (int i = 2; i < 1; ++i) { - m = 1; - } - // NO-MESSAGES: initialization of 'm' is nested into a conditional loop - } - - ~Complex7() = default; -}; - -class Complex8 { - int n; - int m; - -public: - Complex8() : n(0) { - for (int i = 0; i < 2; ++i) { - return; - } - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional loop - } - - ~Complex8() = default; -}; - -class Complex9 { - int n; - int m; - -public: - Complex9() : n(0) { - switch (dice()) { - case 1: - m = 1; - // NO-MESSAGES: initialization of 'm' is nested in a conditional expression - break; - default: - break; - } - } - - ~Complex9() = default; -}; - -class Complex10 { - int n; - int m; - -public: - Complex10() : n(0) { - switch (dice()) { - case 1: - return; - break; - default: - break; - } - m = 1; - // NO-MESSAGES: initialization of 'm' follows a conditional expression - } - - ~Complex10() = default; -}; - -class E {}; -int risky(); // may throw - -class Complex11 { - int n; - int m; - -public: - Complex11() : n(0) { - try { - risky(); - m = 1; - // NO-MESSAGES: initialization of 'm' follows is nested in a try-block - } catch (const E& e) { - return; - } - } - - ~Complex11() = default; -}; - -class Complex12 { - int n; - int m; - -public: - Complex12() : n(0) { - try { - risky(); - } catch (const E& e) { - return; - } - m = 1; - // NO-MESSAGES: initialization of 'm' follows a try-block - } - - ~Complex12() = default; -}; - -class Complex13 { - int n; - int m; - -public: - Complex13() : n(0) { - return; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a return statement - } - - ~Complex13() = default; -}; - -class Complex14 { - int n; - int m; - -public: - Complex14() : n(0) { - goto X; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a goto statement - X: - ; - } - - ~Complex14() = default; -}; - -void returning(); - -class Complex15 { - int n; - int m; - -public: - Complex15() : n(0) { - // CHECK-FIXES: Complex15() : n(0), m(1) { - returning(); - m = 1; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'm' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Complex15() = default; -}; - -[[noreturn]] void not_returning(); - -class Complex16 { - int n; - int m; - -public: - Complex16() : n(0) { - not_returning(); - m = 1; - // NO-MESSAGES: initialization of 'm' follows a non-returning function call - } - - ~Complex16() = default; -}; - -class Complex17 { - int n; - int m; - -public: - Complex17() : n(0) { - throw 1; - m = 1; - // NO-MESSAGES: initialization of 'm' follows a 'throw' statement; - } - - ~Complex17() = default; -}; - -class Complex18 { - int n; - -public: - Complex18() try { - n = risky(); - // NO-MESSAGES: initialization of 'n' in a 'try' body; - } catch (const E& e) { - n = 0; - } - - ~Complex18() = default; -}; - -class Complex19 { - int n; -public: - Complex19() { - // CHECK-FIXES: Complex19() : n(0) { - n = 0; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - explicit Complex19(int) { - // CHECK-FIXES: Complex19(int) : n(12) { - n = 12; - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } - - ~Complex19() = default; -}; - -class Complex20 { - int n; - int m; - -public: - Complex20(int k) : n(0) { - assert(k > 0); - m = 1; - // NO-MESSAGES: initialization of 'm' follows an assertion - } - - ~Complex20() = default; -}; - -class VeryComplex1 { - int n1, n2, n3; - double x1, x2, x3; - int n4, n5, n6; - double x4, x5, x6; - - VeryComplex1() : n3(something_int()), x3(something_double()), - n5(something_int()), x4(something_double()), - x5(something_double()) { - // CHECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()), - // CHECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()), - // CHECK-FIXES: x5(something_double()), x6(something_double()) { - -// FIXME: Order of elements on the constructor initializer list should match -// the order of the declaration of the fields. Thus the correct fixes -// should look like these: -// - // C ECK-FIXES: VeryComplex1() : n2(something_int()), n1(something_int()), n3(something_int()), x2(something_double()), x1(something_double()), x3(something_double()), - // C ECK-FIXES: n4(something_int()), n5(something_int()), n6(something_int()), x4(something_double()), - // C ECK-FIXES: x5(something_double()), x6(something_double()) { -// -// However, the Diagnostics Engine processes fixes in the order of the -// diagnostics and insertions to the same position are handled in left to -// right order thus in the case two adjacent fields are initialized -// inside the constructor in reverse order the provided fix is a -// constructor initializer list that does not match the order of the -// declaration of the fields. - - x2 = something_double(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n2 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n2' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x6 = something_double(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x1 = something_double(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'x1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n6 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n6' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n1 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n1' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - n4 = something_int(); - // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'n4' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - } -}; - -struct Outside { - int n; - double x; - Outside(); -}; - -Outside::Outside() { - // CHECK-FIXES: Outside::Outside() : n(1), x(1.0) { - n = 1; - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'n' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} - x = 1.0; - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'x' should be initialized in a member initializer of the constructor [cppcoreguidelines-prefer-member-initializer] - // CHECK-FIXES: {{^\ *$}} -} diff --git a/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt b/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt index be35b71d15cfe..05d330dd8033b 100644 --- a/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt +++ b/clang-tools-extra/unittests/clang-tidy/CMakeLists.txt @@ -1,7 +1,6 @@ set(LLVM_LINK_COMPONENTS FrontendOpenMP Support - TestingSupport ) get_filename_component(CLANG_LINT_SOURCE_DIR @@ -46,4 +45,5 @@ target_link_libraries(ClangTidyTests clangTidyObjCModule clangTidyReadabilityModule clangTidyUtils + LLVMTestingSupport ) diff --git a/clang/.gitignore b/clang/.gitignore index 9ee83231d375a..1f1e0bf4a2dec 100644 --- a/clang/.gitignore +++ b/clang/.gitignore @@ -38,3 +38,8 @@ test/debuginfo-tests .vscode .vs +#==============================================================================# +# UPMEM: work with CLion. +#==============================================================================# +.idea/ +cmake-build-*/ diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 9e74014134a08..1902518dd0899 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.13.4) +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake + NO_POLICY_SCOPE) + # If we are not building as a part of LLVM, build Clang as an # standalone project, using LLVM as an external library: if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3001d6feb6317..b89e0c476e9e2 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -48,11 +48,55 @@ Major New Features - ... +Recovery AST +^^^^^^^^^^^^ + +clang's AST now improves support for representing broken C++ code. This improves +the quality of subsequent diagnostics after an error is encountered. It also +exposes more information to tools like clang-tidy and clangd that consume +clang’s AST, allowing them to be more accurate on broken code. + +A RecoveryExpr is introduced in clang's AST, marking an expression containing +semantic errors. This preserves the source range and subexpressions of the +broken expression in the AST (rather than discarding the whole expression). + +For the following invalid code: + + .. code-block:: c++ + + int NoArg(); // Line 1 + int x = NoArg(42); // oops! + +clang-10 produces the minimal placeholder: + + .. code-block:: c++ + + // VarDecl col:5 x 'int' + +clang-11 produces a richer AST: + + .. code-block:: c++ + + // VarDecl col:5 x 'int' cinit + // `-RecoveryExpr '' contains-errors lvalue + // `-UnresolvedLookupExpr '' lvalue (ADL) = 'NoArg' + // `-IntegerLiteral 'int' 42 + +Note that error-dependent types and values may now occur outside a template +context. Tools may need to adjust assumptions about dependent code. + +This feature is on by default for C++ code, and can be explicitly controlled +with `-Xclang -f[no-]recovery-ast`. + Improvements to Clang's diagnostics ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ... +- ``-Wimplicit-const-int-float-conversion`` (enabled by default) is a new + option controlled by ``-Wimplicit-int-float-conversion``. It warns on + implicit conversion from a floating constant to an integer type. + Non-comprehensive list of changes in this release ------------------------------------------------- @@ -68,47 +112,58 @@ Non-comprehensive list of changes in this release ``__builtin_rotateright32`` and ``__builtin_rotateright64`` may now be used within constant expressions. +- ``-O`` maps to ``-O1`` instead of ``-O2``. + (`D79916 `_) + +- In a ``-flto={full,thin}`` link, ``-Os``, ``-Oz`` and ``-Og`` can be used + now. ``-Os`` and ``-Oz`` map to the -O2 pipe line while ``-Og`` maps to the + -O1 pipeline. + (`D79919 `_) + +- ``--coverage`` (gcov) defaults to gcov [4.8,8) compatible format now. + +- On x86, ``-fpic/-fPIC -fno-semantic-interposition`` assumes a global + definition of default visibility non-interposable and allows interprocedural + optimizations. In produced assembly ``-Lfunc$local`` local aliases are created + for global symbols of default visibility. + New Compiler Flags ------------------ - ... -- -fpch-codegen and -fpch-debuginfo generate shared code and/or debuginfo - for contents of a precompiled header in a separate object file. This object - file needs to be linked in, but its contents do not need to be generated - for other objects using the precompiled header. This should usually save - compile time. If not using clang-cl, the separate object file needs to - be created explicitly from the precompiled header. - Example of use: - - .. code-block:: console - - $ clang++ -x c++-header header.h -o header.pch -fpch-codegen -fpch-debuginfo - $ clang++ -c header.pch -o shared.o - $ clang++ -c source.cpp -o source.o -include-pch header.pch - $ clang++ -o binary source.o shared.o - - - Using -fpch-instantiate-templates when generating the precompiled header - usually increases the amount of code/debuginfo that can be shared. - - In some cases, especially when building with optimizations enabled, using - -fpch-codegen may generate so much code in the shared object that compiling - it may be a net loss in build time. - - Since headers may bring in private symbols of other libraries, it may be - sometimes necessary to discard unused symbols (such as by adding - -Wl,--gc-sections on ELF platforms to the linking command, and possibly - adding -fdata-sections -ffunction-sections to the command generating - the shared object). +- AArch64 options ``-moutline-atomics``, ``-mno-outline-atomics`` to enable + and disable calls to helper functions implementing atomic operations. These + out-of-line helpers like '__aarch64_cas8_relax' will detect at runtime + AArch64 Large System Extensions (LSE) availability and either use their + atomic instructions, or falls back to LL/SC loop. These options do not apply + if the compilation target supports LSE. Atomic instructions are used directly + in that case. The option's behaviour mirrors GCC, the helpers are implemented + both in compiler-rt and libgcc. + - New option ``-fbinutils-version=`` specifies the targeted binutils version. For example, ``-fbinutils-version=2.35`` means compatibility with GNU as/ld before 2.35 is not needed: new features can be used and there is no need to work around old GNU as/ld bugs. +- ``-fsanitize-coverage-allowlist`` and ``-fsanitize-coverage-blocklist`` are added. + +- -mtls-size={12,24,32,48} allows selecting the size of the TLS (thread-local + storage) in the local exec TLS model of AArch64, which is the default TLS + model for non-PIC objects. Each value represents 4KB, 16MB (default), 4GB, + and 256TB (needs -mcmodel=large). This allows large/many thread local + variables or a compact/fast code in an executable. + Deprecated Compiler Flags ------------------------- The following options are deprecated and ignored. They will be removed in future versions of Clang. +- The clang-cl ``/fallback`` flag, which made clang-cl invoke Microsoft Visual + C++ on files it couldn't compile itself, has been deprecated. It will be + removed in Clang 13. + - ... Modified Compiler Flags @@ -126,6 +181,16 @@ Modified Compiler Flags This behavior matches newer GCC. (`D91760 `_) (`D92054 `_) +- Support has been added for the following processors (command-line identifiers + in parentheses): + + - Arm Cortex-A78C (cortex-a78c). + - Arm Cortex-R82 (cortex-r82). + - Arm Neoverse V1 (neoverse-v1). + - Arm Neoverse N2 (neoverse-n2). + - Fujitsu A64FX (a64fx). + For example, to select architecture support and tuning for Neoverse-V1 based + systems, use ``-mcpu=neoverse-v1``. Removed Compiler Flags ------------------------- @@ -138,7 +203,22 @@ The following options no longer exist. New Pragmas in Clang -------------------- -- ... +- The ``clang max_tokens_here`` pragma can be used together with + `-Wmax-tokens `_ to emit a warning when + the number of preprocessor tokens exceeds a limit. Such limits can be helpful + in limiting code growth and slow compiles due to large header files. + +Modified Pragmas in Clang +------------------------- + +- The "#pragma clang loop vectorize_width" has been extended to support an + optional 'fixed|scalable' argument, which can be used to indicate that the + compiler should use fixed-width or scalable vectorization. Fixed-width is + assumed by default. + + Scalable or vector length agnostic vectorization is an experimental feature + for targets that support scalable vectors. For more information please refer + to the Clang Language Extensions documentation. Attribute Changes in Clang -------------------------- @@ -150,6 +230,21 @@ Attribute Changes in Clang Windows Support --------------- +- Implicitly add ``.exe`` suffix for MinGW targets, even when cross compiling. + (This matches a change from GCC 8.) + +- Windows on Arm64: programs using the C standard library's setjmp and longjmp + functions may crash with a "Security check failure or stack buffer overrun" + exception. To workaround (with reduced security), compile with + /guard:cf,nolongjmp. + +- Windows on Arm64: LLVM 12 adds official binary release hosted on + Windows on Arm64. The binary is built and tested by Linaro alongside + AArch64 and ARM 32-bit Linux binary releases. This first WoA release + includes Clang compiler, LLD Linker, and compiler-rt runtime libraries. + Work on LLDB, sanitizer support, OpenMP, and other features is in progress + and will be included in future Windows on Arm64 LLVM releases. + C Language Changes in Clang --------------------------- @@ -167,10 +262,38 @@ C++1z Feature Support Objective-C Language Changes in Clang ------------------------------------- -OpenCL C Language Changes in Clang ----------------------------------- - -... +OpenCL Kernel Language Changes in Clang +--------------------------------------- + +- Improved online documentation: :doc:`UsersManual` and :doc:`OpenCLSupport` + pages. +- Added ``-cl-std=CL3.0`` and predefined version macro for OpenCL 3.0. +- Added ``-cl-std=CL1.0`` and mapped to the existing OpenCL 1.0 functionality. +- Improved OpenCL extension handling per target. +- Added clang extension for function pointers ``__cl_clang_function_pointers`` + and variadic functions ``__cl_clang_variadic_functions``, more details can be + found in :doc:`LanguageExtensions`. +- Removed extensions without kernel language changes: + ``cl_khr_select_fprounding_mode``, ``cl_khr_gl_sharing``, ``cl_khr_icd``, + ``cl_khr_gl_event``, ``cl_khr_d3d10_sharing``, ``cl_khr_context_abort``, + ``cl_khr_d3d11_sharing``, ``cl_khr_dx9_media_sharing``, + ``cl_khr_image2d_from_buffer``, ``cl_khr_initialize_memory``, + ``cl_khr_gl_depth_images``, ``cl_khr_spir``, ``cl_khr_egl_event``, + ``cl_khr_egl_image``, ``cl_khr_terminate_context``. +- Improved diagnostics for unevaluated ``vec_step`` expression. +- Allow nested pointers (e.g. pointer-to-pointer) kernel arguments beyond OpenCL + 1.2. +- Added ``global_device`` and ``global_host`` address spaces for USM + allocations. + +Miscellaneous improvements in C++ for OpenCL support: + +- Added diagnostics for pointers to member functions and references to + functions. +- Added support of ``vec_step`` builtin. +- Fixed ICE on address spaces with forwarding references and templated copy + constructors. +- Removed warning for variadic macro use. ABI Changes in Clang -------------------- @@ -178,7 +301,52 @@ ABI Changes in Clang OpenMP Support in Clang ----------------------- -- ... +New features for OpenMP 5.0 were implemented. + +- OpenMP 5.0 is the default version supported by the compiler. User can switch + to OpenMP 4.5 using ``-fopenmp-version=45`` option. + +- Added support for declare variant directive. + +- Improved support of math functions and complex types for NVPTX target. + +- Added support for parallel execution of target regions for NVPTX target. + +- Added support for ``scan`` directives and ``inscan`` modifier in ``reduction`` + clauses. + +- Added support for ``iterator`` construct. + +- Added support for ``depobj`` construct. + +- Added support for ``detach`` clauses in task-based directives. + +- Added support for array shaping operations. + +- Added support for cancellation constructs in ``taskloop`` directives. + +- Nonmonotonic modifier is allowed with all schedule kinds. + +- Added support for ``task`` and ``default`` modifiers in ``reduction`` clauses. + +- Added support for strides in array sections. + +- Added support for ``use_device_addr`` clause. + +- Added support for ``uses_allocators`` clause. + +- Added support for ``defaultmap`` clause. + +- Added basic support for ``hint`` clause in ``atomic`` directives. + +- Added basic support for ``affinity`` clause. + +- Added basic support for ``ancestor`` modifier in ``device`` clause. + +- Added support for ``default(firstprivate)`` clause. This clause is the part of + upcoming OpenMP 5.1 and can be enabled using ``-fopenmp-version=51`` option. + +- Bug fixes and optimizations. CUDA Support in Clang --------------------- @@ -247,15 +415,41 @@ release of Clang. Users of the build system should adjust accordingly. AST Matchers ------------ -- The behavior of TK_IgnoreUnlessSpelledInSource with the traverse() matcher - has been changed to no longer match on template instantiations or on +- The ``mapAnyOf()`` matcher was added. This allows convenient matching of + different AST nodes which have a compatible matcher API. For example, + ``mapAnyOf(ifStmt, forStmt).with(hasCondition(integerLiteral()))`` + matches any ``IfStmt`` or ``ForStmt`` with a integer literal as the + condition. + +- The ``binaryOperation()`` matcher allows matching expressions which + appear like binary operators in the code, even if they are really + ``CXXOperatorCallExpr`` for example. It is based on the ``mapAnyOf()`` + matcher functionality. The matcher API for the latter node has been + extended with ``hasLHS()`` etc to facilitate the abstraction. + +- Matcher API for ``CXXRewrittenBinaryOperator`` has been added. In addition + to explicit matching with the ``cxxRewrittenBinaryOperator()`` matcher, the + ``binaryOperation()`` matches on nodes of this type. + +- The behavior of ``TK_IgnoreUnlessSpelledInSource`` with the ``traverse()`` + matcher has been changed to no longer match on template instantiations or on implicit nodes which are not spelled in the source. -- The TK_IgnoreImplicitCastsAndParentheses traversal kind was removed. It - is recommended to use TK_IgnoreUnlessSpelledInSource instead. +- The ``TK_IgnoreImplicitCastsAndParentheses`` traversal kind was removed. It + is recommended to use ``TK_IgnoreUnlessSpelledInSource`` instead. + +- The behavior of the ``forEach()`` matcher was changed to not internally + ignore implicit and parenthesis nodes. This makes it consistent with + the ``has()`` matcher. Uses of ``forEach()`` relying on the old behavior + can now use the ``traverse()`` matcher or ``ignoringParenCasts()``. -- The behavior of the forEach() matcher was changed to not internally ignore - implicit and parenthesis nodes. +- Several AST Matchers have been changed to match based on the active + traversal mode. For example, ``argumentCountIs()`` matches the number of + arguments written in the source, ignoring default arguments represented + by ``CXXDefaultArgExpr`` nodes. + +- Improvements in AST Matchers allow more matching of template declarations, + independent of their template instantations. clang-format ------------ @@ -318,7 +512,38 @@ libclang Static Analyzer --------------- -- ... +.. 3ff220de9009 [analyzer][StdLibraryFunctionsChecker] Add POSIX networking functions +.. ...And a million other patches. +- Improve the analyzer's understanding of several POSIX functions. + +.. https://reviews.llvm.org/D86533#2238207 +- Greatly improved the analyzer’s constraint solver by better understanding + when constraints are imposed on multiple symbolic values that are known to be + equal or known to be non-equal. It will now also efficiently reject impossible + if-branches between known comparison expressions. (Incorrectly stated as a + 11.0.0 feature in the previous release notes) + +.. 820e8d8656ec [Analyzer][WebKit] UncountedLambdaCaptureChecker +- New checker: :ref:`webkit.UncountedLambdaCapturesChecker` + is a WebKit coding convention checker that flags raw pointers to + reference-counted objects captured by lambdas and suggests using intrusive + reference-counting smart pointers instead. + +.. 8a64689e264c [Analyzer][WebKit] UncountedLocalVarsChecker +- New checker: :ref:`alpha.webkit.UncountedLocalVarsChecker` + is a WebKit coding convention checker that intends to make sure that any + uncounted local variable is backed by a ref-counted object with lifetime that + is strictly larger than the scope of the uncounted local variable. + +.. i914f6c4ff8a4 [StaticAnalyzer] Support struct annotations in FuchsiaHandleChecker +- ``fuchia.HandleChecker`` now recognizes handles in structs; All the handles + referenced by the structure (direct value or ptr) would be treated as + containing the release/use/acquire annotations directly. + +.. 8deaec122ec6 [analyzer] Update Fuchsia checker to catch releasing unowned handles. +- Fuchsia checkers can detect the release of an unowned handle. + +- Numerous fixes and improvements to bug report generation. .. _release-notes-ubsan: diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst index b47be97eef964..d851845396ac4 100644 --- a/clang/docs/analyzer/checkers.rst +++ b/clang/docs/analyzer/checkers.rst @@ -2538,6 +2538,8 @@ We also define a set of safe transformations which if passed a safe value as an - casts - unary operators like ``&`` or ``*`` +.. _alpha-webkit-UncountedLocalVarsChecker: + alpha.webkit.UncountedLocalVarsChecker """""""""""""""""""""""""""""""""""""" The goal of this rule is to make sure that any uncounted local variable is backed by a ref-counted object with lifetime that is strictly larger than the scope of the uncounted local variable. To be on the safe side we require the scope of an uncounted variable to be embedded in the scope of ref-counted object that backs it. diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index ce47d54e44b0b..ae69a68608b70 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -538,6 +538,9 @@ class ASTContext : public RefCountedBase { /// need them (like static local vars). llvm::MapVector MangleNumbers; llvm::MapVector StaticLocalNumbers; + /// Mapping the associated device lambda mangling number if present. + mutable llvm::DenseMap + DeviceLambdaManglingNumbers; /// Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index e32101bb22768..89006b1cfa7f4 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1735,6 +1735,12 @@ class CXXRecordDecl : public RecordDecl { getLambdaData().HasKnownInternalLinkage = HasKnownInternalLinkage; } + /// Set the device side mangling number. + void setDeviceLambdaManglingNumber(unsigned Num) const; + + /// Retrieve the device side mangling number. + unsigned getDeviceLambdaManglingNumber() const; + /// Returns the inheritance model used for this record. MSInheritanceModel getMSInheritanceModel() const; diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index 0e8d6dd53d8a6..7b6495d85eb6e 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -96,6 +96,9 @@ class MangleContext { virtual bool shouldMangleCXXName(const NamedDecl *D) = 0; virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0; + virtual bool isDeviceMangleContext() const { return false; } + virtual void setDeviceMangleContext(bool) {} + // FIXME: consider replacing raw_ostream & with something like SmallString &. void mangleName(GlobalDecl GD, raw_ostream &); virtual void mangleCXXName(GlobalDecl GD, raw_ostream &) = 0; diff --git a/clang/include/clang/AST/MangleNumberingContext.h b/clang/include/clang/AST/MangleNumberingContext.h index f1ca6a05dbafe..eb33759682d6f 100644 --- a/clang/include/clang/AST/MangleNumberingContext.h +++ b/clang/include/clang/AST/MangleNumberingContext.h @@ -52,6 +52,11 @@ class MangleNumberingContext { /// this context. virtual unsigned getManglingNumber(const TagDecl *TD, unsigned MSLocalManglingNumber) = 0; + + /// Retrieve the mangling number of a new lambda expression with the + /// given call operator within the device context. No device number is + /// assigned if there's no device numbering context is associated. + virtual unsigned getDeviceManglingNumber(const CXXMethodDecl *) { return 0; } }; } // end namespace clang diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 505ea700fd0e0..7870cea198a7f 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -186,6 +186,9 @@ template class RecursiveASTVisitor { /// code, e.g., implicit constructors and destructors. bool shouldVisitImplicitCode() const { return false; } + /// Return whether this visitor should recurse into lambda body + bool shouldVisitLambdaBody() const { return true; } + /// Return whether this visitor should traverse post-order. bool shouldTraversePostOrder() const { return false; } @@ -2057,6 +2060,15 @@ bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { // by clang. (!D->isDefaulted() || getDerived().shouldVisitImplicitCode()); + if (const auto *MD = dyn_cast(D)) { + if (const CXXRecordDecl *RD = MD->getParent()) { + if (RD->isLambda() && + declaresSameEntity(RD->getLambdaCallOperator(), MD)) { + VisitBody = VisitBody && getDerived().shouldVisitLambdaBody(); + } + } + } + if (VisitBody) { TRY_TO(TraverseStmt(D->getBody())); // Function body. } diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index 6f6dfab59a391..031fa4682c3ab 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -344,7 +344,7 @@ extern const internal::VariadicAllOfMatcher decl; /// int number = 42; /// auto [foo, bar] = std::make_pair{42, 42}; /// \endcode -extern const internal::VariadicAllOfMatcher +extern const internal::VariadicDynCastAllOfMatcher decompositionDecl; /// Matches a declaration of a linkage specification. diff --git a/clang/include/clang/Basic/BuiltinsDPU.def b/clang/include/clang/Basic/BuiltinsDPU.def new file mode 100644 index 0000000000000..d445e362d06bd --- /dev/null +++ b/clang/include/clang/Basic/BuiltinsDPU.def @@ -0,0 +1,21 @@ +//==- BuiltinsDPU.def - DPU Builtin function database ------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DPU-specific builtin function database. Users of this +// file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +BUILTIN(__builtin_dpu_tid, "UiC", "nc") +BUILTIN(__builtin_dpu_sdma, "vvC*v*Ui", "") +BUILTIN(__builtin_dpu_ldma, "vv*vC*Ui", "") + +#undef BUILTIN diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 5c8af65326edb..9d53b5b923bb2 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -266,6 +266,9 @@ CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate. +/// Treat loops as finite: language, always, never. +ENUM_CODEGENOPT(FiniteLoops, FiniteLoopsKind, 2, FiniteLoopsKind::Language) + /// Attempt to use register sized accesses to bit-fields in structures, when /// possible. CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 73d41e3293c66..c550817f0f69f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -140,6 +140,12 @@ class CodeGenOptions : public CodeGenOptionsBase { All, // Keep all frame pointers. }; + enum FiniteLoopsKind { + Language, // Not specified, use language standard. + Always, // All loops are assumed to be finite. + Never, // No loop is assumed to be finite. + }; + /// The code model to use (-mcmodel). std::string CodeModel; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 67c59f3ca09a7..98293356d3c5b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -787,6 +787,8 @@ def ext_main_returns_nonint : ExtWarn<"return type of 'main' is not 'int'">, def note_main_change_return_type : Note<"change return type to 'int'">; def err_main_surplus_args : Error<"too many parameters (%0) for 'main': " "must be 0, 2, or 3">; +def err_dpu_main_surplus_args : Error<"too many parameters (%0) for 'main': " + "must be 0">; def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">, InGroup
; def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " diff --git a/clang/include/clang/Basic/TargetBuiltins.h b/clang/include/clang/Basic/TargetBuiltins.h index b472547012f0d..db7fe4d29c980 100644 --- a/clang/include/clang/Basic/TargetBuiltins.h +++ b/clang/include/clang/Basic/TargetBuiltins.h @@ -320,6 +320,16 @@ namespace clang { }; } + /// DPU builtins + namespace DPU { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsDPU.def" + LastTSBuiltin + }; + } + static constexpr uint64_t LargestBuiltinID = std::max( {NEON::FirstTSBuiltin, ARM::LastTSBuiltin, SVE::FirstTSBuiltin, AArch64::LastTSBuiltin, BPF::LastTSBuiltin, PPC::LastTSBuiltin, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 42c5319041d09..817798926650f 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1147,7 +1147,7 @@ def fprofile_update_EQ : Joined<["-"], "fprofile-update=">, defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling", CodeGenOpts<"PseudoProbeForProfiling">, DefaultFalse, PosFlag, NegFlag, - BothFlags<[NoXarchOption, CC1Option], " pseudo probes for sample profiler">>; + BothFlags<[NoXarchOption, CC1Option], " pseudo probes for sample profiling">>; def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; @@ -2410,6 +2410,11 @@ def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group, defm reroll_loops : BoolFOption<"reroll-loops", CodeGenOpts<"RerollLoops">, DefaultFalse, PosFlag, NegFlag>; +def ffinite_loops: Flag<["-"], "ffinite-loops">, Group, + HelpText<"Assume all loops are finite.">, Flags<[CC1Option]>; +def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group, + HelpText<"Do not assume that any loop is finite.">, Flags<[CC1Option]>; + def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/include/clang/Lex/VariadicMacroSupport.h b/clang/include/clang/Lex/VariadicMacroSupport.h index 989e0ac703c9b..119f02201fc61 100644 --- a/clang/include/clang/Lex/VariadicMacroSupport.h +++ b/clang/include/clang/Lex/VariadicMacroSupport.h @@ -39,17 +39,14 @@ namespace clang { assert(Ident__VA_ARGS__->isPoisoned() && "__VA_ARGS__ should be poisoned " "outside an ISO C/C++ variadic " "macro definition!"); - assert( - !Ident__VA_OPT__ || - (Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!")); + assert(Ident__VA_OPT__->isPoisoned() && "__VA_OPT__ should be poisoned!"); } /// Client code should call this function just before the Preprocessor is /// about to Lex tokens from the definition of a variadic (ISO C/C++) macro. void enterScope() { Ident__VA_ARGS__->setIsPoisoned(false); - if (Ident__VA_OPT__) - Ident__VA_OPT__->setIsPoisoned(false); + Ident__VA_OPT__->setIsPoisoned(false); } /// Client code should call this function as soon as the Preprocessor has @@ -58,8 +55,7 @@ namespace clang { /// (might be explicitly called, and then reinvoked via the destructor). void exitScope() { Ident__VA_ARGS__->setIsPoisoned(true); - if (Ident__VA_OPT__) - Ident__VA_OPT__->setIsPoisoned(true); + Ident__VA_OPT__->setIsPoisoned(true); } ~VariadicMacroScopeGuard() { exitScope(); } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7f7c84eb1b1d8..2530a2776373f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6558,7 +6558,7 @@ class Sema final { /// Number lambda for linkage purposes if necessary. void handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, - Optional> Mangling = None); + Optional> Mangling = None); /// Endow the lambda scope info with the relevant properties. void buildLambdaScope(sema::LambdaScopeInfo *LSI, @@ -11948,8 +11948,8 @@ class Sema final { /// if (diagIfOpenMPDeviceCode(Loc, diag::err_vla_unsupported)) /// return ExprError(); /// // Otherwise, continue parsing as normal. - SemaDiagnosticBuilder diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID); + SemaDiagnosticBuilder + diagIfOpenMPDeviceCode(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD); /// Creates a SemaDiagnosticBuilder that emits the diagnostic if the current /// context is "used as host code". @@ -11965,17 +11965,19 @@ class Sema final { /// return ExprError(); /// // Otherwise, continue parsing as normal. SemaDiagnosticBuilder diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID); + unsigned DiagID, FunctionDecl *FD); - SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID); + SemaDiagnosticBuilder targetDiag(SourceLocation Loc, unsigned DiagID, + FunctionDecl *FD = nullptr); SemaDiagnosticBuilder targetDiag(SourceLocation Loc, - const PartialDiagnostic &PD) { - return targetDiag(Loc, PD.getDiagID()) << PD; + const PartialDiagnostic &PD, + FunctionDecl *FD = nullptr) { + return targetDiag(Loc, PD.getDiagID(), FD) << PD; } /// Check if the expression is allowed to be used in expressions for the /// offloading devices. - void checkDeviceDecl(const ValueDecl *D, SourceLocation Loc); + void checkDeviceDecl(ValueDecl *D, SourceLocation Loc); enum CUDAFunctionTarget { CFT_Device, diff --git a/clang/include/clang/module.modulemap b/clang/include/clang/module.modulemap index 332e533f03477..3c022eca784e9 100644 --- a/clang/include/clang/module.modulemap +++ b/clang/include/clang/module.modulemap @@ -37,6 +37,7 @@ module Clang_Basic { textual header "Basic/BuiltinsARM.def" textual header "Basic/BuiltinsBPF.def" textual header "Basic/Builtins.def" + textual header "Basic/BuiltinsDPU.def" textual header "Basic/BuiltinsHexagon.def" textual header "Basic/BuiltinsHexagonDep.def" textual header "Basic/BuiltinsHexagonMapCustomDep.def" diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 085c50c0667be..0d723fbbcd8c7 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2848,6 +2848,8 @@ ExpectedDecl ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { return CDeclOrErr.takeError(); D2CXX->setLambdaMangling(DCXX->getLambdaManglingNumber(), *CDeclOrErr, DCXX->hasKnownLambdaInternalLinkage()); + D2CXX->setDeviceLambdaManglingNumber( + DCXX->getDeviceLambdaManglingNumber()); } else if (DCXX->isInjectedClassName()) { // We have to be careful to do a similar dance to the one in // Sema::ActOnStartCXXMemberDeclarations diff --git a/clang/lib/AST/CXXABI.h b/clang/lib/AST/CXXABI.h index 31cb369187266..ca9424bcb7a49 100644 --- a/clang/lib/AST/CXXABI.h +++ b/clang/lib/AST/CXXABI.h @@ -22,8 +22,9 @@ class ASTContext; class CXXConstructorDecl; class DeclaratorDecl; class Expr; -class MemberPointerType; +class MangleContext; class MangleNumberingContext; +class MemberPointerType; /// Implements C++ ABI-specific semantic analysis functions. class CXXABI { @@ -75,6 +76,8 @@ class CXXABI { /// Creates an instance of a C++ ABI class. CXXABI *CreateItaniumCXXABI(ASTContext &Ctx); CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx); +std::unique_ptr +createItaniumNumberingContext(MangleContext *); } #endif diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 0368ada0b81c4..0375f9b4432ee 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1593,6 +1593,20 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const { return getLambdaData().ContextDecl.get(Source); } +void CXXRecordDecl::setDeviceLambdaManglingNumber(unsigned Num) const { + assert(isLambda() && "Not a lambda closure type!"); + if (Num) + getASTContext().DeviceLambdaManglingNumbers[this] = Num; +} + +unsigned CXXRecordDecl::getDeviceLambdaManglingNumber() const { + assert(isLambda() && "Not a lambda closure type!"); + auto I = getASTContext().DeviceLambdaManglingNumbers.find(this); + if (I != getASTContext().DeviceLambdaManglingNumbers.end()) + return I->second; + return 0; +} + static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) { QualType T = cast(Conv->getUnderlyingDecl()->getAsFunction()) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 56181bbe11668..1bdad771a9239 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -3497,8 +3497,8 @@ static bool diagnoseMutableFields(EvalInfo &Info, const Expr *E, AccessKinds AK, static bool lifetimeStartedInEvaluation(EvalInfo &Info, APValue::LValueBase Base, bool MutableSubobject = false) { - // A temporary we created. - if (Base.getCallIndex()) + // A temporary or transient heap allocation we created. + if (Base.getCallIndex() || Base.is()) return true; switch (Info.IsEvaluatingDecl) { @@ -10009,6 +10009,7 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { auto *CaptureInitIt = E->capture_init_begin(); const LambdaCapture *CaptureIt = ClosureClass->captures_begin(); bool Success = true; + const ASTRecordLayout &Layout = Info.Ctx.getASTRecordLayout(ClosureClass); for (const auto *Field : ClosureClass->fields()) { assert(CaptureInitIt != E->capture_init_end()); // Get the initializer for this field @@ -10019,8 +10020,13 @@ bool RecordExprEvaluator::VisitLambdaExpr(const LambdaExpr *E) { if (!CurFieldInit) return Error(E); + LValue Subobject = This; + + if (!HandleLValueMember(Info, E, Subobject, Field, &Layout)) + return false; + APValue &FieldVal = Result.getStructField(Field->getFieldIndex()); - if (!EvaluateInPlace(FieldVal, Info, This, CurFieldInit)) { + if (!EvaluateInPlace(FieldVal, Info, Subobject, CurFieldInit)) { if (!Info.keepEvaluatingAfterFailure()) return false; Success = false; @@ -14786,11 +14792,14 @@ bool Expr::EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx, static bool EvaluateDestruction(const ASTContext &Ctx, APValue::LValueBase Base, APValue DestroyedValue, QualType Type, - SourceLocation Loc, Expr::EvalStatus &EStatus) { - EvalInfo Info(Ctx, EStatus, EvalInfo::EM_ConstantExpression); + SourceLocation Loc, Expr::EvalStatus &EStatus, + bool IsConstantDestruction) { + EvalInfo Info(Ctx, EStatus, + IsConstantDestruction ? EvalInfo::EM_ConstantExpression + : EvalInfo::EM_ConstantFold); Info.setEvaluatingDecl(Base, DestroyedValue, EvalInfo::EvaluatingDeclKind::Dtor); - Info.InConstantContext = true; + Info.InConstantContext = IsConstantDestruction; LValue LVal; LVal.set(Base); @@ -14844,7 +14853,8 @@ bool Expr::EvaluateAsConstantExpr(EvalResult &Result, const ASTContext &Ctx, // If this is a class template argument, it's required to have constant // destruction too. if (Kind == ConstantExprKind::ClassTemplateArgument && - (!EvaluateDestruction(Ctx, Base, Result.Val, T, getBeginLoc(), Result) || + (!EvaluateDestruction(Ctx, Base, Result.Val, T, getBeginLoc(), Result, + true) || Result.HasSideEffects)) { // FIXME: Prefix a note to indicate that the problem is lack of constant // destruction. @@ -14910,6 +14920,10 @@ bool VarDecl::evaluateDestruction( Expr::EvalStatus EStatus; EStatus.Diag = &Notes; + // Only treat the destruction as constant destruction if we formally have + // constant initialization (or are usable in a constant expression). + bool IsConstantDestruction = hasConstantInitialization(); + // Make a copy of the value for the destructor to mutate, if we know it. // Otherwise, treat the value as default-initialized; if the destructor works // anyway, then the destruction is constant (and must be essentially empty). @@ -14920,7 +14934,8 @@ bool VarDecl::evaluateDestruction( return false; if (!EvaluateDestruction(getASTContext(), this, std::move(DestroyedValue), - getType(), getLocation(), EStatus) || + getType(), getLocation(), EStatus, + IsConstantDestruction) || EStatus.HasSideEffects) return false; diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 069add8464ae8..be10258a2d774 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -258,3 +258,9 @@ class ItaniumCXXABI : public CXXABI { CXXABI *clang::CreateItaniumCXXABI(ASTContext &Ctx) { return new ItaniumCXXABI(Ctx); } + +std::unique_ptr +clang::createItaniumNumberingContext(MangleContext *Mangler) { + return std::make_unique( + cast(Mangler)); +} diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 6c8d5687c64a8..5cad84a96845b 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -125,6 +125,8 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { llvm::DenseMap Discriminator; llvm::DenseMap Uniquifier; + bool IsDevCtx = false; + public: explicit ItaniumMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags) @@ -137,6 +139,10 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext { bool shouldMangleStringLiteral(const StringLiteral *) override { return false; } + + bool isDeviceMangleContext() const override { return IsDevCtx; } + void setDeviceMangleContext(bool IsDev) override { IsDevCtx = IsDev; } + void mangleCXXName(GlobalDecl GD, raw_ostream &) override; void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &) override; @@ -546,8 +552,8 @@ class CXXNameMangler { unsigned knownArity); void mangleCastExpression(const Expr *E, StringRef CastEncoding); void mangleInitListElements(const InitListExpr *InitList); - void mangleDeclRefExpr(const NamedDecl *D); - void mangleExpression(const Expr *E, unsigned Arity = UnknownArity); + void mangleExpression(const Expr *E, unsigned Arity = UnknownArity, + bool AsTemplateArg = false); void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); void mangleCXXDtorType(CXXDtorType T); @@ -558,6 +564,7 @@ class CXXNameMangler { unsigned NumTemplateArgs); void mangleTemplateArgs(TemplateName TN, const TemplateArgumentList &AL); void mangleTemplateArg(TemplateArgument A, bool NeedExactType); + void mangleTemplateArgExpr(const Expr *E); void mangleValueInTemplateArg(QualType T, const APValue &V, bool TopLevel, bool NeedExactType = false); @@ -726,9 +733,17 @@ void CXXNameMangler::mangleFunctionEncodingBareType(const FunctionDecl *FD) { EnableIfAttr *EIA = dyn_cast(*I); if (!EIA) continue; - Out << 'X'; - mangleExpression(EIA->getCond()); - Out << 'E'; + if (Context.getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver11) { + mangleTemplateArgExpr(EIA->getCond()); + } else { + // Prior to Clang 12, we hardcoded the X/E around enable-if's argument, + // even though should not include an X/E around + // . + Out << 'X'; + mangleExpression(EIA->getCond()); + Out << 'E'; + } } Out << 'E'; FunctionTypeDepth.pop(Saved); @@ -1837,7 +1852,15 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { // (in lexical order) with that same and context. // // The AST keeps track of the number for us. - unsigned Number = Lambda->getLambdaManglingNumber(); + // + // In CUDA/HIP, to ensure the consistent lamba numbering between the device- + // and host-side compilations, an extra device mangle context may be created + // if the host-side CXX ABI has different numbering for lambda. In such case, + // if the mangle context is that device-side one, use the device-side lambda + // mangling number for this lambda. + unsigned Number = Context.isDeviceMangleContext() + ? Lambda->getDeviceLambdaManglingNumber() + : Lambda->getLambdaManglingNumber(); assert(Number > 0 && "Lambda should be mangled as an unnamed class"); if (Number > 1) mangleNumber(Number - 2); @@ -3528,8 +3551,8 @@ void CXXNameMangler::mangleType(const DependentSizedMatrixType *T) { Out << "u" << VendorQualifier.size() << VendorQualifier; Out << "I"; - mangleTemplateArg(T->getRowExpr(), false); - mangleTemplateArg(T->getColumnExpr(), false); + mangleTemplateArgExpr(T->getRowExpr()); + mangleTemplateArgExpr(T->getColumnExpr()); mangleType(T->getElementType()); Out << "E"; } @@ -3871,33 +3894,8 @@ void CXXNameMangler::mangleInitListElements(const InitListExpr *InitList) { mangleExpression(InitList->getInit(i)); } -void CXXNameMangler::mangleDeclRefExpr(const NamedDecl *D) { - switch (D->getKind()) { - default: - // ::= L E # external name - Out << 'L'; - mangle(D); - Out << 'E'; - break; - - case Decl::ParmVar: - mangleFunctionParam(cast(D)); - break; - - case Decl::EnumConstant: { - const EnumConstantDecl *ED = cast(D); - mangleIntegerLiteral(ED->getType(), ED->getInitVal()); - break; - } - - case Decl::NonTypeTemplateParm: - const NonTypeTemplateParmDecl *PD = cast(D); - mangleTemplateParameter(PD->getDepth(), PD->getIndex()); - break; - } -} - -void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { +void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, + bool AsTemplateArg) { // ::= // ::= // ::= @@ -3911,18 +3909,64 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // ::= at # alignof (a type) // ::= // ::= + // ::= fpT # 'this' expression (part of ) // ::= sr # dependent name // ::= sr # dependent template-id // ::= ds # expr.*expr // ::= sZ # size of a parameter pack // ::= sZ # size of a function parameter pack + // ::= u * E # vendor extended expression // ::= // ::= L E # integer literal - // ::= L E # floating literal + // ::= L E # floating literal + // ::= L E # string literal + // ::= L E # nullptr literal "LDnE" + // ::= L 0 E # null pointer template argument + // ::= L _ E # complex floating point literal (C99); not used by clang // ::= L E # external name - // ::= fpT # 'this' expression QualType ImplicitlyConvertedToType; + // A top-level expression that's not needs to be wrapped in + // X...E in a template arg. + bool IsPrimaryExpr = true; + auto NotPrimaryExpr = [&] { + if (AsTemplateArg && IsPrimaryExpr) + Out << 'X'; + IsPrimaryExpr = false; + }; + + auto MangleDeclRefExpr = [&](const NamedDecl *D) { + switch (D->getKind()) { + default: + // ::= L E # external name + Out << 'L'; + mangle(D); + Out << 'E'; + break; + + case Decl::ParmVar: + NotPrimaryExpr(); + mangleFunctionParam(cast(D)); + break; + + case Decl::EnumConstant: { + // + const EnumConstantDecl *ED = cast(D); + mangleIntegerLiteral(ED->getType(), ED->getInitVal()); + break; + } + + case Decl::NonTypeTemplateParm: + NotPrimaryExpr(); + const NonTypeTemplateParmDecl *PD = cast(D); + mangleTemplateParameter(PD->getDepth(), PD->getIndex()); + break; + } + }; + + // 'goto recurse' is used when handling a simple "unwrapping" node which + // produces no output, where ImplicitlyConvertedToType and AsTemplateArg need + // to be preserved. recurse: switch (E->getStmtClass()) { case Expr::NoStmtClass: @@ -3994,6 +4038,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::SourceLocExprClass: case Expr::BuiltinBitCastExprClass: { + NotPrimaryExpr(); if (!NullOut) { // As bad as this diagnostic is, it's better than crashing. DiagnosticsEngine &Diags = Context.getDiags(); @@ -4001,33 +4046,48 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { "cannot yet mangle expression type %0"); Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() << E->getSourceRange(); + return; } break; } case Expr::CXXUuidofExprClass: { + NotPrimaryExpr(); const CXXUuidofExpr *UE = cast(E); - if (UE->isTypeOperand()) { - QualType UuidT = UE->getTypeOperand(Context.getASTContext()); - Out << "u8__uuidoft"; - mangleType(UuidT); + // As of clang 12, uuidof uses the vendor extended expression + // mangling. Previously, it used a special-cased nonstandard extension. + if (Context.getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver11) { + Out << "u8__uuidof"; + if (UE->isTypeOperand()) + mangleType(UE->getTypeOperand(Context.getASTContext())); + else + mangleTemplateArgExpr(UE->getExprOperand()); + Out << 'E'; } else { - Expr *UuidExp = UE->getExprOperand(); - Out << "u8__uuidofz"; - mangleExpression(UuidExp, Arity); + if (UE->isTypeOperand()) { + QualType UuidT = UE->getTypeOperand(Context.getASTContext()); + Out << "u8__uuidoft"; + mangleType(UuidT); + } else { + Expr *UuidExp = UE->getExprOperand(); + Out << "u8__uuidofz"; + mangleExpression(UuidExp); + } } break; } // Even gcc-4.5 doesn't mangle this. case Expr::BinaryConditionalOperatorClass: { + NotPrimaryExpr(); DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "?: operator with omitted middle operand cannot be mangled"); Diags.Report(E->getExprLoc(), DiagID) << E->getStmtClassName() << E->getSourceRange(); - break; + return; } // These are used for internal purposes and cannot be meaningfully mangled. @@ -4035,6 +4095,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { llvm_unreachable("cannot mangle opaque value; mangling wrong thing?"); case Expr::InitListExprClass: { + NotPrimaryExpr(); Out << "il"; mangleInitListElements(cast(E)); Out << "E"; @@ -4042,6 +4103,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::DesignatedInitExprClass: { + NotPrimaryExpr(); auto *DIE = cast(E); for (const auto &Designator : DIE->designators()) { if (Designator.isFieldDesignator()) { @@ -4063,27 +4125,27 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXDefaultArgExprClass: - mangleExpression(cast(E)->getExpr(), Arity); - break; + E = cast(E)->getExpr(); + goto recurse; case Expr::CXXDefaultInitExprClass: - mangleExpression(cast(E)->getExpr(), Arity); - break; + E = cast(E)->getExpr(); + goto recurse; case Expr::CXXStdInitializerListExprClass: - mangleExpression(cast(E)->getSubExpr(), Arity); - break; + E = cast(E)->getSubExpr(); + goto recurse; case Expr::SubstNonTypeTemplateParmExprClass: - mangleExpression(cast(E)->getReplacement(), - Arity); - break; + E = cast(E)->getReplacement(); + goto recurse; case Expr::UserDefinedLiteralClass: // We follow g++'s approach of mangling a UDL as a call to the literal // operator. case Expr::CXXMemberCallExprClass: // fallthrough case Expr::CallExprClass: { + NotPrimaryExpr(); const CallExpr *CE = cast(E); // ::= cp * E @@ -4114,6 +4176,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXNewExprClass: { + NotPrimaryExpr(); const CXXNewExpr *New = cast(E); if (New->isGlobalNew()) Out << "gs"; Out << (New->isArray() ? "na" : "nw"); @@ -4149,6 +4212,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXPseudoDestructorExprClass: { + NotPrimaryExpr(); const auto *PDE = cast(E); if (const Expr *Base = PDE->getBase()) mangleMemberExprBase(Base, PDE->isArrow()); @@ -4175,6 +4239,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::MemberExprClass: { + NotPrimaryExpr(); const MemberExpr *ME = cast(E); mangleMemberExpr(ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, @@ -4185,6 +4250,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::UnresolvedMemberExprClass: { + NotPrimaryExpr(); const UnresolvedMemberExpr *ME = cast(E); mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), ME->isArrow(), ME->getQualifier(), nullptr, @@ -4195,6 +4261,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXDependentScopeMemberExprClass: { + NotPrimaryExpr(); const CXXDependentScopeMemberExpr *ME = cast(E); mangleMemberExpr(ME->isImplicitAccess() ? nullptr : ME->getBase(), @@ -4207,6 +4274,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::UnresolvedLookupExprClass: { + NotPrimaryExpr(); const UnresolvedLookupExpr *ULE = cast(E); mangleUnresolvedName(ULE->getQualifier(), ULE->getName(), ULE->getTemplateArgs(), ULE->getNumTemplateArgs(), @@ -4215,6 +4283,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXUnresolvedConstructExprClass: { + NotPrimaryExpr(); const CXXUnresolvedConstructExpr *CE = cast(E); unsigned N = CE->getNumArgs(); @@ -4225,7 +4294,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { mangleType(CE->getType()); mangleInitListElements(IL); Out << "E"; - return; + break; } Out << "cv"; @@ -4237,14 +4306,17 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXConstructExprClass: { + // An implicit cast is silent, thus may contain . const auto *CE = cast(E); if (!CE->isListInitialization() || CE->isStdInitListInitialization()) { assert( CE->getNumArgs() >= 1 && (CE->getNumArgs() == 1 || isa(CE->getArg(1))) && "implicit CXXConstructExpr must have one argument"); - return mangleExpression(cast(E)->getArg(0)); + E = cast(E)->getArg(0); + goto recurse; } + NotPrimaryExpr(); Out << "il"; for (auto *E : CE->arguments()) mangleExpression(E); @@ -4253,6 +4325,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXTemporaryObjectExprClass: { + NotPrimaryExpr(); const auto *CE = cast(E); unsigned N = CE->getNumArgs(); bool List = CE->isListInitialization(); @@ -4282,17 +4355,20 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXScalarValueInitExprClass: + NotPrimaryExpr(); Out << "cv"; mangleType(E->getType()); Out << "_E"; break; case Expr::CXXNoexceptExprClass: + NotPrimaryExpr(); Out << "nx"; mangleExpression(cast(E)->getOperand()); break; case Expr::UnaryExprOrTypeTraitExprClass: { + // Non-instantiation-dependent traits are an integer literal. const UnaryExprOrTypeTraitExpr *SAE = cast(E); if (!SAE->isInstantiationDependent()) { @@ -4312,13 +4388,41 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { break; } + NotPrimaryExpr(); // But otherwise, they are not. + + auto MangleAlignofSizeofArg = [&] { + if (SAE->isArgumentType()) { + Out << 't'; + mangleType(SAE->getArgumentType()); + } else { + Out << 'z'; + mangleExpression(SAE->getArgumentExpr()); + } + }; + switch(SAE->getKind()) { case UETT_SizeOf: Out << 's'; + MangleAlignofSizeofArg(); break; case UETT_PreferredAlignOf: + // As of clang 12, we mangle __alignof__ differently than alignof. (They + // have acted differently since Clang 8, but were previously mangled the + // same.) + if (Context.getASTContext().getLangOpts().getClangABICompat() > + LangOptions::ClangABI::Ver11) { + Out << "u11__alignof__"; + if (SAE->isArgumentType()) + mangleType(SAE->getArgumentType()); + else + mangleTemplateArgExpr(SAE->getArgumentExpr()); + Out << 'E'; + break; + } + LLVM_FALLTHROUGH; case UETT_AlignOf: Out << 'a'; + MangleAlignofSizeofArg(); break; case UETT_VecStep: { DiagnosticsEngine &Diags = Context.getDiags(); @@ -4336,17 +4440,11 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { return; } } - if (SAE->isArgumentType()) { - Out << 't'; - mangleType(SAE->getArgumentType()); - } else { - Out << 'z'; - mangleExpression(SAE->getArgumentExpr()); - } break; } case Expr::CXXThrowExprClass: { + NotPrimaryExpr(); const CXXThrowExpr *TE = cast(E); // ::= tw # throw expression // ::= tr # rethrow @@ -4360,6 +4458,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXTypeidExprClass: { + NotPrimaryExpr(); const CXXTypeidExpr *TIE = cast(E); // ::= ti # typeid (type) // ::= te # typeid (expression) @@ -4374,6 +4473,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXDeleteExprClass: { + NotPrimaryExpr(); const CXXDeleteExpr *DE = cast(E); // ::= [gs] dl # [::] delete expr // ::= [gs] da # [::] delete [] expr @@ -4384,6 +4484,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::UnaryOperatorClass: { + NotPrimaryExpr(); const UnaryOperator *UO = cast(E); mangleOperatorName(UnaryOperator::getOverloadedOperator(UO->getOpcode()), /*Arity=*/1); @@ -4392,6 +4493,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::ArraySubscriptExprClass: { + NotPrimaryExpr(); const ArraySubscriptExpr *AE = cast(E); // Array subscript is treated as a syntactically weird form of @@ -4403,6 +4505,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::MatrixSubscriptExprClass: { + NotPrimaryExpr(); const MatrixSubscriptExpr *ME = cast(E); Out << "ixix"; mangleExpression(ME->getBase()); @@ -4413,6 +4516,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::CompoundAssignOperatorClass: // fallthrough case Expr::BinaryOperatorClass: { + NotPrimaryExpr(); const BinaryOperator *BO = cast(E); if (BO->getOpcode() == BO_PtrMemD) Out << "ds"; @@ -4425,6 +4529,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXRewrittenBinaryOperatorClass: { + NotPrimaryExpr(); // The mangled form represents the original syntax. CXXRewrittenBinaryOperator::DecomposedForm Decomposed = cast(E)->getDecomposedForm(); @@ -4436,6 +4541,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::ConditionalOperatorClass: { + NotPrimaryExpr(); const ConditionalOperator *CO = cast(E); mangleOperatorName(OO_Conditional, /*Arity=*/3); mangleExpression(CO->getCond()); @@ -4451,19 +4557,22 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::ObjCBridgedCastExprClass: { + NotPrimaryExpr(); // Mangle ownership casts as a vendor extended operator __bridge, // __bridge_transfer, or __bridge_retain. StringRef Kind = cast(E)->getBridgeKindName(); Out << "v1U" << Kind.size() << Kind; + mangleCastExpression(E, "cv"); + break; } - // Fall through to mangle the cast itself. - LLVM_FALLTHROUGH; case Expr::CStyleCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "cv"); break; case Expr::CXXFunctionalCastExprClass: { + NotPrimaryExpr(); auto *Sub = cast(E)->getSubExpr()->IgnoreImplicit(); // FIXME: Add isImplicit to CXXConstructExpr. if (auto *CCE = dyn_cast(Sub)) @@ -4483,22 +4592,28 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXStaticCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "sc"); break; case Expr::CXXDynamicCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "dc"); break; case Expr::CXXReinterpretCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "rc"); break; case Expr::CXXConstCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "cc"); break; case Expr::CXXAddrspaceCastExprClass: + NotPrimaryExpr(); mangleCastExpression(E, "ac"); break; case Expr::CXXOperatorCallExprClass: { + NotPrimaryExpr(); const CXXOperatorCallExpr *CE = cast(E); unsigned NumArgs = CE->getNumArgs(); // A CXXOperatorCallExpr for OO_Arrow models only semantics, not syntax @@ -4512,9 +4627,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::ParenExprClass: - mangleExpression(cast(E)->getSubExpr(), Arity); - break; - + E = cast(E)->getSubExpr(); + goto recurse; case Expr::ConceptSpecializationExprClass: { // ::= L E # external name @@ -4528,10 +4642,12 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::DeclRefExprClass: - mangleDeclRefExpr(cast(E)->getDecl()); + // MangleDeclRefExpr helper handles primary-vs-nonprimary + MangleDeclRefExpr(cast(E)->getDecl()); break; case Expr::SubstNonTypeTemplateParmPackExprClass: + NotPrimaryExpr(); // FIXME: not clear how to mangle this! // template class A { // template void foo(U (&x)[N]...); @@ -4540,14 +4656,16 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { break; case Expr::FunctionParmPackExprClass: { + NotPrimaryExpr(); // FIXME: not clear how to mangle this! const FunctionParmPackExpr *FPPE = cast(E); Out << "v110_SUBSTPACK"; - mangleDeclRefExpr(FPPE->getParameterPack()); + MangleDeclRefExpr(FPPE->getParameterPack()); break; } case Expr::DependentScopeDeclRefExprClass: { + NotPrimaryExpr(); const DependentScopeDeclRefExpr *DRE = cast(E); mangleUnresolvedName(DRE->getQualifier(), DRE->getDeclName(), DRE->getTemplateArgs(), DRE->getNumTemplateArgs(), @@ -4556,24 +4674,27 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXBindTemporaryExprClass: - mangleExpression(cast(E)->getSubExpr()); - break; + E = cast(E)->getSubExpr(); + goto recurse; case Expr::ExprWithCleanupsClass: - mangleExpression(cast(E)->getSubExpr(), Arity); - break; + E = cast(E)->getSubExpr(); + goto recurse; case Expr::FloatingLiteralClass: { + // const FloatingLiteral *FL = cast(E); mangleFloatLiteral(FL->getType(), FL->getValue()); break; } case Expr::FixedPointLiteralClass: + // Currently unimplemented -- might be in future? mangleFixedPointLiteral(); break; case Expr::CharacterLiteralClass: + // Out << 'L'; mangleType(E->getType()); Out << cast(E)->getValue(); @@ -4582,18 +4703,21 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { // FIXME. __objc_yes/__objc_no are mangled same as true/false case Expr::ObjCBoolLiteralExprClass: + // Out << "Lb"; Out << (cast(E)->getValue() ? '1' : '0'); Out << 'E'; break; case Expr::CXXBoolLiteralExprClass: + // Out << "Lb"; Out << (cast(E)->getValue() ? '1' : '0'); Out << 'E'; break; case Expr::IntegerLiteralClass: { + // llvm::APSInt Value(cast(E)->getValue()); if (E->getType()->isSignedIntegerType()) Value.setIsSigned(true); @@ -4602,6 +4726,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::ImaginaryLiteralClass: { + // const ImaginaryLiteral *IE = cast(E); // Mangle as if a complex literal. // Proposal from David Vandevoorde, 2010.06.30. @@ -4625,6 +4750,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::StringLiteralClass: { + // // Revised proposal from David Vandervoorde, 2010.07.15. Out << 'L'; assert(isa(E->getType())); @@ -4634,21 +4760,25 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::GNUNullExprClass: + // // Mangle as if an integer literal 0. mangleIntegerLiteral(E->getType(), llvm::APSInt(32)); break; case Expr::CXXNullPtrLiteralExprClass: { + // Out << "LDnE"; break; } case Expr::PackExpansionExprClass: + NotPrimaryExpr(); Out << "sp"; mangleExpression(cast(E)->getPattern()); break; case Expr::SizeOfPackExprClass: { + NotPrimaryExpr(); auto *SPE = cast(E); if (SPE->isPartiallySubstituted()) { Out << "sP"; @@ -4673,12 +4803,12 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { break; } - case Expr::MaterializeTemporaryExprClass: { - mangleExpression(cast(E)->getSubExpr()); - break; - } + case Expr::MaterializeTemporaryExprClass: + E = cast(E)->getSubExpr(); + goto recurse; case Expr::CXXFoldExprClass: { + NotPrimaryExpr(); auto *FE = cast(E); if (FE->isLeftFold()) Out << (FE->getInit() ? "fL" : "fl"); @@ -4700,27 +4830,34 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { } case Expr::CXXThisExprClass: + NotPrimaryExpr(); Out << "fpT"; break; case Expr::CoawaitExprClass: // FIXME: Propose a non-vendor mangling. + NotPrimaryExpr(); Out << "v18co_await"; mangleExpression(cast(E)->getOperand()); break; case Expr::DependentCoawaitExprClass: // FIXME: Propose a non-vendor mangling. + NotPrimaryExpr(); Out << "v18co_await"; mangleExpression(cast(E)->getOperand()); break; case Expr::CoyieldExprClass: // FIXME: Propose a non-vendor mangling. + NotPrimaryExpr(); Out << "v18co_yield"; mangleExpression(cast(E)->getOperand()); break; } + + if (AsTemplateArg && !IsPrimaryExpr) + Out << 'E'; } /// Mangle an expression which refers to a parameter variable. @@ -4970,26 +5107,9 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { Out << "Dp"; mangleType(A.getAsTemplateOrTemplatePattern()); break; - case TemplateArgument::Expression: { - // It's possible to end up with a DeclRefExpr here in certain - // dependent cases, in which case we should mangle as a - // declaration. - const Expr *E = A.getAsExpr()->IgnoreParenImpCasts(); - if (const DeclRefExpr *DRE = dyn_cast(E)) { - const ValueDecl *D = DRE->getDecl(); - if (isa(D) || isa(D)) { - Out << 'L'; - mangle(D); - Out << 'E'; - break; - } - } - - Out << 'X'; - mangleExpression(E); - Out << 'E'; + case TemplateArgument::Expression: + mangleTemplateArgExpr(A.getAsExpr()); break; - } case TemplateArgument::Integral: mangleIntegerLiteral(A.getIntegralType(), A.getAsIntegral()); break; @@ -5044,6 +5164,38 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A, bool NeedExactType) { } } +void CXXNameMangler::mangleTemplateArgExpr(const Expr *E) { + ASTContext &Ctx = Context.getASTContext(); + if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver11) { + mangleExpression(E, UnknownArity, /*AsTemplateArg=*/true); + return; + } + + // Prior to Clang 12, we didn't omit the X .. E around + // correctly in cases where the template argument was + // constructed from an expression rather than an already-evaluated + // literal. In such a case, we would then e.g. emit 'XLi0EE' instead of + // 'Li0E'. + // + // We did special-case DeclRefExpr to attempt to DTRT for that one + // expression-kind, but while doing so, unfortunately handled ParmVarDecl + // (subtype of VarDecl) _incorrectly_, and emitted 'L_Z .. E' instead of + // the proper 'Xfp_E'. + E = E->IgnoreParenImpCasts(); + if (const DeclRefExpr *DRE = dyn_cast(E)) { + const ValueDecl *D = DRE->getDecl(); + if (isa(D) || isa(D)) { + Out << 'L'; + mangle(D); + Out << 'E'; + return; + } + } + Out << 'X'; + mangleExpression(E); + Out << 'E'; +} + /// Determine whether a given value is equivalent to zero-initialization for /// the purpose of discarding a trailing portion of a 'tl' mangling. /// diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index f9f9fe985b6f9..166aa3b3bd603 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -16,6 +16,7 @@ #include "clang/AST/Attr.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/Mangle.h" #include "clang/AST/MangleNumberingContext.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/Type.h" @@ -64,6 +65,19 @@ class MicrosoftNumberingContext : public MangleNumberingContext { } }; +class MSHIPNumberingContext : public MicrosoftNumberingContext { + std::unique_ptr DeviceCtx; + +public: + MSHIPNumberingContext(MangleContext *DeviceMangler) { + DeviceCtx = createItaniumNumberingContext(DeviceMangler); + } + + unsigned getDeviceManglingNumber(const CXXMethodDecl *CallOperator) override { + return DeviceCtx->getManglingNumber(CallOperator); + } +}; + class MicrosoftCXXABI : public CXXABI { ASTContext &Context; llvm::SmallDenseMap RecordToCopyCtor; @@ -73,8 +87,20 @@ class MicrosoftCXXABI : public CXXABI { llvm::SmallDenseMap UnnamedTagDeclToTypedefNameDecl; + // MangleContext for device numbering context, which is based on Itanium C++ + // ABI. + std::unique_ptr DeviceMangler; + public: - MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } + MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { + if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) { + assert(Context.getTargetInfo().getCXXABI().isMicrosoft() && + Context.getAuxTargetInfo()->getCXXABI().isItaniumFamily() && + "Unexpected combination of C++ ABIs."); + DeviceMangler.reset( + Context.createMangleContext(Context.getAuxTargetInfo())); + } + } MemberPointerInfo getMemberPointerInfo(const MemberPointerType *MPT) const override; @@ -133,6 +159,10 @@ class MicrosoftCXXABI : public CXXABI { std::unique_ptr createMangleNumberingContext() const override { + if (Context.getLangOpts().CUDA && Context.getAuxTargetInfo()) { + assert(DeviceMangler && "Missing device mangler"); + return std::make_unique(DeviceMangler.get()); + } return std::make_unique(); } }; @@ -266,4 +296,3 @@ CXXABI::MemberPointerInfo MicrosoftCXXABI::getMemberPointerInfo( CXXABI *clang::CreateMicrosoftCXXABI(ASTContext &Ctx) { return new MicrosoftCXXABI(Ctx); } - diff --git a/clang/lib/ASTMatchers/ASTMatchFinder.cpp b/clang/lib/ASTMatchers/ASTMatchFinder.cpp index 8ddd3c87e09db..69957a952d17c 100644 --- a/clang/lib/ASTMatchers/ASTMatchFinder.cpp +++ b/clang/lib/ASTMatchers/ASTMatchFinder.cpp @@ -243,10 +243,14 @@ class MatchChildASTVisitor return true; ScopedIncrement ScopedDepth(&CurrentDepth); if (auto *Init = Node->getInit()) - if (!match(*Init)) + if (!traverse(*Init)) return false; - if (!match(*Node->getLoopVariable()) || !match(*Node->getRangeInit()) || - !match(*Node->getBody())) + if (!match(*Node->getLoopVariable())) + return false; + if (match(*Node->getRangeInit())) + if (!VisitorBase::TraverseStmt(Node->getRangeInit())) + return false; + if (!match(*Node->getBody())) return false; return VisitorBase::TraverseStmt(Node->getBody()); } @@ -291,7 +295,7 @@ class MatchChildASTVisitor if (!match(*Node->getBody())) return false; - return true; + return VisitorBase::TraverseStmt(Node->getBody()); } bool shouldVisitTemplateInstantiations() const { return true; } @@ -488,15 +492,21 @@ class MatchASTVisitor : public RecursiveASTVisitor, bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue) { if (auto *RF = dyn_cast(S)) { - for (auto *SubStmt : RF->children()) { - if (SubStmt == RF->getInit() || SubStmt == RF->getLoopVarStmt() || - SubStmt == RF->getRangeInit() || SubStmt == RF->getBody()) { - TraverseStmt(SubStmt, Queue); - } else { - ASTNodeNotSpelledInSourceScope RAII(this, true); - TraverseStmt(SubStmt, Queue); + { + ASTNodeNotAsIsSourceScope RAII(this, true); + TraverseStmt(RF->getInit()); + // Don't traverse under the loop variable + match(*RF->getLoopVariable()); + TraverseStmt(RF->getRangeInit()); + } + { + ASTNodeNotSpelledInSourceScope RAII(this, true); + for (auto *SubStmt : RF->children()) { + if (SubStmt != RF->getBody()) + TraverseStmt(SubStmt); } } + TraverseStmt(RF->getBody()); return true; } else if (auto *RBO = dyn_cast(S)) { { @@ -556,9 +566,9 @@ class MatchASTVisitor : public RecursiveASTVisitor, if (LE->hasExplicitResultType()) TraverseTypeLoc(Proto.getReturnLoc()); TraverseStmt(LE->getTrailingRequiresClause()); - - TraverseStmt(LE->getBody()); } + + TraverseStmt(LE->getBody()); return true; } return RecursiveASTVisitor::dataTraverseNode(S, Queue); @@ -697,6 +707,10 @@ class MatchASTVisitor : public RecursiveASTVisitor, bool shouldVisitTemplateInstantiations() const { return true; } bool shouldVisitImplicitCode() const { return true; } + // We visit the lambda body explicitly, so instruct the RAV + // to not visit it on our behalf too. + bool shouldVisitLambdaBody() const { return false; } + bool IsMatchingInASTNodeNotSpelledInSource() const override { return TraversingASTNodeNotSpelledInSource; } @@ -823,6 +837,14 @@ class MatchASTVisitor : public RecursiveASTVisitor, if (EnableCheckProfiling) Timer.setBucket(&TimeByBucket[MP.second->getID()]); BoundNodesTreeBuilder Builder; + + { + TraversalKindScope RAII(getASTContext(), MP.first.getTraversalKind()); + if (getASTContext().getParentMapContext().traverseIgnored(DynNode) != + DynNode) + continue; + } + if (MP.first.matches(DynNode, this, &Builder)) { MatchVisitor Visitor(ActiveASTContext, MP.second); Builder.visitMatches(&Visitor); diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 6c7e14e3499af..705f1cdf31533 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -732,7 +732,7 @@ const internal::VariadicDynCastAllOfMatcher typeAliasDecl; const internal::VariadicDynCastAllOfMatcher typeAliasTemplateDecl; const internal::VariadicAllOfMatcher decl; -const internal::VariadicAllOfMatcher decompositionDecl; +const internal::VariadicDynCastAllOfMatcher decompositionDecl; const internal::VariadicDynCastAllOfMatcher linkageSpecDecl; const internal::VariadicDynCastAllOfMatcher namedDecl; diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index e5319484393a6..4a81ec38275fa 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -75,6 +75,7 @@ add_clang_library(clangBasic Targets/ARM.cpp Targets/AVR.cpp Targets/BPF.cpp + Targets/DPU.cpp Targets/Hexagon.cpp Targets/Lanai.cpp Targets/Le64.cpp diff --git a/clang/lib/Basic/ProfileList.cpp b/clang/lib/Basic/ProfileList.cpp index 56bc37a79301e..2cb05c1c3c073 100644 --- a/clang/lib/Basic/ProfileList.cpp +++ b/clang/lib/Basic/ProfileList.cpp @@ -82,6 +82,7 @@ static StringRef getSectionName(CodeGenOptions::ProfileInstrKind Kind) { case CodeGenOptions::ProfileCSIRInstr: return "csllvm"; } + llvm_unreachable("Unhandled CodeGenOptions::ProfileInstrKind enum"); } llvm::Optional diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 90a67d03b7b20..e8984bb224dd3 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -19,6 +19,7 @@ #include "Targets/ARM.h" #include "Targets/AVR.h" #include "Targets/BPF.h" +#include "Targets/DPU.h" #include "Targets/Hexagon.h" #include "Targets/Lanai.h" #include "Targets/Le64.h" @@ -633,6 +634,9 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::ve: return new LinuxTargetInfo(Triple, Opts); + + case llvm::Triple::dpu: + return new DPUTargetInfo(Triple, Opts); } } } // namespace targets diff --git a/clang/lib/Basic/Targets/DPU.cpp b/clang/lib/Basic/Targets/DPU.cpp new file mode 100644 index 0000000000000..93e1132d315c7 --- /dev/null +++ b/clang/lib/Basic/Targets/DPU.cpp @@ -0,0 +1,81 @@ +//===--- DPU.cpp - Implement DPU target feature support ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements DPU TargetInfo objects. +// +//===----------------------------------------------------------------------===// + +#include "DPU.h" +#include + +#include "clang/Basic/Builtins.h" +#include "clang/Basic/MacroBuilder.h" +#include "clang/Basic/TargetBuiltins.h" + +using namespace clang; +using namespace clang::targets; + +const Builtin::Info DPUTargetInfo::BuiltinInfo[] = { +#define BUILTIN(ID, TYPE, ATTRS) \ + {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr}, + +#include "clang/Basic/BuiltinsDPU.def" +}; + +void DPUTargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + DefineStd(Builder, "DPU", Opts); + Builder.defineMacro("__ELF__"); + + switch (getTriple().getSubArch()) { + case llvm::Triple::DPUSubArch_v1a: { + Builder.defineMacro("__dpu_v1A__"); + break; + } + case llvm::Triple::DPUSubArch_v1b: { + Builder.defineMacro("__dpu_v1B__"); + break; + } + default: + llvm_unreachable("Unhandled Triple."); + break; + } +} + +ArrayRef DPUTargetInfo::getTargetBuiltins() const { + return llvm::makeArrayRef(BuiltinInfo, clang::DPU::LastTSBuiltin - + Builtin::FirstTSBuiltin); +} + +struct DPUCPUInfo { + llvm::StringLiteral Name; + DPUTargetInfo::CPUKind Kind; +}; + +static constexpr DPUCPUInfo CPUInfo[] = { + {{"v1A"}, DPUTargetInfo::CK_V1A}, + {{"v1B"}, DPUTargetInfo::CK_V1B}, +}; + +DPUTargetInfo::CPUKind DPUTargetInfo::getCPUKind(StringRef Name) const { + const DPUCPUInfo *Item = llvm::find_if( + CPUInfo, [Name](const DPUCPUInfo &Info) { return Info.Name == Name; }); + + if (Item == std::end(CPUInfo)) { + return CK_GENERIC; + } + + return Item->Kind; +} + +void DPUTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + for (const DPUCPUInfo &Info : CPUInfo) + Values.push_back(Info.Name); +} diff --git a/clang/lib/Basic/Targets/DPU.h b/clang/lib/Basic/Targets/DPU.h new file mode 100644 index 0000000000000..d4da1f718a6ef --- /dev/null +++ b/clang/lib/Basic/Targets/DPU.h @@ -0,0 +1,110 @@ +//===--- DPU.h - Declare DPU target feature support -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares DPU TargetInfo objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_DPU_H +#define LLVM_CLANG_LIB_BASIC_TARGETS_DPU_H + +#include "clang/Basic/TargetInfo.h" +#include "clang/Basic/TargetOptions.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Support/Compiler.h" + +namespace clang { +namespace targets { +class DPUTargetInfo : public TargetInfo { + static const Builtin::Info BuiltinInfo[]; + +public: + DPUTargetInfo(const llvm::Triple &Triple, const TargetOptions &) + : TargetInfo(Triple) { + BigEndian = false; + TLSSupported = true; + SuitableAlign = 32; + LongWidth = 64; + LongAlign = 64; + LongLongWidth = 64; + LongLongAlign = 64; + DoubleWidth = 64; + DoubleAlign = 64; + LongDoubleWidth = 64; + LongDoubleAlign = 64; + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + WCharType = UnsignedChar; + WIntType = UnsignedInt; + NoAsmVariants = true; + resetDataLayout( + "e-m:e-p:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:64:64-n32"); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; + + bool hasFeature(StringRef Feature) const override { return Feature == "dpu"; } + + ArrayRef getTargetBuiltins() const override; + + const char *getClobbers() const override { return ""; } + + ArrayRef getGCCRegNames() const override { + static const char *const GCCRegNames[] = { + // 32-bit Integer registers + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + + // 64-bit Integer registers + "d0", "d2", "d4", "d6", + "d8", "d10", "d12", "d14", + "d16", "d18", "d20", "d22" + }; + return llvm::makeArrayRef(GCCRegNames); + } + + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &info) const override { + // return false; + return true; + } + + ArrayRef getGCCRegAliases() const override { + return None; + } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::VoidPtrBuiltinVaList; + } + + enum CPUKind { + CK_GENERIC, + CK_V1A, + CK_V1B + } CPU = CK_GENERIC; + + CPUKind getCPUKind(StringRef Name) const; + + bool isValidCPUName(StringRef Name) const override { + return getCPUKind(Name) != CK_GENERIC; + } + + void fillValidCPUList(SmallVectorImpl &Values) const override; + + bool setCPU(const std::string &Name) override { + CPU = getCPUKind(Name); + return CPU != CK_GENERIC; + } +}; +} // namespace targets +} // namespace clang + +#endif // LLVM_CLANG_LIB_BASIC_TARGETS_DPU_H diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index cfede6e6e756a..ff09c0fa2a234 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -318,9 +318,6 @@ bool PPCTargetInfo::initFeatureMap( .Case("pwr9", true) .Case("pwr8", true) .Default(false); - Features["float128"] = llvm::StringSwitch(CPU) - .Case("pwr9", true) - .Default(false); Features["spe"] = llvm::StringSwitch(CPU) .Case("8548", true) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 0bf02e6057400..786201ea340d2 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -150,7 +150,7 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, } if (HasV) { - Builder.defineMacro("__riscv_v", "1000000"); + Builder.defineMacro("__riscv_v", "10000"); Builder.defineMacro("__riscv_vector"); } @@ -191,10 +191,10 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__riscv_zfh", "1000"); if (HasZvamo) - Builder.defineMacro("__riscv_zvamo", "1000000"); + Builder.defineMacro("__riscv_zvamo", "10000"); if (HasZvlsseg) - Builder.defineMacro("__riscv_zvlsseg", "1000000"); + Builder.defineMacro("__riscv_zvlsseg", "10000"); } /// Return true if has this feature, need to sync with handleTargetFeatures. diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 113541bd5024e..4af115b4f2543 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -36,6 +36,7 @@ #include "llvm/IR/IntrinsicsAMDGPU.h" #include "llvm/IR/IntrinsicsARM.h" #include "llvm/IR/IntrinsicsBPF.h" +#include "llvm/IR/IntrinsicsDPU.h" #include "llvm/IR/IntrinsicsHexagon.h" #include "llvm/IR/IntrinsicsNVPTX.h" #include "llvm/IR/IntrinsicsPowerPC.h" @@ -5138,6 +5139,8 @@ static Value *EmitTargetArchBuiltinExpr(CodeGenFunction *CGF, return CGF->EmitWebAssemblyBuiltinExpr(BuiltinID, E); case llvm::Triple::hexagon: return CGF->EmitHexagonBuiltinExpr(BuiltinID, E); + case llvm::Triple::dpu: + return CGF->EmitDPUBuiltinExpr(BuiltinID, E); default: return nullptr; } @@ -13794,12 +13797,14 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID, case X86::BI__builtin_ia32_reduce_fadd_ps512: { Function *F = CGM.getIntrinsic(Intrinsic::vector_reduce_fadd, Ops[1]->getType()); + Builder.getFastMathFlags().setAllowReassoc(true); return Builder.CreateCall(F, {Ops[0], Ops[1]}); } case X86::BI__builtin_ia32_reduce_fmul_pd512: case X86::BI__builtin_ia32_reduce_fmul_ps512: { Function *F = CGM.getIntrinsic(Intrinsic::vector_reduce_fmul, Ops[1]->getType()); + Builder.getFastMathFlags().setAllowReassoc(true); return Builder.CreateCall(F, {Ops[0], Ops[1]}); } case X86::BI__builtin_ia32_reduce_mul_d512: @@ -17345,6 +17350,34 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, } } +Value *CodeGenFunction::EmitDPUBuiltinExpr(unsigned BuiltinID, + const CallExpr *E) { + switch (BuiltinID) { + case DPU::BI__builtin_dpu_tid: { + llvm::Type *ResultType = ConvertType(E->getType()); + llvm::Function *Callee = CGM.getIntrinsic(Intrinsic::dpu_tid, ResultType); + return Builder.CreateCall(Callee); + } + case DPU::BI__builtin_dpu_sdma: { + llvm::Function *Callee = CGM.getIntrinsic(Intrinsic::dpu_sdma); + Value *Arg0 = EmitPointerWithAlignment(E->getArg(0)).getPointer(); + Value *Arg1 = EmitPointerWithAlignment(E->getArg(1)).getPointer(); + Value *Arg2 = EmitScalarExpr(E->getArg(2)); + return Builder.CreateCall(Callee, {Arg0, Arg1, Arg2}); + } + case DPU::BI__builtin_dpu_ldma: { + llvm::Function *Callee = CGM.getIntrinsic(Intrinsic::dpu_ldma); + Value *Arg0 = EmitPointerWithAlignment(E->getArg(0)).getPointer(); + Value *Arg1 = EmitPointerWithAlignment(E->getArg(1)).getPointer(); + Value *Arg2 = EmitScalarExpr(E->getArg(2)); + return Builder.CreateCall(Callee, {Arg0, Arg1, Arg2}); + } + + default: + return nullptr; + } +} + static std::pair getIntrinsicForHexagonNonGCCBuiltin(unsigned BuiltinID) { struct Info { diff --git a/clang/lib/CodeGen/CGCUDANV.cpp b/clang/lib/CodeGen/CGCUDANV.cpp index 33a2d6f4483ec..e03631a7243a1 100644 --- a/clang/lib/CodeGen/CGCUDANV.cpp +++ b/clang/lib/CodeGen/CGCUDANV.cpp @@ -184,6 +184,14 @@ CGNVCUDARuntime::CGNVCUDARuntime(CodeGenModule &CGM) CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy)); VoidPtrTy = cast(Types.ConvertType(Ctx.VoidPtrTy)); VoidPtrPtrTy = VoidPtrTy->getPointerTo(); + if (CGM.getContext().getAuxTargetInfo()) { + // If the host and device have different C++ ABIs, mark it as the device + // mangle context so that the mangling needs to retrieve the additonal + // device lambda mangling number instead of the regular host one. + DeviceMC->setDeviceMangleContext( + CGM.getContext().getTargetInfo().getCXXABI().isMicrosoft() && + CGM.getContext().getAuxTargetInfo()->getCXXABI().isItaniumFamily()); + } } llvm::FunctionCallee CGNVCUDARuntime::getSetupArgumentFn() const { diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 42801372189b1..bc7582c679894 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1995,9 +1995,14 @@ void CodeGenModule::ConstructAttributeList( if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadNone); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'const' functions have greater restrictions than + // 'pure' functions, so they also cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'pure' functions cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index 57cc2d60e2af0..83dfa0780547d 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -9892,7 +9892,7 @@ void CGOpenMPRuntime::emitTargetNumIterationsCall( llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; CGF.EmitRuntimeCall( OMPBuilder.getOrCreateRuntimeFunction( - CGM.getModule(), OMPRTL___kmpc_push_target_tripcount), + CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), Args); } }; diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 8eb7adbc8fcb4..492f13c075ed6 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -507,12 +507,23 @@ class CodeGenFunction : public CodeGenTypeCache { /// True if the C++ Standard Requires Progress. bool CPlusPlusWithProgress() { + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Never) + return false; + return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 || getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20; } /// True if the C Standard Requires Progress. bool CWithProgress() { + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Always) + return true; + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Never) + return false; + return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x; } @@ -4116,6 +4127,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitNVPTXBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitWebAssemblyBuiltinExpr(unsigned BuiltinID, const CallExpr *E); + llvm::Value *EmitDPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitHexagonBuiltinExpr(unsigned BuiltinID, const CallExpr *E); bool ProcessOrderScopeAMDGCN(llvm::Value *Order, llvm::Value *Scope, llvm::AtomicOrdering &AO, diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index aeffcf0bb43ae..ec9f1a03b82a9 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -26,6 +26,7 @@ add_clang_library(clangDriver ToolChain.cpp ToolChains/Arch/AArch64.cpp ToolChains/Arch/ARM.cpp + ToolChains/Arch/DPU.cpp ToolChains/Arch/Mips.cpp ToolChains/Arch/PPC.cpp ToolChains/Arch/RISCV.cpp @@ -45,6 +46,7 @@ add_clang_library(clangDriver ToolChains/CrossWindows.cpp ToolChains/Cuda.cpp ToolChains/Darwin.cpp + ToolChains/DPURTE.cpp ToolChains/DragonFly.cpp ToolChains/Flang.cpp ToolChains/FreeBSD.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 418e1d3e8ec99..a76eebb72f6c1 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -41,6 +41,7 @@ #include "ToolChains/PPCLinux.h" #include "ToolChains/PS4CPU.h" #include "ToolChains/RISCVToolchain.h" +#include "ToolChains/DPURTE.h" #include "ToolChains/Solaris.h" #include "ToolChains/TCE.h" #include "ToolChains/VEToolchain.h" @@ -5170,6 +5171,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, case llvm::Triple::PS4: TC = std::make_unique(*this, Target, Args); break; + case llvm::Triple::DPURTe: + TC = std::make_unique(*this, Target, Args); + break; case llvm::Triple::Contiki: TC = std::make_unique(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/Arch/DPU.cpp b/clang/lib/Driver/ToolChains/Arch/DPU.cpp new file mode 100644 index 0000000000000..e13d47d0ca98d --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/DPU.cpp @@ -0,0 +1,44 @@ +//===--- DPU.cpp - Tools Implementations ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "DPU.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/ArgList.h" + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +std::string dpu::getDPUVersionFromArgs(const ArgList &Args) { + std::string SubArch; + + if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { + SubArch = A->getValue(); + } else if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + SubArch = A->getValue(); + } + + if (SubArch.empty()) { + SubArch = "v1A"; + } + + return SubArch; +} + +std::string dpu::getDPUTargetCPU(const ArgList &Args, + const llvm::Triple &Triple) { + return getDPUVersionFromArgs(Args); +} + +void dpu::getDPUTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args, ArgStringList &CmdArgs, + std::vector &Features) {} diff --git a/clang/lib/Driver/ToolChains/Arch/DPU.h b/clang/lib/Driver/ToolChains/Arch/DPU.h new file mode 100644 index 0000000000000..106000a05f9fc --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/DPU.h @@ -0,0 +1,38 @@ +//===--- DPU.h - DPU-specific Tool Helpers ----------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_DPU_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_DPU_H + +#include "clang/Driver/Driver.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Option.h" +#include +#include + +namespace clang { +namespace driver { +namespace tools { +namespace dpu { + + std::string getDPUVersionFromArgs(const llvm::opt::ArgList &Args); + + std::string getDPUTargetCPU(const llvm::opt::ArgList &Args, + const llvm::Triple &Triple); + + void getDPUTargetFeatures(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs, + std::vector &Features); + +} // end namespace dpu +} // end namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_DPU_H diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index ffae47e5672ed..c7f2a3ea5e023 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -63,7 +63,7 @@ isExperimentalExtension(StringRef Ext) { Ext == "zbr" || Ext == "zbs" || Ext == "zbt" || Ext == "zbproposedc") return RISCVExtensionVersion{"0", "93"}; if (Ext == "v" || Ext == "zvamo" || Ext == "zvlsseg") - return RISCVExtensionVersion{"1", "0"}; + return RISCVExtensionVersion{"0", "10"}; if (Ext == "zfh") return RISCVExtensionVersion{"0", "1"}; return None; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index fdb8a58cd1b34..1976b48e0f6a4 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4669,20 +4669,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - if (Triple.isOSAIX() && Args.hasArg(options::OPT_maltivec)) { - if (Args.getLastArg(options::OPT_mabi_EQ_vec_extabi)) { - CmdArgs.push_back("-mabi=vec-extabi"); - } else { - D.Diag(diag::err_aix_default_altivec_abi); - } - } - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ_vec_extabi, options::OPT_mabi_EQ_vec_default)) { if (!Triple.isOSAIX()) D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getSpelling() << RawTriple.str(); - if (A->getOption().getID() == options::OPT_mabi_EQ_vec_default) + if (A->getOption().getID() == options::OPT_mabi_EQ_vec_extabi) + CmdArgs.push_back("-mabi=vec-extabi"); + else D.Diag(diag::err_aix_default_altivec_abi); } @@ -5626,6 +5620,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (A->getOption().matches(options::OPT_freroll_loops)) CmdArgs.push_back("-freroll-loops"); + Args.AddLastArg(CmdArgs, options::OPT_ffinite_loops, + options::OPT_fno_finite_loops); + Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); Args.AddLastArg(CmdArgs, options::OPT_funroll_loops, options::OPT_fno_unroll_loops); diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 6a95aa5ec6287..e9ed3320fd7c1 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -9,6 +9,7 @@ #include "CommonArgs.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" +#include "Arch/DPU.h" #include "Arch/Mips.h" #include "Arch/PPC.h" #include "Arch/SystemZ.h" @@ -372,6 +373,10 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, return A->getValue(); return ""; + case llvm::Triple::dpu: { + return dpu::getDPUTargetCPU(Args, T); + } + case llvm::Triple::mips: case llvm::Triple::mipsel: case llvm::Triple::mips64: @@ -605,6 +610,11 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args, CmdArgs.push_back("-plugin-opt=new-pass-manager"); } + // Pass an option to enable pseudo probe emission. + if (Args.hasFlag(options::OPT_fpseudo_probe_for_profiling, + options::OPT_fno_pseudo_probe_for_profiling, false)) + CmdArgs.push_back("-plugin-opt=pseudo-probe-for-profiling"); + // Setup statistics file output. SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D); if (!StatsFile.empty()) diff --git a/clang/lib/Driver/ToolChains/DPUCharacteristics.h b/clang/lib/Driver/ToolChains/DPUCharacteristics.h new file mode 100644 index 0000000000000..dad5c40c96b3a --- /dev/null +++ b/clang/lib/Driver/ToolChains/DPUCharacteristics.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2014-2019 - UPMEM + */ + +#ifndef __DPU_CHARACTERISTICS_H +#define __DPU_CHARACTERISTICS_H + +#define DPU_WRAM_SIZE_V1A 65536 +#define DPU_IRAM_SIZE_V1A 32768 +#define DPU_ATOMIC_SIZE_V1A 256 +#define DPU_NR_THREADS_V1A 24 + +#define DPU_WRAM_SIZE_V1B 63488 +#define DPU_IRAM_SIZE_V1B 31744 +#define DPU_ATOMIC_SIZE_V1B 64 +#define DPU_NR_THREADS_V1B 16 + +#endif /* __DPU_CHARACTERISTICS_H */ diff --git a/clang/lib/Driver/ToolChains/DPURTE.cpp b/clang/lib/Driver/ToolChains/DPURTE.cpp new file mode 100644 index 0000000000000..d506edc78b362 --- /dev/null +++ b/clang/lib/Driver/ToolChains/DPURTE.cpp @@ -0,0 +1,308 @@ +//===--- DPURTE.h - DPU RTE ToolChain Implementations -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Arch/DPU.h" +#include "DPURTE.h" +#include "CommonArgs.h" +#include "InputInfo.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/VirtualFileSystem.h" + +#include "DPUCharacteristics.h" + +using namespace llvm::opt; + +namespace clang { +namespace driver { +namespace toolchains { + +void DPURTE::AddClangSystemIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + CC1Args.push_back("-nostdsysteminc"); + addSystemInclude(DriverArgs, CC1Args, computeSysRoot() + "/stdlib"); + addSystemInclude(DriverArgs, CC1Args, computeSysRoot() + "/syslib"); +} + +std::string DPURTE::computeSysRoot() const { + if (!getDriver().SysRoot.empty()) + return getDriver().SysRoot; + + const std::string InstalledDir(getDriver().getInstalledDir()); + const std::string UpmemDir(InstalledDir + "/../share/upmem/include"); + + if (getVFS().exists(UpmemDir)) + return UpmemDir; + + return std::string(); +} + +Tool *DPURTE::buildLinker() const { return new tools::dpu::Linker(*this); } + +#define NR_TASKLETS "NR_TASKLETS" + +void DPURTE::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const { + Generic_ELF::addClangTargetOptions(DriverArgs, CC1Args, DeviceOffloadKind); + Arg *A = DriverArgs.getLastArg(options::OPT_O_Group); + if (!A || !A->getOption().matches(options::OPT_O0)) { + // In -O0 we need to keep some unused section (from the linker point of + // view) that will be used for debug purpose + CC1Args.push_back("-ffunction-sections"); + } + // add stack-size-section by default to always be able to use + // dpu_stack_analyzer + CC1Args.push_back("-fstack-size-section"); + CC1Args.push_back("-fdata-sections"); + + if (DriverArgs.hasArg(options::OPT_pg)) { + CC1Args.push_back("-DDPU_PROFILING"); + } + + bool nr_tasklets_already_added = false; + for (unsigned int EachArg = 0; EachArg < DriverArgs.size(); EachArg++) { + std::string arg(DriverArgs.getArgString(EachArg)); + if (arg.find(NR_TASKLETS) != ULLONG_MAX) { + nr_tasklets_already_added = true; + break; + } + } + if (!nr_tasklets_already_added) { + CC1Args.push_back("-D" NR_TASKLETS "=1"); + } +} + + +std::string +DPURTE::ComputeLLVMTriple(const llvm::opt::ArgList &Args, types::ID InputType) const { + std::string SubArch = tools::dpu::getDPUVersionFromArgs(Args); + return "dpu" + StringRef(SubArch).lower() + "-upmem-dpurte"; +} +} // namespace toolchains + +namespace tools { +namespace dpu { +void Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const { + const ToolChain &TC = getToolChain(); + const Driver &D = getToolChain().getDriver(); + const llvm::Triple &TargetTriple = TC.getEffectiveTriple(); + + std::string subarch_str(""); + switch (TargetTriple.getSubArch()) { + case llvm::Triple::DPUSubArch_v1a: { + subarch_str.append("v1A"); + break; + } + case llvm::Triple::DPUSubArch_v1b: { + subarch_str.append("v1B"); + break; + } + default: + llvm_unreachable("Unhandled Triple."); + break; + } + + const std::string sysroot = TC.computeSysRoot(); + std::string pg_ext(""); + if (TCArgs.hasArg(options::OPT_pg)) { + pg_ext.append("_p"); + } + + const std::string builtin_path = sysroot + "/built-in" + "/" + subarch_str; + const std::string config_ext = pg_ext + "_" + subarch_str; + + std::string Linker = TC.GetProgramPath(getShortName()); + // Put additional linker options + ArgStringList CmdArgs; + CmdArgs.push_back("--discard-locals"); + + AddLinkerInputs(TC, Inputs, TCArgs, CmdArgs, JA); + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + CmdArgs.push_back("-gc-sections"); + // Must force common allocation, so that symbols with SHN_COMMON (aka .common) + // have space allocated in WRAM. Otherwise, the linker places symbols at + // the very beginning of memory with no allocation. + CmdArgs.push_back("--define-common"); + if (!TCArgs.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { + CmdArgs.push_back("-L"); + CmdArgs.push_back(TCArgs.MakeArgString(builtin_path)); + + // Link rt library + CmdArgs.push_back("-l"); + if (TCArgs.hasArg(options::OPT_flto_EQ)) { + CmdArgs.push_back(llvm::StringSwitch( + TCArgs.getLastArg(options::OPT_flto_EQ)->getValue()) + .Case("thin", TCArgs.MakeArgString("rtltothin" + config_ext)) + .Default(TCArgs.MakeArgString("rtlto" + config_ext))); + } else if (TCArgs.hasArg(options::OPT_flto)) { + CmdArgs.push_back(TCArgs.MakeArgString("rtlto" + config_ext)); + } else { + CmdArgs.push_back(TCArgs.MakeArgString("rt" + config_ext)); + } + + if (TCArgs.hasArg(options::OPT_pg)) { + CmdArgs.push_back("-l"); + CmdArgs.push_back(TCArgs.MakeArgString("rtmcount_" + subarch_str)); + } + } + + bool HasArgScript = false; + for (unsigned int EachArg = 0; EachArg < CmdArgs.size(); EachArg++) { + if ((CmdArgs[EachArg][0] == '-') && + (!strncmp("-T", CmdArgs[EachArg], 2) || + !strncmp("--script", CmdArgs[EachArg], 8))) { + HasArgScript = true; + break; + } + } + + if (!HasArgScript) { + CmdArgs.push_back("-T"); + CmdArgs.push_back(TCArgs.MakeArgString(sysroot + "/link/dpu.lds")); + + constexpr unsigned int DPU_NR_THREADS = std::max(DPU_NR_THREADS_V1A, DPU_NR_THREADS_V1B); +#define STR_BUFFER_SIZE 128 +#define NR_TASKLETS_FMT NR_TASKLETS "=%u" +#define DEFAULT_STACK_SIZE_FMT "STACK_SIZE_DEFAULT=%u" +#define STACK_SIZE_TASKLET_X_FMT "STACK_SIZE_TASKLET_%u=%u" +#define DEFSYM_FMT "--defsym=" + uint32_t nr_running_tasklets = 1; + uint32_t default_stack_size = 1024; + uint32_t stack_size[DPU_NR_THREADS]; + bool nr_running_tasklets_defined = false; + bool stack_size_defined[DPU_NR_THREADS]; + memset(stack_size, 0xff, DPU_NR_THREADS * sizeof(uint32_t)); + memset(stack_size_defined, 0x0, DPU_NR_THREADS * sizeof(bool)); + for (unsigned int EachArg = 0; EachArg < TCArgs.size(); EachArg++) { + std::string arg(TCArgs.getArgString(EachArg)); + if (arg.find("-D") == 0) { + const char *symbol_and_value = &(arg.c_str())[2]; + std::string next_arg; + if (*symbol_and_value == '\0') { + next_arg = TCArgs.getArgString(++EachArg); + symbol_and_value = next_arg.c_str(); + } + + uint32_t tasklet_id, tasklet_stack_size; + if (sscanf(symbol_and_value, NR_TASKLETS_FMT, &nr_running_tasklets) == + 1) { + continue; + } else if (sscanf(symbol_and_value, DEFAULT_STACK_SIZE_FMT, + &default_stack_size) == 1) { + continue; + } else if (sscanf(symbol_and_value, STACK_SIZE_TASKLET_X_FMT, + &tasklet_id, &tasklet_stack_size) == 2) { + stack_size[tasklet_id] = tasklet_stack_size; + } + } else if (arg.find("-Wl,") == 0) { + const char *symbol_and_value = &(arg.c_str())[4]; + uint32_t tasklet_id, tasklet_stack_size; + if (sscanf(symbol_and_value, DEFSYM_FMT NR_TASKLETS_FMT, + &nr_running_tasklets) == 1) { + nr_running_tasklets_defined = true; + } else if (sscanf(symbol_and_value, STACK_SIZE_TASKLET_X_FMT, + &tasklet_id, &tasklet_stack_size) == 2) { + stack_size_defined[tasklet_id] = true; + } + } + } + + if (!nr_running_tasklets_defined) { + static char str_nr_running_tasklets[STR_BUFFER_SIZE]; + sprintf(str_nr_running_tasklets, DEFSYM_FMT NR_TASKLETS_FMT, + nr_running_tasklets); + CmdArgs.push_back(str_nr_running_tasklets); + } + + static char str_tasklet_size[DPU_NR_THREADS][STR_BUFFER_SIZE]; + for (unsigned int each_tasklet = 0; each_tasklet < DPU_NR_THREADS; + each_tasklet++) { + if (stack_size_defined[each_tasklet]) { + continue; + } else if (each_tasklet < nr_running_tasklets && + stack_size[each_tasklet] == 0xffffffff) { + sprintf(str_tasklet_size[each_tasklet], + DEFSYM_FMT STACK_SIZE_TASKLET_X_FMT, each_tasklet, + default_stack_size); + } else if (stack_size[each_tasklet] == 0xffffffff) { + sprintf(str_tasklet_size[each_tasklet], + DEFSYM_FMT STACK_SIZE_TASKLET_X_FMT, each_tasklet, 0); + } else { + sprintf(str_tasklet_size[each_tasklet], + DEFSYM_FMT STACK_SIZE_TASKLET_X_FMT, each_tasklet, + stack_size[each_tasklet]); + } + CmdArgs.push_back(str_tasklet_size[each_tasklet]); + } + + switch (TargetTriple.getSubArch()) { + case llvm::Triple::DPUSubArch_v1a: { + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_IRAM_SIZE=" + + std::to_string(DPU_IRAM_SIZE_V1A))); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_WRAM_SIZE=" + + std::to_string(DPU_WRAM_SIZE_V1A))); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_ATOMIC_SIZE=" + + std::to_string(DPU_ATOMIC_SIZE_V1A))); + // There is an issue on ATOMIC HW buffer on v1A + // We intentionally scrap a bit of space to be safe + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_ATOMIC_DISPLACEMENT=200")); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_NR_THREADS=" + + std::to_string(DPU_NR_THREADS_V1A))); + break; + } + case llvm::Triple::DPUSubArch_v1b: { + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_IRAM_SIZE=" + + std::to_string(DPU_IRAM_SIZE_V1B))); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_WRAM_SIZE=" + + std::to_string(DPU_WRAM_SIZE_V1B))); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_ATOMIC_SIZE=" + + std::to_string(DPU_ATOMIC_SIZE_V1B))); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_ATOMIC_DISPLACEMENT=0")); + CmdArgs.push_back(TCArgs.MakeArgString("--defsym=DPU_NR_THREADS=" + + std::to_string(DPU_NR_THREADS_V1B))); + break; + } + default: + break; + } + } + + if (!TCArgs.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(TCArgs.MakeArgString(sysroot + "/misc/" + subarch_str + "/crt0" + pg_ext + ".o")); + } + + /* Pass -L options to the linker */ + TCArgs.AddAllArgs(CmdArgs, options::OPT_L); + + if (D.isUsingLTO()) { + assert(!Inputs.empty() && "Must have at least one input."); + addLTOOptions(TC, TCArgs, CmdArgs, Output, Inputs[0], + D.getLTOMode() == LTOK_Thin); + } + + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileCurCP(), TCArgs.MakeArgString(Linker), CmdArgs, Inputs)); +} +} // namespace dpu +} // namespace tools +} // namespace driver +} // namespace clang diff --git a/clang/lib/Driver/ToolChains/DPURTE.h b/clang/lib/Driver/ToolChains/DPURTE.h new file mode 100644 index 0000000000000..7b5ce26e56126 --- /dev/null +++ b/clang/lib/Driver/ToolChains/DPURTE.h @@ -0,0 +1,80 @@ +//===--- DPURTE.h - DPU RTE ToolChain Implementations -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DPURTE_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DPURTE_H + +#include "Gnu.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" +#include "llvm/Option/ArgList.h" +#include + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY DPURTE : public Generic_ELF { +public: + DPURTE(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Generic_ELF(D, Triple, Args) {} + + unsigned GetDefaultDwarfVersion() const override { return 4; } + + SanitizerMask getSupportedSanitizers() const override { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + // Safe stack not supported yet Res |= SanitizerKind::SafeStack; + return Res; + } + + bool IsIntegratedAssemblerDefault() const override { return true; } + + bool HasNativeLLVMSupport() const override { return true; } + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void + addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const override; + + std::string computeSysRoot() const override; + + std::string + ComputeLLVMTriple(const llvm::opt::ArgList &Args, + types::ID InputType = types::TY_INVALID) const override; +protected: + Tool *buildLinker() const override; +}; +} // end namespace toolchains +namespace tools { +namespace dpu { +class LLVM_LIBRARY_VISIBILITY Linker : public Tool { +public: + Linker(const ToolChain &TC) : Tool("dpu::Linker", "ld.lld", TC) {} + + bool isLinkJob() const override { return true; } + + bool hasIntegratedCPP() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // end namespace dpu +} // end namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_DPURTE_H diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp index e17a6bd4bdd25..9663a7390ada7 100644 --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/clang/lib/Driver/ToolChains/Linux.cpp @@ -236,15 +236,6 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) ExtraOpts.push_back("relro"); } - if (Triple.isAndroid() && Triple.isAndroidVersionLT(29)) { - // https://github.com/android/ndk/issues/1196 - // The unwinder used by the crash handler on versions of Android prior to - // API 29 did not correctly handle binaries built with rosegment, which is - // enabled by default for LLD. Android only supports LLD, so it's not an - // issue that this flag is not accepted by other linkers. - ExtraOpts.push_back("--no-rosegment"); - } - // Android ARM/AArch64 use max-page-size=4096 to reduce VMA usage. Note, lld // from 11 onwards default max-page-size to 65536 for both ARM and AArch64. if ((Triple.isARM() || Triple.isAArch64()) && Triple.isAndroid()) { diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp index f4b7a57e0bb70..13943b6c404a9 100644 --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -11,6 +11,7 @@ #include "Darwin.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/Version.h" +#include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" @@ -520,7 +521,10 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, // translate 'lld' into 'lld-link', and in the case of the regular msvc // linker, we need to use a special search algorithm. llvm::SmallString<128> linkPath; - StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link"); + StringRef Linker + = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER); + if (Linker.empty()) + Linker = "link"; if (Linker.equals_lower("lld")) Linker = "lld-link"; diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp index f155d74632f93..e162165b25613 100644 --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -296,6 +296,7 @@ void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args, CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++"); CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi"); + CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread"); } std::string OpenBSD::getCompilerRT(const ArgList &Args, diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index d1138bbc9c36f..5dd0ccdfa6fd1 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -371,7 +371,7 @@ class LineJoiner { if (Previous->is(tok::comment)) Previous = Previous->getPreviousNonComment(); if (Previous) { - if (Previous->is(tok::greater)) + if (Previous->is(tok::greater) && !I[-1]->InPPDirective) return 0; if (Previous->is(tok::identifier)) { const FormatToken *PreviousPrevious = diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index d8be4ea14868d..5c5cf46150e27 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1037,7 +1037,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, (Opts.OptimizationLevel > 1)); - Opts.BinutilsVersion = std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ)); @@ -1324,6 +1323,10 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); + if (Args.hasArg(options::OPT_ffinite_loops)) + Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always; + else if (Args.hasArg(options::OPT_fno_finite_loops)) + Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never; return Success; } @@ -2470,6 +2473,8 @@ void CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, bool IsTargetSpecified = Opts.OpenMPIsDevice || Args.hasArg(options::OPT_fopenmp_targets_EQ); + Opts.ConvergentFunctions = Opts.ConvergentFunctions || Opts.OpenMPIsDevice; + if (Opts.OpenMP || Opts.OpenMPSimd) { if (int Version = getLastArgIntValue( Args, OPT_fopenmp_version_EQ, diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index d47ad1b74649e..c64a912ce919d 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -565,7 +565,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts, Builder.defineMacro("__cpp_aggregate_bases", "201603L"); Builder.defineMacro("__cpp_structured_bindings", "201606L"); Builder.defineMacro("__cpp_nontype_template_args", - LangOpts.CPlusPlus20 ? "201911L" : "201411L"); + "201411L"); // (not latest) Builder.defineMacro("__cpp_fold_expressions", "201603L"); Builder.defineMacro("__cpp_guaranteed_copy_elision", "201606L"); Builder.defineMacro("__cpp_nontype_template_parameter_auto", "201606L"); diff --git a/clang/lib/Headers/avx512fintrin.h b/clang/lib/Headers/avx512fintrin.h index 2ee4350b14d43..f226382cbb2c6 100644 --- a/clang/lib/Headers/avx512fintrin.h +++ b/clang/lib/Headers/avx512fintrin.h @@ -9297,9 +9297,12 @@ _mm512_mask_abs_pd(__m512d __W, __mmask8 __K, __m512d __A) /* Vector-reduction arithmetic accepts vectors as inputs and produces scalars as * outputs. This class of vector operation forms the basis of many scientific - * computations. In vector-reduction arithmetic, the evaluation off is + * computations. In vector-reduction arithmetic, the evaluation order is * independent of the order of the input elements of V. + * For floating point types, we always assume the elements are reassociable even + * if -fast-math is off. + * Used bisection method. At each step, we partition the vector with previous * step in half, and the operation is performed on its two halves. * This takes log2(n) steps where n is the number of elements in the vector. @@ -9345,8 +9348,11 @@ _mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W) { return __builtin_ia32_reduce_or_q512(__W); } +// -0.0 is used to ignore the start value since it is the neutral value of +// floating point addition. For more information, please refer to +// https://llvm.org/docs/LangRef.html#llvm-vector-reduce-fadd-intrinsic static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_add_pd(__m512d __W) { - return __builtin_ia32_reduce_fadd_pd512(0.0, __W); + return __builtin_ia32_reduce_fadd_pd512(-0.0, __W); } static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_pd(__m512d __W) { @@ -9356,7 +9362,7 @@ static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_reduce_mul_pd(__m512d __W) static __inline__ double __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W) { __W = _mm512_maskz_mov_pd(__M, __W); - return __builtin_ia32_reduce_fadd_pd512(0.0, __W); + return __builtin_ia32_reduce_fadd_pd512(-0.0, __W); } static __inline__ double __DEFAULT_FN_ATTRS512 @@ -9411,7 +9417,7 @@ _mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W) { static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_reduce_add_ps(__m512 __W) { - return __builtin_ia32_reduce_fadd_ps512(0.0f, __W); + return __builtin_ia32_reduce_fadd_ps512(-0.0f, __W); } static __inline__ float __DEFAULT_FN_ATTRS512 @@ -9422,7 +9428,7 @@ _mm512_reduce_mul_ps(__m512 __W) { static __inline__ float __DEFAULT_FN_ATTRS512 _mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W) { __W = _mm512_maskz_mov_ps(__M, __W); - return __builtin_ia32_reduce_fadd_ps512(0.0f, __W); + return __builtin_ia32_reduce_fadd_ps512(-0.0f, __W); } static __inline__ float __DEFAULT_FN_ATTRS512 diff --git a/clang/lib/Lex/Preprocessor.cpp b/clang/lib/Lex/Preprocessor.cpp index 94f1ce91f8844..177786d903907 100644 --- a/clang/lib/Lex/Preprocessor.cpp +++ b/clang/lib/Lex/Preprocessor.cpp @@ -119,12 +119,8 @@ Preprocessor::Preprocessor(std::shared_ptr PPOpts, // a macro. They get unpoisoned where it is allowed. (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned(); SetPoisonReason(Ident__VA_ARGS__,diag::ext_pp_bad_vaargs_use); - if (getLangOpts().CPlusPlus20) { - (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); - SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); - } else { - Ident__VA_OPT__ = nullptr; - } + (Ident__VA_OPT__ = getIdentifierInfo("__VA_OPT__"))->setIsPoisoned(); + SetPoisonReason(Ident__VA_OPT__,diag::ext_pp_bad_vaopt_use); // Initialize the pragma handlers. RegisterBuiltinPragmas(); diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 97cb2cf0bb8c2..da5681aaf4784 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -148,12 +148,12 @@ bool TokenLexer::MaybeRemoveCommaBeforeVaArgs( return false; // GCC removes the comma in the expansion of " ... , ## __VA_ARGS__ " if - // __VA_ARGS__ is empty, but not in strict mode where there are no - // named arguments, where it remains. With GNU extensions, it is removed - // regardless of named arguments. + // __VA_ARGS__ is empty, but not in strict C99 mode where there are no + // named arguments, where it remains. In all other modes, including C99 + // with GNU extensions, it is removed regardless of named arguments. // Microsoft also appears to support this extension, unofficially. - if (!PP.getLangOpts().GNUMode && !PP.getLangOpts().MSVCCompat && - Macro->getNumParams() < 2) + if (PP.getLangOpts().C99 && !PP.getLangOpts().GNUMode + && Macro->getNumParams() < 2) return false; // Is a comma available to be removed? diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 571164139630a..347d992b16435 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -4216,7 +4216,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, } // Parse _Static_assert declaration. - if (Tok.is(tok::kw__Static_assert)) { + if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) { SourceLocation DeclEnd; ParseStaticAssertDeclaration(DeclEnd); continue; @@ -5180,6 +5180,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_friend: // static_assert-declaration + case tok::kw_static_assert: case tok::kw__Static_assert: // GNU typeof support. diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 55cb3aee6194c..450f9c020f7fe 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -14,6 +14,7 @@ #include "UsedDeclVisitor.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclObjC.h" @@ -537,6 +538,13 @@ void Sema::diagnoseZeroToNullptrConversion(CastKind Kind, const Expr* E) { if (E->IgnoreParenImpCasts()->getType()->isNullPtrType()) return; + // Don't diagnose the conversion from a 0 literal to a null pointer argument + // in a synthesized call to operator<=>. + if (!CodeSynthesisContexts.empty() && + CodeSynthesisContexts.back().Kind == + CodeSynthesisContext::RewritingOperatorAsSpaceship) + return; + // If it is a macro from system header, and if the macro name is not "NULL", // do not warn. SourceLocation MaybeMacroLoc = E->getBeginLoc(); @@ -1733,11 +1741,12 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { } } -Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, - unsigned DiagID) { +Sema::SemaDiagnosticBuilder +Sema::targetDiag(SourceLocation Loc, unsigned DiagID, FunctionDecl *FD) { + FD = FD ? FD : getCurFunctionDecl(); if (LangOpts.OpenMP) - return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID) - : diagIfOpenMPHostCode(Loc, DiagID); + return LangOpts.OpenMPIsDevice ? diagIfOpenMPDeviceCode(Loc, DiagID, FD) + : diagIfOpenMPHostCode(Loc, DiagID, FD); if (getLangOpts().CUDA) return getLangOpts().CUDAIsDevice ? CUDADiagIfDeviceCode(Loc, DiagID) : CUDADiagIfHostCode(Loc, DiagID); @@ -1746,7 +1755,7 @@ Sema::SemaDiagnosticBuilder Sema::targetDiag(SourceLocation Loc, return SYCLDiagIfDeviceCode(Loc, DiagID); return SemaDiagnosticBuilder(SemaDiagnosticBuilder::K_Immediate, Loc, DiagID, - getCurFunctionDecl(), *this); + FD, *this); } Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, @@ -1765,15 +1774,14 @@ Sema::SemaDiagnosticBuilder Sema::Diag(SourceLocation Loc, unsigned DiagID, DiagID, getCurFunctionDecl(), *this); } - SemaDiagnosticBuilder DB = - getLangOpts().CUDAIsDevice - ? CUDADiagIfDeviceCode(Loc, DiagID) - : CUDADiagIfHostCode(Loc, DiagID); + SemaDiagnosticBuilder DB = getLangOpts().CUDAIsDevice + ? CUDADiagIfDeviceCode(Loc, DiagID) + : CUDADiagIfHostCode(Loc, DiagID); SetIsLastErrorImmediate(DB.isImmediate()); return DB; } -void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { +void Sema::checkDeviceDecl(ValueDecl *D, SourceLocation Loc) { if (isUnevaluatedContext()) return; @@ -1791,13 +1799,17 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { return; } + // Try to associate errors with the lexical context, if that is a function, or + // the value declaration otherwise. + FunctionDecl *FD = + isa(C) ? cast(C) : dyn_cast(D); auto CheckType = [&](QualType Ty) { if (Ty->isDependentType()) return; if (Ty->isExtIntType()) { if (!Context.getTargetInfo().hasExtIntType()) { - targetDiag(Loc, diag::err_device_unsupported_type) + targetDiag(Loc, diag::err_device_unsupported_type, FD) << D << false /*show bit size*/ << 0 /*bitsize*/ << Ty << Context.getTargetInfo().getTriple().str(); } @@ -1810,11 +1822,12 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { !Context.getTargetInfo().hasFloat128Type()) || (Ty->isIntegerType() && Context.getTypeSize(Ty) == 128 && !Context.getTargetInfo().hasInt128Type())) { - targetDiag(Loc, diag::err_device_unsupported_type) + if (targetDiag(Loc, diag::err_device_unsupported_type, FD) << D << true /*show bit size*/ << static_cast(Context.getTypeSize(Ty)) << Ty - << Context.getTargetInfo().getTriple().str(); - targetDiag(D->getLocation(), diag::note_defined_here) << D; + << Context.getTargetInfo().getTriple().str()) + D->setInvalidDecl(); + targetDiag(D->getLocation(), diag::note_defined_here, FD) << D; } }; @@ -1826,6 +1839,8 @@ void Sema::checkDeviceDecl(const ValueDecl *D, SourceLocation Loc) { CheckType(ParamTy); CheckType(FPTy->getReturnType()); } + if (const auto *FNPTy = dyn_cast(Ty)) + CheckType(FNPTy->getReturnType()); } /// Looks through the macro-expansion chain for the given diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index c2785fd60fc26..be04970979b38 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5158,6 +5158,20 @@ class ConceptInfo { llvm::DenseMap Results; }; + +// If \p Base is ParenListExpr, assume a chain of comma operators and pick the +// last expr. We expect other ParenListExprs to be resolved to e.g. constructor +// calls before here. (So the ParenListExpr should be nonempty, but check just +// in case) +Expr *unwrapParenList(Expr *Base) { + if (auto *PLE = llvm::dyn_cast_or_null(Base)) { + if (PLE->getNumExprs() == 0) + return nullptr; + Base = PLE->getExpr(PLE->getNumExprs() - 1); + } + return Base; +} + } // namespace void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, @@ -5165,6 +5179,8 @@ void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement, QualType PreferredType) { + Base = unwrapParenList(Base); + OtherOpBase = unwrapParenList(OtherOpBase); if (!Base || !CodeCompleter) return; @@ -5597,12 +5613,13 @@ ProduceSignatureHelp(Sema &SemaRef, Scope *S, QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, ArrayRef Args, SourceLocation OpenParLoc) { - if (!CodeCompleter) + Fn = unwrapParenList(Fn); + if (!CodeCompleter || !Fn) return QualType(); // FIXME: Provide support for variadic template functions. // Ignore type-dependent call expressions entirely. - if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args)) + if (Fn->isTypeDependent() || anyNullArguments(Args)) return QualType(); // In presence of dependent args we surface all possible signatures using the // non-dependent args in the prefix. Afterwards we do a post filtering to make diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 3ee0c43097d7d..1eb18433927ed 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9420,6 +9420,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } + if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) + checkDeviceDecl(NewFD, D.getBeginLoc()); + if (!getLangOpts().CPlusPlus) { // Perform semantic checking on the function declaration. if (!NewFD->isInvalidDecl() && NewFD->isMain()) @@ -11101,6 +11104,13 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { // getting shifty. if (nparams == 4 && Context.getTargetInfo().getTriple().isOSDarwin()) HasExtraParameters = false; + else if (Context.getTargetInfo().getTriple().getArch() == llvm::Triple::dpu && + nparams != 0) { + HasExtraParameters = false; + Diag(FD->getLocation(), diag::err_dpu_main_surplus_args) << nparams; + FD->setInvalidDecl(true); + nparams = 0; + } if (HasExtraParameters) { Diag(FD->getLocation(), diag::err_main_surplus_args) << nparams; @@ -18329,42 +18339,51 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, if (FD->isDependentContext()) return FunctionEmissionStatus::TemplateDiscarded; - FunctionEmissionStatus OMPES = FunctionEmissionStatus::Unknown; + // Check whether this function is an externally visible definition. + auto IsEmittedForExternalSymbol = [this, FD]() { + // We have to check the GVA linkage of the function's *definition* -- if we + // only have a declaration, we don't know whether or not the function will + // be emitted, because (say) the definition could include "inline". + FunctionDecl *Def = FD->getDefinition(); + + return Def && !isDiscardableGVALinkage( + getASTContext().GetGVALinkageForFunction(Def)); + }; + if (LangOpts.OpenMPIsDevice) { + // In OpenMP device mode we will not emit host only functions, or functions + // we don't need due to their linkage. Optional DevTy = OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl()); - if (DevTy.hasValue()) { + // DevTy may be changed later by + // #pragma omp declare target to(*) device_type(*). + // Therefore DevTyhaving no value does not imply host. The emission status + // will be checked again at the end of compilation unit with Final = true. + if (DevTy.hasValue()) if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host) - OMPES = FunctionEmissionStatus::OMPDiscarded; - else if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any) { - OMPES = FunctionEmissionStatus::Emitted; - } - } - } else if (LangOpts.OpenMP) { - // In OpenMP 4.5 all the functions are host functions. - if (LangOpts.OpenMP <= 45) { - OMPES = FunctionEmissionStatus::Emitted; - } else { - Optional DevTy = - OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl()); - // In OpenMP 5.0 or above, DevTy may be changed later by - // #pragma omp declare target to(*) device_type(*). Therefore DevTy - // having no value does not imply host. The emission status will be - // checked again at the end of compilation unit. - if (DevTy.hasValue()) { - if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) { - OMPES = FunctionEmissionStatus::OMPDiscarded; - } else if (*DevTy == OMPDeclareTargetDeclAttr::DT_Host || - *DevTy == OMPDeclareTargetDeclAttr::DT_Any) - OMPES = FunctionEmissionStatus::Emitted; - } else if (Final) - OMPES = FunctionEmissionStatus::Emitted; - } - } - if (OMPES == FunctionEmissionStatus::OMPDiscarded || - (OMPES == FunctionEmissionStatus::Emitted && !LangOpts.CUDA)) - return OMPES; + return FunctionEmissionStatus::OMPDiscarded; + // If we have an explicit value for the device type, or we are in a target + // declare context, we need to emit all extern and used symbols. + if (isInOpenMPDeclareTargetContext() || DevTy.hasValue()) + if (IsEmittedForExternalSymbol()) + return FunctionEmissionStatus::Emitted; + // Device mode only emits what it must, if it wasn't tagged yet and needed, + // we'll omit it. + if (Final) + return FunctionEmissionStatus::OMPDiscarded; + } else if (LangOpts.OpenMP > 45) { + // In OpenMP host compilation prior to 5.0 everything was an emitted host + // function. In 5.0, no_host was introduced which might cause a function to + // be ommitted. + Optional DevTy = + OMPDeclareTargetDeclAttr::getDeviceType(FD->getCanonicalDecl()); + if (DevTy.hasValue()) + if (*DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) + return FunctionEmissionStatus::OMPDiscarded; + } + + if (Final && LangOpts.OpenMP && !LangOpts.CUDA) + return FunctionEmissionStatus::Emitted; if (LangOpts.CUDA) { // When compiling for device, host functions are never emitted. Similarly, @@ -18378,17 +18397,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(FunctionDecl *FD, (T == Sema::CFT_Device || T == Sema::CFT_Global)) return FunctionEmissionStatus::CUDADiscarded; - // Check whether this function is externally visible -- if so, it's - // known-emitted. - // - // We have to check the GVA linkage of the function's *definition* -- if we - // only have a declaration, we don't know whether or not the function will - // be emitted, because (say) the definition could include "inline". - FunctionDecl *Def = FD->getDefinition(); - - if (Def && - !isDiscardableGVALinkage(getASTContext().GetGVALinkageForFunction(Def)) - && (!LangOpts.OpenMP || OMPES == FunctionEmissionStatus::Emitted)) + if (IsEmittedForExternalSymbol()) return FunctionEmissionStatus::Emitted; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 45616dadcbee4..ae8508d6c6018 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -373,7 +373,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, } if (LangOpts.SYCLIsDevice || (LangOpts.OpenMP && LangOpts.OpenMPIsDevice)) { - if (const auto *VD = dyn_cast(D)) + if (auto *VD = dyn_cast(D)) checkDeviceDecl(VD, Loc); if (!Context.getTargetInfo().isTLSSupported()) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index af61c82c2002e..c1c6a4bf5c682 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -432,15 +432,16 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, void Sema::handleLambdaNumbering( CXXRecordDecl *Class, CXXMethodDecl *Method, - Optional> Mangling) { + Optional> Mangling) { if (Mangling) { - unsigned ManglingNumber; bool HasKnownInternalLinkage; + unsigned ManglingNumber, DeviceManglingNumber; Decl *ManglingContextDecl; - std::tie(ManglingNumber, HasKnownInternalLinkage, ManglingContextDecl) = - Mangling.getValue(); + std::tie(HasKnownInternalLinkage, ManglingNumber, DeviceManglingNumber, + ManglingContextDecl) = Mangling.getValue(); Class->setLambdaMangling(ManglingNumber, ManglingContextDecl, HasKnownInternalLinkage); + Class->setDeviceLambdaManglingNumber(DeviceManglingNumber); return; } @@ -476,6 +477,7 @@ void Sema::handleLambdaNumbering( unsigned ManglingNumber = MCtx->getManglingNumber(Method); Class->setLambdaMangling(ManglingNumber, ManglingContextDecl, HasKnownInternalLinkage); + Class->setDeviceLambdaManglingNumber(MCtx->getDeviceManglingNumber(Method)); } } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 78707484f588c..4063c185388d4 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1884,8 +1884,7 @@ void Sema::popOpenMPFunctionRegion(const FunctionScopeInfo *OldFSI) { static bool isOpenMPDeviceDelayedContext(Sema &S) { assert(S.LangOpts.OpenMP && S.LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); - return !S.isInOpenMPTargetExecutionDirective() && - !S.isInOpenMPDeclareTargetContext(); + return !S.isInOpenMPTargetExecutionDirective(); } namespace { @@ -1898,11 +1897,11 @@ enum class FunctionEmissionStatus { } // anonymous namespace Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, - unsigned DiagID) { + unsigned DiagID, + FunctionDecl *FD) { assert(LangOpts.OpenMP && LangOpts.OpenMPIsDevice && "Expected OpenMP device compilation."); - FunctionDecl *FD = getCurFunctionDecl(); SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; if (FD) { FunctionEmissionStatus FES = getEmissionStatus(FD); @@ -1911,6 +1910,13 @@ Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, Kind = SemaDiagnosticBuilder::K_Immediate; break; case FunctionEmissionStatus::Unknown: + // TODO: We should always delay diagnostics here in case a target + // region is in a function we do not emit. However, as the + // current diagnostics are associated with the function containing + // the target region and we do not emit that one, we would miss out + // on diagnostics for the target region itself. We need to anchor + // the diagnostics with the new generated function *or* ensure we + // emit diagnostics associated with the surrounding function. Kind = isOpenMPDeviceDelayedContext(*this) ? SemaDiagnosticBuilder::K_Deferred : SemaDiagnosticBuilder::K_Immediate; @@ -1925,14 +1931,15 @@ Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPDeviceCode(SourceLocation Loc, } } - return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this); } Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, - unsigned DiagID) { + unsigned DiagID, + FunctionDecl *FD) { assert(LangOpts.OpenMP && !LangOpts.OpenMPIsDevice && "Expected OpenMP host compilation."); - FunctionEmissionStatus FES = getEmissionStatus(getCurFunctionDecl()); + FunctionEmissionStatus FES = getEmissionStatus(FD); SemaDiagnosticBuilder::Kind Kind = SemaDiagnosticBuilder::K_Nop; switch (FES) { case FunctionEmissionStatus::Emitted: @@ -1948,7 +1955,7 @@ Sema::SemaDiagnosticBuilder Sema::diagIfOpenMPHostCode(SourceLocation Loc, break; } - return SemaDiagnosticBuilder(Kind, Loc, DiagID, getCurFunctionDecl(), *this); + return SemaDiagnosticBuilder(Kind, Loc, DiagID, FD, *this); } static OpenMPDefaultmapClauseKind diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 0a596e50658bd..3c68f9458e589 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -12504,10 +12504,11 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { E->getCaptureDefault()); getDerived().transformedLocalDecl(OldClass, {Class}); - Optional> Mangling; + Optional> Mangling; if (getDerived().ReplacingOriginal()) - Mangling = std::make_tuple(OldClass->getLambdaManglingNumber(), - OldClass->hasKnownLambdaInternalLinkage(), + Mangling = std::make_tuple(OldClass->hasKnownLambdaInternalLinkage(), + OldClass->getLambdaManglingNumber(), + OldClass->getDeviceLambdaManglingNumber(), OldClass->getLambdaContextDecl()); // Build the call operator. diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 6bfb9bd783b5a..18ab4666a7d8d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -1748,6 +1748,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.NumExplicitCaptures = Record.readInt(); Lambda.HasKnownInternalLinkage = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); + D->setDeviceLambdaManglingNumber(Record.readInt()); Lambda.ContextDecl = readDeclID(); Lambda.Captures = (Capture *)Reader.getContext().Allocate( sizeof(Capture) * Lambda.NumCaptures); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 6bfa7b0e7d6dd..40900af6f9e00 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -5667,6 +5667,7 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) { Record->push_back(Lambda.NumExplicitCaptures); Record->push_back(Lambda.HasKnownInternalLinkage); Record->push_back(Lambda.ManglingNumber); + Record->push_back(D->getDeviceLambdaManglingNumber()); AddDeclRef(D->getLambdaContextDecl()); AddTypeSourceInfo(Lambda.MethodTyInfo); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { diff --git a/clang/test/CodeCompletion/function-overloads.cpp b/clang/test/CodeCompletion/function-overloads.cpp index 11c864c281070..7b8ccef1d580f 100644 --- a/clang/test/CodeCompletion/function-overloads.cpp +++ b/clang/test/CodeCompletion/function-overloads.cpp @@ -21,6 +21,8 @@ namespace NS { void test_adl() { NS::X x; g(x, x); + (void)(f)(1, 2, 3); + (void)(test, test, test, f)(1, 2, 3); } // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:9 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s @@ -31,6 +33,10 @@ void test_adl() { // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:10:21 %s -o - | FileCheck -check-prefix=CHECK-CC4 %s // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:23:7 %s -o - | \ // RUN: FileCheck -check-prefix=CHECK-CC5 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:24:13 %s -o - | \ +// RUN: FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:25:31 %s -o - | \ +// RUN: FileCheck -check-prefix=CHECK-CC1 %s // CHECK-CC1: OVERLOAD: [#int#]f(<#float x#>, float y) // CHECK-CC1: OVERLOAD: [#int#]f(<#int i#>) // CHECK-CC1-NOT, CHECK-CC2-NOT: OVERLOAD: A( diff --git a/clang/test/CodeCompletion/member-access.c b/clang/test/CodeCompletion/member-access.c index 72afbf2ff9479..545349f71731b 100644 --- a/clang/test/CodeCompletion/member-access.c +++ b/clang/test/CodeCompletion/member-access.c @@ -29,3 +29,10 @@ void test3(struct Point2 *p) { // RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:24:5 %s -o - | FileCheck -check-prefix=CHECK-CC3 %s // CHECK-CC3: x (requires fix-it: {24:4-24:5} to "->") + +void test4(struct Point *p) { + (int)(p)->x; + (int)(0,1,2,3,4,p)->x; +} +// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:34:13 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s +// RUN: %clang_cc1 -fsyntax-only -code-completion-with-fixits -code-completion-at=%s:35:23 %s -o - | FileCheck -check-prefix=CHECK-CC1 %s diff --git a/clang/test/CodeGen/X86/avx512-reduceIntrin.c b/clang/test/CodeGen/X86/avx512-reduceIntrin.c index d8a1130f3cef0..62580ca1914e9 100644 --- a/clang/test/CodeGen/X86/avx512-reduceIntrin.c +++ b/clang/test/CodeGen/X86/avx512-reduceIntrin.c @@ -11,13 +11,13 @@ long long test_mm512_reduce_add_epi64(__m512i __W){ long long test_mm512_reduce_mul_epi64(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_mul_epi64( // CHECK: call i64 @llvm.vector.reduce.mul.v8i64(<8 x i64> %{{.*}}) - return _mm512_reduce_mul_epi64(__W); + return _mm512_reduce_mul_epi64(__W); } long long test_mm512_reduce_or_epi64(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_or_epi64( // CHECK: call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> %{{.*}}) - return _mm512_reduce_or_epi64(__W); + return _mm512_reduce_or_epi64(__W); } long long test_mm512_reduce_and_epi64(__m512i __W){ @@ -31,7 +31,7 @@ long long test_mm512_mask_reduce_add_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.add.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_add_epi64(__M, __W); + return _mm512_mask_reduce_add_epi64(__M, __W); } long long test_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W){ @@ -39,7 +39,7 @@ long long test_mm512_mask_reduce_mul_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.mul.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_mul_epi64(__M, __W); + return _mm512_mask_reduce_mul_epi64(__M, __W); } long long test_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W){ @@ -47,7 +47,7 @@ long long test_mm512_mask_reduce_and_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.and.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_and_epi64(__M, __W); + return _mm512_mask_reduce_and_epi64(__M, __W); } long long test_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W){ @@ -55,30 +55,30 @@ long long test_mm512_mask_reduce_or_epi64(__mmask8 __M, __m512i __W){ // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x i64> %{{.*}}, <8 x i64> %{{.*}} // CHECK: call i64 @llvm.vector.reduce.or.v8i64(<8 x i64> %{{.*}}) - return _mm512_mask_reduce_or_epi64(__M, __W); + return _mm512_mask_reduce_or_epi64(__M, __W); } int test_mm512_reduce_add_epi32(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_add_epi32( // CHECK: call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_add_epi32(__W); + return _mm512_reduce_add_epi32(__W); } int test_mm512_reduce_mul_epi32(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_mul_epi32( // CHECK: call i32 @llvm.vector.reduce.mul.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_mul_epi32(__W); + return _mm512_reduce_mul_epi32(__W); } int test_mm512_reduce_or_epi32(__m512i __W){ // CHECK: call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_or_epi32(__W); + return _mm512_reduce_or_epi32(__W); } int test_mm512_reduce_and_epi32(__m512i __W){ // CHECK-LABEL: @test_mm512_reduce_and_epi32( // CHECK: call i32 @llvm.vector.reduce.and.v16i32(<16 x i32> %{{.*}}) - return _mm512_reduce_and_epi32(__W); + return _mm512_reduce_and_epi32(__W); } int test_mm512_mask_reduce_add_epi32(__mmask16 __M, __m512i __W){ @@ -86,7 +86,7 @@ int test_mm512_mask_reduce_add_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_add_epi32(__M, __W); + return _mm512_mask_reduce_add_epi32(__M, __W); } int test_mm512_mask_reduce_mul_epi32(__mmask16 __M, __m512i __W){ @@ -94,7 +94,7 @@ int test_mm512_mask_reduce_mul_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.mul.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_mul_epi32(__M, __W); + return _mm512_mask_reduce_mul_epi32(__M, __W); } int test_mm512_mask_reduce_and_epi32(__mmask16 __M, __m512i __W){ @@ -102,7 +102,7 @@ int test_mm512_mask_reduce_and_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.and.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_and_epi32(__M, __W); + return _mm512_mask_reduce_and_epi32(__M, __W); } int test_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W){ @@ -110,61 +110,65 @@ int test_mm512_mask_reduce_or_epi32(__mmask16 __M, __m512i __W){ // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x i32> %{{.*}}, <16 x i32> %{{.*}} // CHECK: call i32 @llvm.vector.reduce.or.v16i32(<16 x i32> %{{.*}}) - return _mm512_mask_reduce_or_epi32(__M, __W); + return _mm512_mask_reduce_or_epi32(__M, __W); } -double test_mm512_reduce_add_pd(__m512d __W){ +double test_mm512_reduce_add_pd(__m512d __W, double ExtraAddOp){ // CHECK-LABEL: @test_mm512_reduce_add_pd( -// CHECK: call double @llvm.vector.reduce.fadd.v8f64(double 0.000000e+00, <8 x double> %{{.*}}) - return _mm512_reduce_add_pd(__W); +// CHECK-NOT: reassoc +// CHECK: call reassoc double @llvm.vector.reduce.fadd.v8f64(double -0.000000e+00, <8 x double> %{{.*}}) +// CHECK-NOT: reassoc + return _mm512_reduce_add_pd(__W) + ExtraAddOp; } -double test_mm512_reduce_mul_pd(__m512d __W){ +double test_mm512_reduce_mul_pd(__m512d __W, double ExtraMulOp){ // CHECK-LABEL: @test_mm512_reduce_mul_pd( -// CHECK: call double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) - return _mm512_reduce_mul_pd(__W); +// CHECK-NOT: reassoc +// CHECK: call reassoc double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) +// CHECK-NOT: reassoc + return _mm512_reduce_mul_pd(__W) * ExtraMulOp; } float test_mm512_reduce_add_ps(__m512 __W){ // CHECK-LABEL: @test_mm512_reduce_add_ps( -// CHECK: call float @llvm.vector.reduce.fadd.v16f32(float 0.000000e+00, <16 x float> %{{.*}}) - return _mm512_reduce_add_ps(__W); +// CHECK: call reassoc float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}}) + return _mm512_reduce_add_ps(__W); } float test_mm512_reduce_mul_ps(__m512 __W){ // CHECK-LABEL: @test_mm512_reduce_mul_ps( -// CHECK: call float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) - return _mm512_reduce_mul_ps(__W); +// CHECK: call reassoc float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) + return _mm512_reduce_mul_ps(__W); } double test_mm512_mask_reduce_add_pd(__mmask8 __M, __m512d __W){ // CHECK-LABEL: @test_mm512_mask_reduce_add_pd( // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} -// CHECK: call double @llvm.vector.reduce.fadd.v8f64(double 0.000000e+00, <8 x double> %{{.*}}) - return _mm512_mask_reduce_add_pd(__M, __W); +// CHECK: call reassoc double @llvm.vector.reduce.fadd.v8f64(double -0.000000e+00, <8 x double> %{{.*}}) + return _mm512_mask_reduce_add_pd(__M, __W); } double test_mm512_mask_reduce_mul_pd(__mmask8 __M, __m512d __W){ // CHECK-LABEL: @test_mm512_mask_reduce_mul_pd( // CHECK: bitcast i8 %{{.*}} to <8 x i1> // CHECK: select <8 x i1> %{{.*}}, <8 x double> %{{.*}}, <8 x double> %{{.*}} -// CHECK: call double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) - return _mm512_mask_reduce_mul_pd(__M, __W); +// CHECK: call reassoc double @llvm.vector.reduce.fmul.v8f64(double 1.000000e+00, <8 x double> %{{.*}}) + return _mm512_mask_reduce_mul_pd(__M, __W); } float test_mm512_mask_reduce_add_ps(__mmask16 __M, __m512 __W){ // CHECK-LABEL: @test_mm512_mask_reduce_add_ps( // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> {{.*}} -// CHECK: call float @llvm.vector.reduce.fadd.v16f32(float 0.000000e+00, <16 x float> %{{.*}}) - return _mm512_mask_reduce_add_ps(__M, __W); +// CHECK: call reassoc float @llvm.vector.reduce.fadd.v16f32(float -0.000000e+00, <16 x float> %{{.*}}) + return _mm512_mask_reduce_add_ps(__M, __W); } float test_mm512_mask_reduce_mul_ps(__mmask16 __M, __m512 __W){ // CHECK-LABEL: @test_mm512_mask_reduce_mul_ps( // CHECK: bitcast i16 %{{.*}} to <16 x i1> // CHECK: select <16 x i1> %{{.*}}, <16 x float> {{.*}}, <16 x float> %{{.*}} -// CHECK: call float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) - return _mm512_mask_reduce_mul_ps(__M, __W); +// CHECK: call reassoc float @llvm.vector.reduce.fmul.v16f32(float 1.000000e+00, <16 x float> %{{.*}}) + return _mm512_mask_reduce_mul_ps(__M, __W); } diff --git a/clang/test/CodeGen/altivec.c b/clang/test/CodeGen/altivec.c index d69c34d821901..86b570f15d080 100644 --- a/clang/test/CodeGen/altivec.c +++ b/clang/test/CodeGen/altivec.c @@ -6,9 +6,6 @@ // RUN: %clang_cc1 -target-feature +altivec -mabi=vec-extabi -target-cpu pwr8 -triple powerpc64-unknown-aix -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-BE // RUN: not %clang_cc1 -target-feature +altivec -mabi=vec-default -target-cpu pwr8 -triple powerpc-unknown-aix -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR // RUN: not %clang_cc1 -target-feature +altivec -mabi=vec-default -target-cpu pwr8 -triple powerpc64-unknown-aix -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR - -// RUN: not %clang -S -emit-llvm -maltivec -mcpu=pwr8 -target powerpc-unknown-aix %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR -// RUN: not %clang -S -emit-llvm -maltivec -mcpu=pwr8 -target powerpc64-unknown-aix %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR // RUN: %clang -S -emit-llvm -maltivec -mabi=vec-extabi -mcpu=pwr8 -target powerpc-unknown-aix %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-BE // RUN: %clang -S -emit-llvm -maltivec -mabi=vec-extabi -mcpu=pwr8 -target powerpc64-unknown-aix %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-BE // RUN: not %clang -S -emit-llvm -maltivec -mabi=vec-default -mcpu=pwr8 -triple powerpc-unknown-aix -emit-llvm %s 2>&1 | FileCheck %s --check-prefix=AIX-ERROR diff --git a/clang/test/CodeGen/attr-mustprogress-0.c b/clang/test/CodeGen/attr-mustprogress-0.c deleted file mode 100644 index 2af24e88ceef7..0000000000000 --- a/clang/test/CodeGen/attr-mustprogress-0.c +++ /dev/null @@ -1,184 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -std=c89 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s - -int a = 0; -int b = 0; - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f1() { - for (; 1;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f2() { - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @F( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F() { - for (; 1;) { - } - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @w1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void w1() { - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @w2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: ret void -// -void w2() { - while (a == b) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @W( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] -// CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] -// -void W() { - while (a == b) { - } - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @d1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d1() { - do { - } while (1); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @d2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d2() { - do { - } while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @D( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D() { - do { - } while (1); - do { - } while (a == b); -} diff --git a/clang/test/CodeGen/attr-mustprogress-0.cpp b/clang/test/CodeGen/attr-mustprogress-0.cpp deleted file mode 100644 index 3a180cc6b5ad5..0000000000000 --- a/clang/test/CodeGen/attr-mustprogress-0.cpp +++ /dev/null @@ -1,183 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s - -int a = 0; -int b = 0; - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2f1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f1() { - for (; 1;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2f2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f2() { - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Fv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F() { - for (; 1;) { - } - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2w1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void w1() { - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2w2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: ret void -// -void w2() { - while (a == b) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Wv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]] -// CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] -// CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] -// -void W() { - while (a == b) { - } - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2d1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d1() { - do { - } while (1); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2d2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d2() { - do { - } while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Dv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D() { - do { - } while (1); - do { - } while (a == b); -} diff --git a/clang/test/CodeGen/attr-mustprogress-1.c b/clang/test/CodeGen/attr-mustprogress-1.c deleted file mode 100644 index 2ff068b8b90aa..0000000000000 --- a/clang/test/CodeGen/attr-mustprogress-1.c +++ /dev/null @@ -1,197 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s - -int a = 0; -int b = 0; - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f0( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NOT: br label [[FOR_COND]], !llvm.loop !{{.*}} -// -void f0() { - for (; ;) ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f1() { - for (; 1;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @f2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f2() { - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @F( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]], [[LOOP4:!llvm.loop !.*]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F() { - for (; 1;) { - } - for (; a == b;) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @w1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void w1() { - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @w2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP5:!llvm.loop !.*]] -// CHECK: while.end: -// CHECK-NEXT: ret void -// -void w2() { - while (a == b) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @W( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP6:!llvm.loop !.*]] -// CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] -// CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] -// -void W() { - while (a == b) { - } - while (1) { - } -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @d1( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d1() { - do { - } while (1); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @d2( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP7:!llvm.loop !.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d2() { - do { - } while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @D( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], [[LOOP8:!llvm.loop !.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D() { - do { - } while (1); - do { - } while (a == b); -} diff --git a/clang/test/CodeGen/attr-mustprogress-1.cpp b/clang/test/CodeGen/attr-mustprogress-1.cpp deleted file mode 100644 index 945d74663c6d1..0000000000000 --- a/clang/test/CodeGen/attr-mustprogress-1.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes -// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s -// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s - -int a = 0; -int b = 0; - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2f0v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NOT: br label [[FOR_COND]], !llvm.loop !{{.*}} -void f0() { - for (; ;) ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2f1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f1() { - for (; 1;) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone mustprogress -// CHECK-LABEL: @_Z2f2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]] -// CHECK: for.end: -// CHECK-NEXT: ret void -// -void f2() { - for (; a == b;) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Fv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]], [[LOOP4:!llvm.loop !.*]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F() { - for (; 1;) - ; - for (; a == b;) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2F2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[FOR_COND:%.*]] -// CHECK: for.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -// CHECK: for.body: -// CHECK-NEXT: br label [[FOR_COND]], [[LOOP5:!llvm.loop !.*]] -// CHECK: for.end: -// CHECK-NEXT: br label [[FOR_COND1:%.*]] -// CHECK: for.cond1: -// CHECK-NEXT: br i1 true, label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]] -// CHECK: for.body2: -// CHECK-NEXT: br label [[FOR_COND1]] -// CHECK: for.end3: -// CHECK-NEXT: ret void -// -void F2() { - for (; a == b;) - ; - for (; 1;) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2w1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void w1() { - while (1) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone mustprogress -// CHECK-LABEL: @_Z2w2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP6:!llvm.loop !.*]] -// CHECK: while.end: -// CHECK-NEXT: ret void -// -void w2() { - while (a == b) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Wv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_COND:%.*]] -// CHECK: while.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_COND]], [[LOOP7:!llvm.loop !.*]] -// CHECK: while.end: -// CHECK-NEXT: br label [[WHILE_BODY2:%.*]] -// CHECK: while.body2: -// CHECK-NEXT: br label [[WHILE_BODY2]] -// -void W() { - while (a == b) - ; - while (1) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2W2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[WHILE_BODY:%.*]] -// CHECK: while.body: -// CHECK-NEXT: br label [[WHILE_BODY]] -// -void W2() { - while (1) - ; - while (a == b) - ; -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2d1v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d1() { - do - ; - while (1); -} - -// CHECK: Function Attrs: noinline nounwind optnone mustprogress -// CHECK-LABEL: @_Z2d2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP8:!llvm.loop !.*]] -// CHECK: do.end: -// CHECK-NEXT: ret void -// -void d2() { - do - ; - while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z1Dv( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: br i1 true, label [[DO_BODY]], label [[DO_END:%.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], [[LOOP9:!llvm.loop !.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D() { - do - ; - while (1); - do - ; - while (a == b); -} - -// CHECK: Function Attrs: noinline nounwind optnone -// CHECK-LABEL: @_Z2D2v( -// CHECK-NEXT: entry: -// CHECK-NEXT: br label [[DO_BODY:%.*]] -// CHECK: do.body: -// CHECK-NEXT: br label [[DO_COND:%.*]] -// CHECK: do.cond: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 -// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -// CHECK-NEXT: br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP10:!llvm.loop !.*]] -// CHECK: do.end: -// CHECK-NEXT: br label [[DO_BODY1:%.*]] -// CHECK: do.body1: -// CHECK-NEXT: br label [[DO_COND2:%.*]] -// CHECK: do.cond2: -// CHECK-NEXT: br i1 true, label [[DO_BODY1]], label [[DO_END3:%.*]] -// CHECK: do.end3: -// CHECK-NEXT: ret void -// -void D2() { - do - ; - while (a == b); - do - ; - while (1); -} - diff --git a/clang/test/CodeGen/attr-mustprogress.c b/clang/test/CodeGen/attr-mustprogress.c new file mode 100644 index 0000000000000..1f83cd44b3083 --- /dev/null +++ b/clang/test/CodeGen/attr-mustprogress.c @@ -0,0 +1,221 @@ +// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s +// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s +// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s +// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s +// +// RUN: %clang_cc1 -std=c11 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s +// RUN: %clang_cc1 -std=c11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s + +int a = 0; +int b = 0; + +// CHECK: datalayout +// +// CHECK-NOT: mustprogress +// CHECK-LABEL: @f0( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NOT: br {{.*}}!llvm.loop +// +void f0() { + for (; ;) ; +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @f1( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: br i1 true, label %for.body, label %for.end +// CHECK: for.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: for.end: +// CHECK-NEXT: ret void +// +void f1() { + for (; 1;) { + } +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @f2( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end +// CHECK: for.body: +// C99-NOT: br {{.*}} !llvm.loop +// C11: br label %for.cond, !llvm.loop [[LOOP1:!.*]] +// FINITE: br label %for.cond, !llvm.loop [[LOOP1:!.*]] +// CHECK: for.end: +// CHECK-NEXT: ret void +// +void f2() { + for (; a == b;) { + } +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @F( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: br i1 true, label %for.body, label %for.end +// CHECK: for.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: for.end: +// CHECK-NEXT: br label %for.cond1 +// CHECK: for.cond1: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body2, label %for.end3 +// CHECK: for.body2: +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// FINITE: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// CHECK: for.end3: +// CHECK-NEXT: ret void +// +void F() { + for (; 1;) { + } + for (; a == b;) { + } +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @w1( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %while.body +// CHECK: while.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// +void w1() { + while (1) { + } +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @w2( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %while.cond +// CHECK: while.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end +// CHECK: while.body: +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br label %while.cond, !llvm.loop [[LOOP3:!.*]] +// FINITE: br label %while.cond, !llvm.loop [[LOOP3:!.*]] +// CHECK: while.end: +// CHECK-NEXT: ret void +// +void w2() { + while (a == b) { + } +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @W( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label [[WHILE_COND:%.*]] +// CHECK: while.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end +// CHECK: while.body: +// C99-NOT: br {{.*}} !llvm.loop +// C11: br label %while.cond, !llvm.loop [[LOOP4:!.*]] +// FINITE: br label %while.cond, !llvm.loop [[LOOP4:!.*]] +// CHECK: while.end: +// CHECK-NEXT: br label %while.body2 +// CHECK: while.body2: +// CHECK-NOT: br {{.*}} !llvm.loop +// +void W() { + while (a == b) { + } + while (1) { + } +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @d1( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: do.end: +// CHECK-NEXT: ret void +// +void d1() { + do { + } while (1); +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @d2( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP5:!.*]] +// FINITE: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP5:!.*]] +// CHECK: do.end: +// CHECK-NEXT: ret void +// +void d2() { + do { + } while (a == b); +} + +// CHECK-NOT: mustprogress +// CHECK-LABEL: @D( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NOT: br label {{.*}}, !llvm.loop +// CHECK: do.end: +// CHECK-NEXT: br label %do.body1 +// CHECK: do.body1: +// CHECK-NEXT: br label %do.cond2 +// CHECK: do.cond2: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// C99-NOT: br {{.*}}, !llvm.loop +// C11: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP6:!.*]] +// FINITE: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP6:!.*]] +// CHECK: do.end3: +// CHECK-NEXT: ret void +// +void D() { + do { + } while (1); + do { + } while (a == b); +} + +// C11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]} +// C11: [[MP]] = !{!"llvm.loop.mustprogress"} +// C11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]} +// C11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]} +// C11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]} +// C11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} +// C11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} diff --git a/clang/test/CodeGen/complex-builtins.c b/clang/test/CodeGen/complex-builtins.c index 96c0e71170167..6fea8a9f028c9 100644 --- a/clang/test/CodeGen/complex-builtins.c +++ b/clang/test/CodeGen/complex-builtins.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] __builtin_cpow(f,f); __builtin_cpowf(f,f); __builtin_cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/complex-libcalls.c b/clang/test/CodeGen/complex-libcalls.c index 9bd419a838217..44d6849c0a717 100644 --- a/clang/test/CodeGen/complex-libcalls.c +++ b/clang/test/CodeGen/complex-libcalls.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] cpow(f,f); cpowf(f,f); cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/enable_if.c b/clang/test/CodeGen/enable_if.c index 14550b9e2db93..327a201cdeba1 100644 --- a/clang/test/CodeGen/enable_if.c +++ b/clang/test/CodeGen/enable_if.c @@ -31,22 +31,22 @@ void bar(int m) __attribute__((overloadable, enable_if(m > 0, ""))); void bar(int m) __attribute__((overloadable, enable_if(1, ""))); // CHECK-LABEL: define{{.*}} void @test2 void test2() { - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi void (*p)(int) = bar; - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi void (*p2)(int) = &bar; - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi p = bar; - // CHECK: store void (i32)* @_Z3barUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3barUa9enable_ifILi1EEi p = &bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) void *vp1 = (void*)&bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) void *vp2 = (void*)bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) vp1 = (void*)&bar; - // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifIXLi1EEEi to i8*) + // CHECK: store i8* bitcast (void (i32)* @_Z3barUa9enable_ifILi1EEi to i8*) vp1 = (void*)bar; } @@ -54,13 +54,13 @@ void baz(int m) __attribute__((overloadable, enable_if(1, ""))); void baz(int m) __attribute__((overloadable)); // CHECK-LABEL: define{{.*}} void @test3 void test3() { - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi void (*p)(int) = baz; - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi void (*p2)(int) = &baz; - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi p = baz; - // CHECK: store void (i32)* @_Z3bazUa9enable_ifIXLi1EEEi + // CHECK: store void (i32)* @_Z3bazUa9enable_ifILi1EEi p = &baz; } @@ -71,13 +71,13 @@ void qux(int m) __attribute__((overloadable, enable_if(1, ""), void qux(int m) __attribute__((overloadable, enable_if(1, ""))); // CHECK-LABEL: define{{.*}} void @test4 void test4() { - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi void (*p)(int) = qux; - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi void (*p2)(int) = &qux; - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi p = qux; - // CHECK: store void (i32)* @_Z3quxUa9enable_ifIXLi1EEXLi1EEEi + // CHECK: store void (i32)* @_Z3quxUa9enable_ifILi1ELi1EEi p = &qux; } @@ -90,6 +90,6 @@ void test5() { int foo(char *i __attribute__((pass_object_size(0)))) __attribute__((enable_if(1, ""), overloadable)); - // CHECK: call i32 @_Z3fooUa9enable_ifIXLi1EEEPcU17pass_object_size0 + // CHECK: call i32 @_Z3fooUa9enable_ifILi1EEPcU17pass_object_size0 foo((void*)0); } diff --git a/clang/test/CodeGen/function-attributes.c b/clang/test/CodeGen/function-attributes.c index ffb86a6cd272c..f14f24801006b 100644 --- a/clang/test/CodeGen/function-attributes.c +++ b/clang/test/CodeGen/function-attributes.c @@ -115,5 +115,5 @@ void f20(void) { // CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} } // CHECK: attributes [[RT]] = { nounwind optsize returns_twice{{.*}} } // CHECK: attributes [[NR]] = { noreturn optsize } -// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone } +// CHECK: attributes [[NUW_RN]] = { nounwind optsize readnone willreturn } // CHECK: attributes [[RT_CALL]] = { optsize returns_twice } diff --git a/clang/test/CodeGen/profile-filter.c b/clang/test/CodeGen/profile-filter.c index 5415ff96cb145..dc5a31e872a1b 100644 --- a/clang/test/CodeGen/profile-filter.c +++ b/clang/test/CodeGen/profile-filter.c @@ -28,11 +28,11 @@ unsigned i; // EXCLUDE: noprofile // EXCLUDE: @test1 unsigned test1() { - // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // FUNC: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // SECTION-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 - // EXCLUDE-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0), align 8 + // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // FUNC: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // SECTION-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) + // EXCLUDE-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test1, i64 0, i64 0) return i + 1; } @@ -47,10 +47,10 @@ unsigned test1() { // EXCLUDE-NOT: noprofile // EXCLUDE: @test2 unsigned test2() { - // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // FUNC-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // SECTION: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 - // EXCLUDE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0), align 8 + // CHECK: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // FUNC-NOT: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // FILE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // SECTION: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) + // EXCLUDE: %pgocount = load i64, i64* getelementptr inbounds ([1 x i64], [1 x i64]* @__profc_test2, i64 0, i64 0) return i - 1; } diff --git a/clang/test/CodeGen/pseudo-probe-emit.c b/clang/test/CodeGen/pseudo-probe-emit.c index 059673b6992e8..fccc8f04844dd 100644 --- a/clang/test/CodeGen/pseudo-probe-emit.c +++ b/clang/test/CodeGen/pseudo-probe-emit.c @@ -6,12 +6,12 @@ void bar(); void go(); void foo(int x) { - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID:]], i64 1, i32 0, i64 -1) if (x == 0) - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 2, i32 0, i64 -1) bar(); else - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 3, i32 0, i64 -1) go(); - // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0) + // CHECK: call void @llvm.pseudoprobe(i64 [[#GUID]], i64 4, i32 0, i64 -1) } diff --git a/clang/test/CodeGenCUDA/unnamed-types.cu b/clang/test/CodeGenCUDA/unnamed-types.cu index 59bfa6d7a18f1..f598117d969da 100644 --- a/clang/test/CodeGenCUDA/unnamed-types.cu +++ b/clang/test/CodeGenCUDA/unnamed-types.cu @@ -1,12 +1,17 @@ // RUN: %clang_cc1 -std=c++11 -x hip -triple x86_64-linux-gnu -aux-triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s --check-prefix=HOST +// RUN: %clang_cc1 -std=c++11 -x hip -triple x86_64-pc-windows-msvc -aux-triple amdgcn-amd-amdhsa -emit-llvm %s -o - | FileCheck %s --check-prefix=MSVC // RUN: %clang_cc1 -std=c++11 -x hip -triple amdgcn-amd-amdhsa -fcuda-is-device -emit-llvm %s -o - | FileCheck %s --check-prefix=DEVICE #include "Inputs/cuda.h" // HOST: @0 = private unnamed_addr constant [43 x i8] c"_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_\00", align 1 +// HOST: @1 = private unnamed_addr constant [60 x i8] c"_Z2k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_\00", align 1 +// Check that, on MSVC, the same device kernel mangling name is generated. +// MSVC: @0 = private unnamed_addr constant [43 x i8] c"_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_\00", align 1 +// MSVC: @1 = private unnamed_addr constant [60 x i8] c"_Z2k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_\00", align 1 __device__ float d0(float x) { - return [](float x) { return x + 2.f; }(x); + return [](float x) { return x + 1.f; }(x); } __device__ float d1(float x) { @@ -14,11 +19,21 @@ __device__ float d1(float x) { } // DEVICE: amdgpu_kernel void @_Z2k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_( +// DEVICE: define internal float @_ZZZ2f1PfENKUlS_E_clES_ENKUlfE_clEf( template __global__ void k0(float *p, F f) { p[0] = f(p[0]) + d0(p[1]) + d1(p[2]); } +// DEVICE: amdgpu_kernel void @_Z2k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_( +// DEVICE: define internal float @_ZZ2f1PfENKUlfE_clEf( +// DEVICE: define internal float @_ZZ2f1PfENKUlffE_clEff( +// DEVICE: define internal float @_ZZ2f1PfENKUlfE0_clEf( +template +__global__ void k1(float *p, F0 f0, F1 f1, F2 f2) { + p[0] = f0(p[0]) + f1(p[1], p[2]) + f2(p[3]); +} + void f0(float *p) { [](float *p) { *p = 1.f; @@ -29,11 +44,17 @@ void f0(float *p) { // linkages are still required to keep the original `internal` linkage. // HOST: define internal void @_ZZ2f1PfENKUlS_E_clES_( -// DEVICE: define internal float @_ZZZ2f1PfENKUlS_E_clES_ENKUlfE_clEf( void f1(float *p) { [](float *p) { - k0<<<1,1>>>(p, [] __device__ (float x) { return x + 1.f; }); + k0<<<1,1>>>(p, [] __device__ (float x) { return x + 3.f; }); }(p); + k1<<<1,1>>>(p, + [] __device__ (float x) { return x + 4.f; }, + [] __device__ (float x, float y) { return x * y; }, + [] __device__ (float x) { return x + 5.f; }); } // HOST: @__hip_register_globals // HOST: __hipRegisterFunction{{.*}}@_Z17__device_stub__k0IZZ2f1PfENKUlS0_E_clES0_EUlfE_EvS0_T_{{.*}}@0 +// HOST: __hipRegisterFunction{{.*}}@_Z17__device_stub__k1IZ2f1PfEUlfE_Z2f1S0_EUlffE_Z2f1S0_EUlfE0_EvS0_T_T0_T1_{{.*}}@1 +// MSVC: __hipRegisterFunction{{.*}}@"??$k0@V@?0???R1?0??f1@@YAXPEAM@Z@QEBA@0@Z@@@YAXPEAMV@?0???R0?0??f1@@YAX0@Z@QEBA@0@Z@@Z{{.*}}@0 +// MSVC: __hipRegisterFunction{{.*}}@"??$k1@V@?0??f1@@YAXPEAM@Z@V@?0??2@YAX0@Z@V@?0??2@YAX0@Z@@@YAXPEAMV@?0??f1@@YAX0@Z@V@?0??1@YAX0@Z@V@?0??1@YAX0@Z@@Z{{.*}}@1 diff --git a/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp b/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp index 25400a552e5d2..e1d539608fcc8 100644 --- a/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp +++ b/clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp @@ -15,8 +15,8 @@ int f(void) { // CHECK: declare i32 @_Z1tv() [[TF2:#[0-9]+]] // CHECK: attributes [[TF]] = { {{.*}} } -// CHECK: attributes [[NUW_RN]] = { nounwind readnone{{.*}} } -// CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } +// CHECK: attributes [[NUW_RN]] = { nounwind readnone willreturn{{.*}} } +// CHECK: attributes [[NUW_RO]] = { nounwind readonly willreturn{{.*}} } // CHECK: attributes [[TF2]] = { {{.*}} } -// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RN_CALL]] = { nounwind readnone willreturn } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/CodeGenCXX/attr-mustprogress.cpp b/clang/test/CodeGenCXX/attr-mustprogress.cpp new file mode 100644 index 0000000000000..48ac7ad938ba3 --- /dev/null +++ b/clang/test/CodeGenCXX/attr-mustprogress.cpp @@ -0,0 +1,330 @@ +// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s +// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s +// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s +// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s +// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s + +// Make sure -ffinite-loops overrides -std=c++98 for loops. +// RUN: %clang_cc1 -std=c++98 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s + +// Make sure -fno-finite-loops overrides -std=c++11 +// RUN: %clang_cc1 -std=c++11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s + +int a = 0; +int b = 0; + +// CHECK: datalayout + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2f0v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NOT: br {{.*}} llvm.loop +void f0() { + for (; ;) ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2f1v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: br i1 true, label %for.body, label %for.end +// CHECK: for.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: for.end: +// CHECK-NEXT: ret void +// +void f1() { + for (; 1;) + ; +} + +// CXX98-NOT: mustprogress +// CXX11: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2f2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end +// CHECK: for.body: +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11: br label %for.cond, !llvm.loop [[LOOP1:!.*]] +// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP1:!.*]] +// CHECK: for.end: +// CHECK-NEXT: ret void +// +void f2() { + for (; a == b;) + ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z1Fv( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: br i1 true, label %for.body, label %for.end +// CHECK: for.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: for.end: +// CHECK-NEXT: br label %for.cond1 +// CHECK: for.cond1: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body2, label %for.end3 +// CHECK: for.body2: +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// FINITE-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// CHECK: for.end3: +// CHECK-NEXT: ret void +// +void F() { + for (; 1;) + ; + for (; a == b;) + ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2F2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %for.cond +// CHECK: for.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %for.body, label %for.end +// CHECK: for.body: +// CXX98_NOT: br {{.*}} !llvm.loop +// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]] +// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]] +// CHECK: for.end: +// CHECK-NEXT: br label %for.cond1 +// CHECK: for.cond1: +// CHECK-NEXT: br i1 true, label %for.body2, label %for.end3 +// CHECK: for.body2: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: for.end3: +// CHECK-NEXT: ret void +// +void F2() { + for (; a == b;) + ; + for (; 1;) + ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2w1v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %while.body +// CHECK: while.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// +void w1() { + while (1) + ; +} + +// CXX98-NOT: mustprogress +// CXX11: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2w2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %while.cond +// CHECK: while.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end +// CHECK: while.body: +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]] +// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]] +// CHECK: while.end: +// CHECK-NEXT: ret void +// +void w2() { + while (a == b) + ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z1Wv( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %while.cond +// CHECK: while.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end +// CHECK: while.body: +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]] +// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]] +// CHECK: while.end: +// CHECK-NEXT: br label %while.body2 +// CHECK: while.body2: +// CHECK-NOT: br {{.*}}, !llvm.loop +// +void W() { + while (a == b) + ; + while (1) + ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2W2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %while.body +// CHECK: while.body: +// CHECK-NOT: br {{.*}}, !llvm.loop +// +void W2() { + while (1) + ; + while (a == b) + ; +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2d1v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: do.end: +// CHECK-NEXT: ret void +// +void d1() { + do + ; + while (1); +} + +// CXX98-NOT: mustprogress +// CXX11: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2d2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]] +// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]] +// CHECK: do.end: +// CHECK-NEXT: ret void +// +void d2() { + do + ; + while (a == b); +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z1Dv( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: do.end: +// CHECK-NEXT: br label %do.body1 +// CHECK: do.body1: +// CHECK-NEXT: br label %do.cond2 +// CHECK: do.cond2: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]] +// FINITE-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]] +// CHECK: do.end3: +// CHECK-NEXT: ret void +// +void D() { + do + ; + while (1); + do + ; + while (a == b); +} + +// CXX98-NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress +// CHECK-LABEL: @_Z2D2v( +// CHECK-NEXT: entry: +// CHECK-NEXT: br label %do.body +// CHECK: do.body: +// CHECK-NEXT: br label %do.cond +// CHECK: do.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +// CXX98-NOT: br {{.*}}, !llvm.loop +// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]] +// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]] +// CHECK: do.end: +// CHECK-NEXT: br label %do.body1 +// CHECK: do.body1: +// CHECK-NEXT: br label %do.cond2 +// CHECK: do.cond2: +// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK: do.end3: +// CHECK-NEXT: ret void +// +void D2() { + do + ; + while (a == b); + do + ; + while (1); +} + +// CXX11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]} +// CXX11: [[MP]] = !{!"llvm.loop.mustprogress"} +// CXX11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]} +// CXX11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]} +// CXX11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]} +// CXX11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} +// CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} +// CXX11: [[LOOP7]] = distinct !{[[LOOP7]], [[MP]]} +// CXX11: [[LOOP8]] = distinct !{[[LOOP8]], [[MP]]} diff --git a/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp b/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp index 967c83496ab98..d30fefe55b4f6 100644 --- a/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp +++ b/clang/test/CodeGenCXX/builtin-is-constant-evaluated.cpp @@ -4,6 +4,7 @@ // RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s // RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s // RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s +// RUN: FileCheck -check-prefix=CHECK-DTOR -input-file=%t.ll %s using size_t = decltype(sizeof(int)); @@ -131,3 +132,94 @@ void test_ref_to_static_var() { // CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, i32** %r, int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant; } + +int not_constexpr; + +// __builtin_is_constant_evaluated() should never evaluate to true during +// destruction if it would not have done so during construction. +// +// FIXME: The standard doesn't say that it should ever return true when +// evaluating a destructor call, even for a constexpr variable. That seems +// obviously wrong. +struct DestructorBCE { + int n; + constexpr DestructorBCE(int n) : n(n) {} + constexpr ~DestructorBCE() { + if (!__builtin_is_constant_evaluated()) + not_constexpr = 1; + } +}; + +// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_1 +DestructorBCE global_dtor_bce_1(101); + +// CHECK-DTOR: load i32, i32* @not_constexpr +// CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} @global_dtor_bce_2, i32 +// CHECK-DTOR: atexit{{.*}} @_ZN13DestructorBCED{{.*}} @global_dtor_bce_2 +// CHECK-DTOR: } +DestructorBCE global_dtor_bce_2(not_constexpr); + +// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_3 +constexpr DestructorBCE global_dtor_bce_3(103); + +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_1v( +void test_dtor_bce_1() { + // Variable is neither constant initialized (because it has automatic storage + // duration) nor usable in constant expressions, so BCE should not return + // true during destruction. It would be OK if we replaced the constructor + // call with a direct store, but we should emit the destructor call. + + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}}, i32 201) + DestructorBCE local(201); + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_2v( +void test_dtor_bce_2() { + // Non-constant init => BCE is false in destructor. + + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} + DestructorBCE local(not_constexpr); + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_3v( +void test_dtor_bce_3() { + // Should never call dtor for a constexpr variable. + + // CHECK-DTOR-NOT: call {{.*}} @_ZN13DestructorBCEC1Ei( + constexpr DestructorBCE local(203); + // CHECK-DTOR-NOT: @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_1v( +void test_dtor_bce_static_1() { + // Variable is constant initialized, so BCE returns true during constant + // destruction. + + // CHECK: store i32 301 + // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}} + static DestructorBCE local(301); + // CHECK-DTOR-NOT: @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_2v( +void test_dtor_bce_static_2() { + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} + static DestructorBCE local(not_constexpr); + // CHECK-DTOR: call {{.*}}atexit{{.*}} @_ZN13DestructorBCED + // CHECK-DTOR: } +} + +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_3v( +void test_dtor_bce_static_3() { + // CHECK: store i32 303 + // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}} + static constexpr DestructorBCE local(303); + // CHECK-DTOR-NOT: @_ZN13DestructorBCED + // CHECK-DTOR: } +} diff --git a/clang/test/CodeGenCXX/clang-abi-compat.cpp b/clang/test/CodeGenCXX/clang-abi-compat.cpp index 46e7ed812cbc6..80311aa320fe5 100644 --- a/clang/test/CodeGenCXX/clang-abi-compat.cpp +++ b/clang/test/CodeGenCXX/clang-abi-compat.cpp @@ -1,12 +1,23 @@ -// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.8 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=3.9 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=4.0 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=5 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s -// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fclang-abi-compat=11 %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s -// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s -// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fclang-abi-compat=latest %s -emit-llvm -o - | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17 %s +// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - -Wno-c++11-extensions \ +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.0 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.8 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,PRE39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=3.9 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=4.0 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,PRE5,PRE12 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=5 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s +// RUN: %clang_cc1 -std=c++17 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17 %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=11 %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,PRE12,PRE12-CXX17,PRE12-CXX20 %s +// RUN: %clang_cc1 -std=c++98 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - -Wno-c++11-extensions \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12 %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-linux-gnu -fenable-matrix -fclang-abi-compat=latest %s -emit-llvm -o - \ +// RUN: | FileCheck --check-prefixes=CHECK,V39,V5,V12,V12-CXX17,V12-CXX20 %s typedef __attribute__((vector_size(8))) long long v1xi64; void clang39(v1xi64) {} @@ -55,3 +66,73 @@ template void clang12_b(); // CHECK: @_Z9clang12_cIXadL_Z3arrEEEvv template void clang12_c() {} template void clang12_c<&arr>(); + + +/// Tests for changes in clang12: +namespace expr_primary { +struct A { + template struct Int {}; + template struct Ref {}; +}; + +/// Check various DeclRefExpr manglings + +// PRE12: @_ZN12expr_primary5test1INS_1AEEEvNT_3IntIXLi1EEEE +// V12: @_ZN12expr_primary5test1INS_1AEEEvNT_3IntILi1EEE +template void test1(typename T::template Int<1> a) {} +template void test1(typename A::template Int<1> a); + +enum Enum { EnumVal = 4 }; +int Global; + +// PRE12: @_ZN12expr_primary5test2INS_1AEEEvNT_3IntIXLNS_4EnumE4EEEE +// V12: @_ZN12expr_primary5test2INS_1AEEEvNT_3IntILNS_4EnumE4EEE +template void test2(typename T::template Int a) {} +template void test2(typename A::template Int<4> a); + +// CHECK: @_ZN12expr_primary5test3ILi3EEEvNS_1A3IntIXT_EEE +template void test3(typename A::template Int a) {} +template void test3<3>(A::Int<3> a); + +#if __cplusplus >= 202002L +// CHECK-CXX20: @_ZN12expr_primary5test4INS_1AEEEvNT_3RefIL_ZNS_6GlobalEEEE +template void test4(typename T::template Ref<(Global)> a) {} +template void test4(typename A::template Ref a); + +struct B { + struct X { + constexpr X(double) {} + constexpr X(int&) {} + }; + template struct Y {}; +}; + +// PRE12-CXX20: _ZN12expr_primary5test5INS_1BEEEvNT_1YIXLd3ff0000000000000EEEE +// V12-CXX20: _ZN12expr_primary5test5INS_1BEEEvNT_1YILd3ff0000000000000EEE +template void test5(typename T::template Y<1.0>) { } +template void test5(typename B::Y<1.0>); + +// PRE12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIL_ZZNS_5test6EiE1bEEEi +// V12-CXX20: @_ZN12expr_primary5test6INS_1BEEENT_1YIXfp_EEEi +template auto test6(int b) -> typename T::template Y { return {}; } +template auto test6(int b) -> B::Y; +#endif + +/// Verify non-dependent type-traits within a dependent template arg. + +// PRE12: @_ZN12expr_primary5test7INS_1AEEEvNT_3IntIXLm1EEEE +// V12: @_ZN12expr_primary5test7INS_1AEEEvNT_3IntILm1EEE +template void test7(typename T::template Int a) {} +template void test7(A::Int<1>); + +// PRE12: @_ZN12expr_primary5test8ILi2EEEvu11matrix_typeIXLi1EEXT_EiE +// V12: @_ZN12expr_primary5test8ILi2EEEvu11matrix_typeILi1EXT_EiE +template using matrix1xN = int __attribute__((matrix_type(1, N))); +template void test8(matrix1xN a) {} +template void test8<2>(matrix1xN<2> a); + +// PRE12: @_ZN12expr_primary5test9EUa9enable_ifIXLi1EEEv +// V12: @_ZN12expr_primary5test9EUa9enable_ifILi1EEv +void test9(void) __attribute__((enable_if(1, ""))) {} + +} diff --git a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp index 27ac682c10f52..409b62da62c12 100644 --- a/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp +++ b/clang/test/CodeGenCXX/debug-info-gline-tables-only-codeview.cpp @@ -25,6 +25,6 @@ void test() { // CHECK: ![[C]] = !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-SAME: flags: DIFlagFwdDecl // CHECK-NOT: identifier - // CHECK: ![[MTYPE]] = !DISubroutineType(types: !{{.*}}) + // CHECK: ![[MTYPE]] = !DISubroutineType({{.*}}types: !{{.*}}) c.m(); } diff --git a/clang/test/CodeGenCXX/enable_if.cpp b/clang/test/CodeGenCXX/enable_if.cpp index 4e7707aaeed9c..70386b87fcee3 100644 --- a/clang/test/CodeGenCXX/enable_if.cpp +++ b/clang/test/CodeGenCXX/enable_if.cpp @@ -5,7 +5,7 @@ int test5(int); template T test5(T) __attribute__((enable_if(1, "better than non-template"))); -// CHECK: @_Z5test5IiEUa9enable_ifIXLi1EEET_S0_ +// CHECK: @_Z5test5IiEUa9enable_ifILi1EET_S0_ int (*Ptr)(int) = &test5; // Test itanium mangling for attribute enable_if diff --git a/clang/test/CodeGenCXX/mangle-abi-tag.cpp b/clang/test/CodeGenCXX/mangle-abi-tag.cpp index 5d84096d24cd8..9e26604a2c448 100644 --- a/clang/test/CodeGenCXX/mangle-abi-tag.cpp +++ b/clang/test/CodeGenCXX/mangle-abi-tag.cpp @@ -225,7 +225,7 @@ namespace pr30440 { template void g(F); template auto h(A ...a)->decltype (g (0, g < a > (a) ...)) { } -// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIL_ZZNS_1hEDpT_E1aEEfp_EEES2_( +// CHECK-DAG: define {{.*}} @_ZN7pr304401hIJEEEDTcl1gLi0Espcl1gIXfp_EEfp_EEEDpT_( void pr30440_test () { h(); diff --git a/clang/test/CodeGenCXX/mangle-alignof.cpp b/clang/test/CodeGenCXX/mangle-alignof.cpp new file mode 100644 index 0000000000000..0a65c7e87a2d3 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-alignof.cpp @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=c++11 -Wno-gnu-alignof-expression -emit-llvm %s -o - -triple=%itanium_abi_triple | FileCheck %s --check-prefix=CHECK-NEW +// RUN: %clang_cc1 -std=c++11 -Wno-gnu-alignof-expression -emit-llvm %s -o - -triple=%itanium_abi_triple -fclang-abi-compat=11 | FileCheck %s --check-prefix=CHECK-OLD + +// Verify the difference in mangling for alignof and __alignof__ in a new ABI +// compat mode. + +template void f1(decltype(alignof(T))) {} +template void f1(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f1IiEvDTatT_E +// CHECK-NEW: void @_Z2f1IiEvDTatT_E + +template void f2(decltype(__alignof__(T))) {} +template void f2(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f2IiEvDTatT_E +// CHECK-NEW: void @_Z2f2IiEvDTu11__alignof__T_E + +template void f3(decltype(alignof(T(0)))) {} +template void f3(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f3IiEvDTazcvT_Li0EE +// CHECK-NEW: void @_Z2f3IiEvDTazcvT_Li0EE + +template void f4(decltype(__alignof__(T(0)))) {} +template void f4(__SIZE_TYPE__); +// CHECK-OLD: void @_Z2f4IiEvDTazcvT_Li0EE +// CHECK-NEW: void @_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE diff --git a/clang/test/CodeGenCXX/mangle-concept.cpp b/clang/test/CodeGenCXX/mangle-concept.cpp index b0fcd586727e8..e60e6348a5f6d 100644 --- a/clang/test/CodeGenCXX/mangle-concept.cpp +++ b/clang/test/CodeGenCXX/mangle-concept.cpp @@ -6,11 +6,11 @@ template struct S {}; template concept C = true; template S> f0() { return S>{}; } template S> f0<>(); -// CHECK: @_ZN5test12f0IiEENS_1SIXL_ZNS_1CIT_EEEEEEv( +// CHECK: @_ZN5test12f0IiEENS_1SIL_ZNS_1CIT_EEEEEv( } template struct S {}; template concept C = true; template S> f0() { return S>{}; } template S> f0<>(); -// CHECK: @_Z2f0IiE1SIXL_Z1CIT_EEEEv( +// CHECK: @_Z2f0IiE1SIL_Z1CIT_EEEv( diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp index 40688de7e12e8..9b80a6d646955 100644 --- a/clang/test/CodeGenCXX/mangle-template.cpp +++ b/clang/test/CodeGenCXX/mangle-template.cpp @@ -270,7 +270,7 @@ namespace test17 { // Note: there is no J...E here, because we can't form a pack argument, and // the 5u and 6u are mangled with the original type 'j' (unsigned int) not // with the resolved type 'i' (signed int). - // CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_EXLj5EEXT_EXLj6EEEE + // CHECK: define {{.*}} @_ZN6test171hILi4EJLi1ELi2ELi3EEEEvNS_1XIXspT0_ELj5EXT_ELj6EEE template void h(X) {} void i() { h<4, 1, 2, 3>({}); } @@ -323,7 +323,7 @@ namespace partially_dependent_template_args { // callee is unresolved, the rest mangle the converted argument Lj0E // because the callee is resolved. void h() { - // CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fIXLi0EEEcvT__EEE + // CHECK: @_ZN33partially_dependent_template_args5test22g1INS0_1XEEEvDTcl1fILi0EEcvT__EEE g1({}); // CHECK: @_ZN33partially_dependent_template_args5test22g2IiEEvDTplclL_ZNS0_1fILj0EEEiNS0_1XEEilEEcvT__EE g2({}); diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index f8ea9960a5c50..6cec33e3758e7 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1123,7 +1123,7 @@ namespace test56 { namespace test57 { struct X { template int f(); } x; template void f(decltype(x.f<0>() + N)) {} - // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fIXLi0EEEET_E + // CHECK-LABEL: @_ZN6test571fILi0EEEvDTplcldtL_ZNS_1xEE1fILi0EEET_E template void f<0>(int); } diff --git a/clang/test/CodeGenCXX/matrix-type.cpp b/clang/test/CodeGenCXX/matrix-type.cpp index 9bde12e13b86a..9e715e10ce1c6 100644 --- a/clang/test/CodeGenCXX/matrix-type.cpp +++ b/clang/test/CodeGenCXX/matrix-type.cpp @@ -215,14 +215,14 @@ void test_template_deduction() { // CHECK-NEXT: %m4 = alloca [144 x float], align 4 // CHECK-NEXT: %v = alloca %struct.selector.3, align 1 // CHECK-NEXT: %undef.agg.tmp4 = alloca %struct.selector.3, align 1 - // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeIXLm10EEXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m0) + // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m0) // CHECK-NEXT: call void @_Z10use_matrixIiE8selectorILi2EERu11matrix_typeILm10ELm10ET_E([100 x i32]* nonnull align 4 dereferenceable(400) %m1) - // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_EXLm10EET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m2) + // CHECK-NEXT: call void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m2) // CHECK-NEXT: call void @_Z10use_matrixIiLm12ELm12EE8selectorILi0EERu11matrix_typeIXT0_EXT1_ET_E([144 x i32]* nonnull align 4 dereferenceable(576) %m3) // CHECK-NEXT: call void @_Z10use_matrixILm12ELm12EE8selectorILi4EERu11matrix_typeIXT_EXT0_EfE([144 x float]* nonnull align 4 dereferenceable(576) %m4) // CHECK-NEXT: ret void - // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeIXLm10EEXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) + // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi3EERu11matrix_typeILm10EXT0_ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) // CHECK-NEXT: entry: // CHECK-NEXT: %m.addr = alloca [120 x i32]*, align 8 // CHECK-NEXT: store [120 x i32]* %m, [120 x i32]** %m.addr, align 8 @@ -236,7 +236,7 @@ void test_template_deduction() { // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable - // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_EXLm10EET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) + // CHECK-LABEL: define linkonce_odr void @_Z10use_matrixIiLm12EE8selectorILi1EERu11matrix_typeIXT0_ELm10ET_E([120 x i32]* nonnull align 4 dereferenceable(480) %m) // CHECK-NEXT: entry: // CHECK-NEXT: %m.addr = alloca [120 x i32]*, align 8 // CHECK-NEXT: store [120 x i32]* %m, [120 x i32]** %m.addr, align 8 @@ -277,10 +277,10 @@ void test_auto_t() { // CHECK-LABEL: define{{.*}} void @_Z11test_auto_tv() // CHECK-NEXT: entry: // CHECK-NEXT: %m = alloca [130 x i32], align 4 - // CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_EXLm10EEiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) + // CHECK-NEXT: call void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) // CHECK-NEXT: ret void - // CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_EXLm10EEiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) + // CHECK-LABEL: define linkonce_odr void @_Z3fooILm13EEvRu11matrix_typeIXT_ELm10EiE([130 x i32]* nonnull align 4 dereferenceable(520) %m) // CHECK-NEXT: entry: // CHECK-NEXT: %m.addr = alloca [130 x i32]*, align 8 // CHECK-NEXT: store [130 x i32]* %m, [130 x i32]** %m.addr, align 8 @@ -326,7 +326,7 @@ void test_use_matrix_2() { // CHECK-NEXT: store <40 x float> %call, <40 x float>* %0, align 4 // CHECK-NEXT: call void @_Z12use_matrix_2ILm2ELm12EE8selectorILi0EERu11matrix_typeIXplT_Li2EEXdvT0_Li2EEiERu11matrix_typeIXT_EXT0_EfE([24 x i32]* nonnull align 4 dereferenceable(96) %m1, [24 x float]* nonnull align 4 dereferenceable(96) %m2) // CHECK-NEXT: call void @_Z12use_matrix_2ILm5ELm8EE8selectorILi1EERu11matrix_typeIXplT_T0_EXT0_EiERu11matrix_typeIXT_EXmiT0_T_EfE([104 x i32]* nonnull align 4 dereferenceable(416) %m3, [15 x float]* nonnull align 4 dereferenceable(60) %m4) - // CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_EXLm10EEiE([50 x i32]* nonnull align 4 dereferenceable(200) %m5) + // CHECK-NEXT: %call2 = call <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE([50 x i32]* nonnull align 4 dereferenceable(200) %m5) // CHECK-NEXT: %1 = bitcast [20 x float]* %r4 to <20 x float>* // CHECK-NEXT: store <20 x float> %call2, <20 x float>* %1, align 4 // CHECK-NEXT: call void @_Z12use_matrix_3ILm6EE8selectorILi2EERu11matrix_typeIXmiT_Li2EEXT_EiE([24 x i32]* nonnull align 4 dereferenceable(96) %m1) @@ -357,7 +357,7 @@ void test_use_matrix_2() { // CHECK-NEXT: call void @llvm.trap() // CHECK-NEXT: unreachable - // CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_EXLm10EEiE([50 x i32]* nonnull align 4 dereferenceable(200) %m1) + // CHECK-LABEL: define linkonce_odr <20 x float> @_Z12use_matrix_2ILm5EEu11matrix_typeIXplT_T_EXmiT_Li3EEfERu11matrix_typeIXT_ELm10EiE([50 x i32]* nonnull align 4 dereferenceable(200) %m1) // CHECK-NEXT: entry: // CHECK-NEXT: %m1.addr = alloca [50 x i32]*, align 8 // CHECK-NEXT: store [50 x i32]* %m1, [50 x i32]** %m1.addr, align 8 diff --git a/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp b/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp index ec26be292accc..5c02b1eb014c6 100644 --- a/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp +++ b/clang/test/CodeGenCXX/microsoft-uuidof-mangling.cpp @@ -1,4 +1,5 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions | FileCheck %s --check-prefixes=CHECK,CHECK-V12 +// RUN: %clang_cc1 -emit-llvm %s -o - -triple x86_64-unknown-unknown -fms-extensions -fclang-abi-compat=11 | FileCheck %s --check-prefixes=CHECK,CHECK-V11 // rdar://17784718 typedef struct _GUID @@ -24,11 +25,16 @@ struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) TestStruct struct __declspec(uuid("EAFA1952-66F8-438B-8FBA-AF1BBAE42191")) OtherStruct {}; -template void test_uuidofType(void *arg[sizeof(__uuidof(T))] = 0) {} +template void test_uuidofType(decltype(__uuidof(T)) arg) {} -template void test_uuidofExpr(void *arg[sizeof(__uuidof(typename T::member))] = 0) {} +template void test_uuidofExpr(decltype(__uuidof(T::member)) arg) {} -struct HasMember { typedef TestStruct member; }; +struct HasMember { + TestStruct member; +}; + +// Ensure that mangling an "expr-primary" argument is handled properly. +template void test_uuidofExpr2(decltype(T{}, __uuidof(HasMember::member)) arg) {} template struct UUIDTestTwo { UUIDTestTwo(); }; @@ -39,19 +45,27 @@ int main(int argc, const char * argv[]) // type had better not mention TestStruct or OtherStruct! UUIDTestTwo<__uuidof(TestStruct)> uuidof_test2; UUIDTestTwo<__uuidof(OtherStruct)> uuidof_test3; - test_uuidofType(); - test_uuidofExpr(); + test_uuidofType(GUID{}); + test_uuidofExpr(GUID{}); + test_uuidofExpr2(GUID{}); return 0; } // CHECK: define{{.*}} i32 @main -// CHECK: call void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: call void @_Z15test_uuidofTypeI10TestStructEvPPv(i8** null) -// CHECK: call void @_Z15test_uuidofExprI9HasMemberEvPPv(i8** null) - +// CHECK: call void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev( +// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev( +// CHECK: call void @_ZN11UUIDTestTwoIL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev( +// CHECK-V11: call void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E( +// CHECK-V12: call void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE( +// CHECK-V11: call void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofzsrT_6memberE( +// CHECK-V12: call void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE( +// CHECK-V11: call void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofzL_ZN9HasMember6memberEEE( +// CHECK-V12: call void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofL_ZN9HasMember6memberEEEE( // CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC1Ev -// CHECK: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvPPv -// CHECK: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvPPv +// CHECK-V11: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E( +// CHECK-V12: define linkonce_odr void @_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE( +// CHECK-V11: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofzsrT_6memberE( +// CHECK-V12: define linkonce_odr void @_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE( +// CHECK-V11: define linkonce_odr void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofzL_ZN9HasMember6memberEEE( +// CHECK-V12: define linkonce_odr void @_Z16test_uuidofExpr2I10TestStructEvDTcmtlT_Eu8__uuidofL_ZN9HasMember6memberEEEE( // CHECK: define linkonce_odr void @_ZN8UUIDTestI10TestStructL_Z42_GUID_eafa1952_66f8_438b_8fba_af1bbae42191EEC2Ev diff --git a/clang/test/Driver/Xlinker-args.c b/clang/test/Driver/Xlinker-args.c index a44957cd8aef1..cb045a1d40ac1 100644 --- a/clang/test/Driver/Xlinker-args.c +++ b/clang/test/Driver/Xlinker-args.c @@ -17,7 +17,7 @@ // LINUX: "--no-demangle" "-e" "_start" "one" "two" "three" "four" "-z" "five" "-r" {{.*}} "-T" "a.lds" // Check that we forward '-Xlinker' and '-Wl,' on Windows. -// RUN: %clang -target i686-pc-win32 -### \ +// RUN: %clang -target i686-pc-win32 -fuse-ld=link -### \ // RUN: -Xlinker one -Wl,two %s 2>&1 | \ // RUN: FileCheck -check-prefix=WIN %s // WIN: link.exe diff --git a/clang/test/Driver/cl-inputs.c b/clang/test/Driver/cl-inputs.c index 59455a0aa5e5c..8eb44517ee167 100644 --- a/clang/test/Driver/cl-inputs.c +++ b/clang/test/Driver/cl-inputs.c @@ -50,16 +50,16 @@ // RUN: %clang_cl -### /Tc - 2>&1 | FileCheck -check-prefix=STDINTc %s // STDINTc: "-x" "c" -// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -### -- %s cl-test.lib 2>&1 | FileCheck -check-prefix=LIBINPUT %s +// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -fuse-ld=link -### -- %s cl-test.lib 2>&1 | FileCheck -check-prefix=LIBINPUT %s // LIBINPUT: link.exe" // LIBINPUT: "cl-test.lib" -// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -### -- %s cl-test2.lib 2>&1 | FileCheck -check-prefix=LIBINPUT2 %s +// RUN: env LIB=%S/Inputs/cl-libs %clang_cl -fuse-ld=link -### -- %s cl-test2.lib 2>&1 | FileCheck -check-prefix=LIBINPUT2 %s // LIBINPUT2: error: no such file or directory: 'cl-test2.lib' // LIBINPUT2: link.exe" // LIBINPUT2-NOT: "cl-test2.lib" -// RUN: %clang_cl -### -- %s /nonexisting.lib 2>&1 | FileCheck -check-prefix=LIBINPUT3 %s +// RUN: %clang_cl -fuse-ld=link -### -- %s /nonexisting.lib 2>&1 | FileCheck -check-prefix=LIBINPUT3 %s // LIBINPUT3: error: no such file or directory: '/nonexisting.lib' // LIBINPUT3: link.exe" // LIBINPUT3-NOT: "/nonexisting.lib" diff --git a/clang/test/Driver/cl-link-at-file.c b/clang/test/Driver/cl-link-at-file.c index 50ae07fadf5bf..4e665f89b74e1 100644 --- a/clang/test/Driver/cl-link-at-file.c +++ b/clang/test/Driver/cl-link-at-file.c @@ -7,7 +7,7 @@ // RUN: echo /link bar.lib baz.lib > %t.args // RUN: touch %t.obj -// RUN: %clang_cl -### @%t.args -- %t.obj 2>&1 | FileCheck %s -check-prefix=ARGS +// RUN: %clang_cl -fuse-ld=link -### @%t.args -- %t.obj 2>&1 | FileCheck %s -check-prefix=ARGS // If the "/link" option captures all remaining args beyond its response file, // it will also capture "--" and our input argument. In this case, Clang will // be clueless and will emit "argument unused" warnings. If PR17239 is properly diff --git a/clang/test/Driver/cl-link.c b/clang/test/Driver/cl-link.c index 142725fed8eb2..e2f5397e91339 100644 --- a/clang/test/Driver/cl-link.c +++ b/clang/test/Driver/cl-link.c @@ -2,14 +2,14 @@ // be interpreted as a command-line option, e.g. on Mac where %s is commonly // under /Users. -// RUN: %clang_cl /Tc%s -### /link foo bar baz 2>&1 | FileCheck --check-prefix=LINK %s -// RUN: %clang_cl /Tc%s -### /linkfoo bar baz 2>&1 | FileCheck --check-prefix=LINK %s +// RUN: %clang_cl /Tc%s -fuse-ld=link -### /link foo bar baz 2>&1 | FileCheck --check-prefix=LINK %s +// RUN: %clang_cl /Tc%s -fuse-ld=link -### /linkfoo bar baz 2>&1 | FileCheck --check-prefix=LINK %s // LINK: link.exe // LINK: "foo" // LINK: "bar" // LINK: "baz" -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN %s // ASAN: link.exe // ASAN: "-debug" // ASAN: "-incremental:no" @@ -19,7 +19,7 @@ // ASAN: "-wholearchive:{{.*}}clang_rt.asan_cxx-i386.lib" // ASAN: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /MD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /MD /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-MD %s // ASAN-MD: link.exe // ASAN-MD: "-debug" // ASAN-MD: "-incremental:no" @@ -29,13 +29,13 @@ // ASAN-MD: "-wholearchive:{{.*}}clang_rt.asan_dynamic_runtime_thunk-i386.lib" // ASAN-MD: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl /LD -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s -// RUN: %clang_cl /LDd -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s +// RUN: %clang_cl /LD -fuse-ld=link -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s +// RUN: %clang_cl /LDd -fuse-ld=link -### /Tc%s 2>&1 | FileCheck --check-prefix=DLL %s // DLL: link.exe // "-dll" -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LD /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s -// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LDd /Tc%s -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LD /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386-pc-win32 /LDd /Tc%s -fuse-ld=link -### -fsanitize=address 2>&1 | FileCheck --check-prefix=ASAN-DLL %s // ASAN-DLL: link.exe // ASAN-DLL: "-dll" // ASAN-DLL: "-debug" @@ -43,13 +43,13 @@ // ASAN-DLL: "{{.*}}clang_rt.asan_dll_thunk-i386.lib" // ASAN-DLL: "{{.*}}cl-link{{.*}}.obj" -// RUN: %clang_cl /Zi /Tc%s -### 2>&1 | FileCheck --check-prefix=DEBUG %s +// RUN: %clang_cl /Zi /Tc%s -fuse-ld=link -### 2>&1 | FileCheck --check-prefix=DEBUG %s // DEBUG: link.exe // DEBUG: "-debug" // PR27234 -// RUN: %clang_cl /Tc%s nonexistent.obj -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s -// RUN: %clang_cl /Tc%s nonexistent.lib -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.obj -fuse-ld=link -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s +// RUN: %clang_cl /Tc%s nonexistent.lib -fuse-ld=link -### /link /libpath:somepath 2>&1 | FileCheck --check-prefix=NONEXISTENT %s // NONEXISTENT-NOT: no such file // NONEXISTENT: link.exe // NONEXISTENT: "/libpath:somepath" diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 0b788ffcb852f..24d3c78643f85 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -1089,20 +1089,6 @@ // CHECK-ANDROID-HASH-STYLE-M: "{{.*}}ld{{(.exe)?}}" // CHECK-ANDROID-HASH-STYLE-M: "--hash-style=gnu" -// Check that we pass --no-rosegment for pre-29 Android versions and do not for -// 29+. -// RUN: %clang %s -### -o %t.o 2>&1 \ -// RUN: --target=armv7-linux-android28 \ -// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ROSEGMENT-28 %s -// CHECK-ANDROID-ROSEGMENT-28: "{{.*}}ld{{(.exe)?}}" -// CHECK-ANDROID-ROSEGMENT-28: "--no-rosegment" -// -// RUN: %clang %s -### -o %t.o 2>&1 \ -// RUN: --target=armv7-linux-android29 \ -// RUN: | FileCheck --check-prefix=CHECK-ANDROID-ROSEGMENT-29 %s -// CHECK-ANDROID-ROSEGMENT-29: "{{.*}}ld{{(.exe)?}}" -// CHECK-ANDROID-ROSEGMENT-29-NOT: "--no-rosegment" - // RUN: %clang %s -### -o %t.o 2>&1 \ // RUN: --target=armv7-linux-android21 \ // RUN: | FileCheck --check-prefix=CHECK-ANDROID-NOEXECSTACK %s diff --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c index 13dccd21bfd8d..1ee17fc63c321 100644 --- a/clang/test/Driver/msvc-link.c +++ b/clang/test/Driver/msvc-link.c @@ -1,4 +1,4 @@ -// RUN: %clang -target i686-pc-windows-msvc -### %s 2>&1 | FileCheck --check-prefix=BASIC %s +// RUN: %clang -target i686-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=BASIC %s // BASIC: link.exe" // BASIC: "-out:a.exe" // BASIC: "-defaultlib:libcmt" @@ -6,7 +6,7 @@ // BASIC: "-nologo" // BASIC-NOT: "-Brepro" -// RUN: %clang -target i686-pc-windows-msvc -shared -o a.dll -### %s 2>&1 | FileCheck --check-prefix=DLL %s +// RUN: %clang -target i686-pc-windows-msvc -shared -o a.dll -fuse-ld=link -### %s 2>&1 | FileCheck --check-prefix=DLL %s // DLL: link.exe" // DLL: "-out:a.dll" // DLL: "-defaultlib:libcmt" @@ -19,13 +19,13 @@ // LIBPATH: "-libpath:/usr/lib" // LIBPATH: "-nologo" -// RUN: %clang_cl /Brepro -### -- %s 2>&1 | FileCheck --check-prefix=REPRO %s +// RUN: %clang_cl /Brepro -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=REPRO %s // REPRO: link.exe" // REPRO: "-out:msvc-link.exe" // REPRO: "-nologo" // REPRO: "-Brepro" -// RUN: %clang_cl /Brepro- -### -- %s 2>&1 | FileCheck --check-prefix=NOREPRO %s +// RUN: %clang_cl /Brepro- -fuse-ld=link -### -- %s 2>&1 | FileCheck --check-prefix=NOREPRO %s // NOREPRO: link.exe" // NOREPRO: "-out:msvc-link.exe" // NOREPRO: "-nologo" diff --git a/clang/test/Driver/openbsd.cpp b/clang/test/Driver/openbsd.cpp index 9293148680c8c..23c365d28e7ed 100644 --- a/clang/test/Driver/openbsd.cpp +++ b/clang/test/Driver/openbsd.cpp @@ -6,7 +6,7 @@ // RUN: | FileCheck --check-prefix=CHECK-CXX %s // RUN: %clangxx %s -### -o %t.o -target arm-unknown-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-CXX %s -// CHECK-CXX: "-lc++" "-lc++abi" "-lm" +// CHECK-CXX: "-lc++" "-lc++abi" "-lpthread" "-lm" // RUN: %clangxx %s -### -pg -o %t.o -target amd64-pc-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s @@ -16,4 +16,4 @@ // RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s // RUN: %clangxx %s -### -pg -o %t.o -target arm-unknown-openbsd 2>&1 \ // RUN: | FileCheck --check-prefix=CHECK-PG-CXX %s -// CHECK-PG-CXX: "-lc++_p" "-lc++abi_p" "-lm_p" +// CHECK-PG-CXX: "-lc++_p" "-lc++abi_p" "-lpthread_p" "-lm_p" diff --git a/clang/test/Driver/ppc-f128-support-check.c b/clang/test/Driver/ppc-f128-support-check.c index 2e4b7a7ae09ce..24748905612ff 100644 --- a/clang/test/Driver/ppc-f128-support-check.c +++ b/clang/test/Driver/ppc-f128-support-check.c @@ -1,7 +1,7 @@ // RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ -// RUN: -mcpu=pwr9 %s 2>&1 | FileCheck %s --check-prefix=HASF128 +// RUN: -mcpu=pwr9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 // RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ -// RUN: -mcpu=power9 %s 2>&1 | FileCheck %s --check-prefix=HASF128 +// RUN: -mcpu=power9 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=HASF128 // RUN: not %clang -target powerpc64le-unknown-linux-gnu -fsyntax-only \ // RUN: -mcpu=pwr8 -mfloat128 %s 2>&1 | FileCheck %s --check-prefix=NOF128 diff --git a/clang/test/Driver/pseudo-probe-lto.c b/clang/test/Driver/pseudo-probe-lto.c new file mode 100644 index 0000000000000..e319b8c0098bf --- /dev/null +++ b/clang/test/Driver/pseudo-probe-lto.c @@ -0,0 +1,10 @@ +// RUN: touch %t.o +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fpseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=PROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto=thin -fpseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=PROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fno-pseudo-probe-for-profiling -fpseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=PROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto 2>&1 | FileCheck %s --check-prefix=NOPROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fno-pseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=NOPROBE +// RUN: %clang -### %t.o -target x86_64-unknown-linux -flto -fpseudo-probe-for-profiling -fno-pseudo-probe-for-profiling 2>&1 | FileCheck %s --check-prefix=NOPROBE + +// PROBE: -plugin-opt=pseudo-probe-for-profiling +// NOPROBE-NOT: -plugin-opt=pseudo-probe-for-profiling diff --git a/clang/test/Driver/riscv-arch.c b/clang/test/Driver/riscv-arch.c index 3762a4aef1b34..cf148ca885d09 100644 --- a/clang/test/Driver/riscv-arch.c +++ b/clang/test/Driver/riscv-arch.c @@ -384,7 +384,7 @@ // RV32-EXPERIMENTAL-V-BADVERS: error: invalid arch name 'rv32iv0p1' // RV32-EXPERIMENTAL-V-BADVERS: unsupported version number 0.1 for experimental extension -// RUN: %clang -target riscv32-unknown-elf -march=rv32iv1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: %clang -target riscv32-unknown-elf -march=rv32iv0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-V-GOODVERS %s // RV32-EXPERIMENTAL-V-GOODVERS: "-target-feature" "+experimental-v" @@ -412,7 +412,7 @@ // RV32-EXPERIMENTAL-ZVAMO-BADVERS: error: invalid arch name 'rv32izvamo0p1' // RV32-EXPERIMENTAL-ZVAMO-BADVERS: unsupported version number 0.1 for experimental extension -// RUN: %clang -target riscv32-unknown-elf -march=rv32izvamo1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: %clang -target riscv32-unknown-elf -march=rv32izvamo0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVAMO-GOODVERS %s // RV32-EXPERIMENTAL-ZVAMO-GOODVERS: "-target-feature" "+experimental-zvamo" @@ -431,6 +431,6 @@ // RV32-EXPERIMENTAL-ZVLSSEG-BADVERS: error: invalid arch name 'rv32izvlsseg0p1' // RV32-EXPERIMENTAL-ZVLSSEG-BADVERS: unsupported version number 0.1 for experimental extension -// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg1p0 -menable-experimental-extensions -### %s -c 2>&1 | \ +// RUN: %clang -target riscv32-unknown-elf -march=rv32izvlsseg0p10 -menable-experimental-extensions -### %s -c 2>&1 | \ // RUN: FileCheck -check-prefix=RV32-EXPERIMENTAL-ZVLSSEG-GOODVERS %s // RV32-EXPERIMENTAL-ZVLSSEG-GOODVERS: "-target-feature" "+experimental-zvlsseg" diff --git a/clang/test/Frontend/fixed_point_unary.c b/clang/test/Frontend/fixed_point_unary.c index 6ce760daba115..849e38a94bc48 100644 --- a/clang/test/Frontend/fixed_point_unary.c +++ b/clang/test/Frontend/fixed_point_unary.c @@ -90,7 +90,7 @@ void inc_usa() { // SIGNED-LABEL: @inc_uf( // SIGNED-NEXT: entry: // SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2 -// SIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], poison +// SIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], undef // SIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2 // SIGNED-NEXT: ret void // @@ -271,7 +271,7 @@ void dec_usa() { // SIGNED-LABEL: @dec_uf( // SIGNED-NEXT: entry: // SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2 -// SIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], poison +// SIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], undef // SIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2 // SIGNED-NEXT: ret void // diff --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp index f57faed4ed908..2f46f354ee83f 100644 --- a/clang/test/Lexer/cxx-features.cpp +++ b/clang/test/Lexer/cxx-features.cpp @@ -181,7 +181,8 @@ #error "wrong value for __cpp_structured_bindings" #endif -#if check(nontype_template_args, 0, 0, 0, 201411, 201911, 201911) +#if check(nontype_template_args, 0, 0, 0, 201411, 201411, 201411) +// FIXME: 201911 in C++20 #error "wrong value for __cpp_nontype_template_args" #endif diff --git a/clang/test/OpenMP/linking.c b/clang/test/OpenMP/linking.c index 802553c1be752..1c44396264705 100644 --- a/clang/test/OpenMP/linking.c +++ b/clang/test/OpenMP/linking.c @@ -81,7 +81,7 @@ // CHECK-LD-OVERRIDE-64: "-lgomp" "-lrt" // CHECK-LD-OVERRIDE-64: "-lpthread" "-lc" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: %clang -no-canonical-prefixes -fuse-ld=link %s -### -o %t.o 2>&1 \ // RUN: -fopenmp=libomp -target x86_64-msvc-win32 -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-MSVC-LINK-64 %s // CHECK-MSVC-LINK-64: link.exe @@ -95,7 +95,7 @@ // SIMD-ONLY11-NOT: libomp // SIMD-ONLY11-NOT: libgomp // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: %clang -no-canonical-prefixes %s -fuse-ld=link -### -o %t.o 2>&1 \ // RUN: -fopenmp=libiomp5 -target x86_64-msvc-win32 -rtlib=platform \ // RUN: | FileCheck --check-prefix=CHECK-MSVC-ILINK-64 %s diff --git a/clang/test/OpenMP/nvptx_allocate_messages.cpp b/clang/test/OpenMP/nvptx_allocate_messages.cpp index a4d78b6ab5888..9a61da73eb390 100644 --- a/clang/test/OpenMP/nvptx_allocate_messages.cpp +++ b/clang/test/OpenMP/nvptx_allocate_messages.cpp @@ -81,8 +81,7 @@ int main () { #endif // DEVICE && !REQUIRES #pragma omp allocate(b) #if defined(DEVICE) && !defined(REQUIRES) -// expected-note@+3 {{in instantiation of function template specialization 'foo' requested here}} -// expected-note@+2 {{called by 'main'}} +// expected-note@+2 2{{called by 'main'}} #endif // DEVICE && !REQUIRES return (foo() + bar()); } diff --git a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp index c71615d2521fc..87ea00a90822e 100644 --- a/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp +++ b/clang/test/OpenMP/nvptx_target_exceptions_messages.cpp @@ -52,6 +52,7 @@ int maini1() { #pragma omp target map(tofrom \ : a, b) { + // expected-note@+1 {{called by 'maini1'}} S s(a); static long aaa = 23; a = foo() + bar() + b + c + d + aa + aaa + FA(); // expected-note{{called by 'maini1'}} diff --git a/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp b/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp index 814a4756c01b4..a319c78f73c56 100644 --- a/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp +++ b/clang/test/OpenMP/nvptx_unsupported_type_messages.cpp @@ -39,10 +39,12 @@ struct T1 { }; #ifndef _ARCH_PPC -// expected-note@+1 {{'boo' defined here}} +// expected-error@+2 {{'boo' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-note@+1 2{{'boo' defined here}} void boo(__float128 A) { return; } #else -// expected-note@+1 {{'boo' defined here}} +// expected-error@+2 {{'boo' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-note@+1 2{{'boo' defined here}} void boo(long double A) { return; } #endif #pragma omp declare target @@ -51,10 +53,11 @@ T f = a; void foo(T a = T()) { a = a + f; // expected-note {{called by 'foo'}} #ifndef _ARCH_PPC -// expected-error@+4 {{'boo' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-error@+5 {{'boo' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} #else -// expected-error@+2 {{'boo' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +// expected-error@+3 {{'boo' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} #endif +// expected-note@+1 {{called by 'foo'}} boo(0); return; } @@ -77,21 +80,147 @@ T1 bar1() { void baz1() { T1 t = bar1(); } + +inline void dead_inline_declare_target() { + long double *a, b = 0; + a = &b; +} +static void dead_static_declare_target() { + long double *a, b = 0; + a = &b; +} +template +void dead_template_declare_target() { + long double *a, b = 0; + a = &b; +} + +// expected-note@+2 {{'ld_return1a' defined here}} +// expected-error@+1 {{'ld_return1a' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +long double ld_return1a() { return 0; } +// expected-note@+2 {{'ld_arg1a' defined here}} +// expected-error@+1 {{'ld_arg1a' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg1a(long double ld) {} + +typedef long double ld_ty; +// expected-note@+2 {{'ld_return1b' defined here}} +// expected-error@+1 {{'ld_return1b' requires 128 bit size 'ld_ty' (aka 'long double') type support, but device 'nvptx64-unknown-unknown' does not support it}} +ld_ty ld_return1b() { return 0; } +// expected-note@+2 {{'ld_arg1b' defined here}} +// expected-error@+1 {{'ld_arg1b' requires 128 bit size 'ld_ty' (aka 'long double') type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg1b(ld_ty ld) {} + +static long double ld_return1c() { return 0; } +static void ld_arg1c(long double ld) {} + +inline long double ld_return1d() { return 0; } +inline void ld_arg1d(long double ld) {} + +// expected-note@+1 {{'ld_return1e' defined here}} +static long double ld_return1e() { return 0; } +// expected-note@+1 {{'ld_arg1e' defined here}} +static void ld_arg1e(long double ld) {} + +// expected-note@+1 {{'ld_return1f' defined here}} +inline long double ld_return1f() { return 0; } +// expected-note@+1 {{'ld_arg1f' defined here}} +inline void ld_arg1f(long double ld) {} + +inline void ld_use1() { + long double ld = 0; + ld += 1; +} +static void ld_use2() { + long double ld = 0; + ld += 1; +} + +inline void ld_use3() { +// expected-note@+1 {{'ld' defined here}} + long double ld = 0; +// expected-error@+1 {{'ld' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + ld += 1; +} +static void ld_use4() { +// expected-note@+1 {{'ld' defined here}} + long double ld = 0; +// expected-error@+1 {{'ld' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + ld += 1; +} + +void external() { +// expected-error@+1 {{'ld_return1e' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p1 = reinterpret_cast(&ld_return1e); +// expected-error@+1 {{'ld_arg1e' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p2 = reinterpret_cast(&ld_arg1e); +// expected-error@+1 {{'ld_return1f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p3 = reinterpret_cast(&ld_return1f); +// expected-error@+1 {{'ld_arg1f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + void *p4 = reinterpret_cast(&ld_arg1f); +// TODO: The error message "called by" is not great. +// expected-note@+1 {{called by 'external'}} + void *p5 = reinterpret_cast(&ld_use3); +// expected-note@+1 {{called by 'external'}} + void *p6 = reinterpret_cast(&ld_use4); +} + +#ifndef _ARCH_PPC +// expected-note@+2 {{'ld_return2a' defined here}} +// expected-error@+1 {{'ld_return2a' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +__float128 ld_return2a() { return 0; } +// expected-note@+2 {{'ld_arg2a' defined here}} +// expected-error@+1 {{'ld_arg2a' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg2a(__float128 ld) {} + +typedef __float128 fp128_ty; +// expected-note@+2 {{'ld_return2b' defined here}} +// expected-error@+1 {{'ld_return2b' requires 128 bit size 'fp128_ty' (aka '__float128') type support, but device 'nvptx64-unknown-unknown' does not support it}} +fp128_ty ld_return2b() { return 0; } +// expected-note@+2 {{'ld_arg2b' defined here}} +// expected-error@+1 {{'ld_arg2b' requires 128 bit size 'fp128_ty' (aka '__float128') type support, but device 'nvptx64-unknown-unknown' does not support it}} +void ld_arg2b(fp128_ty ld) {} +#endif + #pragma omp end declare target +// TODO: There should not be an error here, dead_inline is never emitted. +// expected-note@+1 {{'f' defined here}} +inline long double dead_inline(long double f) { +#pragma omp target map(f) + // expected-error@+1 {{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + f = 1; + return f; +} + +// TODO: There should not be an error here, dead_static is never emitted. +// expected-note@+1 {{'f' defined here}} +static long double dead_static(long double f) { +#pragma omp target map(f) + // expected-error@+1 {{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + f = 1; + return f; +} + +template +long double dead_template(long double f) { +#pragma omp target map(f) + f = 1; + return f; +} + #ifndef _ARCH_PPC -// expected-note@+1 3{{'f' defined here}} -__float128 foo1(__float128 f) { +// expected-note@+1 {{'f' defined here}} +__float128 foo2(__float128 f) { #pragma omp target map(f) - // expected-error@+1 3{{'f' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} + // expected-error@+1 {{'f' requires 128 bit size '__float128' type support, but device 'nvptx64-unknown-unknown' does not support it}} f = 1; return f; } #else -// expected-note@+1 3{{'f' defined here}} -long double foo1(long double f) { +// expected-note@+1 {{'f' defined here}} +long double foo3(long double f) { #pragma omp target map(f) - // expected-error@+1 3{{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} + // expected-error@+1 {{'f' requires 128 bit size 'long double' type support, but device 'nvptx64-unknown-unknown' does not support it}} f = 1; return f; } diff --git a/clang/test/OpenMP/target_attribute_convergent.cpp b/clang/test/OpenMP/target_attribute_convergent.cpp new file mode 100644 index 0000000000000..932214e987c86 --- /dev/null +++ b/clang/test/OpenMP/target_attribute_convergent.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple nvptx64-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-device -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -verify -fopenmp -x c++ -triple nvptx-unknown-unknown -fopenmp-targets=nvptx-nvidia-cuda -emit-llvm %s -fopenmp-is-device -o - | FileCheck %s +// expected-no-diagnostics + +#pragma omp declare target + +void foo() {} + +#pragma omp end declare target + +// CHECK: Function Attrs: {{.*}}convergent{{.*}} +// CHECK: define hidden void @_Z3foov() [[ATTRIBUTE_NUMBER:#[0-9]+]] +// CHECK: attributes [[ATTRIBUTE_NUMBER]] = { {{.*}}convergent{{.*}} } diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp index 0229ace911f87..c0f53239aa133 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_codegen.cpp @@ -39,7 +39,7 @@ #ifdef CK1 -// HCK_NO_TGT-NOT: @__kmpc_push_target_tripcount +// HCK_NO_TGT-NOT: @__kmpc_push_target_tripcount_mapper // HCK1: define{{.*}} i32 @{{.+}}target_teams_fun{{.*}}( int target_teams_fun(int *g){ @@ -60,7 +60,7 @@ int target_teams_fun(int *g){ // HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]], // HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // HCK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // HCK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // HCK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, // HCK1: call void @[[OFFL1:.+]](i{{32|64}} [[N_PAR]], {{.+}}, i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]]) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp index 6650e05575110..efe7df819fb62 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_if_codegen.cpp @@ -49,10 +49,10 @@ int Arg; // CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test void gtid_test() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( #pragma omp target teams distribute parallel for @@ -107,12 +107,12 @@ int tmain(T Arg) { // CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main() int main() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK-NOT: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK-NOT: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_2:@.+]]( // CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp index b2ab37f22ec33..b99ba9d38a430 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_order_codegen.cpp @@ -14,7 +14,7 @@ // CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test void gtid_test() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: %0 = call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{.+}}, i32 0, i8** null, i8** null, i64* null, i64* null, i8** null, i8** null, i32 0, i32 0) // CHECK: call void [[TARGET_OUTLINE:@.+]]() // CHECK: ret void diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp index e6049145702bc..39ccb87462c02 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_codegen.cpp @@ -60,7 +60,7 @@ int target_teams_fun(int *g){ // HCK1: [[N_PAR:%.+]] = load{{.+}}, {{.+}} [[N_CAST]], // HCK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // HCK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], -// HCK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) +// HCK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // HCK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 5, i8** %{{[^,]+}}, i8** %{{[^,]+}}, // HCK1: call void @[[OFFL1:.+]](i{{32|64}} [[I_PAR]], i{{32|64}} [[N_PAR]], {{.+}}, i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]]) diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp index 8b0eaba07f1cb..19dc15b94f64b 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_if_codegen.cpp @@ -43,10 +43,10 @@ int Arg; // CHECK-LABEL: define {{.*}}void @{{.+}}gtid_test void gtid_test() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( #ifdef OMP5 @@ -110,12 +110,12 @@ int tmain(T Arg) { // CHECK-LABEL: define {{.*}}i{{[0-9]+}} @main() int main() { -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_0:@.+]]( -// CHECK-NOT: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK-NOT: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call void [[OFFLOADING_FUN_1:@.+]]( -// CHECK: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 100) +// CHECK: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 100) // CHECK: call i{{[0-9]+}} @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, // CHECK: call void [[OFFLOADING_FUN_2:@.+]]( // CHECK: = call {{.*}}i{{.+}} @{{.+}}tmain diff --git a/clang/test/OpenMP/teams_distribute_codegen.cpp b/clang/test/OpenMP/teams_distribute_codegen.cpp index 5bbb100e669ec..aab5cced4c70f 100644 --- a/clang/test/OpenMP/teams_distribute_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_codegen.cpp @@ -33,7 +33,7 @@ int teams_argument_global(int n) { // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null, i8** null, i32 {{.+}}, i32 {{.+}}) // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp index b63e5aeddb7a2..8fa73e76009bc 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_codegen.cpp @@ -32,7 +32,7 @@ int teams_argument_global(int n){ // CK1: [[TH_CAST:%.+]] = alloca i{{32|64}}, // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null, i8** null, i32 {{.+}}, i32 {{.+}}) // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp index 3d479c4cd29df..9b3855c61759a 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_parallel_for_simd_codegen.cpp @@ -33,7 +33,7 @@ int teams_argument_global(int n){ // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 4, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/OpenMP/teams_distribute_simd_codegen.cpp b/clang/test/OpenMP/teams_distribute_simd_codegen.cpp index fd1214d22ce9e..6e5d06b0c5689 100644 --- a/clang/test/OpenMP/teams_distribute_simd_codegen.cpp +++ b/clang/test/OpenMP/teams_distribute_simd_codegen.cpp @@ -35,7 +35,7 @@ int teams_argument_global(int n) { // CK1: [[TE_PAR:%.+]] = load{{.+}}, {{.+}} [[TE_CAST]], // CK1: [[TH_PAR:%.+]] = load{{.+}}, {{.+}} [[TH_CAST]], - // CK1: call void @__kmpc_push_target_tripcount(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) + // CK1: call void @__kmpc_push_target_tripcount_mapper(%struct.ident_t* @{{.+}}, i64 -1, i64 %{{.+}}) // CK1: call i32 @__tgt_target_teams_mapper(%struct.ident_t* @{{.+}}, i64 -1, i8* @{{[^,]+}}, i32 5, i8** %{{[^,]+}}, i8** %{{[^,]+}}, i{{64|32}}* {{.+}}@{{[^,]+}}, i32 0, i32 0), i64* {{.+}}@{{[^,]+}}, i32 0, i32 0), i8** null, i8** null, i32 {{.+}}, i32 1) // CK1: call void @[[OFFL1:.+]](i{{32|64}} [[TE_PAR]], i{{32|64}} [[TH_PAR]], diff --git a/clang/test/Preprocessor/macro_fn_comma_swallow2.c b/clang/test/Preprocessor/macro_fn_comma_swallow2.c index 4e4960ca7f18c..93ab2b83664a1 100644 --- a/clang/test/Preprocessor/macro_fn_comma_swallow2.c +++ b/clang/test/Preprocessor/macro_fn_comma_swallow2.c @@ -1,16 +1,11 @@ // Test the __VA_ARGS__ comma swallowing extensions of various compiler dialects. // RUN: %clang_cc1 -E %s | FileCheck -check-prefix=GCC -strict-whitespace %s -// RUN: %clang_cc1 -E -std=c90 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -std=c99 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -std=c11 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -x c++ %s | FileCheck -check-prefix=GCC -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -std=c++03 %s | FileCheck -check-prefix=C99 -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -std=c++11 %s | FileCheck -check-prefix=C99 -strict-whitespace %s // RUN: %clang_cc1 -E -std=gnu99 %s | FileCheck -check-prefix=GCC -strict-whitespace %s // RUN: %clang_cc1 -E -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s -// RUN: %clang_cc1 -E -x c++ -std=c++11 -fms-compatibility %s | FileCheck -check-prefix=MS -strict-whitespace %s // RUN: %clang_cc1 -E -DNAMED %s | FileCheck -check-prefix=GCC -strict-whitespace %s // RUN: %clang_cc1 -E -std=c99 -DNAMED %s | FileCheck -check-prefix=C99 -strict-whitespace %s diff --git a/clang/test/Preprocessor/macro_vaopt_check.cpp b/clang/test/Preprocessor/macro_vaopt_check.cpp index fb52e9946af3d..c5c0ac518bc01 100644 --- a/clang/test/Preprocessor/macro_vaopt_check.cpp +++ b/clang/test/Preprocessor/macro_vaopt_check.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 %s -Eonly -verify -Wno-all -pedantic -std=c++2a +// RUN: %clang_cc1 %s -Eonly -verify -Wno-all -pedantic -std=c++20 +// RUN: %clang_cc1 %s -Eonly -verify -Wno-all -pedantic -std=c++11 +// RUN: %clang_cc1 -x c %s -Eonly -verify -Wno-all -pedantic -std=c99 //expected-error@+1{{missing '('}} #define V1(...) __VA_OPT__ @@ -62,3 +64,11 @@ #define V1(...) __VA_OPT__ ((()) #undef V1 +// __VA_OPT__ can't appear anywhere else. +#if __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}} +#endif + +#ifdef __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}} +#endif + +#define BAD __VA_OPT__ // expected-warning {{__VA_OPT__ can only appear in the expansion of a variadic macro}} diff --git a/clang/test/Preprocessor/macro_vaopt_expand.cpp b/clang/test/Preprocessor/macro_vaopt_expand.cpp index 7ec4f6128cfa8..5eb0facb83f73 100644 --- a/clang/test/Preprocessor/macro_vaopt_expand.cpp +++ b/clang/test/Preprocessor/macro_vaopt_expand.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -E %s -pedantic -std=c++2a | FileCheck -strict-whitespace %s +// RUN: %clang_cc1 -E %s -pedantic -std=c++20 | FileCheck -strict-whitespace %s +// RUN: %clang_cc1 -E %s -pedantic -std=c++11 | FileCheck -strict-whitespace %s +// RUN: %clang_cc1 -E -x c %s -pedantic -std=c99 | FileCheck -strict-whitespace %s #define LPAREN ( #define RPAREN ) diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 0063955052469..88826bbd60b82 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -110,23 +110,23 @@ // CHECK-DOUBLE-NOT: __riscv_float_abi_single // RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions \ -// RUN: -march=rv32iv1p0 -x c -E -dM %s \ +// RUN: -march=rv32iv0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s // RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions \ -// RUN: -march=rv64iv1p0 -x c -E -dM %s \ +// RUN: -march=rv64iv0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvamo0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg1p0 -x c -E -dM %s \ +// RUN: %clang -target riscv64-unknown-linux-gnu -menable-experimental-extensions -march=rv32izvlsseg0p10 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-V-EXT %s -// CHECK-V-EXT: __riscv_v 1000000 +// CHECK-V-EXT: __riscv_v 10000 // CHECK-V-EXT: __riscv_vector 1 -// CHECK-V-EXT: __riscv_zvamo 1000000 -// CHECK-V-EXT: __riscv_zvlsseg 1000000 +// CHECK-V-EXT: __riscv_zvamo 10000 +// CHECK-V-EXT: __riscv_zvlsseg 10000 // RUN: %clang -target riscv32-unknown-linux-gnu -menable-experimental-extensions -march=rv32izba0p93 -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-ZBA-EXT %s diff --git a/clang/test/Sema/libbuiltins-ctype-powerpc64.c b/clang/test/Sema/libbuiltins-ctype-powerpc64.c index bfd79acb0ab02..ba0efb205944b 100644 --- a/clang/test/Sema/libbuiltins-ctype-powerpc64.c +++ b/clang/test/Sema/libbuiltins-ctype-powerpc64.c @@ -62,4 +62,4 @@ void test(int x) { // CHECK: declare signext i32 @toupper(i32 signext) [[NUW_RO:#[0-9]+]] // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/Sema/libbuiltins-ctype-x86_64.c b/clang/test/Sema/libbuiltins-ctype-x86_64.c index 4934e6f16752a..b8a2c7e81584a 100644 --- a/clang/test/Sema/libbuiltins-ctype-x86_64.c +++ b/clang/test/Sema/libbuiltins-ctype-x86_64.c @@ -62,4 +62,4 @@ void test(int x) { // CHECK: declare i32 @toupper(i32) [[NUW_RO:#[0-9]+]] // CHECK: attributes [[NUW_RO]] = { nounwind readonly{{.*}} } -// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly } +// CHECK: attributes [[NUW_RO_CALL]] = { nounwind readonly willreturn } diff --git a/clang/test/Sema/static-assert.c b/clang/test/Sema/static-assert.c index f08e557fc8eab..9105f2366985e 100644 --- a/clang/test/Sema/static-assert.c +++ b/clang/test/Sema/static-assert.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fms-compatibility -DMS -fsyntax-only -verify %s // RUN: %clang_cc1 -std=c99 -pedantic -fsyntax-only -verify=expected,ext %s // RUN: %clang_cc1 -xc++ -std=c++11 -pedantic -fsyntax-only -verify=expected,ext,cxx %s @@ -11,10 +12,17 @@ _Static_assert(1, "1 is nonzero"); // ext-warning {{'_Static_assert' is a C11 ex _Static_assert(0, "0 is nonzero"); // expected-error {{static_assert failed "0 is nonzero"}} \ // ext-warning {{'_Static_assert' is a C11 extension}} +#ifdef MS +static_assert(1, "1 is nonzero"); +#endif + void foo(void) { _Static_assert(1, "1 is nonzero"); // ext-warning {{'_Static_assert' is a C11 extension}} _Static_assert(0, "0 is nonzero"); // expected-error {{static_assert failed "0 is nonzero"}} \ // ext-warning {{'_Static_assert' is a C11 extension}} +#ifdef MS + static_assert(1, "1 is nonzero"); +#endif } _Static_assert(1, invalid); // expected-error {{expected string literal for diagnostic message in static_assert}} \ @@ -25,6 +33,9 @@ struct A { _Static_assert(1, "1 is nonzero"); // ext-warning {{'_Static_assert' is a C11 extension}} _Static_assert(0, "0 is nonzero"); // expected-error {{static_assert failed "0 is nonzero"}} \ // ext-warning {{'_Static_assert' is a C11 extension}} +#ifdef MS + static_assert(1, "1 is nonzero"); +#endif }; #ifdef __cplusplus diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 4adadc9988ab5..86020a09db443 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1437,3 +1437,13 @@ constexpr bool destroy_at_test() { return true; } static_assert(destroy_at_test()); + +namespace PR48582 { + struct S { + void *p = this; + constexpr S() {} + constexpr S(const S&) {} + }; + constexpr bool b = [a = S(), b = S()] { return a.p == b.p; }(); + static_assert(!b); +} diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp index 3647526ff0af7..097ca00640e9a 100644 --- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp +++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp @@ -176,3 +176,37 @@ constexpr bool construct_after_lifetime_2() { return true; } static_assert(construct_after_lifetime_2()); // expected-error {{}} expected-note {{in call}} + +namespace PR48606 { + struct A { mutable int n = 0; }; + + constexpr bool f() { + A a; + A *p = &a; + p->~A(); + std::construct_at(p); + return true; + } + static_assert(f()); + + constexpr bool g() { + A *p = new A; + p->~A(); + std::construct_at(p); + delete p; + return true; + } + static_assert(g()); + + constexpr bool h() { + std::allocator alloc; + A *p = alloc.allocate(1); + std::construct_at(p); + p->~A(); + std::construct_at(p); + p->~A(); + alloc.deallocate(p); + return true; + } + static_assert(h()); +} diff --git a/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp b/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp index 353360e052bb3..b94225274fffb 100644 --- a/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp +++ b/clang/test/SemaCXX/cxx2a-three-way-comparison.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++2a -verify %s +// RUN: %clang_cc1 -std=c++2a -verify %s -Wzero-as-null-pointer-constant // Keep this test before any declarations of operator<=>. namespace PR44786 { @@ -40,3 +40,21 @@ namespace PR47893 { int &f(...); int &r = f(A(), A()); } + +namespace PR44325 { + struct cmp_cat {}; + bool operator<(cmp_cat, void*); + bool operator>(cmp_cat, int cmp_cat::*); + + struct X {}; + cmp_cat operator<=>(X, X); + + bool b1 = X() < X(); // no warning + bool b2 = X() > X(); // no warning + + // FIXME: It's not clear whether warning here is useful, but we can't really + // tell that this is a comparison category in general. This is probably OK, + // as comparisons against zero are only really intended for use in the + // implicit rewrite rules, not for explicit use by programs. + bool c = cmp_cat() < 0; // expected-warning {{zero as null pointer constant}} +} diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 92bf244b0e4af..06c2bbc29e5c5 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -474,6 +474,42 @@ TEST(Matcher, CapturesThis) { EXPECT_TRUE(notMatches("void f() { int z = 3; [&z](){}; }", HasCaptureThis)); } +TEST(Matcher, MatchesMethodsOnLambda) { + StringRef Code = R"cpp( +struct A { + ~A() {} +}; +void foo() +{ + A a; + auto l = [a] { }; + auto lCopy = l; + auto lPtrDecay = +[] { }; + (void)lPtrDecay; +} +)cpp"; + + EXPECT_TRUE(matches( + Code, cxxConstructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))), + isCopyConstructor()))); + EXPECT_TRUE(matches( + Code, cxxConstructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l"))))), + isMoveConstructor()))); + EXPECT_TRUE(matches( + Code, cxxDestructorDecl( + hasBody(compoundStmt()), + hasAncestor(lambdaExpr(hasAncestor(varDecl(hasName("l")))))))); + EXPECT_TRUE(matches( + Code, cxxConversionDecl(hasBody(compoundStmt(has(returnStmt( + hasReturnValue(implicitCastExpr()))))), + hasAncestor(lambdaExpr(hasAncestor( + varDecl(hasName("lPtrDecay")))))))); +} + TEST(Matcher, isClassMessage) { EXPECT_TRUE(matchesObjC( "@interface NSString +(NSString *) stringWithFormat; @end " @@ -2483,6 +2519,78 @@ template<> bool timesTwo(bool){ EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } + + Code = R"cpp( +struct B { + B(int); +}; + +B func1() { return 42; } + )cpp"; + { + auto M = expr(ignoringImplicit(integerLiteral(equals(42)).bind("intLit"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(unless(integerLiteral(equals(24)))).bind("intLit"); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 7))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = + expr(anyOf(integerLiteral(equals(42)).bind("intLit"), unless(expr()))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(allOf(integerLiteral(equals(42)).bind("intLit"), expr())); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(integerLiteral(equals(42)).bind("intLit"), expr()); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr(optionally(integerLiteral(equals(42)).bind("intLit"))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("intLit", 1))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("intLit", 1))); + } + { + auto M = expr().bind("allExprs"); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_AsIs, M), + std::make_unique>("allExprs", 7))); + EXPECT_TRUE(matchAndVerifyResultTrue( + Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + std::make_unique>("allExprs", 1))); + } } TEST(Traversal, traverseNoImplicit) { @@ -2784,6 +2892,36 @@ struct CtorInitsNonTrivial : NonTrivial EXPECT_FALSE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); } + Code = R"cpp( + struct Range { + int* begin() const; + int* end() const; + }; + Range getRange(int); + + void rangeFor() + { + for (auto i : getRange(42)) + { + } + } + )cpp"; + { + auto M = integerLiteral(equals(42)); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + { + auto M = callExpr(hasDescendant(integerLiteral(equals(42)))); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + { + auto M = compoundStmt(hasDescendant(integerLiteral(equals(42)))); + EXPECT_TRUE(matches(Code, traverse(TK_AsIs, M))); + EXPECT_TRUE(matches(Code, traverse(TK_IgnoreUnlessSpelledInSource, M))); + } + Code = R"cpp( void rangeFor() { @@ -2855,6 +2993,40 @@ struct CtorInitsNonTrivial : NonTrivial matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), true, {"-std=c++20"})); } + + Code = R"cpp( + struct Range { + int* begin() const; + int* end() const; + }; + Range getRange(int); + + int getNum(int); + + void rangeFor() + { + for (auto j = getNum(42); auto i : getRange(j)) + { + } + } + )cpp"; + { + auto M = integerLiteral(equals(42)); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"})); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + true, {"-std=c++20"})); + } + { + auto M = compoundStmt(hasDescendant(integerLiteral(equals(42)))); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_AsIs, M), true, {"-std=c++20"})); + EXPECT_TRUE( + matchesConditionally(Code, traverse(TK_IgnoreUnlessSpelledInSource, M), + true, {"-std=c++20"})); + } + Code = R"cpp( void hasDefaultArg(int i, int j = 0) { @@ -3120,6 +3292,12 @@ void func14() { float i = 42.0; } +void func15() { + int count = 0; + auto l = [&] { ++count; }; + (void)l; +} + )cpp"; EXPECT_TRUE( @@ -3304,6 +3482,15 @@ void func14() { functionDecl(hasName("func14"), hasDescendant(floatLiteral()))), langCxx20OrLater())); + EXPECT_TRUE(matches( + Code, + traverse(TK_IgnoreUnlessSpelledInSource, + compoundStmt( + hasDescendant(varDecl(hasName("count")).bind("countVar")), + hasDescendant( + declRefExpr(to(varDecl(equalsBoundNode("countVar"))))))), + langCxx20OrLater())); + Code = R"cpp( void foo() { int explicit_captured = 0; @@ -3853,6 +4040,78 @@ void binop() } } +TEST(IgnoringImpCasts, PathologicalLambda) { + + // Test that deeply nested lambdas are not a performance penalty + StringRef Code = R"cpp( +void f() { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + [] { + int i = 42; + (void)i; + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); + }(); +} + )cpp"; + + EXPECT_TRUE(matches(Code, integerLiteral(equals(42)))); + EXPECT_TRUE(matches(Code, functionDecl(hasDescendant(integerLiteral(equals(42)))))); +} + TEST(IgnoringImpCasts, MatchesImpCasts) { // This test checks that ignoringImpCasts matches when implicit casts are // present and its inner matcher alone does not match. diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 855cf0242fe97..c1f88b9ae17ad 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10248,6 +10248,21 @@ TEST_F(FormatTest, SplitEmptyClass) { "{\n" "};", Style); + + verifyFormat("#include \"stdint.h\"\n" + "namespace rep {}", + Style); + verifyFormat("#include \n" + "namespace rep {}", + Style); + verifyFormat("#include \n" + "namespace rep {}", + "#include \n" + "namespace rep {\n" + "\n" + "\n" + "}", + Style); } TEST_F(FormatTest, SplitEmptyStruct) { diff --git a/clang/unittests/Sema/CodeCompleteTest.cpp b/clang/unittests/Sema/CodeCompleteTest.cpp index d8b303d77bb96..dae0793658c5b 100644 --- a/clang/unittests/Sema/CodeCompleteTest.cpp +++ b/clang/unittests/Sema/CodeCompleteTest.cpp @@ -488,6 +488,7 @@ TEST(PreferredTypeTest, NoCrashOnInvalidTypes) { auto y = new decltype(&1)(^); // GNU decimal type extension is not supported in clang. auto z = new _Decimal128(^); + void foo() { (void)(foo)(^); } )cpp"; EXPECT_THAT(collectPreferredTypes(Code), Each("NULL TYPE")); } diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 685f32dbe0d3a..fc3340ec9d963 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -1005,7 +1005,7 @@

C++20 implementation status

Class types as non-type template parameters
P0732R2 - Clang 12 + Partial P1907R1 diff --git a/cmake/Modules/CMakePolicy.cmake b/cmake/Modules/CMakePolicy.cmake new file mode 100644 index 0000000000000..0ec32ad8637f3 --- /dev/null +++ b/cmake/Modules/CMakePolicy.cmake @@ -0,0 +1,12 @@ +# CMake policy settings shared between LLVM projects + +# CMP0114: ExternalProject step targets fully adopt their steps. +# New in CMake 3.19: https://cmake.org/cmake/help/latest/policy/CMP0114.html +if(POLICY CMP0114) + cmake_policy(SET CMP0114 OLD) +endif() +# CMP0116: Ninja generators transform `DEPFILE`s from `add_custom_command()` +# New in CMake 3.20. https://cmake.org/cmake/help/latest/policy/CMP0116.html +if(POLICY CMP0116) + cmake_policy(SET CMP0116 OLD) +endif() diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt index b511a9a987b3f..73b6bead84245 100644 --- a/compiler-rt/lib/builtins/CMakeLists.txt +++ b/compiler-rt/lib/builtins/CMakeLists.txt @@ -515,6 +515,12 @@ set(aarch64_SOURCES set(OA_HELPERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/outline_atomic_helpers.dir") file(MAKE_DIRECTORY "${OA_HELPERS_DIR}") +if(CMAKE_HOST_UNIX) + set(COMPILER_RT_LINK_OR_COPY create_symlink) +else() + set(COMPILER_RT_LINK_OR_COPY copy) +endif() + foreach(pat cas swp ldadd ldclr ldeor ldset) foreach(size 1 2 4 8 16) foreach(model 1 2 3 4) @@ -522,7 +528,7 @@ foreach(pat cas swp ldadd ldclr ldeor ldset) set(helper_asm "${OA_HELPERS_DIR}/outline_atomic_${pat}${size}_${model}.S") add_custom_command( OUTPUT ${helper_asm} - COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_SOURCE_DIR}/aarch64/lse.S" "${helper_asm}" + COMMAND ${CMAKE_COMMAND} -E ${COMPILER_RT_LINK_OR_COPY} "${CMAKE_CURRENT_SOURCE_DIR}/aarch64/lse.S" "${helper_asm}" ) set_source_files_properties("${helper_asm}" PROPERTIES diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp index 7378b237a7117..5dc9090f36c0f 100644 --- a/compiler-rt/lib/msan/tests/msan_test.cpp +++ b/compiler-rt/lib/msan/tests/msan_test.cpp @@ -3707,7 +3707,9 @@ TEST(MemorySanitizer, getgrent_r) { EXPECT_NOT_POISONED(grp.gr_gid); EXPECT_NOT_POISONED(grpres); } +#endif +#ifdef __GLIBC__ TEST(MemorySanitizer, fgetgrent_r) { FILE *fp = fopen("/etc/group", "r"); struct group grp; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 7f7b38d4215b1..068fc9829e57d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -226,7 +226,7 @@ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) #define SANITIZER_INTERCEPT_GETPWENT \ (SI_FREEBSD || SI_NETBSD || SI_MAC || SI_LINUX_NOT_ANDROID || SI_SOLARIS) -#define SANITIZER_INTERCEPT_FGETGRENT_R (SI_FREEBSD || SI_GLIBC || SI_SOLARIS) +#define SANITIZER_INTERCEPT_FGETGRENT_R (SI_GLIBC || SI_SOLARIS) #define SANITIZER_INTERCEPT_FGETPWENT SI_LINUX_NOT_ANDROID || SI_SOLARIS #define SANITIZER_INTERCEPT_GETPWENT_R \ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) diff --git a/dpu-wrappers/dpu-lldb b/dpu-wrappers/dpu-lldb new file mode 100755 index 0000000000000..e0db59a8abf7f --- /dev/null +++ b/dpu-wrappers/dpu-lldb @@ -0,0 +1,3 @@ +#!/bin/bash +DPU_LLDB_DIR="$(dirname "$0")" +"${DPU_LLDB_DIR}/lldb" --one-line-before-file "command source -s 1 ${DPU_LLDB_DIR}/../share/upmem/lldb/lldb_init_dpu_commands" "$@" diff --git a/dpu-wrappers/dpu-lldb-attach-dpu b/dpu-wrappers/dpu-lldb-attach-dpu new file mode 100755 index 0000000000000..befa5fb0fce7e --- /dev/null +++ b/dpu-wrappers/dpu-lldb-attach-dpu @@ -0,0 +1,8 @@ +#!/bin/bash +DPU_LLDB_DIR="$(dirname "$0")" +"${DPU_LLDB_DIR}/lldb" --source-quietly \ + --source-before-file "${DPU_LLDB_DIR}/../share/upmem/lldb/lldb_init_dpu_commands" \ + --one-line "breakpoint set -n breakpoint_fct" \ + --one-line "process launch" \ + --one-line "dpu_attach $1" \ + -- "${DPU_LLDB_DIR}/../share/upmem/lldb/host-lldb-attach-dpu" "$@" diff --git a/dpu-wrappers/dpu-lldb-attach-dpu-vscode b/dpu-wrappers/dpu-lldb-attach-dpu-vscode new file mode 100755 index 0000000000000..befa5fb0fce7e --- /dev/null +++ b/dpu-wrappers/dpu-lldb-attach-dpu-vscode @@ -0,0 +1,8 @@ +#!/bin/bash +DPU_LLDB_DIR="$(dirname "$0")" +"${DPU_LLDB_DIR}/lldb" --source-quietly \ + --source-before-file "${DPU_LLDB_DIR}/../share/upmem/lldb/lldb_init_dpu_commands" \ + --one-line "breakpoint set -n breakpoint_fct" \ + --one-line "process launch" \ + --one-line "dpu_attach $1" \ + -- "${DPU_LLDB_DIR}/../share/upmem/lldb/host-lldb-attach-dpu" "$@" diff --git a/dpu-wrappers/dpu-lldb-vscode b/dpu-wrappers/dpu-lldb-vscode new file mode 100755 index 0000000000000..44a07ab691701 --- /dev/null +++ b/dpu-wrappers/dpu-lldb-vscode @@ -0,0 +1,3 @@ +#!/bin/bash +DPU_LLDB_DIR="$(dirname "$0")" +"${DPU_LLDB_DIR}/lldb-vscode" --one-line-before-file "command source -s 1 ${DPU_LLDB_DIR}/../share/upmem/lldb/lldb_init_dpu_commands" "$@" diff --git a/dpu-wrappers/dpu-upmem-dpurte-clang.in b/dpu-wrappers/dpu-upmem-dpurte-clang.in new file mode 100755 index 0000000000000..31f1f3e3c3e70 --- /dev/null +++ b/dpu-wrappers/dpu-upmem-dpurte-clang.in @@ -0,0 +1,24 @@ +#!/bin/bash +@OS_DEPRECATION_WARNING@ + +if [ -z ${DPU_ARCH_VERSION+x} ]; +then + DPU_CHIP_ID_FILE="/sys/class/dpu_rank/dpu_rank0/dpu_chip_id" + if [ -f "${DPU_CHIP_ID_FILE}" ]; + then + PLATFORM_ID=`cat ${DPU_CHIP_ID_FILE}` + if (("$PLATFORM_ID" > 8)) + then + export DPU_ARCH_VERSION="v1B" + fi + fi +fi + +# No DPU detected, force to v1A +if [ -z ${DPU_ARCH_VERSION+x} ]; +then + export DPU_ARCH_VERSION="v1A" +fi + +DPU_CLANG_DIR="$(dirname "$0")" +"${DPU_CLANG_DIR}/clang" --target=dpu-upmem-dpurte -mcpu="${DPU_ARCH_VERSION}" -g "$@" diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt index 79aa53830d5ee..760b0e351ab01 100644 --- a/flang/CMakeLists.txt +++ b/flang/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.13.4) +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake + NO_POLICY_SCOPE) + set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) option(LINK_WITH_FIR "Link driver with FIR and LLVM" ON) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 4e7e8f9785462..9bf1a02f0908a 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -29,7 +29,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXX_STANDALONE_BUIL project(libcxx CXX C) set(PACKAGE_NAME libcxx) - set(PACKAGE_VERSION 12.0.0git) + set(PACKAGE_VERSION 12.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libcxx/cmake/Modules/HandleLibCXXABI.cmake b/libcxx/cmake/Modules/HandleLibCXXABI.cmake index c5aa26739e367..5d2764e870e99 100644 --- a/libcxx/cmake/Modules/HandleLibCXXABI.cmake +++ b/libcxx/cmake/Modules/HandleLibCXXABI.cmake @@ -121,6 +121,8 @@ elseif ("${LIBCXX_CXX_ABI_LIBNAME}" STREQUAL "libcxxrt") if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS) set(LIBCXX_CXX_ABI_INCLUDE_PATHS "/usr/include/c++/v1") endif() + # libcxxrt does not provide aligned new and delete operators + set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON) setup_abi_lib( "-DLIBCXXRT" "cxxrt" "cxxrt" "cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h" "" diff --git a/libcxx/cmake/caches/FreeBSD.cmake b/libcxx/cmake/caches/FreeBSD.cmake new file mode 100644 index 0000000000000..9e66e379864b6 --- /dev/null +++ b/libcxx/cmake/caches/FreeBSD.cmake @@ -0,0 +1,9 @@ +set(CMAKE_BUILD_TYPE Release CACHE STRING "") +set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "") + +set(LIBCXX_ENABLE_ASSERTIONS OFF CACHE BOOL "") +set(LIBCXX_ABI_VERSION "1" CACHE STRING "") +set(LIBCXX_ENABLE_STATIC ON CACHE BOOL "") +set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "") +set(LIBCXX_CXX_ABI libcxxrt CACHE STRING "") +set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "") diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 77e5e556d6846..29a317b8ae9a4 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -150,25 +150,25 @@ set(files string.h string_view strstream - support/android/locale_bionic.h - support/fuchsia/xlocale.h - support/ibm/limits.h - support/ibm/locale_mgmt_aix.h - support/ibm/nanosleep.h - support/ibm/support.h - support/ibm/xlocale.h - support/musl/xlocale.h - support/newlib/xlocale.h - support/nuttx/xlocale.h - support/openbsd/xlocale.h - support/solaris/floatingpoint.h - support/solaris/wchar.h - support/solaris/xlocale.h - support/win32/limits_msvc_win32.h - support/win32/locale_win32.h - support/xlocale/__nop_locale_mgmt.h - support/xlocale/__posix_l_fallback.h - support/xlocale/__strtonum_fallback.h + __support/android/locale_bionic.h + __support/fuchsia/xlocale.h + __support/ibm/limits.h + __support/ibm/locale_mgmt_aix.h + __support/ibm/nanosleep.h + __support/ibm/support.h + __support/ibm/xlocale.h + __support/musl/xlocale.h + __support/newlib/xlocale.h + __support/nuttx/xlocale.h + __support/openbsd/xlocale.h + __support/solaris/floatingpoint.h + __support/solaris/wchar.h + __support/solaris/xlocale.h + __support/win32/limits_msvc_win32.h + __support/win32/locale_win32.h + __support/xlocale/__nop_locale_mgmt.h + __support/xlocale/__posix_l_fallback.h + __support/xlocale/__strtonum_fallback.h system_error tgmath.h thread diff --git a/libcxx/include/__locale b/libcxx/include/__locale index a2da7d78049fc..77e5faab2676d 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -21,30 +21,30 @@ #include #if defined(_LIBCPP_MSVCRT_LIKE) # include -# include +# include <__support/win32/locale_win32.h> #elif defined(__NuttX__) -# include +# include <__support/nuttx/xlocale.h> #elif defined(_AIX) || defined(__MVS__) -# include +# include <__support/ibm/xlocale.h> #elif defined(__ANDROID__) -# include +# include <__support/android/locale_bionic.h> #elif defined(__sun__) # include -# include +# include <__support/solaris/xlocale.h> #elif defined(_NEWLIB_VERSION) -# include +# include <__support/newlib/xlocale.h> #elif defined(__OpenBSD__) -# include +# include <__support/openbsd/xlocale.h> #elif (defined(__APPLE__) || defined(__FreeBSD__) \ || defined(__EMSCRIPTEN__) || defined(__IBMCPP__)) # include #elif defined(__Fuchsia__) -# include +# include <__support/fuchsia/xlocale.h> #elif defined(__wasi__) // WASI libc uses musl's locales support. -# include +# include <__support/musl/xlocale.h> #elif defined(_LIBCPP_HAS_MUSL_LIBC) -# include +# include <__support/musl/xlocale.h> #endif #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/support/android/locale_bionic.h b/libcxx/include/__support/android/locale_bionic.h similarity index 90% rename from libcxx/include/support/android/locale_bionic.h rename to libcxx/include/__support/android/locale_bionic.h index f05a6a0522ca2..8c6d4bd0dc322 100644 --- a/libcxx/include/support/android/locale_bionic.h +++ b/libcxx/include/__support/android/locale_bionic.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/android/locale_bionic.h ------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -28,13 +28,13 @@ extern "C" { #include #include #if __ANDROID_API__ < 21 -#include +#include <__support/xlocale/__posix_l_fallback.h> #endif // In NDK versions later than 16, locale-aware functions are provided by // legacy_stdlib_inlines.h #if __NDK_MAJOR__ <= 16 #if __ANDROID_API__ < 21 -#include +#include <__support/xlocale/__strtonum_fallback.h> #elif __ANDROID_API__ < 26 #if defined(__cplusplus) diff --git a/libcxx/include/support/fuchsia/xlocale.h b/libcxx/include/__support/fuchsia/xlocale.h similarity index 74% rename from libcxx/include/support/fuchsia/xlocale.h rename to libcxx/include/__support/fuchsia/xlocale.h index b86ce9efbd116..e8def81480eae 100644 --- a/libcxx/include/support/fuchsia/xlocale.h +++ b/libcxx/include/__support/fuchsia/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/fuchsia/xlocale.h ------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,8 +14,8 @@ #include #include -#include -#include +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> #endif // defined(__Fuchsia__) diff --git a/libcxx/include/support/ibm/limits.h b/libcxx/include/__support/ibm/limits.h similarity index 97% rename from libcxx/include/support/ibm/limits.h rename to libcxx/include/__support/ibm/limits.h index d1c59f066a879..45f1f1e3684ca 100644 --- a/libcxx/include/support/ibm/limits.h +++ b/libcxx/include/__support/ibm/limits.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------- support/ibm/limits.h ---------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/ibm/locale_mgmt_aix.h b/libcxx/include/__support/ibm/locale_mgmt_aix.h similarity index 96% rename from libcxx/include/support/ibm/locale_mgmt_aix.h rename to libcxx/include/__support/ibm/locale_mgmt_aix.h index e452dc32529de..4f658c3eee306 100644 --- a/libcxx/include/support/ibm/locale_mgmt_aix.h +++ b/libcxx/include/__support/ibm/locale_mgmt_aix.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/ibm/locale_mgmt_aix.h --------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/ibm/nanosleep.h b/libcxx/include/__support/ibm/nanosleep.h similarity index 100% rename from libcxx/include/support/ibm/nanosleep.h rename to libcxx/include/__support/ibm/nanosleep.h diff --git a/libcxx/include/support/ibm/support.h b/libcxx/include/__support/ibm/support.h similarity index 95% rename from libcxx/include/support/ibm/support.h rename to libcxx/include/__support/ibm/support.h index 0569cbe7460df..a7751b0176667 100644 --- a/libcxx/include/support/ibm/support.h +++ b/libcxx/include/__support/ibm/support.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===----------------------- support/ibm/support.h ----------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/ibm/xlocale.h b/libcxx/include/__support/ibm/xlocale.h similarity index 97% rename from libcxx/include/support/ibm/xlocale.h rename to libcxx/include/__support/ibm/xlocale.h index fde137cde260f..ad07a255fc951 100644 --- a/libcxx/include/support/ibm/xlocale.h +++ b/libcxx/include/__support/ibm/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------- support/ibm/xlocale.h -------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -9,7 +9,8 @@ #ifndef _LIBCPP_SUPPORT_IBM_XLOCALE_H #define _LIBCPP_SUPPORT_IBM_XLOCALE_H -#include + +#include <__support/ibm/locale_mgmt_aix.h> #include "cstdlib" @@ -218,7 +219,7 @@ size_t strftime_l(char *__s, size_t __size, const char *__fmt, #elif defined(__MVS__) #include // POSIX routines -#include +#include <__support/xlocale/__posix_l_fallback.h> #endif // defined(__MVS__) // The following are not POSIX routines. These are quick-and-dirty hacks diff --git a/libcxx/include/support/musl/xlocale.h b/libcxx/include/__support/musl/xlocale.h similarity index 95% rename from libcxx/include/support/musl/xlocale.h rename to libcxx/include/__support/musl/xlocale.h index 722d13fa1d665..2508a8e8e0ca5 100644 --- a/libcxx/include/support/musl/xlocale.h +++ b/libcxx/include/__support/musl/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------- support/musl/xlocale.h ------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/newlib/xlocale.h b/libcxx/include/__support/newlib/xlocale.h similarity index 82% rename from libcxx/include/support/newlib/xlocale.h rename to libcxx/include/__support/newlib/xlocale.h index 25fa798b6d029..b75f9263a4c40 100644 --- a/libcxx/include/support/newlib/xlocale.h +++ b/libcxx/include/__support/newlib/xlocale.h @@ -17,9 +17,9 @@ #include #if !defined(__NEWLIB__) || __NEWLIB__ < 2 || \ __NEWLIB__ == 2 && __NEWLIB_MINOR__ < 5 -#include -#include -#include +#include <__support/xlocale/__nop_locale_mgmt.h> +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> #endif #endif // _NEWLIB_VERSION diff --git a/libcxx/include/support/nuttx/xlocale.h b/libcxx/include/__support/nuttx/xlocale.h similarity index 70% rename from libcxx/include/support/nuttx/xlocale.h rename to libcxx/include/__support/nuttx/xlocale.h index b70d62005046c..be738e3b64e48 100644 --- a/libcxx/include/support/nuttx/xlocale.h +++ b/libcxx/include/__support/nuttx/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/nuttx/xlocale.h -------------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -11,8 +11,8 @@ #define _LIBCPP_SUPPORT_NUTTX_XLOCALE_H #if defined(__NuttX__) -#include -#include +#include <__support/xlocale/__posix_l_fallback.h> +#include <__support/xlocale/__strtonum_fallback.h> #endif // __NuttX__ #endif diff --git a/libcxx/include/support/openbsd/xlocale.h b/libcxx/include/__support/openbsd/xlocale.h similarity index 78% rename from libcxx/include/support/openbsd/xlocale.h rename to libcxx/include/__support/openbsd/xlocale.h index fbfaedd127c6c..1136fa327fac5 100644 --- a/libcxx/include/support/openbsd/xlocale.h +++ b/libcxx/include/__support/openbsd/xlocale.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/openbsd/xlocale.h -----------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -14,6 +14,6 @@ #include #include #include -#include +#include <__support/xlocale/__strtonum_fallback.h> #endif diff --git a/libcxx/include/support/solaris/floatingpoint.h b/libcxx/include/__support/solaris/floatingpoint.h similarity index 100% rename from libcxx/include/support/solaris/floatingpoint.h rename to libcxx/include/__support/solaris/floatingpoint.h diff --git a/libcxx/include/support/solaris/wchar.h b/libcxx/include/__support/solaris/wchar.h similarity index 100% rename from libcxx/include/support/solaris/wchar.h rename to libcxx/include/__support/solaris/wchar.h diff --git a/libcxx/include/support/solaris/xlocale.h b/libcxx/include/__support/solaris/xlocale.h similarity index 100% rename from libcxx/include/support/solaris/xlocale.h rename to libcxx/include/__support/solaris/xlocale.h diff --git a/libcxx/include/support/win32/limits_msvc_win32.h b/libcxx/include/__support/win32/limits_msvc_win32.h similarity index 96% rename from libcxx/include/support/win32/limits_msvc_win32.h rename to libcxx/include/__support/win32/limits_msvc_win32.h index 7bb835559a3b8..758d24647b1bf 100644 --- a/libcxx/include/support/win32/limits_msvc_win32.h +++ b/libcxx/include/__support/win32/limits_msvc_win32.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------------ support/win32/limits_msvc_win32.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/win32/locale_win32.h b/libcxx/include/__support/win32/locale_win32.h similarity index 99% rename from libcxx/include/support/win32/locale_win32.h rename to libcxx/include/__support/win32/locale_win32.h index 897c36be70c62..d32a7a8ad3042 100644 --- a/libcxx/include/support/win32/locale_win32.h +++ b/libcxx/include/__support/win32/locale_win32.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------------- support/win32/locale_win32.h -------------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/xlocale/__nop_locale_mgmt.h b/libcxx/include/__support/xlocale/__nop_locale_mgmt.h similarity index 94% rename from libcxx/include/support/xlocale/__nop_locale_mgmt.h rename to libcxx/include/__support/xlocale/__nop_locale_mgmt.h index f33d3894c3a9f..57b18842ff454 100644 --- a/libcxx/include/support/xlocale/__nop_locale_mgmt.h +++ b/libcxx/include/__support/xlocale/__nop_locale_mgmt.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===------------ support/xlocale/__nop_locale_mgmt.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/xlocale/__posix_l_fallback.h b/libcxx/include/__support/xlocale/__posix_l_fallback.h similarity index 98% rename from libcxx/include/support/xlocale/__posix_l_fallback.h rename to libcxx/include/__support/xlocale/__posix_l_fallback.h index f3df6c46fbab6..00d69d19e8c8d 100644 --- a/libcxx/include/support/xlocale/__posix_l_fallback.h +++ b/libcxx/include/__support/xlocale/__posix_l_fallback.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===--------------- support/xlocale/__posix_l_fallback.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/support/xlocale/__strtonum_fallback.h b/libcxx/include/__support/xlocale/__strtonum_fallback.h similarity index 96% rename from libcxx/include/support/xlocale/__strtonum_fallback.h rename to libcxx/include/__support/xlocale/__strtonum_fallback.h index df38598056a6b..1172a5d57236d 100644 --- a/libcxx/include/support/xlocale/__strtonum_fallback.h +++ b/libcxx/include/__support/xlocale/__strtonum_fallback.h @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------- support/xlocale/__strtonum_fallback.h -----------------===// +//===-----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index 473c9c3bbe49f..de572f3ff84d5 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -17,7 +17,7 @@ #include #ifdef __MVS__ -# include +# include <__support/ibm/nanosleep.h> #endif #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER diff --git a/libcxx/include/bit b/libcxx/include/bit index fe360179c5ca0..f8c37c3d6bbfe 100644 --- a/libcxx/include/bit +++ b/libcxx/include/bit @@ -62,7 +62,7 @@ namespace std { #include <__debug> #if defined(__IBMCPP__) -#include "support/ibm/support.h" +#include "__support/ibm/support.h" #endif #if defined(_LIBCPP_COMPILER_MSVC) #include diff --git a/libcxx/include/limits b/libcxx/include/limits index 6d5d1e1aca75e..8f97cd10a8b1f 100644 --- a/libcxx/include/limits +++ b/libcxx/include/limits @@ -105,11 +105,11 @@ template<> class numeric_limits; #include #if defined(_LIBCPP_COMPILER_MSVC) -#include "support/win32/limits_msvc_win32.h" +#include "__support/win32/limits_msvc_win32.h" #endif // _LIBCPP_MSVCRT #if defined(__IBMCPP__) -#include "support/ibm/limits.h" +#include "__support/ibm/limits.h" #endif // __IBMCPP__ #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) diff --git a/libcxx/include/memory b/libcxx/include/memory index a00916c8c03ff..39d0f5bee6a56 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -2647,7 +2647,7 @@ private: _Alloc *__alloc = reinterpret_cast<_Alloc*>(__first); return __alloc; } - _Tp* __get_elem() _NOEXCEPT { + _LIBCPP_NO_CFI _Tp* __get_elem() _NOEXCEPT { _CompressedPair *__as_pair = reinterpret_cast<_CompressedPair*>(__blob_); typename _CompressedPair::_Base2* __second = _CompressedPair::__get_second_base(__as_pair); _Tp *__elem = reinterpret_cast<_Tp*>(__second); diff --git a/libcxx/src/CMakeLists.txt b/libcxx/src/CMakeLists.txt index c482068fa99ae..9965104cb5b23 100644 --- a/libcxx/src/CMakeLists.txt +++ b/libcxx/src/CMakeLists.txt @@ -107,7 +107,7 @@ endif() if (LIBCXX_CONFIGURE_IDE) file(GLOB_RECURSE LIBCXX_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/*) if(WIN32) - file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/support/win32/*.h) + file( GLOB LIBCXX_WIN32_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../include/__support/win32/*.h) list(APPEND LIBCXX_HEADERS ${LIBCXX_WIN32_HEADERS}) endif() # Force them all into the headers dir on MSVC, otherwise they end up at diff --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp index 6b73ed771cd1b..9ae1fb5199bf1 100644 --- a/libcxx/src/atomic.cpp +++ b/libcxx/src/atomic.cpp @@ -19,6 +19,12 @@ #include #include +// libc++ uses SYS_futex as a universal syscall name. However, on 32 bit architectures +// with a 64 bit time_t, we need to specify SYS_futex_time64. +#if !defined(SYS_futex) && defined(SYS_futex_time64) +# define SYS_futex SYS_futex_time64 +#endif + #else // <- Add other operating systems here // Baseline needs no new headers diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index f109389f68f31..a0209d0ce8cf4 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -29,7 +29,7 @@ #include "cwctype" #include "__sso_allocator" #if defined(_LIBCPP_MSVCRT) || defined(__MINGW32__) -#include "support/win32/locale_win32.h" +#include "__support/win32/locale_win32.h" #elif !defined(__BIONIC__) && !defined(__NuttX__) #include #endif diff --git a/libcxx/src/support/solaris/xlocale.cpp b/libcxx/src/support/solaris/xlocale.cpp index d68a39f4dfe50..d25adcd21d307 100644 --- a/libcxx/src/support/solaris/xlocale.cpp +++ b/libcxx/src/support/solaris/xlocale.cpp @@ -8,7 +8,7 @@ #ifdef __sun__ -#include "support/solaris/xlocale.h" +#include "__support/solaris/xlocale.h" #include #include #include diff --git a/libcxx/src/support/win32/locale_win32.cpp b/libcxx/src/support/win32/locale_win32.cpp index b7062db352adc..e7c6005fc1a36 100644 --- a/libcxx/src/support/win32/locale_win32.cpp +++ b/libcxx/src/support/win32/locale_win32.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/win32/locale_win32.cpp ------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/src/support/win32/support.cpp b/libcxx/src/support/win32/support.cpp index d156e02e3e849..52453f5479266 100644 --- a/libcxx/src/support/win32/support.cpp +++ b/libcxx/src/support/win32/support.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -//===----------------------- support/win32/support.h ----------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/src/support/win32/thread_win32.cpp b/libcxx/src/support/win32/thread_win32.cpp index 83e7e9f6ce5bf..35c4c871457de 100644 --- a/libcxx/src/support/win32/thread_win32.cpp +++ b/libcxx/src/support/win32/thread_win32.cpp @@ -1,5 +1,5 @@ // -*- C++ -*- -//===-------------------- support/win32/thread_win32.cpp ------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/libcxx/test/libcxx/debug/extern-templates.sh.cpp b/libcxx/test/libcxx/debug/extern-templates.sh.cpp index d5039d4f30296..0e19895ba8f0a 100644 --- a/libcxx/test/libcxx/debug/extern-templates.sh.cpp +++ b/libcxx/test/libcxx/debug/extern-templates.sh.cpp @@ -15,7 +15,7 @@ // UNSUPPORTED: libcpp-has-no-localization // RUN: %{cxx} %{flags} %{compile_flags} %s %{link_flags} -fPIC -DTU1 -D_LIBCPP_DEBUG=1 -fvisibility=hidden -shared -o %t.lib -// RUN: %{cxx} %{flags} %{compile_flags} %s %t.lib %{link_flags} -fPIC -DTU2 -D_LIBCPP_DEBUG=1 -fvisibility=hidden -o %t.exe +// RUN: cd %T && %{cxx} %{flags} %{compile_flags} %s ./%basename_t.tmp.lib %{link_flags} -fPIC -DTU2 -D_LIBCPP_DEBUG=1 -fvisibility=hidden -o %t.exe // RUN: %{exec} %t.exe #include diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index b803347c2a8e3..426c855288fcf 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -28,7 +28,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_B project(libcxxabi CXX C) set(PACKAGE_NAME libcxxabi) - set(PACKAGE_VERSION 11.0.0git) + set(PACKAGE_VERSION 11.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index 6bfc02d153796..e5fca98f92717 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -96,7 +96,6 @@ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ - X(UUIDOfExpr) \ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ @@ -2035,21 +2034,6 @@ class ThrowExpr : public Node { } }; -// MSVC __uuidof extension, generated by clang in -fms-extensions mode. -class UUIDOfExpr : public Node { - Node *Operand; -public: - UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} - - template void match(Fn F) const { F(Operand); } - - void printLeft(OutputStream &S) const override { - S << "__uuidof("; - Operand->print(S); - S << ")"; - } -}; - class BoolExpr : public Node { bool Value; @@ -5013,6 +4997,43 @@ Node *AbstractManglingParser::parseExpr() { } } return nullptr; + case 'u': { + ++First; + Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); + if (!Name) + return nullptr; + // Special case legacy __uuidof mangling. The 't' and 'z' appear where the + // standard encoding expects a , and would be otherwise be + // interpreted as node 'short' or 'ellipsis'. However, neither + // __uuidof(short) nor __uuidof(...) can actually appear, so there is no + // actual conflict here. + if (Name->getBaseName() == "__uuidof") { + if (numLeft() < 2) + return nullptr; + if (*First == 't') { + ++First; + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make(Name, makeNodeArray(&Ty, &Ty + 1)); + } + if (*First == 'z') { + ++First; + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make(Name, makeNodeArray(&Ex, &Ex + 1)); + } + } + size_t ExprsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseTemplateArg(); + if (E == nullptr) + return E; + Names.push_back(E); + } + return make(Name, popTrailingNodeArray(ExprsBegin)); + } case '1': case '2': case '3': @@ -5024,21 +5045,6 @@ Node *AbstractManglingParser::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } - - if (consumeIf("u8__uuidoft")) { - Node *Ty = getDerived().parseType(); - if (!Ty) - return nullptr; - return make(Ty); - } - - if (consumeIf("u8__uuidofz")) { - Node *Ex = getDerived().parseExpr(); - if (!Ex) - return nullptr; - return make(Ex); - } - return nullptr; } diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index 3954fdba048e4..512cc3928fdd6 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -29776,8 +29776,18 @@ const char* cases[][2] = // Vendor extension types are substitution candidates. {"_Z1fu3fooS_", "f(foo, foo)"}, - {"_ZN3FooIXu8__uuidofzdeL_Z3sucEEEC1Ev", "Foo<__uuidof(*(suc))>::Foo()"}, - {"_ZN3FooIXu8__uuidoft13SomeUUIDClassEEC1Ev", "Foo<__uuidof(SomeUUIDClass)>::Foo()"}, + // alignof with type and expression, and __alignof__ with the same. + {"_Z2f1IiEvDTatT_E", "void f1(decltype(alignof (int)))"}, + {"_Z2f3IiEvDTazcvT_Li0EE", "void f3(decltype(alignof ((int)(0))))"}, + {"_Z2f2IiEvDTu11__alignof__T_EE", "void f2(decltype(__alignof__(int)))"}, + {"_Z2f4IiEvDTu11__alignof__XcvT_Li0EEEE", "void f4(decltype(__alignof__((int)(0))))"}, + + // Legacy nonstandard mangling for __uuidof. + {"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidoftT_E", "void test_uuidofType(decltype(__uuidof(TestStruct)))"}, + {"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr(decltype(__uuidof(HasMember::member)))"}, + // Current __uuidof mangling using vendor extended expression. + {"_Z15test_uuidofTypeI10TestStructEvDTu8__uuidofT_EE", "void test_uuidofType(decltype(__uuidof(TestStruct)))"}, + {"_Z15test_uuidofExprI9HasMemberEvDTu8__uuidofXsrT_6memberEEE", "void test_uuidofExpr(decltype(__uuidof(HasMember::member)))"}, // C++2a char8_t: {"_ZTSPDu", "typeinfo name for char8_t*"}, diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index 8ae32fbccf4e2..48cb8e004e08c 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -24,7 +24,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_B project(libunwind LANGUAGES C CXX ASM) set(PACKAGE_NAME libunwind) - set(PACKAGE_VERSION 12.0.0git) + set(PACKAGE_VERSION 12.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") diff --git a/lld/.gitignore b/lld/.gitignore index 0a288ee8ce966..6e72b447f50a7 100644 --- a/lld/.gitignore +++ b/lld/.gitignore @@ -22,3 +22,9 @@ #==============================================================================# # Sphinx build files. docs/_build + +#==============================================================================# +# UPMEM: work with CLion. +#==============================================================================# +.idea/ +cmake-build-*/ diff --git a/lld/CMakeLists.txt b/lld/CMakeLists.txt index d4e561b50d8f8..b6041748c1619 100644 --- a/lld/CMakeLists.txt +++ b/lld/CMakeLists.txt @@ -1,3 +1,9 @@ +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake + NO_POLICY_SCOPE) + # Check if lld is built as a standalone project. if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) project(lld) diff --git a/lld/Common/CMakeLists.txt b/lld/Common/CMakeLists.txt index 0437d5afb8eb3..bbf4ed79969aa 100644 --- a/lld/Common/CMakeLists.txt +++ b/lld/Common/CMakeLists.txt @@ -4,6 +4,12 @@ if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) list(APPEND LLD_SYSTEM_LIBS atomic) endif() +set(LLD_SYSTEM_LIBS ${LLVM_PTHREAD_LIB}) + +if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) + list(APPEND LLD_SYSTEM_LIBS atomic) +endif() + find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc) find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc) diff --git a/lld/ELF/Arch/DPU.cpp b/lld/ELF/Arch/DPU.cpp new file mode 100644 index 0000000000000..97bc1fe9f413b --- /dev/null +++ b/lld/ELF/Arch/DPU.cpp @@ -0,0 +1,253 @@ +//===- DPU.cpp ----------------------------------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "InputFiles.h" +#include "Relocations.h" +#include "Target.h" +#include + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +#define DEBUG_TYPE "dpu-ld" + +namespace { + +class DPU final : public TargetInfo { +public: + DPU(); + RelExpr getRelExpr(RelType Type, const Symbol &S, + const uint8_t *Loc) const override; + void relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const override; + uint64_t fixupTargetVA(uint64_t TargetVA) const override; + uint32_t calcEFlags() const override; +}; + +} // end anonymous namespace + +DPU::DPU() {} + +RelExpr DPU::getRelExpr(const RelType Type, const Symbol &S, + const uint8_t *Loc) const { + switch (Type) { + default: + error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type)); + return R_NONE; + case R_DPU_NONE: + return R_NONE; + case R_DPU_8: + case R_DPU_16: + case R_DPU_32: + case R_DPU_64: + case R_DPU_PC: + case R_DPU_IMM5: + case R_DPU_IMM8_DMA: + case R_DPU_IMM24_PC: + case R_DPU_IMM27_PC: + case R_DPU_IMM28_PC_OPC8: + case R_DPU_IMM8_STR: + case R_DPU_IMM12_STR: + case R_DPU_IMM16_STR: + case R_DPU_IMM16_ATM: + case R_DPU_IMM24: + case R_DPU_IMM24_RB: + case R_DPU_IMM27: + case R_DPU_IMM28: + case R_DPU_IMM32: + case R_DPU_IMM32_ZERO_RB: + case R_DPU_IMM17_24: + case R_DPU_IMM32_DUS_RB: + return R_ABS; + } +} + +#define ATOMIC_SECTION_OFFSET (0xF0000000ULL) +#define IRAM_SECTION_OFFSET (0x80000000ULL) +#define MRAM_SECTION_OFFSET (0x08000000ULL) +uint64_t DPU::fixupTargetVA(uint64_t TargetVA) const { + // BE CAREFUL: this code is based on the assertions defined by the DPU linker + // script: + // - IRAM: memory mapped at virtual address 0x8XXXXXXX + // - MRAM: memory mapped at virtual address 0x08XXXXXX + // - WRAM: no address remap + // The LSBits may be the addition of an instruction offset to the address, + // which must be converted to an absolute address. + // TODO: fix pointer length everywhere. For example: + // __sys_bootstrap: + // release zero, 0x5, nz, . + 1 + // In obj: + // Ltmp0 + 1 + // Ltmp0 becomes 0x8xxxxxx1 at this level. + + // Make sure MSBs are clean. + TargetVA &= 0xFFFFFFFF; + + if ((TargetVA & ATOMIC_SECTION_OFFSET) == ATOMIC_SECTION_OFFSET) { + return TargetVA & ~ATOMIC_SECTION_OFFSET; + } else if (TargetVA & IRAM_SECTION_OFFSET) { + const uint32_t shift = 3; + TargetVA &= ~IRAM_SECTION_OFFSET; + return (TargetVA >> shift) + (TargetVA & ((1ULL << shift) - 1ULL)); + } else if (TargetVA & MRAM_SECTION_OFFSET) { + return (TargetVA & ~MRAM_SECTION_OFFSET); + } else { + return TargetVA; + } +} + +void DPU::relocate(uint8_t *loc, const Relocation &rel, const uint64_t val) const { + const endianness E = support::little; + uint64_t Data = read64(loc); + RelType Type = rel.type; + + switch (Type) { + case R_DPU_8: + *loc = (uint8_t)val; + return; + case R_DPU_32: + write32(loc, (uint32_t)val); + return; + case R_DPU_64: + write64(loc, val); + return; + case R_DPU_16: + case R_DPU_PC: + write16(loc, (uint16_t)val); + return; + case R_DPU_IMM8_DMA: + *(loc + 3) = (uint8_t)val; + return; + case R_DPU_IMM5: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0x1l) << 28); + break; + case R_DPU_IMM24_PC: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16); + break; + case R_DPU_IMM27_PC: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x7l) << 39); + break; + case R_DPU_IMM28_PC_OPC8: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x7l) << 39) | (((val >> 11) & 0x1l) << 44); + break; + case R_DPU_IMM8_STR: + Data |= (((val >> 0) & 0xfl) << 16) | (((val >> 4) & 0xfl) << 0); + break; + case R_DPU_IMM12_STR: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0x7l) << 39) | + (((val >> 7) & 0x1l) << 24) | (((val >> 8) & 0x1l) << 15) | + (((val >> 9) & 0x1l) << 14) | (((val >> 10) & 0x1l) << 13) | + (((val >> 11) & 0x1l) << 12); + break; + case R_DPU_IMM16_STR: + Data |= (((val >> 0) & 0xfl) << 16) | (((val >> 4) & 0xfffl) << 0); + break; + case R_DPU_IMM16_ATM: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x1fl) << 26) | (((val >> 13) & 0x7l) << 39); + break; + case R_DPU_IMM24: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x1l) << 15) | (((val >> 9) & 0x1l) << 14) | + (((val >> 10) & 0x1l) << 13) | (((val >> 11) & 0x1l) << 12) | + (((val >> 12) & 0xfffl) << 0); + break; + case R_DPU_IMM24_RB: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0x7l) << 39) | + (((val >> 7) & 0x1l) << 24) | (((val >> 8) & 0x1l) << 15) | + (((val >> 9) & 0x1l) << 14) | (((val >> 10) & 0x1l) << 13) | + (((val >> 11) & 0x1l) << 12) | (((val >> 12) & 0xfffl) << 0); + break; + case R_DPU_IMM27: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x1l) << 15) | (((val >> 9) & 0x1l) << 14) | + (((val >> 10) & 0x1l) << 13) | (((val >> 11) & 0x1l) << 12) | + (((val >> 12) & 0xfffl) << 0) | (((val >> 24) & 0x7l) << 39); + break; + case R_DPU_IMM28: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x1l) << 15) | (((val >> 9) & 0x1l) << 14) | + (((val >> 10) & 0x1l) << 13) | (((val >> 11) & 0x1l) << 12) | + (((val >> 12) & 0xfffl) << 0) | (((val >> 24) & 0x7l) << 39) | + (((val >> 27) & 0x1l) << 44); + break; + case R_DPU_IMM32: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x1l) << 15) | (((val >> 9) & 0x1l) << 14) | + (((val >> 10) & 0x1l) << 13) | (((val >> 11) & 0x1l) << 12) | + (((val >> 12) & 0xfffl) << 0) | (((val >> 24) & 0xffl) << 24); + break; + case R_DPU_IMM32_ZERO_RB: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0x7l) << 34) | + (((val >> 7) & 0x1l) << 39) | (((val >> 8) & 0x1l) << 15) | + (((val >> 9) & 0x1l) << 14) | (((val >> 10) & 0x1l) << 13) | + (((val >> 11) & 0x1l) << 12) | (((val >> 12) & 0xfffl) << 0) | + (((val >> 24) & 0xffl) << 24); + break; + case R_DPU_IMM17_24: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0xfl) << 16) | + (((val >> 8) & 0x1l) << 15) | (((val >> 9) & 0x1l) << 14) | + (((val >> 10) & 0x1l) << 13) | (((val >> 11) & 0x1l) << 12) | + (((val >> 12) & 0x1fl) << 0) | (((val >> 16) & 0x1l) << 5) | + (((val >> 16) & 0x1l) << 6) | (((val >> 16) & 0x1l) << 7) | + (((val >> 16) & 0x1l) << 8) | (((val >> 16) & 0x1l) << 9) | + (((val >> 16) & 0x1l) << 10) | (((val >> 16) & 0x1l) << 11); + break; + case R_DPU_IMM32_DUS_RB: + Data |= (((val >> 0) & 0xfl) << 20) | (((val >> 4) & 0x7l) << 34) | + (((val >> 7) & 0x1l) << 44) | (((val >> 8) & 0x1l) << 15) | + (((val >> 9) & 0x1l) << 14) | (((val >> 10) & 0x1l) << 13) | + (((val >> 11) & 0x1l) << 12) | (((val >> 12) & 0xfffl) << 0) | + (((val >> 24) & 0xffl) << 24); + break; + default: + error(getErrorLocation(loc) + "unrecognized reloc " + Twine(Type)); + } + write64(loc, Data); +} + +#define UNKNOWN_E_FLAGS (0xffffffff) +static uint32_t getEFlags(InputFile *File) { + return cast>(File)->getObj().getHeader().e_flags; +} + +static uint32_t getEABI(uint32_t e_flags) { + if (!(e_flags & llvm::ELF::EF_DPU_EABI_SET)) + return ~llvm::ELF::EF_DPU_EABI_SET; + else + return EF_EABI_DPU_GET(e_flags); +} + +static uint32_t getEABI(InputFile *File) { return getEABI(getEFlags(File)); } + +uint32_t DPU::calcEFlags() const { + uint32_t e_flags = UNKNOWN_E_FLAGS; + InputFile *first_file = NULL; + for (InputFile *F : objectFiles) { + if (e_flags == UNKNOWN_E_FLAGS) { + e_flags = getEFlags(F); + first_file = F; + } else if (getEABI(e_flags) != getEABI(F)) { + error("uncompatible abi between '" + toString(first_file) + "' and '" + + toString(F) + "' (" + std::to_string(getEABI(e_flags)) + + " != " + std::to_string(getEABI(F)) + ")"); + } + } + return e_flags; +} + +TargetInfo *elf::getDPUTargetInfo() { + static DPU Target; + return &Target; +} diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index f85d0fb9f55e3..82033f13f7afb 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -8,6 +8,8 @@ add_lld_library(lldELF Arch/AMDGPU.cpp Arch/ARM.cpp Arch/AVR.cpp + # UPMEM + Arch/DPU.cpp Arch/Hexagon.cpp Arch/Mips.cpp Arch/MipsArchTree.cpp diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index a23491d62dc83..0b73ae88f62d5 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -25,6 +25,8 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/ARMAttributeParser.h" #include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/DPUAttributeParser.h" +#include "llvm/Support/DPUBuildAttributes.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Path.h" #include "llvm/Support/RISCVAttributeParser.h" @@ -904,6 +906,26 @@ InputSectionBase *ObjFile::createInputSection(const Elf_Shdr &sec) { } } + if (config->emachine == EM_DPU && sec.sh_type == SHT_DPU_ATTRIBUTES) { + DPUAttributeParser attributes; + ArrayRef contents = check(this->getObj().getSectionContents(sec)); + if (Error e = attributes.parse(contents, support::little)) { + auto *isec = make(*this, sec, name); + warn(toString(isec) + ": " + llvm::toString(std::move(e))); + } else { + + // FIXME: Retain the first attribute section we see. Tools such as + // llvm-objdump make use of the attribute section to determine which + // standard extensions to enable. In a full implementation we would merge + // all attribute sections. + if (in.attributes == nullptr) { + in.attributes = make(*this, sec, name); + return in.attributes; + } + return &InputSection::discarded; + } + } + if (config->emachine == EM_RISCV && sec.sh_type == SHT_RISCV_ATTRIBUTES) { RISCVAttributeParser attributes; ArrayRef contents = check(this->getObj().getSectionContents(sec)); @@ -1633,6 +1655,8 @@ static uint16_t getBitcodeMachineKind(StringRef path, const Triple &t) { return t.isOSIAMCU() ? EM_IAMCU : EM_386; case Triple::x86_64: return EM_X86_64; + case Triple::dpu: + return EM_DPU; default: error(path + ": could not infer e_machine from bitcode target triple " + t.str()); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index f40bb258b9af2..01018d47cae69 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -901,7 +901,10 @@ void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef rels) { continue; } - if (expr != R_ABS && expr != R_DTPREL && expr != R_RISCV_ADD) { + // R_ABS/R_DTPREL and some other relocations can be used from non-SHF_ALLOC + // sections. + if (expr != R_ABS && expr != R_DTPREL && expr != R_GOTPLTREL && + expr != R_RISCV_ADD) { std::string msg = getLocation(offset) + ": has non-ABS relocation " + toString(type) + " against symbol '" + toString(sym) + "'"; @@ -1097,7 +1100,7 @@ void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) { target->relocate(bufLoc, rel, targetVA); break; default: - target->relocate(bufLoc, rel, targetVA); + target->relocate(bufLoc, rel, target->fixupTargetVA(targetVA)); break; } } diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index cb816d8ed12d1..9cd0365ad8bc2 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -60,6 +60,9 @@ TargetInfo *elf::getTarget() { return getARMTargetInfo(); case EM_AVR: return getAVRTargetInfo(); +// UPMEM + case EM_DPU: + return getDPUTargetInfo(); case EM_HEXAGON: return getHexagonTargetInfo(); case EM_MIPS: @@ -190,3 +193,7 @@ uint64_t TargetInfo::getImageBase() const { return *config->imageBase; return config->isPic ? 0 : defaultImageBase; } + +uint64_t TargetInfo::fixupTargetVA(uint64_t targetVA) const { + return targetVA; +} diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index 68b6c5d2ca351..7c3844139a9ab 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -91,6 +91,11 @@ class TargetInfo { virtual void applyJumpInstrMod(uint8_t *loc, JumpModType type, JumpModType val) const {} + // UPMEM + // Allows to fix target virtual addresses on the fly depending on the properties + // of the source section + virtual uint64_t fixupTargetVA(uint64_t targetVA) const; + virtual ~TargetInfo(); // This deletes a jump insn at the end of the section if it is a fall thru to @@ -174,6 +179,8 @@ TargetInfo *getAArch64TargetInfo(); TargetInfo *getAMDGPUTargetInfo(); TargetInfo *getARMTargetInfo(); TargetInfo *getAVRTargetInfo(); +// UPMEM +TargetInfo *getDPUTargetInfo(); TargetInfo *getHexagonTargetInfo(); TargetInfo *getMSP430TargetInfo(); TargetInfo *getPPC64TargetInfo(); diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index e0b17ca3e030d..24ed23bb2b7d4 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -24,28 +24,124 @@ Non-comprehensive list of changes in this release ELF Improvements ---------------- -* ``--error-handling-script`` is added to allow for user-defined handlers upon +* ``--dependency-file`` has been added. (Similar to ``cc -M -MF``.) + (`D82437 `_) +* ``--error-handling-script`` has been added to allow for user-defined handlers upon missing libraries. (`D87758 `_) +* ``--exclude-libs`` can now localize defined version symbols and bitcode referenced libcall symbols. + (`D94280 `_) +* ``--gdb-index`` now works with DWARF v5 and ``--icf={safe,all}``. + (`D85579 `_) + (`D89751 `_) +* ``--gdb-index --emit-relocs`` can now be used together. + (`D94354 `_) +* ``--icf={safe,all}`` conservatively no longer fold text sections with LSDA. + Previously ICF on ``-fexceptions`` code could be unsafe. + (`D84610 `_) +* ``--icf={safe,all}`` can now fold two sections with relocations referencing aliased symbols. + (`D88830 `_) +* ``--lto-pseudo-probe-for-profiling`` has been added. + (`D95056 `_) +* ``--no-lto-whole-program-visibility`` has been added. + (`D92060 `_) +* ``--oformat-binary`` has been fixed to respect LMA. + (`D85086 `_) +* ``--reproduce`` includes ``--lto-sample-profile``, ``--just-symbols``, ``--call-graph-ordering-file``, ``--retain-symbols-file`` files. +* ``-r --gc-sections`` is now supported. + (`D84131 `_) +* A ``-u`` specified symbol will no longer change the binding to ``STB_WEAK``. + (`D88945 `_) +* ``--wrap`` support has been improved. + + If ``foo`` is not referenced, there is no longer an undefined symbol ``__wrap_foo``. + + If ``__real_foo`` is not referenced, there is no longer an undefined symbol ``foo``. +* ``SHF_LINK_ORDER`` sections can now have zero ``sh_link`` values. +* ``SHF_LINK_ORDER`` and non-``SHF_LINK_ORDER`` sections can now be mixed within an input section description. + (`D84001 `_) +* ``LOG2CEIL`` is now supported in linker scripts. + (`D84054 `_) +* ``DEFINED`` has been fixed to check whether the symbol is defined. + (`D83758 `_) +* An input section description may now have multiple ``SORT_*``. + The matched sections are ordered by radix sort with the keys being ``(SORT*, --sort-section, input order)``. + (`D91127 `_) +* Users can now provide a GNU style linker script to convert ``.ctors`` into ``.init_array``. + (`D91187 `_) +* An empty output section can now be discarded even if it is assigned to a program header. + (`D92301 `_) +* Non-``SHF_ALLOC`` sections now have larger file offsets than ``SHF_ALLOC`` sections. + (`D85867 `_) +* Some symbol versioning improvements. + + Defined ``foo@@v1`` now resolve undefined ``foo@v1`` (`D92259 `_) + + Undefined ``foo@v1`` now gets an error (`D92260 `_) +* The AArch64 port now has support for ``STO_AARCH64_VARIANT_PCS`` and ``DT_AARCH64_VARIANT_PCS``. + (`D93045 `_) +* The AArch64 port now has support for ``R_AARCH64_LD64_GOTPAGE_LO15``. +* The PowerPC64 port now detects missing R_PPC64_TLSGD/R_PPC64_TLSLD and disables TLS relaxation. + This allows linking with object files produced by very old IBM XL compilers. + (`D92959 `_) +* Many PowerPC PC-relative relocations are now supported. +* ``R_PPC_ADDR24`` and ``R_PPC64_ADDR16_HIGH`` are now supported. +* powerpcle is now supported. Tested with FreeBSD loader and freestanding. + (`D93917 `_) +* RISC-V: the first ``SHT_RISCV_ATTRIBUTES`` section is now retained. + (`D86309 `_) +* LTO pipeline now defaults to the new PM if the CMake variable ``ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER`` is on. + (`D92885 `_) Breaking changes ---------------- -* ... +* A COMMON symbol can now cause the fetch of an archive providing a ``STB_GLOBAL`` definition. + This behavior follows GNU ld newer than December 1999. + If you see ``duplicate symbol`` errors with the new behavior, check out `PR49226 `_. + (`D86142 `_) COFF Improvements ----------------- -* ... +* Error out clearly if creating a DLL with too many exported symbols. + (`D86701 `_) MinGW Improvements ------------------ -* ... +* Enabled dynamicbase by default. (`D86654 `_) -MachO Improvements +* Tolerate mismatches between COMDAT section sizes with different amount of + padding (produced by binutils) by inspecting the aux section definition. + (`D86659 `_) + +* Support setting the subsystem version via the subsystem argument. + (`D88804 `_) + +* Implemented the GNU -wrap option. + (`D89004 `_, + `D91689 `_) + +* Handle the ``--demangle`` and ``--no-demangle`` options. + (`D93950 `_) + + +Mach-O Improvements ------------------ -* Item 1. +We've gotten the new implementation of LLD for Mach-O to the point where it is +able to link large x86_64 programs, and we'd love to get some alpha testing on +it. The new Darwin back-end can be invoked as follows: + +.. code-block:: + clang -fuse-ld=lld.darwinnew /path/to/file.c + +To reach this point, we implemented numerous features, and it's easier to list +the major features we *haven't* yet completed: + +* LTO support +* Stack unwinding for exceptions +* Support for arm64, arm, and i386 architectures + +If you stumble upon an issue and it doesn't fall into one of these categories, +please file a bug report! + WebAssembly Improvements ------------------------ diff --git a/lld/test/ELF/lto/parallel.ll b/lld/test/ELF/lto/parallel.ll index d9cb4fed7bfae..d89431e8b4a16 100644 --- a/lld/test/ELF/lto/parallel.ll +++ b/lld/test/ELF/lto/parallel.ll @@ -14,7 +14,7 @@ target triple = "x86_64-unknown-linux-gnu" ; CHECK0-NOT: bar ; CHECK0: T foo ; CHECK0-NOT: bar -define void @foo() { +define void @foo() mustprogress { call void @bar() ret void } @@ -22,7 +22,7 @@ define void @foo() { ; CHECK1-NOT: foo ; CHECK1: T bar ; CHECK1-NOT: foo -define void @bar() { +define void @bar() mustprogress { call void @foo() ret void } diff --git a/lld/test/ELF/non-abs-reloc.s b/lld/test/ELF/non-abs-reloc.s index 72a65424ed1f4..82f913efe4d82 100644 --- a/lld/test/ELF/non-abs-reloc.s +++ b/lld/test/ELF/non-abs-reloc.s @@ -1,17 +1,17 @@ // REQUIRES: x86 // RUN: split-file %s %t -// RUN: llvm-mc -filetype=obj -triple=x86_64 %t/asm -o %t.o -// RUN: ld.lld -T %t/lds %t.o -o %t.exe 2>&1 | FileCheck %s -// CHECK: warning: {{.*}}.o:(.nonalloc1+0x1): has non-ABS relocation R_X86_64_PC32 against symbol '_start' -// CHECK-NEXT: warning: {{.*}}.o:(.nonalloc1+0x6): has non-ABS relocation R_X86_64_PC32 against symbol '_start' +// RUN: llvm-mc -filetype=obj -triple=i386 %t/asm -o %t.o +// RUN: ld.lld -T %t/lds %t.o -o %t.exe 2>&1 | FileCheck %s --implicit-check-not=warning: --implicit-check-not=error: +// CHECK: warning: {{.*}}.o:(.nonalloc1+0x1): has non-ABS relocation R_386_PC32 against symbol '_start' +// CHECK-NEXT: warning: {{.*}}.o:(.nonalloc1+0x6): has non-ABS relocation R_386_PC32 against symbol '_start' // RUN: llvm-objdump -D --no-show-raw-insn %t.exe | FileCheck --check-prefix=DISASM %s // DISASM: Disassembly of section .nonalloc: // DISASM-EMPTY: // DISASM-NEXT: <.nonalloc>: // DISASM-NEXT: 0: nop -// DISASM-NEXT: 1: callq 0x0 -// DISASM-NEXT: 6: callq 0x0 +// DISASM-NEXT: 1: calll 0x0 +// DISASM-NEXT: 6: calll 0x0 //--- lds SECTIONS { @@ -20,6 +20,7 @@ SECTIONS { //--- asm .globl _start _start: +.L0: nop .section .nonalloc0 @@ -30,3 +31,8 @@ _start: .long _start - . - 4 .byte 0xe8 .long _start - . - 4 + +// GCC may relocate DW_AT_GNU_call_site_value with R_386_GOTOFF. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98946 +.section .debug_info + .long .L0@gotoff diff --git a/lld/test/wasm/lto/parallel.ll b/lld/test/wasm/lto/parallel.ll index a93c3558d9694..261cf2ef7dae3 100644 --- a/lld/test/wasm/lto/parallel.ll +++ b/lld/test/wasm/lto/parallel.ll @@ -10,7 +10,7 @@ target triple = "wasm32-unknown-unknown-wasm" ; CHECK0-NOT: bar ; CHECK0: T foo ; CHECK0-NOT: bar -define void @foo() { +define void @foo() mustprogress { call void @bar() ret void } @@ -18,7 +18,7 @@ define void @foo() { ; CHECK1-NOT: foo ; CHECK1: T bar ; CHECK1-NOT: foo -define void @bar() { +define void @bar() mustprogress { call void @foo() ret void } diff --git a/lldb/.gitignore b/lldb/.gitignore index 33ad1465f8db1..fc352bcb91166 100644 --- a/lldb/.gitignore +++ b/lldb/.gitignore @@ -52,3 +52,8 @@ tags # Ignore test trace directories. 20??-??-??-??_??_??/ +#==============================================================================# +# UPMEM: work with CLion. +#==============================================================================# +.idea/ +cmake-build-*/ diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index b5633e21c56a3..760ed778a5d45 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.13.4) +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake + NO_POLICY_SCOPE) + # Add path for custom modules. set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} @@ -31,11 +37,8 @@ if (WIN32) endif() if (LLDB_ENABLE_PYTHON) - execute_process( - COMMAND ${Python3_EXECUTABLE} - -c "import distutils.sysconfig; print(distutils.sysconfig.get_python_lib(True, False, ''))" - OUTPUT_VARIABLE LLDB_PYTHON_DEFAULT_RELATIVE_PATH - OUTPUT_STRIP_TRAILING_WHITESPACE) + find_package(Python3 REQUIRED) + file(RELATIVE_PATH LLDB_PYTHON_DEFAULT_RELATIVE_PATH "/usr" ${Python3_SITELIB}) file(TO_CMAKE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} LLDB_PYTHON_DEFAULT_RELATIVE_PATH) set(LLDB_PYTHON_RELATIVE_PATH ${LLDB_PYTHON_DEFAULT_RELATIVE_PATH} diff --git a/lldb/bindings/interface/SBProcess.i b/lldb/bindings/interface/SBProcess.i index e30b89d1ed39d..18c1c6814542a 100644 --- a/lldb/bindings/interface/SBProcess.i +++ b/lldb/bindings/interface/SBProcess.i @@ -397,6 +397,13 @@ public: bool IsInstrumentationRuntimePresent(lldb::InstrumentationRuntimeType type); + lldb::SBError + SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr); + lldb::SBError SaveCore(const char *file_name); diff --git a/lldb/bindings/interface/SBSymbol.i b/lldb/bindings/interface/SBSymbol.i index fa0b3e4e1378d..c4b266d57089c 100644 --- a/lldb/bindings/interface/SBSymbol.i +++ b/lldb/bindings/interface/SBSymbol.i @@ -43,6 +43,9 @@ public: lldb::SBInstructionList GetInstructions (lldb::SBTarget target, const char *flavor_string); + uint64_t + GetIntegerValue(); + SBAddress GetStartAddress (); diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake index 4ed5c647c5d2a..ff4086e460e27 100644 --- a/lldb/cmake/modules/AddLLDB.cmake +++ b/lldb/cmake/modules/AddLLDB.cmake @@ -92,6 +92,11 @@ function(add_lldb_library name) ${pass_NO_INSTALL_RPATH} ) + if (HAVE_LIBDPU) + target_link_directories(${name} PUBLIC ${UPMEM_API_LIB}) + target_link_libraries(${name} PUBLIC dpu dpuverbose) + endif() + if(CLANG_LINK_CLANG_DYLIB) target_link_libraries(${name} PRIVATE clang-cpp) else() diff --git a/lldb/cmake/modules/LLDBGenerateConfig.cmake b/lldb/cmake/modules/LLDBGenerateConfig.cmake index caeb3969002bb..df89a960b2f0e 100644 --- a/lldb/cmake/modules/LLDBGenerateConfig.cmake +++ b/lldb/cmake/modules/LLDBGenerateConfig.cmake @@ -21,6 +21,11 @@ check_cxx_symbol_exists(__NR_process_vm_readv "sys/syscall.h" HAVE_NR_PROCESS_VM check_library_exists(compression compression_encode_buffer "" HAVE_LIBCOMPRESSION) +set(CMAKE_REQUIRED_LIBRARIES dpuverbose) +check_library_exists(dpu dpu_get_program "${UPMEM_API_LIB}" HAVE_LIBDPU) +set(CMAKE_REQUIRED_LIBRARIES) + + # These checks exist in LLVM's configuration, so I want to match the LLVM names # so that the check isn't duplicated, but we translate them into the LLDB names # so that I don't have to change all the uses at the moment. diff --git a/lldb/cmake/modules/LLDBStandalone.cmake b/lldb/cmake/modules/LLDBStandalone.cmake index 94781c3583744..9238959a9fe39 100644 --- a/lldb/cmake/modules/LLDBStandalone.cmake +++ b/lldb/cmake/modules/LLDBStandalone.cmake @@ -1,3 +1,9 @@ +if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS) + set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +endif() + +list(APPEND CMAKE_MODULE_PATH "${LLVM_COMMON_CMAKE_UTILS}/Modules") + option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) find_package(LLVM REQUIRED CONFIG HINTS ${LLVM_DIR} NO_CMAKE_FIND_ROOT_PATH) diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h index a90ec2a29a399..41647c8be3242 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -362,6 +362,12 @@ class LLDB_API SBProcess { bool IsInstrumentationRuntimePresent(InstrumentationRuntimeType type); + lldb::SBError SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr); + /// Save the state of the process in a core file (or mini dump on Windows). lldb::SBError SaveCore(const char *file_name); diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h index 66f73c82a73a5..87bf4a9deb0fe 100644 --- a/lldb/include/lldb/API/SBSymbol.h +++ b/lldb/include/lldb/API/SBSymbol.h @@ -41,6 +41,8 @@ class LLDB_API SBSymbol { lldb::SBInstructionList GetInstructions(lldb::SBTarget target, const char *flavor_string); + uint64_t GetIntegerValue(); + SBAddress GetStartAddress(); SBAddress GetEndAddress(); diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 9a694de0f60a0..4ea7296346c07 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -311,6 +311,8 @@ class InstructionList { uint32_t GetIndexOfInstructionAtAddress(const Address &addr); + lldb::InstructionSP GetInstructionAtOffset(const lldb::addr_t offset); + void Clear(); void Append(lldb::InstructionSP &inst_sp); diff --git a/lldb/include/lldb/Host/ProcessLaunchInfo.h b/lldb/include/lldb/Host/ProcessLaunchInfo.h index ee97555808251..f7cbba05e0e8d 100644 --- a/lldb/include/lldb/Host/ProcessLaunchInfo.h +++ b/lldb/include/lldb/Host/ProcessLaunchInfo.h @@ -146,7 +146,12 @@ class ProcessLaunchInfo : public ProcessInfo { return m_flags.Test(lldb::eLaunchFlagDetachOnError); } + void SetArch(ArchSpec arch) { m_arch = arch; } + + ArchSpec GetArch() const { return m_arch; } + protected: + ArchSpec arch; FileSpec m_working_dir; std::string m_plugin_name; FileSpec m_shell; diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 5be9cb657382a..8973d71fca6e4 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -306,6 +306,20 @@ class NativeProcessProtocol { MainLoop &mainloop) const = 0; }; + virtual void SaveCore(const char *save_core_filename, + const char *executable_path, Status &error) { + error.SetErrorString("Not Implemented"); + } + + virtual void SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr, + Status &error) { + error.SetErrorString("Not Implemented"); + } + /// StartTracing API for starting a tracing instance with the /// TraceOptions on a specific thread or process. /// diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index fbdb5069b39fc..dac75f068c17c 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -2455,6 +2455,20 @@ void PruneThreadPlans(); lldb::StructuredDataPluginSP GetStructuredDataPlugin(ConstString type_name) const; + virtual void SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr, + Status &error) { + error.SetErrorString("Not implemented"); + } + + virtual void SaveCore(const char *save_core_filename, + const char *executable_path, Status &error) { + error.SetErrorString("Not implemented"); + } + /// Starts tracing with the configuration provided in options. To enable /// tracing on the complete process the thread_id in the options should be /// set to LLDB_INVALID_THREAD_ID. The API returns a user_id which is needed diff --git a/lldb/include/lldb/Utility/ArchSpec.h b/lldb/include/lldb/Utility/ArchSpec.h index fdfe6aceb033c..7aca1b48c3b29 100644 --- a/lldb/include/lldb/Utility/ArchSpec.h +++ b/lldb/include/lldb/Utility/ArchSpec.h @@ -203,6 +203,8 @@ class ArchSpec { eCore_wasm32, + eCore_dpu, + kNumCores, kCore_invalid, diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index 3b6ed8030985d..1c6d3c8166a6b 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -167,6 +167,9 @@ class StringExtractorGDBRemote : public StringExtractor { eServerPacketType_jTraceMetaRead, // deprecated eServerPacketType_jTraceStop, // deprecated eServerPacketType_jTraceConfigRead, // deprecated + eServerPacketType_jSaveCore, // DPU + + eServerPacketType_qDpuPrintInfo, // dpu specific packet eServerPacketType_jLLDBTraceSupportedType, }; diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.dpu.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.dpu.rules new file mode 100644 index 0000000000000..322fa2a78f49d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.dpu.rules @@ -0,0 +1,75 @@ +#---------------------------------------------------------------------- +# Clients fill in the source files to build +#---------------------------------------------------------------------- +# C_SOURCES := main.c +# CXX_SOURCES := +# OBJC_SOURCES := +# OBJCXX_SOURCES := +# DYLIB_C_SOURCES := +# DYLIB_OBJC_SOURCES := +# DYLIB_CXX_SOURCES := +# +# Specifying DYLIB_ONLY has the effect of building dylib only, skipping +# the building of the a.out executable program. For example, +# DYLIB_ONLY := YES +# +# Also might be of interest: +# FRAMEWORK_INCLUDES (Darwin only) := +# CFLAGS_EXTRAS := +# LD_EXTRAS := +# SPLIT_DEBUG_SYMBOLS := YES +# CROSS_COMPILE := +# +# And test/functionalities/archives/Makefile: +# MAKE_DSYM := NO +# ARCHIVE_NAME := libfoo.a +# ARCHIVE_C_SOURCES := a.c b.c + +# Uncomment line below for debugging shell commands +# SHELL = /bin/sh -x + +SRCDIR := $(shell dirname $(firstword $(MAKEFILE_LIST)))/ +BUILDDIR := $(shell pwd) +THIS_FILE_DIR := $(shell dirname $(lastword $(MAKEFILE_LIST)))/ +LLDB_BASE_DIR := $(THIS_FILE_DIR)../../../../../ +UPMEM_HOME ?= /usr + +OBJECTS = +EXE = a.out +LDFLAGS ?= +CFLAGS ?= -g -O0 + +HOST_OBJECT = +HOST_EXE = +HOST_LDFLAGS = -L$(UPMEM_HOME)/lib64 -L$(UPMEM_HOME)/lib -ldpu +HOST_CFLAGS ?= -g -O2 --std=c99 + +#---------------------------------------------------------------------- +# Check if we have any C source files +#---------------------------------------------------------------------- +ifneq "$(strip $(C_SOURCES))" "" + OBJECTS +=$(strip $(C_SOURCES:.c=.o)) +endif + +#---------------------------------------------------------------------- +# Check if we have any Host C source files +#---------------------------------------------------------------------- +ifneq "$(strip $(HOST_C_SOURCES))" "" + HOST_OBJECTS +=$(strip $(HOST_C_SOURCES:.c=.o.host)) + HOST_EXE = host.out +endif + +#---------------------------------------------------------------------- +# Compile the executable from all the objects. +#---------------------------------------------------------------------- +$(EXE) : $(OBJECTS) $(HOST_EXE) + ${UPMEM_HOME}/bin/dpu-upmem-dpurte-clang $(OBJECTS) $(LDFLAGS) -o $@ + +%.o: %.c + ${UPMEM_HOME}/bin/dpu-upmem-dpurte-clang $(CFLAGS) $< -c -o $@ + +$(HOST_EXE) : $(HOST_OBJECTS) + gcc $^ $(HOST_LDFLAGS) -o $@ + +%.o.host: %.c + gcc -DDPU_EXE="\"$(CURDIR)/$(EXE)\"" $(HOST_CFLAGS) -I$(UPMEM_HOME)/include/dpu $^ -c -o $@ diff --git a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules index f4aa6d646711f..45bfd4e6c1375 100644 --- a/lldb/packages/Python/lldbsuite/test/make/Makefile.rules +++ b/lldb/packages/Python/lldbsuite/test/make/Makefile.rules @@ -197,6 +197,10 @@ else ifeq "$(findstring mips,$(ARCH))" "mips" override ARCHFLAG := - endif + ifeq "$(ARCH)" "dpu" + override ARCH := + override ARCHFLAG := + endif ifeq "$(SPLIT_DEBUG_SYMBOLS)" "YES" DSYM = $(EXE).debug diff --git a/lldb/scripts/dpu/dpu_commands.py b/lldb/scripts/dpu/dpu_commands.py new file mode 100644 index 0000000000000..f8f0439c9f9bf --- /dev/null +++ b/lldb/scripts/dpu/dpu_commands.py @@ -0,0 +1,671 @@ +import os +import re +import sys +import subprocess +import time + +import psutil + +import lldb + +SUB_LLDB_PROCESS_PORT = int(os.environ.get("SUB_LLDB_PROCESS_PORT", 2066)) +SUB_LLDB_PROCESS_MAX_RETRY = int(os.environ.get("SUB_LLDB_PROCESS_MAX_RETRY", 10)) + +def wait_until_port_open(port, pid): + proc = psutil.Process(pid) + for i in range(SUB_LLDB_PROCESS_MAX_RETRY): + if proc.status() == psutil.STATUS_ZOMBIE: + print("lldb-server-dpu with pid", pid, "died.") + return False + + conn = proc.connections() + + port_is_open = False + for c in conn: + if (c.laddr.port == port + and c.status == 'LISTEN'): + port_is_open = True + break + + if port_is_open: + print("lldb-server-dpu is ready for connection.") + return True + else: + slack_time = pow(2, i) * 0.25 + print("Attempt", i, "failed. Retry in ", slack_time, " seconds.") + time.sleep(slack_time) + + return False + + +def check_target(target): + if target.GetTriple() == "dpu-upmem-dpurte": + print("Command not allowed on dpu target") + return False + return True + + +def decompute_dpu_pid(pid): + rank_id = (pid // (100*100)) % 100 + slice_id = (pid // 100) % 100 + dpu_id = pid % 100 + return rank_id, slice_id, dpu_id + + +def compute_dpu_pid(rank_id, slice_id, dpu_id): + return dpu_id + 100 * (slice_id + 100 * (rank_id + 100)) + + +def set_debug_mode(debugger, target, rank, debug_mode): + command = ("hw_set_debug_mode((dpu_rank_t *)" + rank.GetValue() + ", " + + str(debug_mode) + ")") + res = target.EvaluateExpression(command) + if res.GetError().Fail(): + raise Exception("Command ", command, " failed.\n", res.GetError().description) + + status = res.GetValueAsUnsigned() + success = status == 0 + return success + + +def setup_for_onboot(debugger, target, dpu_addr): + command = "setup_for_onboot((dpu_t *)" + dpu_addr + ")" + res = target.EvaluateExpression(command) + if res.GetError().Fail(): + raise Exception("Command ", command, " failed.\n", res.GetError().description) + + status = res.GetChildMemberWithName("status").GetValueAsUnsigned() + instr = res.GetChildMemberWithName("instr").GetValueAsUnsigned() + + return status, instr + + +def get_dpu_from_command(command, debugger, target): + if type(command) is lldb.SBValue: + return command + try: + addr = int(command, 16) + return target.CreateValueFromExpression( + "dpu", "(struct dpu_t *)" + str(addr)) + except ValueError: + command_values = command.split('.') + if len(command_values) == 3: + rank_id = command_values[0] + dpus = dpu_list(debugger, None, None, None) + if rank_id in dpus: + addr = next((dpu[0] for dpu in dpus[rank_id] + if (command == + str(rank_id) + "." + str(dpu[1]) + "." + + str(dpu[2]))), + 0) + return addr + print("Could not interpret command '" + command + "'") + return None + + +def get_rank_id(rank, target): + full_rank_id = rank.GetChildMemberWithName("rank_id").GetValueAsUnsigned() + # See /api/include/lowlevel/dpu_target_macros.h:DPU_TARGET_SHIFT + dpu_target_shift = 12 + dpu_target_mask = ((1 << dpu_target_shift) - 1) + rank_id = full_rank_id & dpu_target_mask + target_id = full_rank_id >> dpu_target_shift + return rank_id, target_id + + +def get_nb_slices_and_nb_dpus_per_slice(rank, target): + uint32_type = target.FindFirstType("uint32_t") + topology = rank.GetChildMemberWithName("description") \ + .GetChildMemberWithName("hw") \ + .GetChildMemberWithName("topology") + nb_dpus_per_slice = topology \ + .GetChildMemberWithName("nr_of_dpus_per_control_interface") \ + .Cast(uint32_type).GetValueAsUnsigned() & 0xff + nb_slices = topology \ + .GetChildMemberWithName("nr_of_control_interfaces") \ + .Cast(uint32_type).GetValueAsUnsigned() & 0xff + return nb_slices, nb_dpus_per_slice + + +def get_dpu_program_path(dpu): + program_path = dpu.GetChildMemberWithName("program") \ + .GetChildMemberWithName("program_path") + if program_path.GetChildAtIndex(0).GetValue() is None: + return None + return re.search('"(.+)"', str(program_path)).group(1) + + +def get_dpu_status(dpus_running, dpus_in_fault, slice_id, dpu_id): + dpu_mask = 1 << dpu_id + if (dpu_mask & dpus_running) != 0: + return "RUNNING" + elif (dpu_mask & dpus_in_fault) != 0: + return "ERROR" + else: + return "IDLE" + + +def break_to_next_boot_and_get_dpus(debugger, target): + launch_rank_function = "dpu_launch_thread_on_rank" + launch_dpu_function = "dpu_launch_thread_on_dpu" + launch_rank_bkp = \ + target.BreakpointCreateByName(launch_rank_function) + launch_dpu_bkp = target.BreakpointCreateByName(launch_dpu_function) + + process = target.GetProcess() + process.Continue() + + target.BreakpointDelete(launch_rank_bkp.GetID()) + target.BreakpointDelete(launch_dpu_bkp.GetID()) + + dpu_list = [] + thread = process.GetSelectedThread() + current_frame = 0 + frame = thread.GetFrameAtIndex(current_frame) + function_name = frame.GetFunctionName() + if thread.GetStopReason() != lldb.eStopReasonBreakpoint: + return dpu_list, frame + + # Look for frame from which the host needs to step out to complete the boot + # of the dpu + nb_frames = thread.GetNumFrames() + while ((function_name != launch_rank_function) + and (function_name != launch_dpu_function)): + current_frame = current_frame + 1 + if current_frame == nb_frames: + return dpu_list, frame + frame = thread.GetFrameAtIndex(current_frame) + function_name = frame.GetFunctionName() + + thread.SetSelectedFrame(current_frame) + if function_name == launch_rank_function: + rank = frame.FindVariable("rank") + nb_ci, nb_dpu_per_ci = \ + get_nb_slices_and_nb_dpus_per_slice(rank, target) + nb_dpu = nb_ci * nb_dpu_per_ci + for each_dpu in range(0, nb_dpu): + local_dpu = rank.GetValueForExpressionPath("->dpus[" + str(each_dpu) + "]") + _enabled = local_dpu.GetChildMemberWithName("enabled").GetValueAsUnsigned() + if _enabled == 1: + dpu_list.append(local_dpu) + elif function_name == launch_dpu_function: + dpu_list.append(frame.FindVariable("dpu")) + + return dpu_list, frame + + +def dpu_attach_on_boot(debugger, command, result, internal_dict): + ''' + usage: dpu_attach_on_boot [] + ''' + target = debugger.GetSelectedTarget() + if not(check_target(target)): + return None + + dpus_booting, host_frame = \ + break_to_next_boot_and_get_dpus(debugger, target) + if dpus_booting is None or len(dpus_booting) == 0: + print("Could not find any dpu booting") + return None + + # If a dpu is specified in the command, wait for this specific dpu to boot + if command != "": + dpu_to_attach = get_dpu_from_command(command, debugger, target) + if dpu_to_attach is None: + print("Could not find the dpu to attach to") + return None + dpus_booting = list(filter( + lambda dpu: dpu.GetAddress() == dpu_to_attach.GetAddress(), + dpus_booting)) + print("Waiting for specified DPU to boot.") + for i in range(10): + if len(dpus_booting) == 1: + break + slack_time = pow(2, i) * 0.25 + print("Attempt", i, "failed. Retry in ", slack_time, " seconds.") + time.sleep(slack_time) + + dpus_booting, host_frame =\ + break_to_next_boot_and_get_dpus(debugger, target) + dpus_booting = list(filter( + lambda dpu: dpu.GetAddress() == dpu_to_attach.GetAddress(), + dpus_booting)) + + if len(dpus_booting) != 1: + print("Could not find the dpu booting") + return None + + # As the object that represents the dpu will disapear, + # we capture the address here + dpu_addr = str(dpus_booting[0].GetAddress()) + + print("Setting up dpu '" + dpu_addr + "' for attach on boot...") + + # Replace first instruction for a breakpoint + setup_for_onboot_status, setup_for_onboot_instr = setup_for_onboot(debugger, target, dpu_addr) + if setup_for_onboot_status != 0: # DPU_OK + print("setup_for_onboot failed with", setup_for_onboot_status, "during dpu_attach_on_boot.") + if setup_for_onboot_instr == 1: + print("Could not copy instruction from IRAM.") + else: + print("Could not set instruction to IRAM.") + return None + + # step out from frame dpu_launch_thread_on_rank or dpu_launch_thread_on_dpu + # we breakpoint in earlier during break_to_next_boot_and_get_dpus() + error = lldb.SBError() + target.GetProcess().GetSelectedThread().StepOutOfFrame(host_frame, error) + print("dpu '" + str(dpu_addr) + "' has booted") + + # Attach to the DPU we just setup + # it has breakpointed at the very first instruction + target_dpu = dpu_attach(debugger, dpu_addr, None, None) + if target_dpu is None: + print("Could not attach to dpu") + return None + + # Restore the first instruction + target_dpu.GetProcess().WriteMemory(0x80000000, + setup_for_onboot_instr.to_bytes(8, byteorder='little'), + error) + + return target_dpu + + +def dpu_attach(debugger, command, result, internal_dict): + ''' + usage: dpu_attach + ''' + target = debugger.GetSelectedTarget() + if not(check_target(target)): + return None + + dpu = get_dpu_from_command(command, debugger, target) + if dpu is None or not(dpu.IsValid): + print("Could not find dpu") + return None + + # the dpu object can be a completelly resolved SBValue + # or just a wrapped pointer + dpu_address = dpu.GetAddress() + if not dpu_address.IsValid(): + dpu_address = dpu.GetValue() + + print("Attaching to dpu '" + str(dpu_address) + "'") + + rank = dpu.GetChildMemberWithName("rank") + if not(rank.IsValid()): + print("Could not find dpu rank") + return None + + rank_id, target_id = get_rank_id(rank, target) + if target_id != 3: # 3 => dpu_type_t:HW + print("Could not attach to DPU (hardware only)") + return None + slice_id = dpu.GetChildMemberWithName("slice_id").GetValueAsUnsigned() + dpu_id = dpu.GetChildMemberWithName("dpu_id").GetValueAsUnsigned() + pid = compute_dpu_pid(rank_id, slice_id, dpu_id) + + nb_slices, nb_dpus_per_slice = get_nb_slices_and_nb_dpus_per_slice( + rank, target) + structures_value_env = "" + slices_target_env = "" + host_muxs_mram_state_env = "" + slices_info = rank.GetChildMemberWithName("runtime") \ + .GetChildMemberWithName("control_interface") \ + .GetChildMemberWithName("slice_info") + for each_slice in range(nb_slices): + structures_value_env += str(each_slice) + ":" + slices_target_env += str(each_slice) + ":" + host_muxs_mram_state_env += str(each_slice) + ":" + + slice_info = slices_info.GetChildAtIndex(each_slice) + if not(slice_info.IsValid()): + print("Could not find dpu slice_info") + return None + slice_target = slice_info.GetChildMemberWithName("slice_target") + if not(slice_target.IsValid()): + print("Could not find dpu slice_target") + return None + + structures_value_env += str(slice_info.GetChildMemberWithName( + "structure_value") .GetValueAsUnsigned()) + "&" + host_muxs_mram_state_env += \ + str(slice_info.GetChildMemberWithName("host_mux_mram_state").GetValueAsUnsigned()) + "&" + slice_target_type = slice_target.GetChildMemberWithName("type") \ + .GetValueAsUnsigned() + slice_target_dpu_group_id = slice_target.GetChildMemberWithName( + "dpu_id") .GetValueAsUnsigned() + slices_target_env += str((slice_target_dpu_group_id << + 32) + slice_target_type) + "&" + + if not(set_debug_mode(debugger, target, rank, 1)): + print("Could not set dpu in debug mode") + return None + + lldb_server_dpu_env = os.environ.copy() + lldb_server_dpu_env["UPMEM_LLDB_STRUCTURES_VALUE"] = structures_value_env + lldb_server_dpu_env["UPMEM_LLDB_SLICES_TARGET"] = slices_target_env + lldb_server_dpu_env["UPMEM_LLDB_HOST_MUXS_MRAM_STATE"] = \ + host_muxs_mram_state_env + + program_path = get_dpu_program_path(dpu) + + if not(program_path is None): + module_spec = lldb.SBModuleSpec() + module_spec.SetFileSpec(lldb.SBFileSpec(program_path)) + + nr_tasklets = lldb.SBModule(module_spec).FindSymbol('NR_TASKLETS') + if nr_tasklets.IsValid(): + lldb_server_dpu_env["UPMEM_LLDB_NR_TASKLETS"] = \ + str(nr_tasklets.GetIntegerValue()) + + if program_path is not None and not os.path.exists(program_path): + program_path = None + target_dpu = \ + debugger.CreateTargetWithFileAndTargetTriple(program_path, + "dpu-upmem-dpurte") + if not(target_dpu.IsValid()): + print("Could not create dpu target") + return None + + # Get the address of the error_storage variable. + # As we need to send this address *before* the lldb server has started we cannot send it as a + # normal lldb GDBRemote packet. Instead, we set an environment variable with the value that we + # have looked up from the loaded bianry. If we cannot find one, then this environment variable + # remains unset, and we cannot detach and re-attach within different processes. + storage = target_dpu.FindFirstGlobalVariable("error_storage") + if storage.IsValid(): + lldb_server_dpu_env["UPMEM_LLDB_ERROR_STORE_ADDR"] = str(storage.location) + + sub_lldb = subprocess.Popen(['lldb-server-dpu', + 'gdbserver', + '--attach', + str(pid), + ':' + str(SUB_LLDB_PROCESS_PORT)], + env=lldb_server_dpu_env) + + # The creation and initialization of the process above could take quite some time. + # We wait here for the communication channel to be created. + print("Waiting for lldb-server-dpu with pid", sub_lldb.pid, "to finish initialization.") + if not(wait_until_port_open(SUB_LLDB_PROCESS_PORT, sub_lldb.pid)): + print("lldb-server-dpu did not succesfully open communication channel.") + return None + + listener = debugger.GetListener() + error = lldb.SBError() + process_dpu = target_dpu.ConnectRemote(listener, + "connect://localhost:" + str(SUB_LLDB_PROCESS_PORT), + "gdb-remote", + error) + if not(process_dpu.IsValid()): + print("Could not connect to dpu") + return None + + open_print_sequence_fct_ctx = target_dpu \ + .FindFunctions("__open_print_sequence") + close_print_sequence_fct_ctx = target_dpu \ + .FindFunctions("__close_print_sequence") + if (open_print_sequence_fct_ctx.IsValid() + and close_print_sequence_fct_ctx.IsValid()): + open_print_sequence_fct = open_print_sequence_fct_ctx \ + .GetContextAtIndex(0).GetFunction() + close_print_sequence_fct = close_print_sequence_fct_ctx \ + .GetContextAtIndex(0).GetFunction() + if (open_print_sequence_fct.IsValid() + and close_print_sequence_fct.IsValid()): + print_buffer_var = target_dpu \ + .FindFirstGlobalVariable("__stdout_buffer") + print_buffer_size_var = target_dpu \ + .FindFirstGlobalVariable("__stdout_buffer_size") + print_buffer_var_var = target_dpu \ + .FindFirstGlobalVariable("__stdout_buffer_state") + + if (print_buffer_var.IsValid() + and print_buffer_size_var.IsValid() + and print_buffer_var_var.IsValid()): + + open_print_sequence_addr = open_print_sequence_fct \ + .GetStartAddress().GetFileAddress() + close_print_sequence_addr = close_print_sequence_fct \ + .GetStartAddress().GetFileAddress() + print_buffer_addr = print_buffer_var \ + .GetAddress().GetFileAddress() + print_buffer_size = print_buffer_size_var.GetValueAsUnsigned() + print_buffer_var_addr = print_buffer_var_var.GetAddress() \ + .GetFileAddress() + + process_dpu.SetDpuPrintInfo(open_print_sequence_addr, + close_print_sequence_addr, + print_buffer_addr, + print_buffer_size, + print_buffer_var_addr) + + debugger.SetSelectedTarget(target) + if not(set_debug_mode(debugger, target, rank, 0)): + print("Could not unset dpu from debug mode") + return None + + debugger.SetSelectedTarget(target_dpu) + return target_dpu + + +def print_list_rank(rank_id, dpus_info, verbose, status_filter, result): + if verbose: + for dpu_addr, slice_id, dpu_id, status, program in dpus_info: + if status_filter is None or status_filter == status: + result.PutCString( + "'%s' %2u.%u.%u %7s '%s'" % + ( + str(dpu_addr.GetAddress()), + int(rank_id), + slice_id, + dpu_id, + status, + program + ) + ) + else: + default_program = dpus_info[0][4] + idle = 0 + running = 0 + error = 0 + for dpu_addr, slice_id, dpu_id, status, program in dpus_info: + if status == "IDLE": + idle += 1 + if status == "RUNNING": + running += 1 + if status == "ERROR": + error += 1 + if program != default_program: + default_program = None + result.PutCString( + "RANK#%2u: %2u DPUs ( %2u IDLE - %2u RUNNING - %2u ERROR ) '%s'" % + (int(rank_id), + len(dpus_info), + idle, + running, + error, + (default_program if default_program is not None else "DPUs are not loaded with the same program"))) + + +def print_list(rank_list, result, command): + if result is None: + return + verbose = False + rank_filter = None + status_filter = None + if command is not None: + args = command.split() + nb_args = len(args) + for arg_id, arg in enumerate(args): + if arg == '-v': + verbose = True + elif arg == '-r' and nb_args > arg_id + 1: + rank_filter = args[arg_id + 1] + elif arg[:2] == '-r': + rank_filter = arg[2:] + elif arg == '-s' and nb_args > arg_id + 1: + status_filter = args[arg_id + 1] + elif arg[:2] == '-s': + status_filter = arg[2:] + + for rank_id, dpus_info in rank_list.items(): + if rank_filter is None or rank_filter == rank_id: + print_list_rank( + rank_id, + dpus_info, + verbose or rank_filter is not None or status_filter is not None, + status_filter, + result) + + +def get_allocated_dpus(debugger): + target = debugger.GetSelectedTarget() + if not(check_target(target)): + return None + + nb_allocated_rank = \ + target.FindFirstGlobalVariable("dpu_rank_handler_dpu_rank_list_size") + if nb_allocated_rank is None: + print("dpu_list: internal error 1 (can't get number of ranks)") + return None + + rank_list = target.FindFirstGlobalVariable( + "dpu_rank_handler_dpu_rank_list") + if rank_list is None: + print("dpu_list: internal error 2 (can't get rank list)") + return None + + result_list = {} + for each_rank in range(0, nb_allocated_rank.GetValueAsUnsigned()): + rank = rank_list.GetValueForExpressionPath("[" + str(each_rank) + "]") + if rank.GetValueAsUnsigned() == 0: + continue + + rank_id, _ = get_rank_id(rank, target) + + nb_slices, nb_dpus_per_slice = \ + get_nb_slices_and_nb_dpus_per_slice(rank, target) + + run_context = rank.GetChildMemberWithName("runtime") \ + .GetChildMemberWithName("run_context") + dpus_running = run_context.GetChildMemberWithName("dpu_running") + dpus_in_fault = run_context.GetChildMemberWithName("dpu_in_fault") + dpus = rank.GetChildMemberWithName("dpus") + + for slice_id in range(0, nb_slices): + dpus_running_in_slice = dpus_running.GetChildAtIndex(slice_id) \ + .GetValueAsUnsigned() + dpus_in_fault_in_slice = dpus_in_fault.GetChildAtIndex(slice_id) \ + .GetValueAsUnsigned() + for dpu_id in range(0, nb_dpus_per_slice): + dpu = rank.GetValueForExpressionPath( + "->dpus[" + + str(slice_id * nb_dpus_per_slice + dpu_id) + + "]") + + if dpu.GetChildMemberWithName("enabled").GetValue() != 'true': + continue + + program_path = get_dpu_program_path(dpu) + if program_path is None: + program_path = "" + + dpu_status = get_dpu_status(dpus_running_in_slice, + dpus_in_fault_in_slice, + slice_id, + dpu_id) + + result_list.setdefault(str(rank_id), []).append((dpu, + slice_id, dpu_id, + dpu_status, program_path)) + + return result_list + + +def dpu_list(debugger, command, result, internal_dict): + ''' + usage: dpu_list [-v] [-r ] [-s ] + options: + \t-v \tVerbose mode, print detail information for all DPUs + \t-r \tFilter DPUs of the specified rank_id + \t-s \tFilter DPUs of the specified status + ''' + result_list = get_allocated_dpus(debugger) + if result_list is None: + return None + + print_list(result_list, result, command) + return result_list + + +def dpu_attach_first(debugger, command, result, internal_dict): + allocated_dpus = get_allocated_dpus(debugger) + if not allocated_dpus: + print("Could not find any dpu to attach to") + return None + + first_dpu, _, _, _, _ = next(iter(allocated_dpus.values()))[0] + return dpu_attach(debugger, first_dpu, result, internal_dict) + + +def host_synchronize(debugger, target, rank): + command = "host_synchronize((dpu_rank_t *)" + rank.GetValue() + ")" + + res = target.EvaluateExpression(command) + if res.GetError().Fail(): + raise Exception("Command ", command, " failed.\n", res.GetError().description) + + status = res.GetValueAsUnsigned() + return status + + +def get_rank_from_pid(debugger, pid): + target_rank_id, _, _ = decompute_dpu_pid(pid) + target = debugger.GetSelectedTarget() + if not(check_target(target)): + return None + + nb_allocated_rank = \ + target.FindFirstGlobalVariable("dpu_rank_handler_dpu_rank_list_size") + if nb_allocated_rank is None: + print("get_rank_from_pid: internal error 1 (can't get number of ranks)") + return None + + rank_list = target.FindFirstGlobalVariable( + "dpu_rank_handler_dpu_rank_list") + if rank_list is None: + print("get_rank_from_pid: internal error 2 (can't get rank list)") + return None + + for each_rank in range(0, nb_allocated_rank.GetValueAsUnsigned()): + rank = rank_list.GetValueForExpressionPath("[" + str(each_rank) + "]") + if rank.GetValueAsUnsigned() == 0: + continue + rank_id, _ = get_rank_id(rank, target) + if rank_id != target_rank_id: + continue + return rank + + +def dpu_detach(debugger, command, result, internal_dict): + ''' + usage: dpu_detach + ''' + target = debugger.GetSelectedTarget() + if target.GetTriple() != "dpu-upmem-dpurte": + print("Current target is not a DPU target") + return None + pid = target.GetProcess().GetProcessID() + target.GetProcess().Detach() + debugger.DeleteTarget(target) + rank = get_rank_from_pid(debugger, pid) + + target = debugger.GetSelectedTarget() + status = host_synchronize(debugger, target, rank) + + if status != 0: + print("host_synchronize fail with", status, "during dpu_detach.") + + return status diff --git a/lldb/scripts/dpu/lldb_init_dpu_commands b/lldb/scripts/dpu/lldb_init_dpu_commands new file mode 100644 index 0000000000000..64df2b1166676 --- /dev/null +++ b/lldb/scripts/dpu/lldb_init_dpu_commands @@ -0,0 +1,6 @@ +script from lldb import dpu_commands +command script add -f dpu_commands.dpu_attach dpu_attach +command script add -f dpu_commands.dpu_list dpu_list +command script add -f dpu_commands.dpu_attach_on_boot dpu_attach_on_boot +command script add -f dpu_commands.dpu_detach dpu_detach +command script add -f dpu_commands.dpu_attach_first dpu_attach_first diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index d7b7fd7cacadf..9c62291a4501a 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -1228,6 +1228,39 @@ bool SBProcess::IsInstrumentationRuntimePresent( return runtime_sp->IsActive(); } +lldb::SBError SBProcess::SetDpuPrintInfo( + const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, const uint32_t print_buffer_var_addr) { + LLDB_RECORD_METHOD(lldb::SBError, SBProcess, SetDpuPrintInfo, + (const uint32_t, const uint32_t, const uint32_t, + const uint32_t, const uint32_t), + open_print_sequence_addr, close_print_sequence_addr, + print_buffer_addr, print_buffer_size, + print_buffer_var_addr); + + lldb::SBError error; + ProcessSP process_sp(GetSP()); + if (!process_sp) { + error.SetErrorString("SBProcess is invalid"); + return LLDB_RECORD_RESULT(error); + } + + std::lock_guard guard( + process_sp->GetTarget().GetAPIMutex()); + + if (process_sp->GetState() != eStateStopped) { + error.SetErrorString("the process is not stopped"); + return LLDB_RECORD_RESULT(error); + } + + Status status_error; + process_sp->SetDpuPrintInfo( + open_print_sequence_addr, close_print_sequence_addr, print_buffer_addr, + print_buffer_size, print_buffer_var_addr, status_error); + return LLDB_RECORD_RESULT(error); +} + lldb::SBError SBProcess::SaveCore(const char *file_name) { LLDB_RECORD_METHOD(lldb::SBError, SBProcess, SaveCore, (const char *), file_name); diff --git a/lldb/source/API/SBSymbol.cpp b/lldb/source/API/SBSymbol.cpp index eafc3e630bcd5..f04ec818c4266 100644 --- a/lldb/source/API/SBSymbol.cpp +++ b/lldb/source/API/SBSymbol.cpp @@ -146,6 +146,12 @@ lldb_private::Symbol *SBSymbol::get() { return m_opaque_ptr; } void SBSymbol::reset(lldb_private::Symbol *symbol) { m_opaque_ptr = symbol; } +uint64_t SBSymbol::GetIntegerValue() { + LLDB_RECORD_METHOD_NO_ARGS(uint64_t, SBSymbol, GetIntegerValue); + + return LLDB_RECORD_RESULT(m_opaque_ptr->GetIntegerValue()); +} + SBAddress SBSymbol::GetStartAddress() { LLDB_RECORD_METHOD_NO_ARGS(lldb::SBAddress, SBSymbol, GetStartAddress); diff --git a/lldb/source/Core/Disassembler.cpp b/lldb/source/Core/Disassembler.cpp index 3a975d9296f47..e1c0351975b28 100644 --- a/lldb/source/Core/Disassembler.cpp +++ b/lldb/source/Core/Disassembler.cpp @@ -551,16 +551,23 @@ bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, range.GetBaseAddress() = frame.GetFrameCodeAddress(); } - if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) - range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); - - Disassembler::Limit limit = {Disassembler::Limit::Bytes, - range.GetByteSize()}; - if (limit.value == 0) - limit.value = DEFAULT_DISASM_BYTE_SIZE; - - return Disassemble(debugger, arch, nullptr, nullptr, frame, - range.GetBaseAddress(), limit, false, 0, 0, strm); + if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) + range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); + + Disassembler::Limit limit = {Disassembler::Limit::Bytes, range.GetByteSize()}; + // Note, this was previously the following definition (with num_instructions + // defined here separately) I am unsure as to whether we need this, or whether + // the "new" check is correct for the DPU backend size_t + // num_instructions_found = GetInstructionList().GetSize(); + + // Limit limit = (num_instructions == 0) + // ? Limit{Limit::Bytes, range.GetByteSize()} + // : Limit{Limit::Instructions, num_instructions}; + if (limit.value == 0) + limit.value = DEFAULT_DISASM_BYTE_SIZE; + + return Disassemble(debugger, arch, nullptr, nullptr, frame, + range.GetBaseAddress(), limit, false, 0, 0, strm); } Instruction::Instruction(const Address &address, AddressClass addr_class) @@ -647,9 +654,7 @@ bool Instruction::DumpEmulation(const ArchSpec &arch) { return false; } -bool Instruction::CanSetBreakpoint () { - return !HasDelaySlot(); -} +bool Instruction::CanSetBreakpoint() { return !HasDelaySlot(); } bool Instruction::HasDelaySlot() { // Default is false. @@ -988,14 +993,12 @@ void InstructionList::Append(lldb::InstructionSP &inst_sp) { m_instructions.push_back(inst_sp); } -uint32_t -InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, - bool ignore_calls, - bool *found_calls) const { +uint32_t InstructionList::GetIndexOfNextBranchInstruction( + uint32_t start, bool ignore_calls, bool *found_calls) const { size_t num_instructions = m_instructions.size(); uint32_t next_branch = UINT32_MAX; - + if (found_calls) *found_calls = false; for (size_t i = start; i < num_instructions; i++) { @@ -1026,6 +1029,23 @@ InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { return index; } +InstructionSP +InstructionList::GetInstructionAtOffset(const lldb::addr_t offset) { + InstructionSP instruction_sp; + size_t num_instructions = m_instructions.size(); + uint32_t index = UINT32_MAX; + for (size_t i = 0; i < num_instructions; i++) { + if (m_instructions[i]->GetAddress().GetOffset() == offset) { + index = i; + break; + } + } + if (index != UINT32_MAX) { + instruction_sp = m_instructions[index]; + } + return instruction_sp; +} + uint32_t InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, Target &target) { diff --git a/lldb/source/Host/CMakeLists.txt b/lldb/source/Host/CMakeLists.txt index 7456cb98bfa19..899ba5ed23f1b 100644 --- a/lldb/source/Host/CMakeLists.txt +++ b/lldb/source/Host/CMakeLists.txt @@ -177,3 +177,25 @@ add_lldb_library(lldbHost if (LLDB_ENABLE_LIBEDIT) target_include_directories(lldbHost PUBLIC ${LibEdit_INCLUDE_DIRS}) endif() + +if(HAVE_LIBDPU) + +add_lldb_library(lldbHostDpu + ${HOST_SOURCES} + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + lldbUtility + ${EXTRA_LIBS} + ${LLDBObjCLibs} + + LINK_COMPONENTS + Object + Support + ) + +target_compile_options(lldbHostDpu PRIVATE -DUSE_DPU) + +endif() diff --git a/lldb/source/Host/common/HostInfoBase.cpp b/lldb/source/Host/common/HostInfoBase.cpp index 333137a7fd25c..7ba63b095b44e 100644 --- a/lldb/source/Host/common/HostInfoBase.cpp +++ b/lldb/source/Host/common/HostInfoBase.cpp @@ -321,7 +321,11 @@ bool HostInfoBase::ComputeUserPluginsDirectory(FileSpec &file_spec) { void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) { +#if defined(USE_DPU) + llvm::Triple triple("dpu-upmem-dpurte"); +#else llvm::Triple triple(llvm::sys::getProcessTriple()); +#endif arch_32.Clear(); arch_64.Clear(); diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index cad9ce218b103..8d58bbdd23385 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -21,6 +21,7 @@ #include "lldb/Host/LZMA.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Utility/ArchSpec.h" @@ -324,9 +325,9 @@ const uint32_t ObjectFileELF::g_core_uuid_magic(0xE210C); // Static methods. void ObjectFileELF::Initialize() { - PluginManager::RegisterPlugin(GetPluginNameStatic(), - GetPluginDescriptionStatic(), CreateInstance, - CreateMemoryInstance, GetModuleSpecifications); + PluginManager::RegisterPlugin( + GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, + CreateMemoryInstance, GetModuleSpecifications, SaveCore); } void ObjectFileELF::Terminate() { @@ -3277,6 +3278,9 @@ ObjectFile::Type ObjectFileELF::CalculateType() { } ObjectFile::Strata ObjectFileELF::CalculateStrata() { + if (m_header.e_machine == EM_DPU) + return eStrataRawImage; + switch (m_header.e_type) { case llvm::ELF::ET_NONE: // 0 - No file type @@ -3412,3 +3416,20 @@ ObjectFileELF::GetLoadableData(Target &target) { } return loadables; } + +bool ObjectFileELF::SaveCore(const lldb::ProcessSP &process_sp, + const FileSpec &outfile, Status &error) { + if (!process_sp) + return false; + + Target &target = process_sp->GetTarget(); + + Module *exe_module = target.GetExecutableModulePointer(); + if (!exe_module) + return false; + const FileSpec &exefile = exe_module->GetFileSpec(); + + process_sp->SaveCore(outfile.GetCString(), exefile.GetCString(), error); + + return true; +} diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 062271f1caf0f..feae704fcc566 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -81,6 +81,10 @@ class ObjectFileELF : public lldb_private::ObjectFile { lldb::offset_t length, lldb_private::ModuleSpecList &specs); + static bool SaveCore(const lldb::ProcessSP &process_sp, + const lldb_private::FileSpec &outfile, + lldb_private::Status &error); + static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset, lldb::addr_t length); diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt index 91f20ec22ac55..d8ee1c8c62b77 100644 --- a/lldb/source/Plugins/Process/CMakeLists.txt +++ b/lldb/source/Plugins/Process/CMakeLists.txt @@ -13,6 +13,9 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Windows") elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin") add_subdirectory(MacOSX-Kernel) endif() +if (HAVE_LIBDPU) + add_subdirectory(Dpu) +endif() add_subdirectory(gdb-remote) add_subdirectory(Utility) add_subdirectory(elf-core) diff --git a/lldb/source/Plugins/Process/Dpu/CMakeLists.txt b/lldb/source/Plugins/Process/Dpu/CMakeLists.txt new file mode 100644 index 0000000000000..8bc2c20cf2847 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/CMakeLists.txt @@ -0,0 +1,23 @@ +include_directories(${UPMEM_API_HEADERS}) + +add_lldb_library(lldbPluginProcessDpu PLUGIN + DpuRank.cpp + Dpu.cpp + DpuContext.cpp + ProcessDpu.cpp + RegisterContextDpu.cpp + RegisterInfo_dpu.cpp + ThreadDpu.cpp + + LINK_LIBS + lldbCore + lldbHostDpu + lldbSymbol + lldbTarget + lldbUtility + lldbPluginProcessPOSIX + lldbPluginProcessUtility + LINK_COMPONENTS + Support + EXTRA_CXXFLAGS -g + ) diff --git a/lldb/source/Plugins/Process/Dpu/Dpu.cpp b/lldb/source/Plugins/Process/Dpu/Dpu.cpp new file mode 100644 index 0000000000000..8840b1684a3e3 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/Dpu.cpp @@ -0,0 +1,888 @@ +//===-- Dpu.cpp ----------------------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Dpu.h" +#include "DpuRank.h" + +#include "ProcessDpu.h" + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +} + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::dpu; + +namespace { +const uint32_t instruction_size_mod = sizeof(dpuinstruction_t) - 1; +const uint32_t instruction_size_mask = ~instruction_size_mod; +const uint32_t dpuword_size_mod = sizeof(dpuword_t) - 1; +const uint32_t dpuword_size_mask = ~dpuword_size_mod; +const uint32_t mram_aligned = 8; +const uint32_t mram_aligned_mod = mram_aligned - 1; +const uint32_t mram_aligned_mask = ~mram_aligned_mod; +} // namespace + +// ----------------------------------------------------------------------------- +// DPU handling +// ----------------------------------------------------------------------------- + +Dpu::Dpu(DpuRank *rank, dpu_t *dpu, FILE *stdout_file_, bool valid) + : m_rank(rank), m_dpu(dpu), printf_enable(false), + printf_buffer_last_idx((uint32_t)LLDB_INVALID_ADDRESS), + printf_buffer_var_addr((uint32_t)LLDB_INVALID_ADDRESS), + error_store_addr((uint32_t)0 /*nullptr*/), m_valid(valid) { + nr_threads = m_rank->GetNrThreads(); + nr_reg_per_thread = rank->GetDesc()->hw.dpu.nr_of_work_registers_per_thread; + + m_context = new DpuContext(m_dpu, m_rank->AllocContext(), nr_threads); + + stdout_file = stdout_file_; +} + +Dpu::~Dpu() { + delete m_context; +} + +bool Dpu::SetPrintfSequenceAddrs(const uint32_t _open_print_sequence_addr, + const uint32_t _close_print_sequence_addr, + const uint32_t _printf_buffer_address, + const uint32_t _printf_buffer_size, + const uint32_t _printf_buffer_var_addr) { + open_print_sequence_addr = + _open_print_sequence_addr + + sizeof(dpuinstruction_t); // we add sizeof(dpuinstruction_t) to avoid to + // be on the 'acquire' which could makes us loop + // forever + close_print_sequence_addr = _close_print_sequence_addr; + printf_buffer_address = _printf_buffer_address; + printf_buffer_size = _printf_buffer_size; + printf_buffer_var_addr = _printf_buffer_var_addr; + if (open_print_sequence_addr != (lldb::addr_t)LLDB_INVALID_ADDRESS && + close_print_sequence_addr != (lldb::addr_t)LLDB_INVALID_ADDRESS) { + printf_enable = true; + if (!ReadIRAM(open_print_sequence_addr, &open_print_sequence_inst, + sizeof(open_print_sequence_inst))) + return false; + if (!ReadIRAM(close_print_sequence_addr, &close_print_sequence_inst, + sizeof(close_print_sequence_inst))) + return false; + } + return true; +} + +bool Dpu::SetPrintfSequenceAddrsFromRuntimeInfo(dpu_program_t *runtime) { + lldb::addr_t _open_print_sequence_addr = runtime->open_print_sequence_addr; + lldb::addr_t _close_print_sequence_addr = runtime->close_print_sequence_addr; + if (_open_print_sequence_addr != (lldb::addr_t)LLDB_INVALID_ADDRESS && + _close_print_sequence_addr != (lldb::addr_t)LLDB_INVALID_ADDRESS) { + _open_print_sequence_addr = InstIdx2InstAddr(_open_print_sequence_addr); + _close_print_sequence_addr = InstIdx2InstAddr(_close_print_sequence_addr); + return SetPrintfSequenceAddrs( + _open_print_sequence_addr, _close_print_sequence_addr, + runtime->printf_buffer_address, runtime->printf_buffer_size, + runtime->printf_write_pointer_address); + } + return true; +} + +bool Dpu::SetErrorStoreAddr(const uint32_t _error_store_addr) { + error_store_addr = _error_store_addr; + return true; +} + +bool Dpu::SetErrorStoreAddrFromRuntimeInfo(dpu_program_t *runtime) { + struct dpu_symbol_t dpu_error_storage; + if (dpu_get_symbol(runtime, "error_storage", &dpu_error_storage) != DPU_OK) { + return false; + } + return Dpu::SetErrorStoreAddr(dpu_error_storage.address); +} + +bool Dpu::LoadElf(const FileSpec &elf_file_path) { + ModuleSP elf_mod(new Module(elf_file_path, k_dpu_arch)); + + struct dpu_set_t set = dpu_set_from_dpu(m_dpu); + dpu_error_t status = dpu_load(set, elf_file_path.GetCString(), NULL); + if (status != DPU_OK) + return false; + + dpu_program_t *runtime = dpu_get_program(m_dpu); + if (!runtime) + return false; + + uint8_t nr_threads_enabled = runtime->nr_threads_enabled; + if (nr_threads_enabled != (uint8_t)-1) + nr_threads = nr_threads_enabled; + + if (!SetPrintfSequenceAddrsFromRuntimeInfo(runtime)) + return false; + + // JIRA: SW-64 + // TODO: We would like to be able to check this, rather than ignoring the + // result. At present, however, we cannot as there are some situations where + // we *don't* want to fail. This needs to be refactored so that we either a) + // warn the user, or b) integrate the failure in the same way as the + // SetPrintfSequence... does. + // if (!SetErrorStoreAddrFromRuntimeInfo(runtime)) + // return false; + SetErrorStoreAddrFromRuntimeInfo(runtime); + + return true; +} + +bool Dpu::Boot() { + struct dpu_context_t *tmp_context; + // Extract a potential context from the dpu structure (that could have been + // created by the dpu_loader). + dpu_pop_debug_context(m_dpu, &tmp_context); + + // If the dpu contains a context, it means that a core file has been loaded. + // In this case, do not do the boot sequence, the dpu is already in a state + // ready to be resume with 'dpu_finalize_fault_process_for_dpu'. + if (tmp_context != NULL) { + // Free our previously allocated context and get the one created by the + // dpu_loader. + m_context->UpdateContext(tmp_context); + return true; + } + + dpuinstruction_t first_instruction; + ReadIRAM(0, (void *)(&first_instruction), sizeof(dpuinstruction_t)); + + const dpuinstruction_t breakpoint_instruction = 0x00007e6320000000; + WriteIRAMUntraced(0, (const void *)(&breakpoint_instruction), + sizeof(dpuinstruction_t)); + + int res = dpu_custom_for_dpu(m_dpu, DPU_COMMAND_DPU_PREEXECUTION, NULL); + if (res != DPU_OK) + return false; + + res = dpu_custom_for_dpu(m_dpu, DPU_COMMAND_EVENT_START, + (dpu_custom_command_args_t)DPU_EVENT_DEBUG_ACTION); + if (res != DPU_OK) + return false; + + res = dpu_launch_thread_on_dpu(m_dpu, DPU_BOOT_THREAD, false); + if (res != DPU_OK) + return false; + + dpu_is_running = true; + while (1) { + unsigned int exit_status; + switch (PollStatus(&exit_status)) { + case StateType::eStateStopped: + res = + dpu_custom_for_dpu(m_dpu, DPU_COMMAND_EVENT_END, + (dpu_custom_command_args_t)DPU_EVENT_DEBUG_ACTION); + if (res != DPU_OK) + return false; + + WriteIRAMUntraced(0, (const void *)(&first_instruction), + sizeof(dpuinstruction_t)); + return true; + case StateType::eStateRunning: + break; + default: + return false; + } + } +} + +bool Dpu::StopThreads(bool force) { + std::lock_guard guard(m_rank->GetLock()); + + if (!dpu_is_running && !force) + return true; + dpu_is_running = false; + + return m_context->StopThreads(error_store_addr); +} + +StateType Dpu::StepOverPrintfSequenceAndContinue(StateType result_state, + unsigned int *exit_status) { + dpu_thread_t thread_in_fault = m_context->Get()->bkp_fault_thread_index; + lldb::addr_t pc_of_thread_in_fault = + m_context->GetPcOfThread(thread_in_fault); + if (pc_of_thread_in_fault == open_print_sequence_addr || + pc_of_thread_in_fault == close_print_sequence_addr) { + result_state = StepThread(thread_in_fault, exit_status); + + *exit_status = m_context->GetExitStatus(); + + if (result_state != StateType::eStateStopped) + return result_state; + if (ResumeThreads(NULL, true)) + return StateType::eStateRunning; + else + return StateType::eStateCrashed; + } + return result_state; +} + +StateType Dpu::PollStatus(unsigned int *exit_status) { + std::lock_guard guard(m_rank->GetLock()); + bool dpu_is_in_fault; + StateType result_state = StateType::eStateRunning; + + if (!dpu_is_running) + return StateType::eStateInvalid; + + dpu_poll_dpu(m_dpu, &dpu_is_running, &dpu_is_in_fault); + if (dpu_is_in_fault) { + result_state = StateType::eStateStopped; + } else if (!dpu_is_running) { + result_state = m_context->DpuIsRunning(nr_threads) + ? StateType::eStateStopped + : StateType::eStateExited; + } else { + return StateType::eStateRunning; + } + + if (!StopThreads(true)) { + return StateType::eStateCrashed; + } + // Needs to be after StopThreads to make sure that context is up to + // date. + *exit_status = m_context->GetExitStatus(); + + if (dpu_is_in_fault && m_context->Get()->bkp_fault && printf_enable) { + return StepOverPrintfSequenceAndContinue(result_state, exit_status); + } + + return result_state; +} + +dpu::Dpu::eResumeThreadsType +Dpu::ResumeThreads(llvm::SmallVector *resume_list, + bool allowed_polling) { + std::lock_guard guard(m_rank->GetLock()); + if (!m_valid) { + return eResumeThreadsError; + } + + if (!m_context->ContextReadyForResumeOrStep()) { + return m_context->RestoreFaultContext() ? eResumeThreadsInFault + : eResumeThreadsError; + } + + int ret = DPU_OK; + if (registers_has_been_modified) { + ret = dpu_restore_context_for_dpu(m_dpu, m_context->Get()); + if (ret != DPU_OK) + return eResumeThreadsError; + registers_has_been_modified = eResumeThreadsError; + } + + bool status = m_context->ResumeThreads(resume_list); + + if (allowed_polling && status) + dpu_is_running = true; + + return status ? eResumeThreadsSuccess : eResumeThreadsError; +} + +bool Dpu::PrepareStepOverPrintfBkp( + const uint32_t thread_index, + dpuinstruction_t &inst_to_restore_if_printf_enable, + dpuinstruction_t &inst_to_replace_with, const uint32_t current_pc) { + if (current_pc == open_print_sequence_addr) { + inst_to_replace_with = open_print_sequence_inst; + + if (printf_buffer_var_addr != (uint32_t)LLDB_INVALID_ADDRESS) { + if (!ReadWRAM(printf_buffer_var_addr, &printf_buffer_last_idx, + sizeof(printf_buffer_last_idx))) + return false; + } + } else if (current_pc == close_print_sequence_addr) { + inst_to_replace_with = close_print_sequence_inst; + if (printf_buffer_var_addr != (uint32_t)LLDB_INVALID_ADDRESS && + printf_buffer_last_idx != (uint32_t)LLDB_INVALID_ADDRESS) { + uint32_t printf_buffer_current_idx; + if (!ReadWRAM(printf_buffer_var_addr, &printf_buffer_current_idx, + sizeof(printf_buffer_current_idx))) + return false; + + size_t mram_buffer_size; + uint8_t *mram_buffer = (uint8_t *)calloc(1, printf_buffer_size); + if (mram_buffer == NULL) + return false; + if (printf_buffer_current_idx <= printf_buffer_last_idx) { + mram_buffer_size = printf_buffer_size - + (printf_buffer_last_idx - printf_buffer_current_idx); + if (!ReadMRAM(printf_buffer_last_idx, mram_buffer, + printf_buffer_size - printf_buffer_last_idx)) { + goto PrepareStepOverPrintfBkp_err; + } + if (!ReadMRAM(printf_buffer_address & (k_dpu_mram_base - 1), + &mram_buffer[printf_buffer_size - printf_buffer_last_idx], + printf_buffer_current_idx)) { + goto PrepareStepOverPrintfBkp_err; + } + } else { + mram_buffer_size = printf_buffer_current_idx - printf_buffer_last_idx; + if (!ReadMRAM((printf_buffer_last_idx + printf_buffer_address) & + (k_dpu_mram_base - 1), + mram_buffer, mram_buffer_size)) { + goto PrepareStepOverPrintfBkp_err; + } + } + + if (stdout_file != NULL) { + if (dpulog_read_and_display_contents_of( + mram_buffer, mram_buffer_size, dpulog_c_print_fct, + (void *)stdout_file) != DPU_OK) { + goto PrepareStepOverPrintfBkp_err; + } + + fflush(stdout_file); + } + + free(mram_buffer); + return true; + PrepareStepOverPrintfBkp_err: + free(mram_buffer); + return false; + } + } + + return true; +} + +#define UNKNOWN_INSTRUCTION (0ULL) + +StateType Dpu::StepThread(uint32_t thread_index, unsigned int *exit_status) { + std::lock_guard guard(m_rank->GetLock()); + + if (!m_context->ContextReadyForResumeOrStep()) + return StateType::eStateCrashed; + + // If the thread is not in the scheduling list, do not try to step it. + // This behavior is expected as lldb can ask to step one thread and resume all + // the other, which result in stepping all the thread contained in the + // scheduling list. + if (!m_context->ScheduledThread(thread_index)) + return StateType::eStateStopped; + + int ret = DPU_OK; + if (registers_has_been_modified) { + ret = dpu_restore_context_for_dpu(m_dpu, m_context->Get()); + if (ret != DPU_OK) + return StateType::eStateCrashed; + registers_has_been_modified = false; + } + + uint64_t inst_to_restore_if_printf_enable = UNKNOWN_INSTRUCTION; + uint32_t current_pc; + if (printf_enable) { + uint64_t inst_to_replace_with = UNKNOWN_INSTRUCTION; + current_pc = m_context->GetPcOfThread(thread_index); + + if (!PrepareStepOverPrintfBkp(thread_index, + inst_to_restore_if_printf_enable, + inst_to_replace_with, current_pc)) + return StateType::eStateCrashed; + + if (inst_to_replace_with != UNKNOWN_INSTRUCTION) { + // Read what should be the bkp instruction and write the expected + // instruction instead + if (!ReadIRAM(current_pc, &inst_to_restore_if_printf_enable, + sizeof(inst_to_restore_if_printf_enable))) + return StateType::eStateCrashed; + if (!WriteIRAMUntraced(current_pc, (const void *)&inst_to_replace_with, + sizeof(inst_to_replace_with))) + return StateType::eStateCrashed; + } + } + + ret = m_context->StepThread(thread_index); + + // Write back the breakpoint + if (inst_to_restore_if_printf_enable != UNKNOWN_INSTRUCTION) { + if (!WriteIRAMUntraced(current_pc, + (const void *)&inst_to_restore_if_printf_enable, + sizeof(inst_to_restore_if_printf_enable))) + return StateType::eStateCrashed; + } + + if (ret != DPU_OK) + return StateType::eStateCrashed; + if (!m_context->DpuIsRunning(nr_threads)) { + *exit_status = m_context->GetExitStatus(); + return StateType::eStateExited; + } + return StateType::eStateStopped; +} + +bool Dpu::WriteWRAMHandlingAlignment(uint32_t offset, const void *buf, size_t size) { + std::lock_guard guard(m_rank->GetLock()); + + dpu_error_t ret; + // fast path, everything is aligned + if (((offset & dpuword_size_mod) == 0) && ((size & dpuword_size_mod) == 0)) { + const dpuword_t *words = static_cast(buf); + ret = dpu_copy_to_wram_for_dpu(m_dpu, offset / sizeof(dpuword_t), words, + size / sizeof(dpuword_t)); + return ret == DPU_OK; + } + + // slow path + + // compute final_offset to start from and the final_size to use + uint32_t final_offset_in_dpuword = + (offset & dpuword_size_mask) / sizeof(dpuword_t); + size_t padding = offset & dpuword_size_mod; + size_t final_size_in_dpuword = + ((size + dpuword_size_mod + padding) & dpuword_size_mask) / + sizeof(dpuword_t); + + // allocating the buffer of dpuwords to read/write from + dpuword_t *words = new dpuword_t[final_size_in_dpuword]; + if (words == NULL) + return false; + + // reading the dpuwords + ret = dpu_copy_from_wram_for_dpu(m_dpu, words, final_offset_in_dpuword, + final_size_in_dpuword); + if (ret != DPU_OK) { + delete[] words; + return false; + } + + // copy the dpuwords into our buffer + memcpy(&((uint8_t *)words)[padding], buf, size); + + // writing the buffer + ret = dpu_copy_to_wram_for_dpu(m_dpu, final_offset_in_dpuword, words, + final_size_in_dpuword); + + delete[] words; + return ret == DPU_OK; +} + +bool Dpu::WriteWRAM(uint32_t offset, const void *buf, size_t size) { + uint32_t locationInWRAM = offset; + size_t pointerOffsetBuf = 0; + size_t offsetToAlignLocation = sizeof(dpuword_t) - (locationInWRAM % sizeof(dpuword_t)); + + // align addr + if ((offsetToAlignLocation != sizeof(dpuword_t)) && (offsetToAlignLocation < size)) { + if (!WriteWRAMHandlingAlignment(locationInWRAM, buf, offsetToAlignLocation)) { + return false; + } + locationInWRAM += offsetToAlignLocation; + size -= offsetToAlignLocation; + pointerOffsetBuf += offsetToAlignLocation; + } + + // align size + size_t sizeToAlignSize = size % sizeof(dpuword_t); + if (sizeToAlignSize != 0) { + const void *localBufPointer = (static_cast(buf) + + pointerOffsetBuf + (size - sizeToAlignSize)); + + if (!WriteWRAMHandlingAlignment((locationInWRAM + size) - sizeToAlignSize, + localBufPointer, sizeToAlignSize)) { + return false; + } + size -= sizeToAlignSize; + } + + const void *localBufPointer = static_cast(buf) + pointerOffsetBuf; + return WriteWRAMHandlingAlignment(locationInWRAM, localBufPointer, size); +} + +bool Dpu::ReadWRAM(uint32_t offset, void *buf, size_t size) { + std::lock_guard guard(m_rank->GetLock()); + dpuword_t *words = static_cast(buf); + + dpu_error_t ret; + uint32_t padding = offset & dpuword_size_mod; + size_t final_size = (size + dpuword_size_mod + padding) & dpuword_size_mask; + + // if an aligned copy copy more than asked by the function, let's read more + // and then copy only the wanted part into the output buffer. + if (final_size != size) { + iram_size_t final_size_in_dpuword = final_size / sizeof(dpuword_t); + uint32_t final_offset_in_dpuword = + (offset & dpuword_size_mask) / sizeof(dpuword_t); + + words = new dpuword_t[final_size_in_dpuword]; + if (words == NULL) + return false; + + ret = dpu_copy_from_wram_for_dpu(m_dpu, words, final_offset_in_dpuword, + final_size_in_dpuword); + + memcpy(buf, &words[padding], size); + delete[] words; + + } else { + ret = dpu_copy_from_wram_for_dpu(m_dpu, words, offset / sizeof(dpuword_t), + size / sizeof(dpuword_t)); + } + return ret == DPU_OK; +} + +bool Dpu::WriteIRAMUntraced(uint32_t offset, const void *buf, size_t size) { + if (dpu_custom_for_dpu(m_dpu, DPU_COMMAND_EVENT_START, + (dpu_custom_command_args_t)DPU_EVENT_DEBUG_ACTION) != + DPU_OK) + return false; + + if (!WriteIRAM(offset, buf, size)) + return false; + + if (dpu_custom_for_dpu(m_dpu, DPU_COMMAND_EVENT_END, + (dpu_custom_command_args_t)DPU_EVENT_DEBUG_ACTION) != + DPU_OK) + return false; + + return true; +} + +bool Dpu::WriteIRAM(uint32_t offset, const void *buf, size_t size) { + std::lock_guard guard(m_rank->GetLock()); + + dpu_error_t ret; + // fast path, everything is aligned + if (((offset & instruction_size_mod) == 0) && + ((size & instruction_size_mod) == 0)) { + const dpuinstruction_t *instrs = static_cast(buf); + ret = dpu_copy_to_iram_for_dpu(m_dpu, offset / sizeof(dpuinstruction_t), + instrs, size / sizeof(dpuinstruction_t)); + return ret == DPU_OK; + } + + // slow path + + // compute final_offset to start from and the final_size to use + uint32_t final_offset_in_instructions = offset & instruction_size_mask; + size_t padding = offset & instruction_size_mod; + size_t final_size_in_instructions = + ((size + instruction_size_mod + padding) & instruction_size_mask) / + sizeof(dpuinstruction_t); + + // allocating the buffer of instruction to read/write from + dpuinstruction_t *instrs = new dpuinstruction_t[final_size_in_instructions]; + if (instrs == NULL) + return false; + + ret = dpu_copy_from_iram_for_dpu(m_dpu, instrs, final_offset_in_instructions, + final_size_in_instructions); + if (ret != DPU_OK) { + delete[] instrs; + return false; + } + + memcpy(&((uint8_t *)instrs)[padding], buf, size); + + ret = dpu_copy_to_iram_for_dpu(m_dpu, final_offset_in_instructions, instrs, + final_size_in_instructions); + + delete[] instrs; + return ret == DPU_OK; +} + +bool Dpu::ReadIRAM(uint32_t offset, void *buf, size_t size) { + std::lock_guard guard(m_rank->GetLock()); + dpuinstruction_t *instrs = static_cast(buf); + + dpu_error_t ret; + uint32_t padding = offset & instruction_size_mod; + size_t final_size = + (size + instruction_size_mod + padding) & instruction_size_mask; + + // if an aligned copy copy more than asked by the function, let's read more + // and then copy only the wanted part into the output buffer. + if (final_size != size) { + iram_size_t final_size_in_instructions = + final_size / sizeof(dpuinstruction_t); + uint32_t final_offset_in_instructions = + (offset & instruction_size_mask) / sizeof(dpuinstruction_t); + + instrs = new dpuinstruction_t[final_size_in_instructions]; + if (instrs == NULL) + return false; + + ret = + dpu_copy_from_iram_for_dpu(m_dpu, instrs, final_offset_in_instructions, + final_size_in_instructions); + + memcpy(buf, &instrs[padding], size); + delete[] instrs; + } else { + ret = dpu_copy_from_iram_for_dpu(m_dpu, instrs, + offset / sizeof(dpuinstruction_t), + size / sizeof(dpuinstruction_t)); + } + return ret == DPU_OK; +} + +bool Dpu::WriteMRAMHandlingAlignment(uint32_t offset, const void *buf, size_t size) { + std::lock_guard guard(m_rank->GetLock()); + + dpu_error_t ret; + // fast path, everything is aligned + if (((offset & mram_aligned_mod) == 0) && ((size & mram_aligned_mod) == 0)) { + const uint8_t *bytes = static_cast(buf); + ret = dpu_copy_to_mram(m_dpu, offset, bytes, size); + return ret == DPU_OK; + } + + // slow path + + // compute final_offset to start from and the final_size to use + uint32_t final_offset = offset & mram_aligned_mask; + size_t padding = offset & mram_aligned_mod; + size_t final_size = (size + padding + mram_aligned_mod) & mram_aligned_mask; + + // allocation the buffer of mram to read/write from + uint8_t *bytes = new uint8_t[final_size]; + if (bytes == NULL) + return false; + + ret = dpu_copy_from_mram(m_dpu, bytes, final_offset, final_size); + if (ret != DPU_OK) { + delete[] bytes; + return false; + } + + memcpy(&((uint8_t *)bytes)[padding], buf, size); + + ret = dpu_copy_to_mram(m_dpu, final_offset, bytes, final_size); + + delete[] bytes; + return ret == DPU_OK; +} + +bool Dpu::WriteMRAM(uint32_t offset, const void *buf, size_t size) { + uint32_t locationInMRAM = offset; + size_t pointerOffsetBuf = 0; + size_t offsetToAlignLocation = mram_aligned - (locationInMRAM % mram_aligned); + + // align addr + if ((offsetToAlignLocation != mram_aligned) && (offsetToAlignLocation < size)) { + if (!WriteMRAMHandlingAlignment(locationInMRAM, buf, offsetToAlignLocation)) { + return false; + } + locationInMRAM += offsetToAlignLocation; + size -= offsetToAlignLocation; + pointerOffsetBuf += offsetToAlignLocation; + } + + // align size + size_t sizeToAlignSize = size % mram_aligned; + if (sizeToAlignSize != 0) { + const void *localBufPointer = (static_cast(buf) + + pointerOffsetBuf + (size - sizeToAlignSize)); + + if (!WriteMRAMHandlingAlignment((locationInMRAM + size) - sizeToAlignSize, + localBufPointer, sizeToAlignSize)) { + return false; + } + size -= sizeToAlignSize; + } + + const void *localBufPointer = static_cast(buf) + pointerOffsetBuf; + return WriteMRAMHandlingAlignment(locationInMRAM, localBufPointer, size); +} + +bool Dpu::ReadMRAM(uint32_t offset, void *buf, size_t size) { + std::lock_guard guard(m_rank->GetLock()); + uint8_t *bytes = static_cast(buf); + dpu_error_t ret; + + const uint32_t padding = offset & mram_aligned_mod; + size_t final_size = (size + mram_aligned_mod + padding) & mram_aligned_mask; + + if (final_size != size) { + const uint32_t final_offset = offset & mram_aligned_mask; + bytes = new uint8_t[final_size]; + if (bytes == NULL) + return false; + + ret = dpu_copy_from_mram(m_dpu, bytes, final_offset, final_size); + memcpy(buf, &bytes[padding], size); + delete[] bytes; + } else { + ret = dpu_copy_from_mram(m_dpu, bytes, offset, size); + } + + return ret == DPU_OK; +} + +bool Dpu::AllocIRAMBuffer(uint8_t **iram, uint32_t *iram_size) { + dpu_description_t description = dpu_get_description(dpu_get_rank(m_dpu)); + uint32_t nb_instructions = description->hw.memories.iram_size; + *iram_size = nb_instructions * sizeof(dpuinstruction_t); + *iram = new uint8_t[*iram_size]; + return *iram != NULL; +} + +bool Dpu::FreeIRAMBuffer(uint8_t *iram) { + delete[] iram; + return true; +} + +bool Dpu::GenerateSaveCore(const char *exe_path, const char *core_file_path, + uint8_t *iram, uint32_t iram_size) { + struct dpu_rank_t *rank = dpu_get_rank(m_dpu); + dpu_description_t description = dpu_get_description(rank); + uint32_t nb_word_in_wram = description->hw.memories.wram_size; + uint32_t wram_size = nb_word_in_wram * sizeof(dpuword_t); + uint32_t mram_size = description->hw.memories.mram_size; + uint8_t *wram = new uint8_t[wram_size]; + uint8_t *mram = new uint8_t[mram_size]; + + dpu_error_t status; + if (wram != NULL && mram != NULL) { + status = dpu_copy_from_wram_for_dpu(m_dpu, (dpuword_t *)wram, 0, + nb_word_in_wram); + if (status != DPU_OK) + goto dpu_generate_save_core_exit; + status = dpu_copy_from_mram(m_dpu, mram, 0, mram_size); + if (status != DPU_OK) + goto dpu_generate_save_core_exit; + + status = + dpu_create_core_dump(rank, exe_path, core_file_path, m_context->Get(), + wram, mram, iram, wram_size, mram_size, iram_size); + if (status != DPU_OK) + goto dpu_generate_save_core_exit; + + } else { + status = DPU_ERR_SYSTEM; + } + +dpu_generate_save_core_exit: + delete[] wram; + delete[] mram; + + return status; +} + +uint32_t *Dpu::ThreadContextRegs(int thread_index) { + return m_context->Get()->registers + thread_index * nr_reg_per_thread; +} + +uint16_t *Dpu::ThreadContextPC(int thread_index) { + return m_context->Get()->pcs + thread_index; +} + +bool *Dpu::ThreadContextZF(int thread_index) { + return m_context->Get()->zero_flags + thread_index; +} + +bool *Dpu::ThreadContextCF(int thread_index) { + return m_context->Get()->carry_flags + thread_index; +} + +bool *Dpu::ThreadRegistersHasBeenModified() { + return ®isters_has_been_modified; +} + +const std::string bkp_fault_description[10] = {"", + "Heap Full", + "Division by Zero", + "Assert", + "Halt", + "Printf Overflow", + "Already Profiling", + "Not Profiling", + "Wrong Alignment", + "Performance counter invalid"}; + +lldb::StateType Dpu::GetThreadState(uint32_t thread_index, + std::string &description, + lldb::StopReason &stop_reason, + bool stepping) { + stop_reason = eStopReasonNone; + struct dpu_context_t *context = m_context->Get(); + bool bkp_fault = context->bkp_fault; + bool dma_fault = context->dma_fault; + bool mem_fault = context->mem_fault; + dpu_thread_t bkp_fault_thread_index = context->bkp_fault_thread_index; + dpu_thread_t dma_fault_thread_index = context->dma_fault_thread_index; + dpu_thread_t mem_fault_thread_index = context->mem_fault_thread_index; + uint32_t bkp_fault_id = context->bkp_fault_id; + if (bkp_fault && bkp_fault_thread_index == thread_index) { + if (bkp_fault_id == 0) { + stop_reason = eStopReasonBreakpoint; + return eStateStopped; + } else { + description = "fault " + std::to_string(bkp_fault_id) + " (" + + bkp_fault_description[bkp_fault_id] + ")"; + stop_reason = eStopReasonException; + return eStateCrashed; + } + } else if (dma_fault && dma_fault_thread_index == thread_index) { + description = "dma fault"; + stop_reason = eStopReasonException; + return eStateCrashed; + } else if (mem_fault && mem_fault_thread_index == thread_index) { + description = "memory fault"; + stop_reason = eStopReasonException; + return eStateCrashed; + } else if (m_context->GetPcOfThread(thread_index) != 0 && + m_context->ScheduledThread(thread_index) && stepping) { + description = "stepping"; + stop_reason = eStopReasonTrace; + } else if (m_context->GetPcOfThread(thread_index) != 0 && stepping) { + description = "stopped"; + stop_reason = eStopReasonTrace; + } + + if (!m_context->ScheduledThread(thread_index)) { + return eStateSuspended; + } else { + return eStateStopped; + } +} + +unsigned int Dpu::GetSliceID() { return dpu_get_slice_id(m_dpu); } + +unsigned int Dpu::GetDpuID() { return dpu_get_member_id(m_dpu); } + +void Dpu::SetAttachSession() { attach_session = true; } + +bool Dpu::AttachSession() { return attach_session; } + +bool Dpu::PrintfEnable() { return printf_enable; } + +lldb::addr_t Dpu::GetOpenPrintfSequenceAddr() { + return open_print_sequence_addr; +} +lldb::addr_t Dpu::GetClosePrintfSequenceAddr() { + return close_print_sequence_addr; +} diff --git a/lldb/source/Plugins/Process/Dpu/Dpu.h b/lldb/source/Plugins/Process/Dpu/Dpu.h new file mode 100644 index 0000000000000..53dc26a8e367d --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/Dpu.h @@ -0,0 +1,138 @@ +//===-- Dpu.h ------------------------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Dpu_H_ +#define liblldb_Dpu_H_ + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "DpuContext.h" + +extern "C" { +#include +} + +namespace lldb_private { +namespace dpu { + +class DpuRank; + +class Dpu { +public: + Dpu(DpuRank *rank, dpu_t *dpu, FILE *stdout_fd, bool valid); + ~Dpu(); + + bool SetPrintfSequenceAddrs(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_var_addr); + bool SetPrintfSequenceAddrsFromRuntimeInfo(dpu_program_t *runtime); + bool SetErrorStoreAddr(const uint32_t error_store_addr); + bool SetErrorStoreAddrFromRuntimeInfo(dpu_program_t *runtime); + + bool LoadElf(const FileSpec &elf_file_path); + bool Boot(); + + lldb::StateType + StepOverPrintfSequenceAndContinue(lldb::StateType result_state, + unsigned int *exit_status); + lldb::StateType PollStatus(unsigned int *exit_status); + + enum eResumeThreadsType { + eResumeThreadsSuccess, + eResumeThreadsError, + eResumeThreadsInFault, // ie: The threads were in fault before the resume. + }; + eResumeThreadsType ResumeThreads(llvm::SmallVector *resume_list, + bool allowed_polling = true); + bool StopThreads(bool force = false); + + bool + PrepareStepOverPrintfBkp(const uint32_t thread_index, + dpuinstruction_t &inst_to_restore_if_printf_enable, + dpuinstruction_t &inst_to_replace_with, + const uint32_t current_pc); + lldb::StateType StepThread(uint32_t thread_index, unsigned int *exit_status); + + bool WriteWRAM(uint32_t offset, const void *buf, size_t size); + bool ReadWRAM(uint32_t offset, void *buf, size_t size); + bool WriteIRAM(uint32_t offset, const void *buf, size_t size); + bool ReadIRAM(uint32_t offset, void *buf, size_t size); + bool WriteMRAM(uint32_t offset, const void *buf, size_t size); + bool ReadMRAM(uint32_t offset, void *buf, size_t size); + + bool AllocIRAMBuffer(uint8_t **iram, uint32_t *iram_size); + bool FreeIRAMBuffer(uint8_t *iram); + bool GenerateSaveCore(const char *exe_path, const char *core_file_path, + uint8_t *iram, uint32_t iram_size); + + int GetNrThreads() { return nr_threads; } + void SetNrThreads(int _nr_threads) { nr_threads = _nr_threads; } + + uint32_t *ThreadContextRegs(int thread_index); + uint16_t *ThreadContextPC(int thread_index); + bool *ThreadContextZF(int thread_index); + bool *ThreadContextCF(int thread_index); + bool *ThreadRegistersHasBeenModified(); + + lldb::StateType GetThreadState(uint32_t thread_index, + std::string &description, + lldb::StopReason &stop_reason, bool stepping); + + unsigned int GetSliceID(); + unsigned int GetDpuID(); + + void SetAttachSession(); + bool AttachSession(); + + bool PrintfEnable(); + lldb::addr_t GetOpenPrintfSequenceAddr(); + lldb::addr_t GetClosePrintfSequenceAddr(); + +private: + bool WriteWRAMHandlingAlignment(uint32_t offset, const void *buf, size_t size); + bool WriteMRAMHandlingAlignment(uint32_t offset, const void *buf, size_t size); + + bool WriteIRAMUntraced(uint32_t offset, const void *buf, size_t size); + + DpuRank *m_rank; + dpu_t *m_dpu; + int nr_threads; + uint32_t nr_reg_per_thread; + DpuContext *m_context; + bool dpu_is_running = false; + bool attach_session = false; + bool registers_has_been_modified = false; + bool printf_enable = false; + lldb::addr_t open_print_sequence_addr, close_print_sequence_addr; + dpuinstruction_t open_print_sequence_inst, close_print_sequence_inst; + uint32_t printf_buffer_last_idx, printf_buffer_var_addr, + printf_buffer_address, printf_buffer_size; + uint32_t error_store_addr; + FILE *stdout_file; + bool m_valid; +}; +} // namespace dpu +} // namespace lldb_private + +#endif // liblldb_Dpu_H_ diff --git a/lldb/source/Plugins/Process/Dpu/DpuContext.cpp b/lldb/source/Plugins/Process/Dpu/DpuContext.cpp new file mode 100644 index 0000000000000..e1cd9f51391b7 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/DpuContext.cpp @@ -0,0 +1,202 @@ +//===-- DpuContext.cpp ---------------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DpuContext.h" + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "RegisterContextDpu.h" + +extern "C" { +#include +#include +} + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::dpu; + +// ----------------------------------------------------------------------------- +// DPU context handling +// ----------------------------------------------------------------------------- + +DpuContext::DpuContext(dpu_t *dpu, struct dpu_context_t *context, + uint32_t _nr_threads) + : m_dpu(dpu), m_context(context), nr_threads(_nr_threads) { + running_threads = new uint8_t[nr_threads]; + last_resume_threads = new uint8_t[nr_threads]; + for (unsigned int each_thread = 1; each_thread < nr_threads; each_thread++) { + running_threads[each_thread] = 0xff; + last_resume_threads[each_thread] = 0xff; + } + running_threads[0] = 0; + last_resume_threads[0] = 0; + + m_context->bkp_fault = false; + m_context->dma_fault = false; + m_context->mem_fault = false; +} + +DpuContext::~DpuContext() { + dpu_free_dpu_context(m_context); + delete m_context; + delete[] running_threads; + delete[] last_resume_threads; +} + +struct dpu_context_t *DpuContext::Get() { + return m_context; +} + +void DpuContext::UpdateContext(struct dpu_context_t *new_context) { + dpu_free_dpu_context(m_context); + delete m_context; + m_context = new_context; + UpdateRunningThreads(); +} + +void DpuContext::UpdateRunningThreads() { + for (unsigned int each_thread = 0; each_thread < nr_threads; each_thread++) { + if ((m_context->scheduling[each_thread] == 0xff) != + (last_resume_threads[each_thread] == 0xff)) { + running_threads[each_thread] = m_context->scheduling[each_thread]; + } + } +} + +bool DpuContext::StopThreads(uint32_t error_store_addr) { + ResetScheduling(); + + int ret = DPU_OK; + ret = + dpu_initialize_fault_process_for_dpu(m_dpu, m_context, error_store_addr); + if (ret != DPU_OK) + return false; + ret = dpu_extract_context_for_dpu(m_dpu, m_context); + + UpdateRunningThreads(); + + return ret == DPU_OK; +} + +bool DpuContext::ResumeThreads(llvm::SmallVector *resume_list) { + ResetScheduling(); + ResetLastResumeThreads(); + + if (resume_list == NULL) { + for (unsigned int each_thread = 0; each_thread < nr_threads; + each_thread++) { + if (!AddThreadInScheduling(each_thread)) { + return false; + } + } + } else { + for (auto thread_id : *resume_list) { + if (!AddThreadInScheduling(thread_id)) { + return false; + } + } + } + + return dpu_finalize_fault_process_for_dpu(m_dpu, m_context) == DPU_OK; +} + +dpu_error_t DpuContext::StepThread(uint32_t thread_index) { + ResetScheduling(); + ResetLastResumeThreads(); + AddThreadInScheduling(thread_index); + + dpu_error_t ret = + dpu_execute_thread_step_in_fault_for_dpu(m_dpu, thread_index, m_context); + if (ret != DPU_OK) + return ret; + ret = dpu_extract_context_for_dpu(m_dpu, m_context); + + UpdateRunningThreads(); + + return ret; +} + +unsigned int DpuContext::GetExitStatus() { + return m_context->registers[lldb_private::r0_dpu]; +} + +lldb::addr_t DpuContext::GetPcOfThread(dpu_thread_t thread) { + return InstIdx2InstAddr(m_context->pcs[thread]); +} + +bool DpuContext::ScheduledThread(uint32_t thread) { + return running_threads[thread] != 0xff; +} + +bool DpuContext::ContextReadyForResumeOrStep() { + m_context->bkp_fault = false; + return !(m_context->dma_fault || m_context->mem_fault); +} + +bool DpuContext::AddThreadInScheduling(unsigned int thread) { + // If the thread was not running, it can't be added in the scheduling list + if (running_threads[thread] == 0xff) { + return true; + } + + if (m_context->nr_of_running_threads >= nr_threads) + return false; + + last_resume_threads[thread] = m_context->nr_of_running_threads; + m_context->scheduling[thread] = m_context->nr_of_running_threads; + m_context->nr_of_running_threads++; + return true; +} + +void DpuContext::ResetScheduling() { + m_context->nr_of_running_threads = 0; + for (dpu_thread_t each_thread = 0; each_thread < nr_threads; ++each_thread) { + m_context->scheduling[each_thread] = 0xff; + } +} + +void DpuContext::ResetLastResumeThreads() { + for (dpu_thread_t each_thread = 0; each_thread < nr_threads; ++each_thread) { + last_resume_threads[each_thread] = 0xff; + } +} + +bool DpuContext::DpuIsRunning(int nr_running_threads) { + for (int each_thread = 0; each_thread < nr_running_threads; each_thread++) { + if (running_threads[each_thread] != 0xff) + return true; + } + return false; +} + +bool DpuContext::RestoreFaultContext() { + for (dpu_thread_t each_thread = 0; each_thread < nr_threads; ++each_thread) { + if (m_context->scheduling[each_thread] == + m_context->nr_of_running_threads - 1) { + m_context->scheduling[each_thread] = 0; + } else if (m_context->scheduling[each_thread] != 0xff) { + m_context->scheduling[each_thread]++; + } + } + return dpu_finalize_fault_process_for_dpu(m_dpu, m_context) == DPU_OK; +} diff --git a/lldb/source/Plugins/Process/Dpu/DpuContext.h b/lldb/source/Plugins/Process/Dpu/DpuContext.h new file mode 100644 index 0000000000000..d78d3719e29a6 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/DpuContext.h @@ -0,0 +1,81 @@ +//===-- DpuContext.h ----------------------------------------- -*- C++ -*- ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DpuContext_H_ +#define liblldb_DpuContext_H_ + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +#include "ProcessDpu.h" + +extern "C" { +#include +#include +} + +namespace lldb_private { +namespace dpu { + +static inline lldb::addr_t InstIdx2InstAddr(lldb::addr_t nb_of_inst) { + return (nb_of_inst * sizeof(dpuinstruction_t)) | k_dpu_iram_base; +} + +class DpuContext { +public: + DpuContext(dpu_t *dpu, struct dpu_context_t *context, uint32_t nr_threads); + ~DpuContext(); + + struct dpu_context_t *Get(); + + void UpdateContext(struct dpu_context_t *new_context); + + bool StopThreads(uint32_t error_store_addr); + bool ResumeThreads(llvm::SmallVector *resume_list); + dpu_error_t StepThread(uint32_t thread_index); + + unsigned int GetExitStatus(); + lldb::addr_t GetPcOfThread(dpu_thread_t thread); + + bool ScheduledThread(uint32_t thread); + bool ContextReadyForResumeOrStep(); + + bool DpuIsRunning(int nr_running_threads); + + bool RestoreFaultContext(); + +private: + bool AddThreadInScheduling(unsigned int thread); + void ResetScheduling(); + void ResetLastResumeThreads(); + void UpdateRunningThreads(); + + dpu_t *m_dpu; + struct dpu_context_t *m_context; + uint32_t nr_threads; + uint8_t *running_threads; + uint8_t *last_resume_threads; +}; + +} // namespace dpu +} // namespace lldb_private + +#endif // liblldb_DpuContext_H_ diff --git a/lldb/source/Plugins/Process/Dpu/DpuRank.cpp b/lldb/source/Plugins/Process/Dpu/DpuRank.cpp new file mode 100644 index 0000000000000..ccacff124844f --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/DpuRank.cpp @@ -0,0 +1,150 @@ +//===-- DpuRank.cpp ------------------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "Dpu.h" +#include "DpuRank.h" + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +} + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::dpu; + +// ----------------------------------------------------------------------------- +// DPU rank handling +// ----------------------------------------------------------------------------- + +DpuRank::DpuRank() : nr_threads(0), m_lock() { + m_rank = NULL; + stdout_fd = NULL; +} + +DpuRank::~DpuRank() { + while (!m_dpus.empty()) { + delete m_dpus.back(); + m_dpus.pop_back(); + } + dpu_free_rank(m_rank); + fclose(stdout_fd); +} + +bool DpuRank::Open(const char *profile, FILE *stdout_file, bool valid) { + std::lock_guard guard(m_lock); + + int ret = dpu_get_rank_of_type(profile, &m_rank); + if (ret != DPU_OK) + return false; + m_desc = dpu_get_description(m_rank); + + nr_threads = m_desc->hw.dpu.nr_of_threads; + + struct dpu_set_t rank = dpu_set_from_rank(&m_rank); + struct dpu_set_t dpu; + + DPU_FOREACH(rank, dpu) { + m_dpus.push_back(new Dpu(this, dpu.dpu, stdout_file, valid)); + } + + stdout_fd = stdout_file; + + return true; +} + +FILE *DpuRank::GetStdout() { return stdout_fd; } + +bool DpuRank::IsValid() { return m_rank ? true : false; } + +bool DpuRank::Reset() { + std::lock_guard guard(m_lock); + return dpu_reset_rank(m_rank) == DPU_OK; +} + +Dpu *DpuRank::GetDpuFromSliceIdAndDpuId(unsigned int slice_id, + unsigned int dpu_id) { + for (Dpu *dpu : m_dpus) { + if (dpu->GetSliceID() == slice_id && dpu->GetDpuID() == dpu_id) { + return dpu; + } + } + return nullptr; +} + +Dpu *DpuRank::GetDpu(size_t index) { + return index < m_dpus.size() ? m_dpus[index] : nullptr; +} + +bool DpuRank::SaveContext() { + return dpu_save_context_for_rank(m_rank) == DPU_OK; +} + +bool DpuRank::RestoreContext() { + return dpu_restore_context_for_rank(m_rank) == DPU_OK; +} + +bool DpuRank::RestoreMuxContext() { + return dpu_restore_mux_context_for_rank(m_rank) == DPU_OK; +} + +void DpuRank::SetSliceInfo(uint32_t slice_id, uint64_t structure_value, + uint64_t slice_target, + dpu_bitfield_t host_mux_mram_state) { + dpu_set_debug_slice_info(m_rank, slice_id, structure_value, slice_target, + host_mux_mram_state); +} + +struct dpu_context_t *DpuRank::AllocContext() { + struct dpu_context_t *context = new struct dpu_context_t; + if (dpu_context_fill_from_rank(context, m_rank) != DPU_OK) { + delete context; + return NULL; + } + return context; +} + +bool DpuRank::ResumeDpus() { + for (Dpu *dpu : m_dpus) { + if (dpu->ResumeThreads(NULL, false) == Dpu::eResumeThreadsError) + return false; + } + return true; +} + +bool DpuRank::StopDpus() { + for (Dpu *dpu : m_dpus) { + if (!dpu->StopThreads(true)) + return false; + } + return true; +} + +uint8_t DpuRank::GetNrCis() { + return dpu_get_description(m_rank)->hw.topology.nr_of_control_interfaces; +} diff --git a/lldb/source/Plugins/Process/Dpu/DpuRank.h b/lldb/source/Plugins/Process/Dpu/DpuRank.h new file mode 100644 index 0000000000000..19a6e7abb0b43 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/DpuRank.h @@ -0,0 +1,81 @@ +//===-- DpuRank.h -------------------------------------------- -*- C++ -*- ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DpuRank_H_ +#define liblldb_DpuRank_H_ + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include + +// Other libraries and framework includes +#include "lldb/Core/Module.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" + +extern "C" { +#include +#include +} + +#include "Dpu.h" + +namespace lldb_private { +namespace dpu { + +class DpuRank { +public: + DpuRank(); + ~DpuRank(); + bool Open(const char *profile, FILE *stdout_fd, bool valid = true); + bool IsValid(); + bool Reset(); + Dpu *GetDpu(size_t index); + + dpu_description_t GetDesc() { return m_desc; } + int GetNrThreads() { return nr_threads; } + std::recursive_mutex &GetLock() { return m_lock; } + + Dpu *GetDpuFromSliceIdAndDpuId(unsigned int slice_id, unsigned int dpu_id); + bool ResumeDpus(); + bool StopDpus(); + + bool SaveContext(); + bool RestoreContext(); + bool RestoreMuxContext(); + + void SetSliceInfo(uint32_t slice_id, uint64_t structure_value, + uint64_t slice_target, dpu_bitfield_t host_mux_mram_state); + + struct dpu_context_t *AllocContext(); + + uint8_t GetNrCis(); + + FILE *GetStdout(); + +private: + dpu_rank_t *m_rank; + dpu_description_t m_desc; + int nr_threads; + std::recursive_mutex + m_lock; /* protect rank resources including the comm channel */ + std::vector m_dpus; + FILE *stdout_fd; +}; + +} // namespace dpu +} // namespace lldb_private + +#endif // liblldb_DpuRank_H_ diff --git a/lldb/source/Plugins/Process/Dpu/ProcessDpu.cpp b/lldb/source/Plugins/Process/Dpu/ProcessDpu.cpp new file mode 100644 index 0000000000000..c3e63b6912e0f --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/ProcessDpu.cpp @@ -0,0 +1,762 @@ +//===-- ProcessDpu.cpp -------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ProcessDpu.h" + +// C Includes +#include +#include +#include +#include + +// C++ Includes +#include +#include +#include +#include + +// Other libraries and framework includes +#include "dpu_types.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/File.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostProcess.h" +#include "lldb/Host/ProcessLaunchInfo.h" +#include "lldb/Host/PseudoTerminal.h" +#include "lldb/Host/ThreadLauncher.h" +#include "lldb/Host/common/NativeRegisterContext.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/State.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/StringExtractor.h" +#include "llvm/Support/Errno.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Threading.h" + +#include "DpuRank.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "ThreadDpu.h" + +#include +#include /* TODO only exists on Linux */ +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::dpu; +using namespace lldb_private::process_dpu; +using namespace llvm; + +LLDB_PLUGIN_DEFINE(ProcessDpu) + +namespace { +// Control interface polling period +const long k_ci_polling_interval_ns = 10000; /* ns */ +} // end of anonymous namespace + +// ----------------------------------------------------------------------------- +// Public Static Methods +// ----------------------------------------------------------------------------- + +extern "C" { +// Function of libdpuverbose to force all output of the dpu libraries to be by +// redirect in the given file +extern void set_verbose_output_file(FILE *); +} + +llvm::Expected> +ProcessDpu::Factory::Launch(ProcessLaunchInfo &launch_info, + NativeDelegate &native_delegate, + MainLoop &mainloop) const { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + int terminal_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor(); + if (terminal_fd == PseudoTerminal::invalid_fd) { + terminal_fd = open( + launch_info.GetFileActionForFD(STDOUT_FILENO)->GetPath().str().c_str(), + O_RDWR); + } + + FILE *stdout_fd = fdopen(terminal_fd, "w"); + if (stdout_fd == NULL) { + return Status("Cannot open terminal_fd ").ToError(); + } + + // propagate sub-process stdout to host + fflush(stdout); + stdout = stdout_fd; + + bool verbose_set = getenv("UPMEM_VERBOSE") != NULL; + if (!verbose_set) { + set_verbose_output_file(stdout_fd); + } + + DpuRank *rank = new DpuRank(); + bool success = rank->Open(NULL, stdout_fd); + if (!success && !verbose_set) { + fprintf(stdout_fd, "***********************************************\n" + "*** dpu-lldb: Could not allocate a DPU rank ***\n" + "***********************************************\n"); + setenv("UPMEM_PROFILE", "", true); + success = rank->Open("backend=simulator", stdout_fd, false); + } + if (!success) + return Status("Cannot get a DPU rank ").ToError(); + + success = rank->Reset(); + if (!success) + return Status("Cannot reset DPU rank ").ToError(); + + Dpu *dpu = rank->GetDpu(0); + success = dpu->LoadElf(launch_info.GetExecutableFile()); + if (!success) + return Status("Cannot load Elf in DPU rank ").ToError(); + + success = dpu->Boot(); + if (!success) + return Status("Cannot boot DPU rank ").ToError(); + + ::pid_t pid = 666 << 5; // TODO unique Rank ID + LLDB_LOG(log, "Dpu Rank {0}", pid); + + return std::unique_ptr(new ProcessDpu( + pid, terminal_fd, native_delegate, k_dpu_arch, mainloop, rank, dpu)); +} + +#define SLICE_DELIM ":" +#define VALUE_DELIM "&" +#define PARSE_ENV(env_var, nr_cis, buffer) \ + do { \ + char *_PARSE_ENV_env = std::getenv(env_var); \ + if (_PARSE_ENV_env == NULL) { \ + break; \ + } \ + char *_PARSE_ENV_ptr = strtok(_PARSE_ENV_env, SLICE_DELIM); \ + if (_PARSE_ENV_ptr == NULL) { \ + break; \ + } \ + do { \ + uint32_t _PARSE_ENV_slice_id = ::strtoll(_PARSE_ENV_ptr, NULL, 10); \ + _PARSE_ENV_ptr = strtok(NULL, VALUE_DELIM); \ + if (_PARSE_ENV_ptr == NULL) { \ + return Status("Could not parse " env_var " correctly ").ToError(); \ + } \ + buffer[_PARSE_ENV_slice_id] = ::strtoll(_PARSE_ENV_ptr, NULL, 10); \ + } while ((_PARSE_ENV_ptr = strtok(NULL, SLICE_DELIM)) != NULL); \ + } while (0) + +llvm::Expected> +ProcessDpu::Factory::Attach( + lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate, + MainLoop &mainloop) const { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "attaching to pid = {0:x}", pid); + + unsigned int rank_id, slice_id, dpu_id; + dpu_id = pid % 100; + slice_id = (pid / 100) % 100; + rank_id = (pid / (100 * 100)) % 100; + + char rank_path[128]; + sprintf(rank_path, "/dev/dpu_rank%u", rank_id); + + if (access(rank_path, F_OK) != 0) { + return Status("'%s' does not exist. Run 'dpu-diag' for a full diagnostic ", + rank_path) + .ToError(); + } + + char profile[256]; + sprintf(profile, "backend=hw,rankPath=%s,ignoreVpd=true", rank_path); + + PseudoTerminal pseudo_terminal; + if (pseudo_terminal.OpenFirstAvailablePrimary(O_RDWR | O_NOCTTY)) { + return Status("Cannot open first available master on pseudo terminal ") + .ToError(); + } + + int terminal_fd = pseudo_terminal.ReleasePrimaryFileDescriptor(); + if (terminal_fd == -1) { + return Status("Cannot release master file descriptor ").ToError(); + } + + FILE *stdout_fd = fdopen(terminal_fd, "w"); + if (stdout_fd == NULL) { + return Status("Cannot open terminal_fd ").ToError(); + } + + bool verbose_set = getenv("UPMEM_VERBOSE") != NULL; + if (!verbose_set) { + set_verbose_output_file(stdout_fd); + } + + DpuRank *rank = new DpuRank(); + bool success = rank->Open(profile, stdout_fd); + if (!success) + return Status("Cannot get a DPU rank ").ToError(); + + Dpu *dpu = rank->GetDpuFromSliceIdAndDpuId(slice_id, dpu_id); + if (dpu == nullptr) + return Status("Cannot find the DPU in the rank ").ToError(); + + char *nr_tasklets_ptr = std::getenv("UPMEM_LLDB_NR_TASKLETS"); + + if (nr_tasklets_ptr != NULL) + dpu->SetNrThreads(::strtoll(nr_tasklets_ptr, NULL, 10)); + + char *error_store_addr_ptr = std::getenv("UPMEM_LLDB_ERROR_STORE_ADDR"); + + if (error_store_addr_ptr != NULL) + dpu->SetErrorStoreAddr(::strtol(error_store_addr_ptr, NULL, 16)); + + success = rank->SaveContext(); + if (!success) + return Status("Cannot save the rank context ").ToError(); + + uint8_t nr_cis = rank->GetNrCis(); + uint64_t *structures_value = new uint64_t[nr_cis]; + uint64_t *slices_target = new uint64_t[nr_cis]; + dpu_bitfield_t *host_muxs_mram_state = new dpu_bitfield_t[nr_cis]; + memset(structures_value, 0, sizeof(uint64_t) * nr_cis); + memset(slices_target, 0, sizeof(uint64_t) * nr_cis); + memset(host_muxs_mram_state, 0, sizeof(dpu_bitfield_t) * nr_cis); + PARSE_ENV("UPMEM_LLDB_STRUCTURES_VALUE", nr_cis, structures_value); + PARSE_ENV("UPMEM_LLDB_SLICES_TARGET", nr_cis, slices_target); + PARSE_ENV("UPMEM_LLDB_HOST_MUXS_MRAM_STATE", nr_cis, host_muxs_mram_state); + + for (uint32_t each_ci = 0; each_ci < nr_cis; each_ci++) { + rank->SetSliceInfo(each_ci, structures_value[each_ci], + slices_target[each_ci], host_muxs_mram_state[each_ci]); + LLDB_LOG(log, "saving slice context ([{0}]: {1:x}, {2:x}, {3:x})", each_ci, + structures_value[each_ci], slices_target[each_ci], + host_muxs_mram_state[each_ci]); + } + delete[] structures_value; + delete[] slices_target; + delete[] host_muxs_mram_state; + + success = rank->StopDpus(); + if (!success) + return Status("Cannot stop the rank ").ToError(); + + dpu->SetAttachSession(); + + return std::unique_ptr(new ProcessDpu( + pid, terminal_fd, native_delegate, k_dpu_arch, mainloop, rank, dpu)); +} + +lldb_private::ConstString ProcessDpu::GetPluginNameStatic() { + static ConstString g_name("dpu"); + return g_name; +} + +const char *ProcessDpu::GetPluginDescriptionStatic() { return "dpu plug-in."; } + +lldb::ProcessSP ProcessDpu::CreateInstance( + lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path, bool can_connect) { + lldb::ProcessSP process_sp; + return process_sp; +} + +void ProcessDpu::Initialize() { + static llvm::once_flag g_once_flag; + + llvm::call_once(g_once_flag, []() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), + ProcessDpu::CreateInstance); + }); +} + +void ProcessDpu::Terminate() { + // TODO: Work out if it is safe to do this. + PluginManager::UnregisterPlugin(ProcessDpu::CreateInstance); +} + +// ----------------------------------------------------------------------------- +// Public Instance Methods +// ----------------------------------------------------------------------------- + +ProcessDpu::~ProcessDpu() { + delete m_rank; +} + +llvm::Expected> +ProcessDpu::GetSoftwareBreakpointTrapOpcode(size_t size_hint) { + static const uint8_t g_dpu_opcode[] = { 0x00, 0x00,0x00, 0x20,0x63,0x7e,0x00,0x00}; + switch (GetArchitecture().GetMachine()) { + case llvm::Triple::dpu: + return llvm::makeArrayRef(g_dpu_opcode); + default: + return NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_hint); + } +} + +ProcessDpu::ProcessDpu(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop, DpuRank *rank, + Dpu *dpu) + : NativeProcessProtocol(pid, terminal_fd, delegate), m_arch(arch), + m_dpu(dpu), m_rank(rank) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + + // Set the timer for polling the CI + LLDB_LOG(log, "Setting timer of polling the CI"); + struct itimerspec polling_spec; + polling_spec.it_value.tv_sec = 0; + polling_spec.it_value.tv_nsec = k_ci_polling_interval_ns; + polling_spec.it_interval.tv_sec = 0; + polling_spec.it_interval.tv_nsec = k_ci_polling_interval_ns; + int tfd = timerfd_create(CLOCK_MONOTONIC, 0); + assert(tfd != -1); + m_timer_fd.reset(new NativeFile(tfd, File::eOpenOptionRead, true)); + + Status status; + m_timer_handle = mainloop.RegisterReadObject( + m_timer_fd, [this](MainLoopBase &) { InterfaceTimerCallback(); }, status); + timerfd_settime(tfd, 0, &polling_spec, nullptr); + assert(m_timer_handle && status.Success()); + + for (int thread_id = 0; thread_id < m_dpu->GetNrThreads(); thread_id++) { + m_threads.push_back( + std::make_unique(*this, pid + thread_id, thread_id)); + } + + dpu_description_t desc = rank->GetDesc(); + m_iram_size = desc->hw.memories.iram_size * sizeof(dpuinstruction_t); + m_mram_size = desc->hw.memories.mram_size; + m_wram_size = desc->hw.memories.wram_size * sizeof(dpuword_t); + + if (dpu->PrintfEnable()) { + SetSoftwareBreakpoint(dpu->GetOpenPrintfSequenceAddr() | k_dpu_iram_base, + 8); + SetSoftwareBreakpoint(dpu->GetClosePrintfSequenceAddr() | k_dpu_iram_base, + 8); + } + + SetCurrentThreadID(pid); + SetState(StateType::eStateStopped, false); + + m_iram_region.GetRange().SetRangeBase(k_dpu_iram_base); + m_iram_region.GetRange().SetRangeEnd(k_dpu_iram_base + m_iram_size); + m_iram_region.SetReadable(MemoryRegionInfo::eYes); + m_iram_region.SetWritable(MemoryRegionInfo::eYes); + m_iram_region.SetExecutable(MemoryRegionInfo::eYes); + m_iram_region.SetMapped(MemoryRegionInfo::eYes); + + m_mram_region.GetRange().SetRangeBase(k_dpu_mram_base); + m_mram_region.GetRange().SetRangeEnd(k_dpu_mram_base + m_mram_size); + m_mram_region.SetReadable(MemoryRegionInfo::eYes); + m_mram_region.SetWritable(MemoryRegionInfo::eYes); + m_mram_region.SetExecutable(MemoryRegionInfo::eNo); + m_mram_region.SetMapped(MemoryRegionInfo::eYes); + + m_wram_region.GetRange().SetRangeBase(k_dpu_wram_base); + m_wram_region.GetRange().SetRangeEnd(k_dpu_wram_base + m_wram_size); + m_wram_region.SetReadable(MemoryRegionInfo::eYes); + m_wram_region.SetWritable(MemoryRegionInfo::eYes); + m_wram_region.SetExecutable(MemoryRegionInfo::eNo); + m_wram_region.SetMapped(MemoryRegionInfo::eYes); +} + +void ProcessDpu::InterfaceTimerCallback() { + unsigned int exit_status; + StateType current_state = m_dpu->PollStatus(&exit_status); + if (current_state != StateType::eStateInvalid) { + if (current_state == StateType::eStateExited) { + if (m_dpu->AttachSession()) { + Detach(); + } + SetExitStatus(WaitStatus(WaitStatus::Exit, (uint8_t)exit_status), true); + } + SetState(current_state, true); + } +} + +bool ProcessDpu::SupportHardwareSingleStepping() const { return true; } + +bool ProcessDpu::StepThread(uint32_t thread_id) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + unsigned int exit_status; + lldb::StateType ret_state_type; + LLDB_LOG(log, "stepping thread {0}", thread_id); + ret_state_type = m_dpu->StepThread(thread_id, &exit_status); + if (ret_state_type == lldb::StateType::eStateExited) + SetExitStatus(WaitStatus(WaitStatus::Exit, (uint8_t)exit_status), true); + if (ret_state_type != StateType::eStateStopped) { + SetState(ret_state_type, true); + return false; + } + return true; +} + +Status ProcessDpu::Resume(const ResumeActionList &resume_actions) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + llvm::SmallVector resume_list, stepping_list; + + for (const auto &thread : m_threads) { + lldb::tid_t tid = thread->GetID(); + ThreadDpu *current_thread = GetThreadByID(tid); + const ResumeAction *action = resume_actions.GetActionForThread(tid, true); + if (action == NULL) { + current_thread->SetSteppingMode(false); + continue; + } + switch (action->state) { + case lldb::StateType::eStateRunning: + resume_list.push_back(current_thread->GetIndex()); + current_thread->SetSteppingMode(false); + break; + case lldb::StateType::eStateStepping: + stepping_list.push_back(current_thread->GetIndex()); + current_thread->SetSteppingMode(true); + break; + default: + return DpuErrorStatus("Resume: Unexpected action!"); + } + } + LLDB_LOG(log, "{0} to resume {1} to step", resume_list.size(), + stepping_list.size()); + + if (stepping_list.empty()) { + if (resume_list.empty()) { + return DpuErrorStatus("Resume: No Action to perform"); + } + SetState(lldb::StateType::eStateRunning, true); + LLDB_LOG(log, "resuming threads"); + if (m_dpu->ResumeThreads(&resume_list) != dpu::Dpu::eResumeThreadsSuccess) + return DpuErrorStatus("Resume: Error while resuming threads"); + } else { + SetState(lldb::StateType::eStateStepping, true); + for (auto thread_id : resume_list) { + if (!StepThread(thread_id)) + return Status(); + } + for (auto thread_id : stepping_list) { + if (!StepThread(thread_id)) + return Status(); + } + SetState(StateType::eStateStopped, true); + } + + return Status(); +} + +Status ProcessDpu::Halt() { + Status error; + + return error; +} + +Status ProcessDpu::Detach() { + Status error; + bool success; + + if (m_dpu->PrintfEnable()) { + RemoveSoftwareBreakpoint(m_dpu->GetOpenPrintfSequenceAddr() | + k_dpu_iram_base); + RemoveSoftwareBreakpoint(m_dpu->GetClosePrintfSequenceAddr() | + k_dpu_iram_base); + } + + success = m_rank->RestoreMuxContext(); + if (!success) + return DpuErrorStatus("Detach: Cannot restore the muxs context"); + + success = m_rank->ResumeDpus(); + if (!success) + return DpuErrorStatus("Detach: Cannot resume DPUs"); + + success = m_rank->RestoreContext(); + if (!success) + return DpuErrorStatus("Detach: Cannot restore the rank context context"); + + return error; +} + +Status ProcessDpu::Signal(int signo) { + Status error; + + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "sending signal {0} ({1}) to pid {1}", signo, + Host::GetSignalAsCString(signo), GetID()); + + return error; +} + +Status ProcessDpu::Interrupt() { + if (!m_dpu->StopThreads()) + return DpuErrorStatus("Cannot interrupt DPU"); + SetState(StateType::eStateStopped, true); + return Status(); +} + +Status ProcessDpu::Kill() { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_PROCESS)); + LLDB_LOG(log, "pid {0}", GetID()); + + Status error; + + switch (m_state) { + case StateType::eStateInvalid: + case StateType::eStateExited: + case StateType::eStateCrashed: + case StateType::eStateDetached: + case StateType::eStateUnloaded: + // Nothing to do - the process is already dead. + LLDB_LOG(log, "ignored for PID {0} due to current state: {1}", GetID(), + m_state); + return error; + + case StateType::eStateConnected: + case StateType::eStateAttaching: + case StateType::eStateLaunching: + case StateType::eStateStopped: + case StateType::eStateRunning: + case StateType::eStateStepping: + case StateType::eStateSuspended: + Detach(); + // We can try to kill a process in these states. + break; + } + + // TODO: kill it + + return error; +} + +Status ProcessDpu::GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) { + if (m_wram_region.GetRange().Contains(load_addr)) { + range_info = m_wram_region; + } else if (m_mram_region.GetRange().Contains(load_addr)) { + range_info = m_mram_region; + } else if (m_iram_region.GetRange().Contains(load_addr)) { + range_info = m_iram_region; + } else { + range_info.GetRange().SetRangeBase(load_addr); + range_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS); + range_info.SetReadable(MemoryRegionInfo::eNo); + range_info.SetWritable(MemoryRegionInfo::eNo); + range_info.SetExecutable(MemoryRegionInfo::eNo); + range_info.SetMapped(MemoryRegionInfo::eNo); + } + + return Status(); +} + +llvm::Expected ProcessDpu::AllocateMemory(size_t size, + uint32_t permissions) { + // return DpuErrorStatus("AllocateMemory: not implemented"); + return llvm::make_error(); +} + +llvm::Error ProcessDpu::DeallocateMemory(lldb::addr_t addr) { + // return DpuErrorStatus("DeallocateMemory: not implemented"); + return llvm::make_error(); +} + +lldb::addr_t ProcessDpu::GetSharedLibraryInfoAddress() { + // punt on this for now + return LLDB_INVALID_ADDRESS; +} + +size_t ProcessDpu::UpdateThreads() { return m_threads.size(); } + +Status ProcessDpu::SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) { + if (hardware) + return SetHardwareBreakpoint(addr, size); + else + return SetSoftwareBreakpoint(addr, size); +} + +Status ProcessDpu::RemoveBreakpoint(lldb::addr_t addr, bool hardware) { + if (hardware) + return RemoveHardwareBreakpoint(addr); + else + return NativeProcessProtocol::RemoveBreakpoint(addr); +} + +ProcessDpu::eMemoryAddressSpace +ProcessDpu::ComputeMemoryAddressSpace(lldb::addr_t addr, size_t size) { + if (addr >= k_dpu_iram_base && + (addr + size) <= (k_dpu_iram_base + m_iram_size)) { + return eMemoryAddressSpaceIRAM; + } else if (addr >= k_dpu_mram_base && + (addr + size) <= (k_dpu_mram_base + m_mram_size)) { + return eMemoryAddressSpaceMRAM; + } else if (addr >= k_dpu_wram_base && + (addr + size) <= (k_dpu_wram_base + m_wram_size)) { + return eMemoryAddressSpaceWRAM; + } else { + return eMemoryAddressSpaceUNKNOWN; + } +} + +Status ProcessDpu::ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0:X}, buf = {1}, size = {2}", addr, buf, size); + + bytes_read = 0; + switch (ComputeMemoryAddressSpace(addr, size)) { + case eMemoryAddressSpaceIRAM: { + if (!m_dpu->ReadIRAM(addr - k_dpu_iram_base, buf, size)) + return Status("ReadMemory: Cannot copy from IRAM"); + break; + } + + case eMemoryAddressSpaceMRAM: { + if (!m_dpu->ReadMRAM(addr - k_dpu_mram_base, buf, size)) + return Status("ReadMemory: Cannot copy from MRAM"); + break; + } + + case eMemoryAddressSpaceWRAM: { + if (!m_dpu->ReadWRAM(addr, buf, size)) + return Status("ReadMemory: Cannot copy from WRAM"); + break; + } + + case eMemoryAddressSpaceUNKNOWN: { + return Status("ReadMemory: Cannot read, unknown address space"); + } + } + + bytes_read = size; + + return Status(); +} + +Status ProcessDpu::WriteMemory(lldb::addr_t addr, const void *buf, size_t size, + size_t &bytes_written) { + Log *log(ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_MEMORY)); + LLDB_LOG(log, "addr = {0:X}, buf = {1}, size = {2}", addr, buf, size); + + bytes_written = 0; + switch (ComputeMemoryAddressSpace(addr, size)) { + case eMemoryAddressSpaceIRAM: { + if (!m_dpu->WriteIRAM(addr - k_dpu_iram_base, buf, size)) + return Status("WriteMemory: Cannot copy to IRAM"); + break; + } + + case eMemoryAddressSpaceMRAM: { + if (!m_dpu->WriteMRAM(addr - k_dpu_mram_base, buf, size)) + return Status("WriteMemory: Cannot copy to MRAM"); + break; + } + + case eMemoryAddressSpaceWRAM: { + if (!m_dpu->WriteWRAM(addr, buf, size)) + return Status("WriteMemory: Cannot copy to WRAM"); + break; + } + + case eMemoryAddressSpaceUNKNOWN: { + return Status("WriteMemory: Cannot write, unknown address space"); + } + } + + bytes_written = size; + + return Status(); +} + +Status ProcessDpu::GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) { + return DpuErrorStatus("GetLoadedModuleFileSpec: Not Implemented"); +} + +Status ProcessDpu::GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) { + return DpuErrorStatus("GetFileLoadAddress: Not Implemented"); +} + +ThreadDpu *ProcessDpu::GetThreadByID(lldb::tid_t tid) { + return static_cast(NativeProcessProtocol::GetThreadByID(tid)); +} + +void ProcessDpu::GetThreadContext(int thread_index, uint32_t *®s, + uint16_t *&pc, bool *&zf, bool *&cf, + bool *®isters_has_been_modified) { + regs = m_dpu->ThreadContextRegs(thread_index); + pc = m_dpu->ThreadContextPC(thread_index); + zf = m_dpu->ThreadContextZF(thread_index); + cf = m_dpu->ThreadContextCF(thread_index); + registers_has_been_modified = m_dpu->ThreadRegistersHasBeenModified(); +} + +lldb::StateType ProcessDpu::GetThreadState(int thread_index, + std::string &description, + lldb::StopReason &stop_reason, + bool stepping) { + return m_dpu->GetThreadState(thread_index, description, stop_reason, + stepping); +} + +void ProcessDpu::SaveCore(const char *save_core_filename, + const char *executable_path, Status &error) { + uint8_t *iram; + uint32_t iram_size; + if (!m_dpu->AllocIRAMBuffer(&iram, &iram_size)) { + error.SetErrorString("Cannot alloc a IRAM Buffer"); + return; + } + + // Read the iram without breakpoint + size_t bytes_read; + ReadMemoryWithoutTrap(k_dpu_iram_base, (void *)iram, iram_size, bytes_read); + if (bytes_read != iram_size) { + error.SetErrorString("Cannot read all the IRAM without trap"); + return; + } + + if (!m_dpu->GenerateSaveCore(executable_path, save_core_filename, iram, + iram_size)) { + error.SetErrorString("Cannot generate save core"); + return; + } + + m_dpu->FreeIRAMBuffer(iram); +} + +void ProcessDpu::SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_var_addr, Status &error) { + if (!m_dpu->SetPrintfSequenceAddrs( + open_print_sequence_addr, close_print_sequence_addr, + print_buffer_addr, print_buffer_size, print_var_addr)) + error.SetErrorString("Cannot set Dpu print info"); + + if (m_dpu->PrintfEnable()) { + SetSoftwareBreakpoint(m_dpu->GetOpenPrintfSequenceAddr() | k_dpu_iram_base, + 8); + SetSoftwareBreakpoint(m_dpu->GetClosePrintfSequenceAddr() | k_dpu_iram_base, + 8); + } +} + +Status ProcessDpu::DpuErrorStatus(const char *message) { + FILE *stdout = m_rank->GetStdout(); + if (stdout != NULL) { + fprintf(stdout, "dpu-lldb: %s\n", message); + } + return Status("dpu-lldb: %s", message); +} diff --git a/lldb/source/Plugins/Process/Dpu/ProcessDpu.h b/lldb/source/Plugins/Process/Dpu/ProcessDpu.h new file mode 100644 index 0000000000000..0a03ab6cd77a2 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/ProcessDpu.h @@ -0,0 +1,195 @@ +//===-- ProcessDpu.h ---------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ProcessDpu_H_ +#define liblldb_ProcessDpu_H_ + +#include +#include + +#include "lldb/Host/Debug.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/linux/Support.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-forward.h" // for IOObjectSP +#include "lldb/lldb-types.h" + +#include "ThreadDpu.h" +#include "lldb/Host/common/NativeProcessProtocol.h" + +namespace lldb_private { +class Status; +class Scalar; + +namespace dpu { +class Dpu; +class DpuRank; +class DpuContext; + +const ArchSpec k_dpu_arch("dpu-upmem-dpurte"); + +constexpr lldb::addr_t k_dpu_wram_base = 0x00000000; +constexpr lldb::addr_t k_dpu_mram_base = 0x08000000; +constexpr lldb::addr_t k_dpu_iram_base = 0x80000000; +} // namespace dpu + +namespace process_dpu { +/// @class ProcessDpu +/// Manages communication with the inferior (debugee) process. +/// +/// Changes in the inferior process state are broadcasted. +class ProcessDpu : public NativeProcessProtocol { +public: + class Factory : public NativeProcessProtocol::Factory { + public: + llvm::Expected> + Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + + llvm::Expected> + Attach(lldb::pid_t pid, NativeDelegate &native_delegate, + MainLoop &mainloop) const override; + }; + + static lldb::ProcessSP + CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const lldb_private::FileSpec *crash_file_path, + bool can_connect); + + static void Initialize(); + + static void Terminate(); + + static lldb_private::ConstString GetPluginNameStatic(); + + static const char *GetPluginDescriptionStatic(); + + // --------------------------------------------------------------------- + // NativeProcessProtocol Interface + // --------------------------------------------------------------------- + Status Resume(const ResumeActionList &resume_actions) override; + + Status Halt() override; + + Status Detach() override; + + Status Signal(int signo) override; + + Status Interrupt() override; + + Status Kill() override; + + Status GetMemoryRegionInfo(lldb::addr_t load_addr, + MemoryRegionInfo &range_info) override; + + Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, + size_t &bytes_read) override; + + Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, + size_t &bytes_written) override; + + virtual llvm::Expected + AllocateMemory(size_t size, uint32_t permissions) override; + + virtual llvm::Error DeallocateMemory(lldb::addr_t addr) override; + + lldb::addr_t GetSharedLibraryInfoAddress() override; + + size_t UpdateThreads() override; + + const ArchSpec &GetArchitecture() const override { return m_arch; } + + Status SetBreakpoint(lldb::addr_t addr, uint32_t size, + bool hardware) override; + + Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false) override; + + Status GetLoadedModuleFileSpec(const char *module_path, + FileSpec &file_spec) override; + + Status GetFileLoadAddress(const llvm::StringRef &file_name, + lldb::addr_t &load_addr) override; + + ThreadDpu *GetThreadByID(lldb::tid_t id); + + llvm::ErrorOr> + GetAuxvData() const override { + return getProcFile(GetID(), "auxv"); + } + + // --------------------------------------------------------------------- + // Interface used by RegisterContext-derived classes. + // --------------------------------------------------------------------- + bool SupportHardwareSingleStepping() const; + + // --------------------------------------------------------------------- + // Other methods + // --------------------------------------------------------------------- + void GetThreadContext(int thread_index, uint32_t *®s, uint16_t *&pc, + bool *&zf, bool *&cf, + bool *®isters_has_been_modified); + + lldb::StateType GetThreadState(int thread_index, std::string &description, + lldb::StopReason &stop_reason, bool stepping); + + bool StepThread(uint32_t thread_id); + + void SaveCore(const char *save_core_filename, const char *executable_path, + Status &error) override; + + void SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr, + Status &error) override; + + ~ProcessDpu(); +protected: + llvm::Expected> + GetSoftwareBreakpointTrapOpcode(size_t size_hint) override; + +private: + ProcessDpu(::pid_t pid, int terminal_fd, NativeDelegate &delegate, + const ArchSpec &arch, MainLoop &mainloop, dpu::DpuRank *rank, + dpu::Dpu *dpu); + + void InterfaceTimerCallback(); + + Status DpuErrorStatus(const char *message); + + enum eMemoryAddressSpace { + eMemoryAddressSpaceIRAM, + eMemoryAddressSpaceMRAM, + eMemoryAddressSpaceWRAM, + eMemoryAddressSpaceUNKNOWN + }; + eMemoryAddressSpace ComputeMemoryAddressSpace(lldb::addr_t addr, + size_t size); + + ArchSpec m_arch; + lldb::IOObjectSP m_timer_fd; + MainLoop::ReadHandleUP m_timer_handle; + dpu::Dpu *m_dpu; + dpu::DpuRank *m_rank; + MemoryRegionInfo m_iram_region; + MemoryRegionInfo m_mram_region; + MemoryRegionInfo m_wram_region; + + lldb::addr_t m_iram_size; + lldb::addr_t m_mram_size; + lldb::addr_t m_wram_size; +}; + +} // namespace process_dpu +} // namespace lldb_private + +#endif // #ifndef liblldb_ProcessDpu_H_ diff --git a/lldb/source/Plugins/Process/Dpu/RegisterContextDpu.cpp b/lldb/source/Plugins/Process/Dpu/RegisterContextDpu.cpp new file mode 100644 index 0000000000000..edbbe7d8f15b9 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/RegisterContextDpu.cpp @@ -0,0 +1,198 @@ +//===-- RegisterContextDpu.cpp --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RegisterContextDpu.h" + +#include "Plugins/Process/Dpu/ProcessDpu.h" +#include "Plugins/Process/Dpu/RegisterInfo_dpu.h" +#include "Plugins/Process/POSIX/ProcessPOSIXLog.h" +#include "lldb/Host/common/NativeProcessProtocol.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" + +#include + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_dpu; + +namespace { + +constexpr lldb::addr_t k_dpu_iram_base = 0x80000000; + +} // end of anonymous namespace + +// ----------------------------------------------------------------------------- +// DPU general purpose registers. +static const uint32_t g_regnums_dpu[] = { + r0_dpu, + r1_dpu, + r2_dpu, + r3_dpu, + r4_dpu, + r5_dpu, + r6_dpu, + r7_dpu, + r8_dpu, + r9_dpu, + r10_dpu, + r11_dpu, + r12_dpu, + r13_dpu, + r14_dpu, + r15_dpu, + r16_dpu, + r17_dpu, + r18_dpu, + r19_dpu, + r20_dpu, + r21_dpu, + r22_dpu, + r23_dpu, + pc_dpu, + zf_dpu, + cf_dpu, + LLDB_INVALID_REGNUM // register sets need to end with this flag +}; +static_assert(((sizeof g_regnums_dpu / sizeof g_regnums_dpu[0]) - 1) == + k_num_registers_dpu, + "g_regnums_dpu has wrong number of register infos"); + +static const RegisterSet g_reg_sets_dpu = {"General Purpose Registers", "gpr", + k_num_registers_dpu, g_regnums_dpu}; + +constexpr size_t k_dpu_reg_context_size = + k_num_registers_dpu * sizeof(uint32_t); + +RegisterContextDpu::RegisterContextDpu(ThreadDpu &thread, ProcessDpu &process) + : NativeRegisterContextRegisterInfo(thread, new RegisterInfo_dpu()) { + process.GetThreadContext(thread.GetIndex(), m_context_reg, m_context_pc, + m_context_zf, m_context_cf, + m_registers_has_been_modified); +} + +uint32_t RegisterContextDpu::GetRegisterSetCount() const { return 1; } + +uint32_t RegisterContextDpu::GetUserRegisterCount() const { + return k_num_registers_dpu; +} + +const RegisterSet * +RegisterContextDpu::GetRegisterSet(uint32_t set_index) const { + if (set_index) // single register set + return nullptr; + + return &g_reg_sets_dpu; +} + +Status RegisterContextDpu::ReadRegister(const RegisterInfo *info, + RegisterValue &value) { + if (!info) + return Status("RegisterInfo is NULL"); + + const uint32_t reg = info->kinds[lldb::eRegisterKindLLDB]; + + if (reg == pc_dpu) { + uint32_t pc = + *m_context_pc * 8 /*sizeof(iram_instruction_t)*/ + k_dpu_iram_base; + if (m_thread.GetState() == eStateSuspended) + pc++; + value.SetUInt32(pc); + } else if (reg == zf_dpu) + value.SetUInt32(*m_context_zf ? 1 : 0); + else if (reg == cf_dpu) + value.SetUInt32(*m_context_cf ? 1 : 0); + else + value.SetUInt32(m_context_reg[reg]); + + return Status(); +} + +Status RegisterContextDpu::WriteRegister(const RegisterInfo *info, + const RegisterValue &value) { + if (!info) + return Status("RegisterInfo is NULL"); + + const uint32_t reg = info->kinds[lldb::eRegisterKindLLDB]; + + if (reg == pc_dpu) + *m_context_pc = (value.GetAsUInt32() - k_dpu_iram_base) / + 8 /*sizeof(iram_instruction_t)*/; + else if (reg == zf_dpu) + *m_context_zf = (value.GetAsUInt32() == 1); + else if (reg == cf_dpu) + *m_context_cf = (value.GetAsUInt32() == 1); + else + m_context_reg[reg] = value.GetAsUInt32(); + + *m_registers_has_been_modified = true; + + return Status(); +} + +Status RegisterContextDpu::ReadAllRegisterValues(lldb::DataBufferSP &data_sp) { + Status error; + + data_sp.reset(new DataBufferHeap(k_dpu_reg_context_size, 0)); + if (!data_sp) + return Status("failed to allocate DataBufferHeap instance"); + uint8_t *dst = data_sp->GetBytes(); + if (dst == nullptr) + return Status("invalid DataBufferHeap instance"); + + uint32_t pc = + *m_context_pc * 8 /*sizeof(iram_instruction_t)*/ + k_dpu_iram_base; + uint32_t zf = m_context_zf ? 1 : 0; + uint32_t cf = m_context_cf ? 1 : 0; + + ::memcpy(dst, m_context_reg, k_dpu_reg_context_size - sizeof(pc) - sizeof(zf) - sizeof(cf)); + ::memcpy(dst + k_dpu_reg_context_size - sizeof(pc) - sizeof(zf) - sizeof(cf), &pc, sizeof(pc)); + ::memcpy(dst + k_dpu_reg_context_size - sizeof(zf) - sizeof(cf), &zf, sizeof(zf)); + ::memcpy(dst + k_dpu_reg_context_size - sizeof(cf), &cf, sizeof(cf)); + + return error; +} + +Status +RegisterContextDpu::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) { + Status error; + + if (!data_sp) + return Status("invalid data_sp provided"); + uint8_t *src = data_sp->GetBytes(); + if (src == nullptr) + return Status("invalid data_sp provided"); + + if (data_sp->GetByteSize() != k_dpu_reg_context_size) { + error.SetErrorStringWithFormat( + "RegisterContextDpu::%s data_sp contained mismatched " + "data size, expected %" PRIu64 ", actual %" PRIu64, + __FUNCTION__, (uint64_t)k_dpu_reg_context_size, data_sp->GetByteSize()); + return error; + } + + uint32_t pc; + uint32_t zf, cf; + + ::memcpy(m_context_reg, src, k_dpu_reg_context_size - sizeof(pc) - sizeof(zf) - sizeof(cf)); + ::memcpy(&pc, src + k_dpu_reg_context_size - sizeof(pc) - sizeof(zf) - sizeof(cf), sizeof(pc)); + ::memcpy(&zf, src + k_dpu_reg_context_size - sizeof(zf) - sizeof(cf), sizeof(zf)); + ::memcpy(&cf, src + k_dpu_reg_context_size - sizeof(cf), sizeof(cf)); + + *m_context_pc = (pc - k_dpu_iram_base) / 8 /*sizeof(iram_instruction_t)*/; + *m_context_zf = zf == 1; + *m_context_cf = cf == 1; + + *m_registers_has_been_modified = true; + + return error; +} diff --git a/lldb/source/Plugins/Process/Dpu/RegisterContextDpu.h b/lldb/source/Plugins/Process/Dpu/RegisterContextDpu.h new file mode 100644 index 0000000000000..97aeb4caed9b8 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/RegisterContextDpu.h @@ -0,0 +1,54 @@ +//===-- RegisterContextDpu.h ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_RegisterContextDpu_h +#define lldb_RegisterContextDpu_h + +#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h" +#include "Plugins/Process/Utility/lldb-dpu-register-enums.h" +#include "lldb/Host/common/NativeThreadProtocol.h" + +namespace lldb_private { +namespace process_dpu { + +class ProcessDpu; +class ThreadDpu; + +class RegisterContextDpu : public NativeRegisterContextRegisterInfo { +public: + RegisterContextDpu(ThreadDpu &thread, ProcessDpu &process); + + uint32_t GetRegisterSetCount() const override; + + const RegisterSet *GetRegisterSet(uint32_t set_index) const override; + + uint32_t GetUserRegisterCount() const override; + + Status ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override; + + Status WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override; + + Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override; + + Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override; + +private: + uint32_t *m_context_reg; + uint16_t *m_context_pc; + bool *m_context_zf; + bool *m_context_cf; + bool *m_registers_has_been_modified; +}; + +} // namespace process_dpu +} // namespace lldb_private + +#endif // #ifndef lldb_RegisterContextDpu_h diff --git a/lldb/source/Plugins/Process/Dpu/RegisterInfo_dpu.cpp b/lldb/source/Plugins/Process/Dpu/RegisterInfo_dpu.cpp new file mode 100644 index 0000000000000..7605a1b9c5688 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/RegisterInfo_dpu.cpp @@ -0,0 +1,205 @@ +//===-- RegisterInfo_dpu.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#include +#include +#include + +#include "lldb/lldb-defines.h" +#include "llvm/Support/Compiler.h" + +#include "ProcessDpu.h" +#include "RegisterInfo_dpu.h" + +using namespace lldb; +using namespace lldb_private; + +enum { + dwarf_r0 = 0, + dwarf_r1, + dwarf_r2, + dwarf_r3, + dwarf_r4, + dwarf_r5, + dwarf_r6, + dwarf_r7, + dwarf_r8, + dwarf_r9, + dwarf_r10, + dwarf_r11, + dwarf_r12, + dwarf_r13, + dwarf_r14, + dwarf_r15, + dwarf_r16, + dwarf_r17, + dwarf_r18, + dwarf_r19, + dwarf_r20, + dwarf_r21, + dwarf_r22, + dwarf_r23, + dwarf_pc, + dwarf_zf, + dwarf_cf, +}; +// The register numbers used in the eh_frame unwind information. +// Should be the same as DWARF register numbers. +enum { + ehframe_r0 = dwarf_r0, + ehframe_r1 = dwarf_r1, + ehframe_r2 = dwarf_r2, + ehframe_r3 = dwarf_r3, + ehframe_r4 = dwarf_r4, + ehframe_r5 = dwarf_r5, + ehframe_r6 = dwarf_r6, + ehframe_r7 = dwarf_r7, + ehframe_r8 = dwarf_r8, + ehframe_r9 = dwarf_r9, + ehframe_r10 = dwarf_r10, + ehframe_r11 = dwarf_r11, + ehframe_r12 = dwarf_r12, + ehframe_r13 = dwarf_r13, + ehframe_r14 = dwarf_r14, + ehframe_r15 = dwarf_r15, + ehframe_r16 = dwarf_r16, + ehframe_r17 = dwarf_r17, + ehframe_r18 = dwarf_r18, + ehframe_r19 = dwarf_r19, + ehframe_r20 = dwarf_r20, + ehframe_r21 = dwarf_r21, + ehframe_r22 = dwarf_r22, + ehframe_r23 = dwarf_r23, + ehframe_pc = dwarf_pc, + ehframe_zf = dwarf_zf, + ehframe_cf = dwarf_cf, +}; + +enum { + gpr_r0 = 0, + gpr_r1, + gpr_r2, + gpr_r3, + gpr_r4, + gpr_r5, + gpr_r6, + gpr_r7, + gpr_r8, + gpr_r9, + gpr_r10, + gpr_r11, + gpr_r12, + gpr_r13, + gpr_r14, + gpr_r15, + gpr_r16, + gpr_r17, + gpr_r18, + gpr_r19, + gpr_r20, + gpr_r21, + gpr_r22, + gpr_r23, + gpr_sp = gpr_r22, + gpr_lr = gpr_r23, + gpr_pc, + gpr_zf, + gpr_cf, +}; + +#define XSTR(s) STR(s) +#define STR(s) #s +#define DEFINE_GPR(idx, generic) \ + { \ + "r" STR(idx), nullptr, 4, ((idx)*4), eEncodingUint, eFormatHex, \ + {ehframe_r##idx, dwarf_r##idx, generic, gpr_r##idx, gpr_r##idx}, \ + nullptr, nullptr, nullptr, 0 \ + } + +static RegisterInfo g_register_infos_dpu[] = { + // NAME ALT SZ OFFSET ENCODING FORMAT + // EH_FRAME DWARF GENERIC + // PROCESS PLUGIN LLDB NATIVE VALUE REGS INVALIDATE REGS + DEFINE_GPR(0, LLDB_REGNUM_GENERIC_ARG1), + DEFINE_GPR(1, LLDB_REGNUM_GENERIC_ARG2), + DEFINE_GPR(2, LLDB_REGNUM_GENERIC_ARG3), + DEFINE_GPR(3, LLDB_REGNUM_GENERIC_ARG4), + DEFINE_GPR(4, LLDB_REGNUM_GENERIC_ARG5), + DEFINE_GPR(5, LLDB_REGNUM_GENERIC_ARG6), + DEFINE_GPR(6, LLDB_REGNUM_GENERIC_ARG7), + DEFINE_GPR(7, LLDB_REGNUM_GENERIC_ARG8), + DEFINE_GPR(8, LLDB_INVALID_REGNUM), + DEFINE_GPR(9, LLDB_INVALID_REGNUM), + DEFINE_GPR(10, LLDB_INVALID_REGNUM), + DEFINE_GPR(11, LLDB_INVALID_REGNUM), + DEFINE_GPR(12, LLDB_INVALID_REGNUM), + DEFINE_GPR(13, LLDB_INVALID_REGNUM), + DEFINE_GPR(14, LLDB_INVALID_REGNUM), + DEFINE_GPR(15, LLDB_INVALID_REGNUM), + DEFINE_GPR(16, LLDB_INVALID_REGNUM), + DEFINE_GPR(17, LLDB_INVALID_REGNUM), + DEFINE_GPR(18, LLDB_INVALID_REGNUM), + DEFINE_GPR(19, LLDB_INVALID_REGNUM), + DEFINE_GPR(20, LLDB_INVALID_REGNUM), + DEFINE_GPR(21, LLDB_INVALID_REGNUM), + DEFINE_GPR(22, LLDB_REGNUM_GENERIC_SP), + DEFINE_GPR(23, LLDB_REGNUM_GENERIC_RA), + {"pc", + nullptr, + 4, + 24 * 4, + eEncodingUint, + eFormatHex, + {ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, + gpr_pc}, + nullptr, + nullptr, + nullptr, + 0}, + {"zf", + nullptr, + 4, + 25 * 4, + lldb::eEncodingUint, + lldb::eFormatHex, + {ehframe_zf, dwarf_zf, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_zf}, + nullptr, + nullptr, + nullptr, + 0}, + {"cf", + nullptr, + 4, + 26 * 4, + lldb::eEncodingUint, + lldb::eFormatHex, + {ehframe_cf, dwarf_cf, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_cf}, + nullptr, + nullptr, + nullptr, + 0}, +}; + +const uint32_t k_register_infos_count = + sizeof(g_register_infos_dpu) / sizeof(g_register_infos_dpu[0]); + +RegisterInfo_dpu::RegisterInfo_dpu() + : lldb_private::RegisterInfoInterface(dpu::k_dpu_arch) {} + +size_t RegisterInfo_dpu::GetGPRSize() const { + return sizeof(struct RegisterInfo_dpu::GPR); +} + +const lldb_private::RegisterInfo *RegisterInfo_dpu::GetRegisterInfo() const { + return g_register_infos_dpu; +} + +uint32_t RegisterInfo_dpu::GetRegisterCount() const { + return k_register_infos_count; +} diff --git a/lldb/source/Plugins/Process/Dpu/RegisterInfo_dpu.h b/lldb/source/Plugins/Process/Dpu/RegisterInfo_dpu.h new file mode 100644 index 0000000000000..d36015c26138b --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/RegisterInfo_dpu.h @@ -0,0 +1,35 @@ +//===-- RegisterInfo_dpu.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RegisterInfo_dpu_h_ +#define liblldb_RegisterInfo_dpu_h_ + +#include "Plugins/Process/Utility/RegisterInfoInterface.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/lldb-private.h" + +class RegisterInfo_dpu : public lldb_private::RegisterInfoInterface { +public: + struct GPR { + uint32_t r[24]; // R0-R23 + uint32_t pc; // PC + uint32_t zf; + uint32_t cf; + }; + + RegisterInfo_dpu(); + + size_t GetGPRSize() const override; + + const lldb_private::RegisterInfo *GetRegisterInfo() const override; + + uint32_t GetRegisterCount() const override; +}; + +#endif // liblldb_RegisterInfo_dpu_h_ diff --git a/lldb/source/Plugins/Process/Dpu/ThreadDpu.cpp b/lldb/source/Plugins/Process/Dpu/ThreadDpu.cpp new file mode 100644 index 0000000000000..c674ad17305b5 --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/ThreadDpu.cpp @@ -0,0 +1,71 @@ +//===-- ThreadDpu.cpp --------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ThreadDpu.h" + +#include +#include + +// For llvm::to_string +#include "llvm/Support/ScopedPrinter.h" + +#include "ProcessDpu.h" +#include "RegisterContextDpu.h" + +#include "lldb/Host/HostNativeThread.h" +#include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/State.h" +#include "lldb/lldb-enumerations.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_dpu; + +ThreadDpu::ThreadDpu(ProcessDpu &process, lldb::tid_t tid, int index) + : NativeThreadProtocol(process, tid), m_thread_index(index), + m_state(eStateStopped), + m_reg_context_up(std::make_unique(*this, process)) {} + +std::string ThreadDpu::GetName() { + return "DPUthread" + llvm::to_string(m_thread_index); +} + +lldb::StateType ThreadDpu::GetState() { return m_state; } + +bool ThreadDpu::GetStopReason(ThreadStopInfo &stop_info, + std::string &description) { + description.clear(); + memset(&stop_info.details, 0, sizeof(stop_info.details)); + m_state = GetProcess().GetThreadState(m_thread_index, description, + stop_info.reason, m_stepping); + + return true; +} + +Status ThreadDpu::SetWatchpoint(lldb::addr_t addr, size_t size, + uint32_t watch_flags, bool hardware) { + return Status("watchpoint not implemented"); +} + +Status ThreadDpu::RemoveWatchpoint(lldb::addr_t addr) { + return Status("watchpoint not implemented"); +} + +Status ThreadDpu::SetHardwareBreakpoint(lldb::addr_t addr, size_t size) { + return Status("no hardware breakpoint"); +} + +Status ThreadDpu::RemoveHardwareBreakpoint(lldb::addr_t addr) { + return Status("no hardware breakpoint"); +} + +ProcessDpu &ThreadDpu::GetProcess() { + return static_cast(m_process); +} diff --git a/lldb/source/Plugins/Process/Dpu/ThreadDpu.h b/lldb/source/Plugins/Process/Dpu/ThreadDpu.h new file mode 100644 index 0000000000000..caea2cf639ace --- /dev/null +++ b/lldb/source/Plugins/Process/Dpu/ThreadDpu.h @@ -0,0 +1,77 @@ +//===-- ThreadDpu.h ----------------------------------- -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadDpu_H_ +#define liblldb_ThreadDpu_H_ + +#include "Plugins/Process/Dpu/RegisterContextDpu.h" +#include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/lldb-private-forward.h" + +namespace lldb_private { +namespace process_dpu { + +class ProcessDpu; + +class ThreadDpu : public NativeThreadProtocol { + friend class ProcessDpu; + +public: + ThreadDpu(ProcessDpu &process, lldb::tid_t tid, int index); + + // --------------------------------------------------------------------- + // NativeThreadProtocol Interface + // --------------------------------------------------------------------- + std::string GetName() override; + + lldb::StateType GetState() override; + + bool GetStopReason(ThreadStopInfo &stop_info, + std::string &description) override; + + RegisterContextDpu &GetRegisterContext() override { + return *m_reg_context_up; + } + + Status SetWatchpoint(lldb::addr_t addr, size_t size, uint32_t watch_flags, + bool hardware) override; + + Status RemoveWatchpoint(lldb::addr_t addr) override; + + Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size) override; + + Status RemoveHardwareBreakpoint(lldb::addr_t addr) override; + + int GetIndex() { return m_thread_index; } + + void SetSteppingMode(bool on) { m_stepping = on; }; + +private: + // --------------------------------------------------------------------- + // Interface for friend classes + // --------------------------------------------------------------------- + + // --------------------------------------------------------------------- + // Private interface + // --------------------------------------------------------------------- + ProcessDpu &GetProcess(); + + // --------------------------------------------------------------------- + // Member Variables + // --------------------------------------------------------------------- + int m_thread_index; + lldb::StateType m_state; + std::unique_ptr m_reg_context_up; + + bool m_stepping; +}; +} // namespace process_dpu +} // namespace lldb_private + +#endif // #ifndef liblldb_ThreadDpu_H_ diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt index 9965d89f4c4ba..8e2978df3e5af 100644 --- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt +++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt @@ -28,6 +28,7 @@ add_lldb_library(lldbPluginProcessUtility RegisterContextLinux_mips64.cpp RegisterContextLinux_mips.cpp RegisterContextLinux_s390x.cpp + RegisterContextDPU.cpp RegisterContextMach_arm.cpp RegisterContextMach_i386.cpp RegisterContextMach_x86_64.cpp @@ -51,6 +52,7 @@ add_lldb_library(lldbPluginProcessUtility RegisterInfoPOSIX_ppc64le.cpp StopInfoMachException.cpp ThreadMemory.cpp + UnwindDPU.cpp LINK_LIBS lldbBreakpoint diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDPU.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDPU.cpp new file mode 100644 index 0000000000000..3871b489aed68 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDPU.cpp @@ -0,0 +1,228 @@ +//===-- RegisterContextDPU.cpp --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Address.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/ArmUnwindInfo.h" +#include "lldb/Symbol/DWARFCallFrameInfo.h" +#include "lldb/Symbol/FuncUnwinders.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/DynamicLoader.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/SectionLoadList.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/lldb-private.h" + +#include "RegisterContextDPU.h" +#include "lldb-dpu-register-enums.h" + +using namespace lldb; +using namespace lldb_private; + +RegisterContextDPU::RegisterContextDPU( + Thread &thread, RegisterContextDPUSP prev_frame_reg_ctx_sp, + lldb::addr_t cfa, lldb::addr_t pc, uint32_t frame_number) + : RegisterContext(thread, frame_number), m_thread(thread), + reg_ctx_sp(thread.GetRegisterContext()), m_frame_number(frame_number), + m_cfa(cfa), m_pc(pc), m_prev_frame(prev_frame_reg_ctx_sp) {} + +void RegisterContextDPU::InvalidateAllRegisters() { + reg_ctx_sp->InvalidateAllRegisters(); +} + +size_t RegisterContextDPU::GetRegisterCount() { + return reg_ctx_sp->GetRegisterCount(); +} + +const RegisterInfo *RegisterContextDPU::GetRegisterInfoAtIndex(size_t reg) { + return reg_ctx_sp->GetRegisterInfoAtIndex(reg); +} + +size_t RegisterContextDPU::GetRegisterSetCount() { + return reg_ctx_sp->GetRegisterSetCount(); +} + +const RegisterSet *RegisterContextDPU::GetRegisterSet(size_t reg_set) { + return reg_ctx_sp->GetRegisterSet(reg_set); +} + +bool RegisterContextDPU::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + if (m_frame_number == 0) { + return reg_ctx_sp->ReadRegister(reg_info, value); + } + // Do not try to get r22 from the saved location, we alreay have the good one + // here. The one from the saved location can be false depending on our + // position in the prologue + if (reg_info == reg_ctx_sp->GetRegisterInfoByName("r22")) { + value = m_cfa; + return true; + } else if (reg_info == reg_ctx_sp->GetRegisterInfoByName("pc")) { + value = m_pc; + return true; + } else if (reg_info == reg_ctx_sp->GetRegisterInfoByName("zf") || + reg_info == reg_ctx_sp->GetRegisterInfoByName("cf")) { + return false; + } + + return m_prev_frame->ReadRegisterFromSavedLocation(reg_info, value); +} + +bool RegisterContextDPU::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + if (m_frame_number == 0) { + return reg_ctx_sp->WriteRegister(reg_info, value); + } + if (reg_info == reg_ctx_sp->GetRegisterInfoByName("r22") || + reg_info == reg_ctx_sp->GetRegisterInfoByName("pc") || + reg_info == reg_ctx_sp->GetRegisterInfoByName("zf") || + reg_info == reg_ctx_sp->GetRegisterInfoByName("cf")) { + return false; + } + return m_prev_frame->WriteRegisterToSavedLocation(reg_info, value); +} + +uint32_t +RegisterContextDPU::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) { + return reg_ctx_sp->ConvertRegisterKindToRegisterNumber(kind, num); +} + +bool RegisterContextDPU::PCInPrologue(lldb::addr_t start_addr, + uint32_t nb_callee_saved_regs) { + // We consider here only a subset of the prologue + // The subset is the 2 first instruction (stack managment) and all the saving + // of callee register + // We store callee register with double store (instruction of 8 bytes for 2 + // callee registers = 4 bytes per callee register) + // We need to add 8 bytes (1 instruction) for the add of the stack pointer + lldb::addr_t end_addr = (start_addr + nb_callee_saved_regs * 4 + 8); + return m_pc >= start_addr && m_pc < end_addr; +} + +bool RegisterContextDPU::GetUnwindPlanSP(Address &pc_addr, + lldb::UnwindPlanSP &unwind_plan_sp) { + ModuleSP module_sp(pc_addr.GetModule()); + DWARFCallFrameInfo *debug_frame = + module_sp->GetUnwindTable().GetDebugFrameInfo(); + + if (debug_frame) { + debug_frame->GetUnwindPlan(pc_addr, *unwind_plan_sp); + return true; + } else { + return false; + } +} + +bool RegisterContextDPU::LookForRegisterLocation(const RegisterInfo *reg_info, + lldb::addr_t &addr) { + Address fct_base_addr; + if (!GetFunctionBaseAddress(fct_base_addr, m_pc)) { + return false; + } + + UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (GetUnwindPlanSP(fct_base_addr, unwind_plan_sp)) { + uint32_t row_id = 0; + addr = LLDB_INVALID_ADDRESS; + while (unwind_plan_sp->IsValidRowIndex(row_id)) { + uint32_t nb_callee_saved_regs = 0; + UnwindPlan::RowSP row = unwind_plan_sp->GetRowAtIndex(row_id++); + for (unsigned int each_reg = 0; + each_reg < lldb_private::k_num_registers_dpu; each_reg++) { + UnwindPlan::Row::RegisterLocation reg_loc; + row->GetRegisterInfo(each_reg, reg_loc); + if (!reg_loc.IsUndefined() && !reg_loc.IsUnspecified()) { + nb_callee_saved_regs++; + if (reg_info->byte_offset / 4 == each_reg) { + addr = reg_loc.GetOffset() + m_cfa; + } + } + } + if (addr != LLDB_INVALID_ADDRESS && + !PCInPrologue(fct_base_addr.GetFileAddress(), nb_callee_saved_regs) && + !PCIsInstructionReturn(m_pc)) + return true; + } + } + + return false; +} + +bool RegisterContextDPU::ReadRegisterFromSavedLocation( + const RegisterInfo *reg_info, RegisterValue &value) { + lldb::addr_t reg_addr; + if (LookForRegisterLocation(reg_info, reg_addr)) { + Status error; + uint32_t val; + m_thread.GetProcess()->ReadMemory(reg_addr, &val, 4, error); + value.SetUInt32(val); + return true; + } else if (m_frame_number == 0) { + return reg_ctx_sp->ReadRegister(reg_info, value); + } + return m_prev_frame->ReadRegisterFromSavedLocation(reg_info, value); +} + +bool RegisterContextDPU::WriteRegisterToSavedLocation( + const RegisterInfo *reg_info, const RegisterValue &value) { + lldb::addr_t reg_addr; + if (LookForRegisterLocation(reg_info, reg_addr)) { + Status error; + uint32_t val = value.GetAsUInt32(); + m_thread.GetProcess()->WriteMemory(reg_addr, &val, 4, error); + return true; + } else if (m_frame_number == 0) { + return reg_ctx_sp->WriteRegister(reg_info, value); + } + return m_prev_frame->WriteRegisterToSavedLocation(reg_info, value); +} + +bool RegisterContextDPU::GetFunctionBaseAddress(Address &addr, + lldb::addr_t pc) { + Address resolved_addr; + m_thread.GetProcess()->GetTarget().ResolveLoadAddress(pc, resolved_addr); + addr = Address(); + + SymbolContext sc; + ModuleSP module_sp(resolved_addr.GetModule()); + if (!module_sp) { + return false; + } + module_sp->ResolveSymbolContextForAddress(resolved_addr, + eSymbolContextFunction, sc); + Function *fct = sc.function; + if (fct == NULL) { + return false; + } else { + addr = sc.function->GetAddressRange().GetBaseAddress(); + return true; + } +} + +bool RegisterContextDPU::PCIsInstructionReturn(lldb::addr_t pc) { + Status error; + uint64_t instruction; + m_thread.GetProcess()->ReadMemory(pc, &instruction, 8, error); + return instruction == 0x8c5f00000000ULL; // 0x8c5f00000000 => 'jump r23' +} diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDPU.h b/lldb/source/Plugins/Process/Utility/RegisterContextDPU.h new file mode 100644 index 0000000000000..bde92f182c633 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/RegisterContextDPU.h @@ -0,0 +1,77 @@ +//===-- RegisterContextDPU.h --------------------------------------------*- C++ +//-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_RegisterContextDPU_h_ +#define lldb_RegisterContextDPU_h_ + +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/RegisterNumber.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class RegisterContextDPU; +typedef std::shared_ptr RegisterContextDPUSP; + +class RegisterContextDPU : public lldb_private::RegisterContext { +public: + RegisterContextDPU(Thread &thread, RegisterContextDPUSP prev_frame_reg_ctx_sp, + lldb::addr_t cfa, lldb::addr_t pc, uint32_t frame_number); + + ~RegisterContextDPU() override = default; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const RegisterSet *GetRegisterSet(size_t reg_set) override; + + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) override; + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + bool ReadRegisterFromSavedLocation(const RegisterInfo *reg_info, + RegisterValue &value); + + bool WriteRegisterToSavedLocation(const RegisterInfo *reg_info, + const RegisterValue &value); + + bool GetFunctionBaseAddress(Address &addr, lldb::addr_t pc); + + bool PCIsInstructionReturn(lldb::addr_t pc); + + bool GetUnwindPlanSP(Address &pc_addr, lldb::UnwindPlanSP &unwind_plan_sp); + +private: + bool LookForRegisterLocation(const RegisterInfo *reg_info, lldb::addr_t &addr); + + bool PCInPrologue(lldb::addr_t start_addr, uint32_t nb_callee_saved_regs); + + Thread &m_thread; + lldb::RegisterContextSP reg_ctx_sp; + uint32_t m_frame_number; + lldb::addr_t m_cfa, m_pc; + RegisterContextDPUSP m_prev_frame; +}; +} + +#endif /* lldb_RegisterContextDPU_h_ */ diff --git a/lldb/source/Plugins/Process/Utility/UnwindDPU.cpp b/lldb/source/Plugins/Process/Utility/UnwindDPU.cpp new file mode 100644 index 0000000000000..f95186db51602 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/UnwindDPU.cpp @@ -0,0 +1,154 @@ +//===-- UnwindDPU.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/FuncUnwinders.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/ABI.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" + +#include "RegisterContextDPU.h" +#include "UnwindDPU.h" + +using namespace lldb; +using namespace lldb_private; + +UnwindDPU::UnwindDPU(Thread &thread) : Unwind(thread), m_frames() {} + +void UnwindDPU::DoClear() { m_frames.clear(); } + +#define FORMAT_PC(pc) (0x80000000 | ((pc)*8)) + +bool UnwindDPU::SetFrame(CursorSP *prev_frame, lldb::addr_t cfa, + lldb::addr_t pc, Address &fct_base_addr) { + constexpr std::size_t nb_frame_max = 256; + if (m_frames.size() > nb_frame_max) + return false; + + CursorSP new_frame(new Cursor()); + RegisterContextDPUSP prev_reg_ctx_sp = + *prev_frame != NULL ? (*prev_frame)->reg_ctx_sp : NULL; + RegisterContextDPUSP new_reg_ctx_sp(new RegisterContextDPU( + m_thread, prev_reg_ctx_sp, cfa, pc, m_frames.size())); + new_frame->cfa = cfa; + new_frame->pc = pc; + new_frame->reg_ctx_sp = new_reg_ctx_sp; + m_frames.push_back(new_frame); + *prev_frame = new_frame; + + // If the current function is __bootstrap, we can stop the unwinding + if ((*prev_frame)->reg_ctx_sp->GetFunctionBaseAddress(fct_base_addr, pc) && + fct_base_addr.GetFileAddress() == FORMAT_PC(0)) { + return false; + } + + return true; +} + +uint32_t UnwindDPU::DoGetFrameCount() { + if (!m_frames.empty()) + return m_frames.size(); + + lldb::RegisterContextSP reg_ctx_sp = m_thread.GetRegisterContext(); + + RegisterValue reg_r22, reg_pc; + reg_ctx_sp->ReadRegister(reg_ctx_sp->GetRegisterInfoByName("r22"), reg_r22); + reg_ctx_sp->ReadRegister(reg_ctx_sp->GetRegisterInfoByName("pc"), reg_pc); + + CursorSP prev_frame = NULL; + lldb::addr_t first_pc_addr = reg_pc.GetAsUInt32(); + lldb::addr_t first_r22_value = reg_r22.GetAsUInt32(); + + Address fct_base_addr; + if (!SetFrame(&prev_frame, first_r22_value, first_pc_addr, fct_base_addr)) + return m_frames.size(); + + lldb::addr_t start_addr = fct_base_addr.GetFileAddress(); + int32_t cfa_offset = 1; + if (start_addr != LLDB_INVALID_ADDRESS) { + // Check if we have the stack size save in the cfi information. + // If we have it, use it to set the cfa in order to have it set to the right + // value from the beginning so that comparison between frame always give the + // expected answer. + UnwindPlanSP unwind_plan_sp(new UnwindPlan(lldb::eRegisterKindGeneric)); + if (prev_frame->reg_ctx_sp->GetUnwindPlanSP(fct_base_addr, + unwind_plan_sp)) { + if (unwind_plan_sp->IsValidRowIndex(0)) { + UnwindPlan::RowSP row = unwind_plan_sp->GetRowAtIndex(0); + UnwindPlan::Row::FAValue &CFAValue = row->GetCFAValue(); + if (!CFAValue.IsUnspecified()) + cfa_offset = -CFAValue.GetOffset(); + } + } + } + // If we are in the 2 first instruction of the function, or in the return + // instruction of the function, the information to get the next frame are not + // the same as usual. r22 is already the good one. pc is in r23. + // Also, if the cfa_offset is null, it means that we are a leaf, function, + // apply same method to compute the frame (but add 1 to the cfa in order to + // differenciate it from the previous frame (StackID comparison). + if ((start_addr != LLDB_INVALID_ADDRESS) && + (((first_pc_addr >= start_addr) && (first_pc_addr < (start_addr + 16))) || + prev_frame->reg_ctx_sp->PCIsInstructionReturn(first_pc_addr) || + cfa_offset == 0)) { + RegisterValue reg_r23; + reg_ctx_sp->ReadRegister(reg_ctx_sp->GetRegisterInfoByName("r23"), reg_r23); + prev_frame->cfa += (cfa_offset == 0 ? 1 : cfa_offset); + if (!SetFrame(&prev_frame, first_r22_value, + FORMAT_PC(reg_r23.GetAsUInt32()), fct_base_addr)) + return m_frames.size(); + } + + while (true) { + Status error; + lldb::addr_t cfa_addr = 0; + lldb::addr_t pc_addr = 0; + const uint32_t reg_size_in_bytes = 4; + if ((m_thread.GetProcess()->ReadMemory(prev_frame->cfa - 4, &cfa_addr, + reg_size_in_bytes, + error) != reg_size_in_bytes) || + (m_thread.GetProcess()->ReadMemory(prev_frame->cfa - 8, &pc_addr, + reg_size_in_bytes, + error) != reg_size_in_bytes) || + (!SetFrame(&prev_frame, cfa_addr, FORMAT_PC(pc_addr), fct_base_addr))) + return m_frames.size(); + } + + return m_frames.size(); +} + +bool UnwindDPU::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, + lldb::addr_t &pc, bool &behaves_like_zeroth_frame) { + if (frame_idx >= DoGetFrameCount()) + return false; + + behaves_like_zeroth_frame = frame_idx == 0; + cfa = m_frames[frame_idx]->cfa; + pc = m_frames[frame_idx]->pc; + return true; +} + +lldb::RegisterContextSP +UnwindDPU::DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) { + lldb::RegisterContextSP reg_ctx_sp; + uint32_t frame_idx = frame->GetConcreteFrameIndex(); + + if (frame_idx >= DoGetFrameCount()) + return reg_ctx_sp; + + Cursor *frame_cursor = m_frames[frame_idx].get(); + reg_ctx_sp = frame_cursor->reg_ctx_sp; + return reg_ctx_sp; +} diff --git a/lldb/source/Plugins/Process/Utility/UnwindDPU.h b/lldb/source/Plugins/Process/Utility/UnwindDPU.h new file mode 100644 index 0000000000000..dd6f622e84964 --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/UnwindDPU.h @@ -0,0 +1,67 @@ +//===-- UnwindDPU.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef dpu_UnwindDPU_h_ +#define dpu_UnwindDPU_h_ + +// C Includes +// C++ Includes +#include + +// Other libraries and framework includes +// Project includes +#include "lldb/Symbol/FuncUnwinders.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Unwind.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-public.h" + +#include "RegisterContextDPU.h" + +namespace lldb_private { + +class UnwindDPU : public lldb_private::Unwind { +public: + UnwindDPU(lldb_private::Thread &thread); + + ~UnwindDPU() override = default; + +protected: + void DoClear() override; + + uint32_t DoGetFrameCount() override; + + bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa, + lldb::addr_t &pc, bool &behaves_like_zeroth_frame) override; + + lldb::RegisterContextSP + DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override; + +private: + struct Cursor { + lldb::addr_t pc; // The start address of the function/symbol for this + // frame - current pc if unknown + lldb::addr_t cfa; // The canonical frame address for this stack frame + RegisterContextDPUSP reg_ctx_sp; + + Cursor() + : pc(LLDB_INVALID_ADDRESS), cfa(LLDB_INVALID_ADDRESS), + reg_ctx_sp() {} + }; + + typedef std::shared_ptr CursorSP; + std::vector m_frames; + + bool SetFrame(CursorSP *prev_frame, lldb::addr_t cfa, lldb::addr_t pc, + Address &fct_base_addr); +}; +} // namespace lldb_private +#endif /* dpu_UnwindDPU_h_ */ diff --git a/lldb/source/Plugins/Process/Utility/lldb-dpu-register-enums.h b/lldb/source/Plugins/Process/Utility/lldb-dpu-register-enums.h new file mode 100644 index 0000000000000..95a418d4be41c --- /dev/null +++ b/lldb/source/Plugins/Process/Utility/lldb-dpu-register-enums.h @@ -0,0 +1,54 @@ +//===-- lldb-dpu-register-enums.h -----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_dpu_register_enums_h +#define lldb_dpu_register_enums_h + +namespace lldb_private { +// LLDB register codes (e.g. RegisterKind == eRegisterKindLLDB) + +//--------------------------------------------------------------------------- +// Internal codes for all DPU registers. +//--------------------------------------------------------------------------- +enum { + r0_dpu, + r1_dpu, + r2_dpu, + r3_dpu, + r4_dpu, + r5_dpu, + r6_dpu, + r7_dpu, + r8_dpu, + r9_dpu, + r10_dpu, + r11_dpu, + r12_dpu, + r13_dpu, + r14_dpu, + r15_dpu, + r16_dpu, + r17_dpu, + r18_dpu, + r19_dpu, + r20_dpu, + r21_dpu, + r22_dpu, + r23_dpu, + sp_dpu = r22_dpu, + lr_dpu = r23_dpu, + pc_dpu, + zf_dpu, + cf_dpu, + + k_num_registers_dpu, +}; +} // namespace lldb_private + +#endif // #ifndef lldb_dpu_register_enums_h diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp index ae19367ca3ae0..c785d6fc10762 100644 --- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -55,6 +55,11 @@ lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp, const FileSpec *crash_file, bool can_connect) { lldb::ProcessSP process_sp; + + // Do not use ElfCore for DPU core, GDBRemote will be used instead + if (target_sp->GetArchitecture().GetTriple().getArch() == llvm::Triple::dpu) + return process_sp; + if (crash_file && !can_connect) { // Read enough data for a ELF32 header or ELF64 header Note: Here we care // about e_type field only, so it is safe to ignore possible presence of diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 4981345d6a181..bf2e9f4f7dbb6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -44,6 +44,7 @@ #define DEBUGSERVER_BASENAME "lldb-server.exe" #else #define DEBUGSERVER_BASENAME "lldb-server" +#define DEBUGSERVER_BASENAME_DPU "lldb-server-dpu" #endif #if defined(HAVE_LIBCOMPRESSION) @@ -920,6 +921,7 @@ Status GDBRemoteCommunication::StartDebugserverProcess( // Always check to see if we have an environment override for the path to the // debugserver to use and use it if we do. std::string env_debugserver_path = host_env.lookup("LLDB_DEBUGSERVER_PATH"); + ArchSpec dpu_arch("dpu-upmem-dpurte"); if (!env_debugserver_path.empty()) { debugserver_file_spec.SetFile(env_debugserver_path, FileSpec::Style::native); @@ -927,6 +929,14 @@ Status GDBRemoteCommunication::StartDebugserverProcess( "GDBRemoteCommunication::%s() gdb-remote stub exe path set " "from environment variable: %s", __FUNCTION__, env_debugserver_path.c_str()); + } else if (launch_info.GetArch() == dpu_arch) { + debugserver_file_spec = HostInfo::GetSupportExeDir(); + if (debugserver_file_spec) { + debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME_DPU); + } else { + debugserver_file_spec = + platform->LocateExecutable(DEBUGSERVER_BASENAME_DPU); + } } else debugserver_file_spec = g_debugserver_file_spec; bool debugserver_exists = diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index d375a312ae2ce..057159601d73c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -3372,6 +3372,73 @@ bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) { response.IsOKResponse(); } +void GDBRemoteCommunicationClient::SendDpuPrintInfoPacket( + const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, const uint32_t print_buffer_var_addr, + Status &error) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("qDpuPrintInfo:"); + + StructuredData::Dictionary json_packet; + json_packet.AddIntegerItem("open_print_sequence_addr", + open_print_sequence_addr); + json_packet.AddIntegerItem("close_print_sequence_addr", + close_print_sequence_addr); + json_packet.AddIntegerItem("print_buffer_addr", print_buffer_addr); + json_packet.AddIntegerItem("print_buffer_size", print_buffer_size); + json_packet.AddIntegerItem("print_buffer_var_addr", print_buffer_var_addr); + + StreamString json_string; + json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsNormalResponse()) { + error = response.GetStatus(); + LLDB_LOG(log, "Target does not support SaveCore, error {0}}", error); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + escaped_packet.GetData()); + } +} + +void GDBRemoteCommunicationClient::SendSaveCorePacket( + const char *save_core_filename, const char *executable_path, + Status &error) { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jSaveCore:"); + + StructuredData::Dictionary json_packet; + json_packet.AddStringItem("save_core_filename", save_core_filename); + json_packet.AddStringItem("executable_path", executable_path); + + StreamString json_string; + json_packet.Dump(json_string, false); + escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize()); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsNormalResponse()) { + error = response.GetStatus(); + LLDB_LOG(log, "Target does not support SaveCore, error {0}}", error); + } + } else { + LLDB_LOG(log, "failed to send packet"); + error.SetErrorStringWithFormat("failed to send packet: '%s'", + escaped_packet.GetData()); + } +} + lldb::user_id_t GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options, Status &error) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index af3755fce7745..367a61187f53f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -505,6 +505,16 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { ConfigureRemoteStructuredData(ConstString type_name, const StructuredData::ObjectSP &config_sp); + void SendDpuPrintInfoPacket(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr, + Status &error); + + void SendSaveCorePacket(const char *save_core_filename, + const char *executable_path, Status &error); + lldb::user_id_t SendStartTracePacket(const TraceOptions &options, Status &error); diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 62a09a2a432cd..472eb732d81c8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -185,6 +185,13 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { StringExtractorGDBRemote::eServerPacketType_QPassSignals, &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_qDpuPrintInfo, + &GDBRemoteCommunicationServerLLGS::Handle_qDpuPrintInfo); + + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jSaveCore, + &GDBRemoteCommunicationServerLLGS::Handle_jSaveCore); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceStart, &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart); @@ -1169,6 +1176,78 @@ void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { } } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_qDpuPrintInfo( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("qDpuPrintInfo:")) + return SendIllFormedResponse(packet, "qDpuPrintInfo: Ill formed packet "); + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "qDpuPrintInfo: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + uint32_t open_print_sequence_addr, close_print_sequence_addr, + print_buffer_addr, print_buffer_size, print_buffer_var_addr; + Status error; + + json_dict->GetValueForKeyAsInteger("open_print_sequence_addr", + open_print_sequence_addr); + json_dict->GetValueForKeyAsInteger("close_print_sequence_addr", + close_print_sequence_addr); + json_dict->GetValueForKeyAsInteger("print_buffer_addr", print_buffer_addr); + json_dict->GetValueForKeyAsInteger("print_buffer_size", print_buffer_size); + json_dict->GetValueForKeyAsInteger("print_buffer_var_addr", + print_buffer_var_addr); + + m_debugged_process_up->SetDpuPrintInfo( + open_print_sequence_addr, close_print_sequence_addr, print_buffer_addr, + print_buffer_size, print_buffer_var_addr, error); + + return SendPacketNoLock(""); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jSaveCore( + StringExtractorGDBRemote &packet) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(68); + + if (!packet.ConsumeFront("jSaveCore:")) + return SendIllFormedResponse(packet, "jSaveCore: Ill formed packet "); + + auto json_object = StructuredData::ParseJSON(packet.Peek()); + + if (!json_object || + json_object->GetType() != lldb::eStructuredDataTypeDictionary) + return SendIllFormedResponse(packet, "jSaveCore: Ill formed packet "); + + auto json_dict = json_object->GetAsDictionary(); + + ConstString save_core_filename, executable_path; + Status error; + + json_dict->GetValueForKeyAsString("save_core_filename", save_core_filename); + json_dict->GetValueForKeyAsString("executable_path", executable_path); + + m_debugged_process_up->SaveCore(save_core_filename.AsCString(), + executable_path.AsCString(), error); + + return SendPacketNoLock(""); +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( StringExtractorGDBRemote &packet) { @@ -1481,9 +1560,8 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", m_debugged_process_up->GetID(), error); - // No OK response for kill packet. - // return SendOKResponse (); - return PacketResult::Success; + // kill packet wait for an answer, let's just give him one. + return SendPacketNoLock("X00"); } GDBRemoteCommunication::PacketResult diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index c511399245592..440faaa1d23b9 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -167,6 +167,10 @@ class GDBRemoteCommunicationServerLLGS PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet); + PacketResult Handle_qDpuPrintInfo(StringExtractorGDBRemote &packet); + + PacketResult Handle_jSaveCore(StringExtractorGDBRemote &packet); + PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet); PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index aba870c42e551..3d46cee1f7508 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -33,6 +33,7 @@ #include "lldb/Breakpoint/Watchpoint.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/StreamFile.h" @@ -61,6 +62,7 @@ #include "lldb/Target/ABI.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/SystemRuntime.h" #include "lldb/Target/Target.h" #include "lldb/Target/TargetList.h" @@ -208,8 +210,8 @@ ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp, const FileSpec *crash_file_path, bool can_connect) { lldb::ProcessSP process_sp; - if (crash_file_path == nullptr) - process_sp = std::make_shared(target_sp, listener_sp); + process_sp = std::make_shared(target_sp, listener_sp, + crash_file_path); return process_sp; } @@ -222,16 +224,15 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, Module *exe_module = target_sp->GetExecutableModulePointer(); if (exe_module) { ObjectFile *exe_objfile = exe_module->GetObjectFile(); - // We can't debug core files... switch (exe_objfile->GetType()) { case ObjectFile::eTypeInvalid: - case ObjectFile::eTypeCoreFile: case ObjectFile::eTypeDebugInfo: case ObjectFile::eTypeObjectFile: case ObjectFile::eTypeSharedLibrary: case ObjectFile::eTypeStubLibrary: case ObjectFile::eTypeJIT: return false; + case ObjectFile::eTypeCoreFile: case ObjectFile::eTypeExecutable: case ObjectFile::eTypeDynamicLinker: case ObjectFile::eTypeUnknown: @@ -244,9 +245,58 @@ bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp, return true; } +Status ProcessGDBRemote::DoLoadCore() { + Status error; + Target &target = GetTarget(); + // Save the initial_module for later + const lldb::ModuleSP initial_module = target.GetExecutableModule(); + + // Set m_crash_file_path as executable module + lldb::ModuleSP module( + new Module(*m_crash_file_path, target.GetArchitecture())); + module->GetObjectFile()->SetType(ObjectFile::Type::eTypeExecutable); + target.SetExecutableModule(module, eLoadDependentsNo); + + // Check if we have a initial_module, otherwise return + if (!initial_module) + return error; + + // Add initial_module in the target modules list + ModuleList matching_modules; + matching_modules.Append(initial_module); + ModuleSpec initial_module_spec(initial_module->GetFileSpec()); + target.GetOrCreateModule(initial_module_spec, false); + + // Load the section of the initial_module + SectionList *section_list = initial_module->GetSectionList(); + SectionSP section_sp; + addr_t addr; + switch (target.GetArchitecture().GetTriple().getArch()) { + case llvm::Triple::dpu: { + ConstString const_sect_name(".text"); + addr = 0x80000000; + section_sp = section_list->FindSectionByName(const_sect_name); + break; + } + default: + return Status("Cannot load core for this architecture\n"); + } + target.GetSectionLoadList().SetSectionLoadAddress(section_sp, addr); + + target.ModulesDidLoad(matching_modules); + lldb::ProcessSP process_sp = target.CalculateProcess(); + if (process_sp) { + process_sp->Destroy(true); + } + + return error; +} + +//---------------------------------------------------------------------- // ProcessGDBRemote constructor ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, - ListenerSP listener_sp) + ListenerSP listener_sp, + const FileSpec *crash_file_path) : Process(target_sp, listener_sp), m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(), m_register_info_sp(nullptr), @@ -261,7 +311,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_waiting_for_attach(false), m_destroy_tried_resuming(false), m_command_sp(), m_breakpoint_pc_offset(0), m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false), - m_allow_flash_writes(false), m_erased_flash_ranges() { + m_allow_flash_writes(false), m_erased_flash_ranges(), + m_crash_file_path(crash_file_path) { m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, @@ -1199,6 +1250,22 @@ Status ProcessGDBRemote::DoAttachToProcessWithName( return error; } +void ProcessGDBRemote::SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr, + Status &error) { + m_gdb_comm.SendDpuPrintInfoPacket( + open_print_sequence_addr, close_print_sequence_addr, print_buffer_addr, + print_buffer_size, print_buffer_var_addr, error); +} + +void ProcessGDBRemote::SaveCore(const char *save_core_filename, + const char *executable_path, Status &error) { + m_gdb_comm.SendSaveCorePacket(save_core_filename, executable_path, error); +} + lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options, Status &error) { return m_gdb_comm.SendStartTracePacket(options, error); @@ -3430,6 +3497,7 @@ Status ProcessGDBRemote::LaunchAndConnectToDebugserver( debugserver_launch_info.SetMonitorProcessCallback( std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), false); debugserver_launch_info.SetUserID(process_info.GetUserID()); + debugserver_launch_info.SetArch(process_info.GetArchitecture()); #if defined(__APPLE__) // On macOS 11, we need to support x86_64 applications translated to diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 0921bf17c4e4c..042c96bc48b6c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -49,7 +49,8 @@ class ThreadGDBRemote; class ProcessGDBRemote : public Process, private GDBRemoteClientBase::ContinueDelegate { public: - ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); + ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp, + const FileSpec *crash_file_path); ~ProcessGDBRemote() override; @@ -72,6 +73,8 @@ class ProcessGDBRemote : public Process, bool CanDebug(lldb::TargetSP target_sp, bool plugin_specified_by_name) override; + lldb_private::Status DoLoadCore() override; + CommandObject *GetPluginCommandObject() override; // Creating a new process, or attaching to an existing one @@ -163,6 +166,16 @@ class ProcessGDBRemote : public Process, Status GetWatchpointSupportInfo(uint32_t &num) override; + void SetDpuPrintInfo(const uint32_t open_print_sequence_addr, + const uint32_t close_print_sequence_addr, + const uint32_t print_buffer_addr, + const uint32_t print_buffer_size, + const uint32_t print_buffer_var_addr, + Status &error) override; + + void SaveCore(const char *save_core_filename, const char *executable_path, + Status &error) override; + lldb::user_id_t StartTrace(const TraceOptions &options, Status &error) override; @@ -415,6 +428,7 @@ class ProcessGDBRemote : public Process, std::string m_partial_profile_data; std::map m_thread_id_to_used_usec_map; uint64_t m_last_signals_version = 0; + const FileSpec *m_crash_file_path; static bool NewThreadNotifyBreakpointHit(void *baton, StoppointCallbackContext *context, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 421298802645b..bce25297c4c74 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -173,6 +173,7 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data, break; case DW_FORM_strp: + case DW_FORM_line_strp: case DW_FORM_sec_offset: data.GetU32(&offset); break; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index 305f1cbd2826a..ec78c5bbc9f4e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -150,40 +150,40 @@ struct FormSize { uint8_t valid:1, size:7; }; static FormSize g_form_sizes[] = { - {0,0}, // 0x00 unused - {0,0}, // 0x01 DW_FORM_addr - {0,0}, // 0x02 unused - {0,0}, // 0x03 DW_FORM_block2 - {0,0}, // 0x04 DW_FORM_block4 - {1,2}, // 0x05 DW_FORM_data2 - {1,4}, // 0x06 DW_FORM_data4 - {1,8}, // 0x07 DW_FORM_data8 - {0,0}, // 0x08 DW_FORM_string - {0,0}, // 0x09 DW_FORM_block - {0,0}, // 0x0a DW_FORM_block1 - {1,1}, // 0x0b DW_FORM_data1 - {1,1}, // 0x0c DW_FORM_flag - {0,0}, // 0x0d DW_FORM_sdata - {1,4}, // 0x0e DW_FORM_strp - {0,0}, // 0x0f DW_FORM_udata - {0,0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes for - // DWARF32, 8 bytes for DWARF32 in DWARF 3 and later - {1,1}, // 0x11 DW_FORM_ref1 - {1,2}, // 0x12 DW_FORM_ref2 - {1,4}, // 0x13 DW_FORM_ref4 - {1,8}, // 0x14 DW_FORM_ref8 - {0,0}, // 0x15 DW_FORM_ref_udata - {0,0}, // 0x16 DW_FORM_indirect - {1,4}, // 0x17 DW_FORM_sec_offset - {0,0}, // 0x18 DW_FORM_exprloc - {1,0}, // 0x19 DW_FORM_flag_present - {0,0}, // 0x1a - {0,0}, // 0x1b - {0,0}, // 0x1c - {0,0}, // 0x1d - {0,0}, // 0x1e - {0,0}, // 0x1f - {1,8}, // 0x20 DW_FORM_ref_sig8 + {0, 0}, // 0x00 unused + {0, 0}, // 0x01 DW_FORM_addr + {0, 0}, // 0x02 unused + {0, 0}, // 0x03 DW_FORM_block2 + {0, 0}, // 0x04 DW_FORM_block4 + {1, 2}, // 0x05 DW_FORM_data2 + {1, 4}, // 0x06 DW_FORM_data4 + {1, 8}, // 0x07 DW_FORM_data8 + {0, 0}, // 0x08 DW_FORM_string + {0, 0}, // 0x09 DW_FORM_block + {0, 0}, // 0x0a DW_FORM_block1 + {1, 1}, // 0x0b DW_FORM_data1 + {1, 1}, // 0x0c DW_FORM_flag + {0, 0}, // 0x0d DW_FORM_sdata + {1, 4}, // 0x0e DW_FORM_strp + {0, 0}, // 0x0f DW_FORM_udata + {0, 0}, // 0x10 DW_FORM_ref_addr (addr size for DWARF2 and earlier, 4 bytes + // for DWARF32, 8 bytes for DWARF32 in DWARF 3 and later + {1, 1}, // 0x11 DW_FORM_ref1 + {1, 2}, // 0x12 DW_FORM_ref2 + {1, 4}, // 0x13 DW_FORM_ref4 + {1, 8}, // 0x14 DW_FORM_ref8 + {0, 0}, // 0x15 DW_FORM_ref_udata + {0, 0}, // 0x16 DW_FORM_indirect + {1, 4}, // 0x17 DW_FORM_sec_offset + {0, 0}, // 0x18 DW_FORM_exprloc + {1, 0}, // 0x19 DW_FORM_flag_present + {0, 0}, // 0x1a DW_FORM_strx (ULEB128) + {0, 0}, // 0x1b DW_FORM_addrx (ULEB128) + {1, 4}, // 0x1c DW_FORM_ref_sup4 + {0, 0}, // 0x1d DW_FORM_strp_sup (4 bytes for DWARF32, 8 bytes for DWARF64) + {1, 16}, // 0x1e DW_FORM_data16 + {1, 4}, // 0x1f DW_FORM_line_strp + {1, 8}, // 0x20 DW_FORM_ref_sig8 }; llvm::Optional @@ -286,6 +286,7 @@ bool DWARFFormValue::SkipValue(dw_form_t form, // 32 bit for DWARF 32, 64 for DWARF 64 case DW_FORM_sec_offset: case DW_FORM_strp: + case DW_FORM_line_strp: *offset_ptr += 4; return true; @@ -398,7 +399,8 @@ void DWARFFormValue::Dump(Stream &s) const { case DW_FORM_udata: s.PutULEB128(uvalue); break; - case DW_FORM_strp: { + case DW_FORM_strp: + case DW_FORM_line_strp: { const char *dbg_str = AsCString(); if (dbg_str) { s.QuotedCString(dbg_str); @@ -606,6 +608,7 @@ bool DWARFFormValue::FormIsSupported(dw_form_t form) { case DW_FORM_flag: case DW_FORM_sdata: case DW_FORM_strp: + case DW_FORM_line_strp: case DW_FORM_strx: case DW_FORM_strx1: case DW_FORM_strx2: diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index a77ecddfbab65..ee816b1b6ce85 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -1969,6 +1969,12 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target, trap_opcode = g_i386_opcode; trap_opcode_size = sizeof(g_i386_opcode); } break; + case llvm::Triple::dpu: { + static const uint8_t g_dpu_opcode[] = {0x00, 0x00, 0x00, 0x20, + 0x63, 0x7e, 0x00, 0x00}; + trap_opcode = g_dpu_opcode; + trap_opcode_size = sizeof(g_dpu_opcode); + } break; default: return 0; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 518a6934059e0..457f9b37b065a 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1353,7 +1353,7 @@ bool Process::StateChangedIsHijackedForSynchronousResume() { StateType Process::GetPrivateState() { return m_private_state.GetValue(); } void Process::SetPrivateState(StateType new_state) { - if (m_finalizing) + if (m_finalizing && (new_state != lldb::eStateExited)) return; Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_STATE | diff --git a/lldb/source/Target/StackID.cpp b/lldb/source/Target/StackID.cpp index 410d5b7e820a5..cc22912143674 100644 --- a/lldb/source/Target/StackID.cpp +++ b/lldb/source/Target/StackID.cpp @@ -7,9 +7,11 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/StackID.h" +#include "lldb/Core/Module.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Stream.h" using namespace lldb_private; @@ -70,8 +72,15 @@ bool lldb_private::operator<(const StackID &lhs, const StackID &rhs) { // constructor. But I'm not going to waste a bool per StackID on this till we // need it. - if (lhs_cfa != rhs_cfa) - return lhs_cfa < rhs_cfa; + if (lhs_cfa != rhs_cfa) { + ArchSpec dpu_arch("dpu-upmem-dpurte"); + if (lhs.GetSymbolContextScope() + ->CalculateSymbolContextModule() + ->GetArchitecture() == dpu_arch) + return lhs_cfa > rhs_cfa; + else + return lhs_cfa < rhs_cfa; + } SymbolContextScope *lhs_scope = lhs.GetSymbolContextScope(); SymbolContextScope *rhs_scope = rhs.GetSymbolContextScope(); diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 049e458d8b19d..d72ebb9cdf0ea 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "lldb/Target/Thread.h" +#include "Plugins/Process/Utility/UnwindDPU.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/FormatEntity.h" @@ -1353,8 +1354,21 @@ ThreadPlanSP Thread::QueueThreadPlanForStepThrough(StackID &return_stack_id, bool abort_other_plans, bool stop_other_threads, Status &status) { - ThreadPlanSP thread_plan_sp( - new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads)); + ThreadPlanSP thread_plan_sp; + ArchSpec dpu_arch("dpu-upmem-dpurte"); + Target *target = CalculateTarget().get(); + if (target->GetArchitecture() == dpu_arch) { + lldb::StackFrameSP stack_frame_sp = + GetStackFrameList()->GetFrameWithStackID(return_stack_id); + if (!stack_frame_sp) + return thread_plan_sp; + thread_plan_sp.reset(new ThreadPlanRunToAddress( + *this, stack_frame_sp->GetFrameCodeAddress().GetLoadAddress(target), + stop_other_threads)); + } else { + thread_plan_sp.reset( + new ThreadPlanStepThrough(*this, return_stack_id, stop_other_threads)); + } if (!thread_plan_sp || !thread_plan_sp->ValidatePlan(nullptr)) return ThreadPlanSP(); @@ -1868,8 +1882,14 @@ size_t Thread::GetStackFrameStatus(Stream &strm, uint32_t first_frame, } Unwind &Thread::GetUnwinder() { - if (!m_unwinder_up) - m_unwinder_up = std::make_unique(*this); + if (!m_unwinder_up) { + const ArchSpec target_arch(CalculateTarget()->GetArchitecture()); + const llvm::Triple::ArchType machine = target_arch.GetMachine(); + if (machine == llvm::Triple::dpu) + m_unwinder_up = std::make_unique(*this); + else + m_unwinder_up = std::make_unique(*this); + } return *m_unwinder_up; } diff --git a/lldb/source/Target/ThreadPlanStepInRange.cpp b/lldb/source/Target/ThreadPlanStepInRange.cpp index a03bd93ac6381..ffd814d23f009 100644 --- a/lldb/source/Target/ThreadPlanStepInRange.cpp +++ b/lldb/source/Target/ThreadPlanStepInRange.cpp @@ -18,6 +18,7 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanStepOut.h" #include "lldb/Target/ThreadPlanStepThrough.h" +#include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" @@ -216,7 +217,10 @@ bool ThreadPlanStepInRange::ShouldStop(Event *event_ptr) { // We may have set the plan up above in the FrameIsOlder section: - if (!m_sub_plan_sp) + // DPU do not have a plan up above, do not try to step through + ArchSpec dpu_arch("dpu-upmem-dpurte"); + if (!m_sub_plan_sp && + !(dpu_arch == thread.CalculateTarget()->GetArchitecture())) m_sub_plan_sp = thread.QueueThreadPlanForStepThrough( m_stack_id, false, stop_others, m_status); diff --git a/lldb/source/Utility/ArchSpec.cpp b/lldb/source/Utility/ArchSpec.cpp index c13e2389cfed1..2034a56c9707c 100644 --- a/lldb/source/Utility/ArchSpec.cpp +++ b/lldb/source/Utility/ArchSpec.cpp @@ -229,6 +229,9 @@ static const CoreDefinition g_core_definitions[] = { {eByteOrderLittle, 4, 1, 4, llvm::Triple::wasm32, ArchSpec::eCore_wasm32, "wasm32"}, + + {eByteOrderLittle, 4, 8, 8, llvm::Triple::dpu, ArchSpec::eCore_dpu, + "dpu"}, }; // Ensure that we have an entry in the g_core_definitions for each core. If you @@ -405,6 +408,8 @@ static const ArchDefinitionEntry g_elf_arch_entries[] = { ArchSpec::eRISCVSubType_riscv32, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv32 {ArchSpec::eCore_riscv64, llvm::ELF::EM_RISCV, ArchSpec::eRISCVSubType_riscv64, 0xFFFFFFFFu, 0xFFFFFFFFu}, // riscv64 + {ArchSpec::eCore_dpu, llvm::ELF::EM_DPU, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // DPU }; static const ArchDefinition g_elf_arch_def = { diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index def0968664261..9befb6d1840e2 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -173,6 +173,11 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_qC; break; + case 'D': + if (PACKET_STARTS_WITH("qDpuPrintInfo:")) + return eServerPacketType_qDpuPrintInfo; + break; + case 'E': if (PACKET_STARTS_WITH("qEcho:")) return eServerPacketType_qEcho; @@ -310,6 +315,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_jTraceStart; if (PACKET_STARTS_WITH("jTraceStop:")) return eServerPacketType_jTraceStop; + if (PACKET_STARTS_WITH("jSaveCore:")) + return eServerPacketType_jSaveCore; if (PACKET_MATCHES("jLLDBTraceSupportedType")) return eServerPacketType_jLLDBTraceSupportedType; break; diff --git a/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp b/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp index 5cf5ff3562030..532d6a8d72046 100644 --- a/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp +++ b/lldb/test/API/api/multiple-debuggers/multi-process-driver.cpp @@ -216,8 +216,8 @@ void *do_one_debugger (void *in) return (void*) 1; } -int main (int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + #if !defined(_MSC_VER) signal(SIGPIPE, SIG_IGN); #endif diff --git a/lldb/test/API/api/multiple-targets/main.cpp b/lldb/test/API/api/multiple-targets/main.cpp index 35fb4e0d613ed..a9653adb41833 100644 --- a/lldb/test/API/api/multiple-targets/main.cpp +++ b/lldb/test/API/api/multiple-targets/main.cpp @@ -5,8 +5,8 @@ #include "lldb/API/SBTarget.h" using namespace lldb; -int main (int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + // We are expecting the program path and a path to an executable to load if (argc != 2) return 1; diff --git a/lldb/test/API/api/multithreaded/driver.cpp.template b/lldb/test/API/api/multithreaded/driver.cpp.template index 32459425c88c3..1a7c0b0f4e76b 100644 --- a/lldb/test/API/api/multithreaded/driver.cpp.template +++ b/lldb/test/API/api/multithreaded/driver.cpp.template @@ -19,7 +19,7 @@ using namespace lldb; void test(SBDebugger &dbg, std::vector args); -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; // Ignore SIGPIPE. The lldb driver does this as well, // because we seem to get spurious SIGPIPES on some diff --git a/lldb/test/API/benchmarks/expression/main.cpp b/lldb/test/API/benchmarks/expression/main.cpp index 1a095d350227b..ba44ce91fec70 100644 --- a/lldb/test/API/benchmarks/expression/main.cpp +++ b/lldb/test/API/benchmarks/expression/main.cpp @@ -20,7 +20,7 @@ class Data { {} }; -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; Data *data[1000]; Data **ptr = data; for (int i = 0; i < 1000; ++i) { diff --git a/lldb/test/API/commands/command/script/import/main.c b/lldb/test/API/commands/command/script/import/main.c index dffc8c77b04c4..9bfbd72a68dd8 100644 --- a/lldb/test/API/commands/command/script/import/main.c +++ b/lldb/test/API/commands/command/script/import/main.c @@ -1,6 +1,6 @@ #include -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; printf("Hello world.\n"); // Set break point at this line. if (argc == 1) return 0; diff --git a/lldb/test/API/commands/command/script/main.cpp b/lldb/test/API/commands/command/script/main.cpp index b953498b0d37b..5351e62ceaf8f 100644 --- a/lldb/test/API/commands/command/script/main.cpp +++ b/lldb/test/API/commands/command/script/main.cpp @@ -41,8 +41,8 @@ foo (int i, int j) } int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + int array[9]; memset(array,0,9*sizeof(int)); diff --git a/lldb/test/API/commands/expression/expr-in-syscall/main.cpp b/lldb/test/API/commands/expression/expr-in-syscall/main.cpp index 743b69434d5fe..462695a980788 100644 --- a/lldb/test/API/commands/expression/expr-in-syscall/main.cpp +++ b/lldb/test/API/commands/expression/expr-in-syscall/main.cpp @@ -3,8 +3,8 @@ volatile int release_flag = 0; -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + while (! release_flag) // Wait for debugger to attach std::this_thread::sleep_for(std::chrono::seconds(3)); diff --git a/lldb/test/API/commands/expression/formatters/main.cpp b/lldb/test/API/commands/expression/formatters/main.cpp index 7360c479f10a5..9aafacb828ffa 100644 --- a/lldb/test/API/commands/expression/formatters/main.cpp +++ b/lldb/test/API/commands/expression/formatters/main.cpp @@ -38,8 +38,8 @@ foo *new_foo(int x) { } -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + foo foo1(12); foo foo2(121); foo * newd_foo = new_foo(1); diff --git a/lldb/test/API/commands/expression/import-std-module/basic/main.cpp b/lldb/test/API/commands/expression/import-std-module/basic/main.cpp index 2f6d078daa335..0ee28aabe5b7c 100644 --- a/lldb/test/API/commands/expression/import-std-module/basic/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/basic/main.cpp @@ -1,7 +1,7 @@ // We need to import any std module. It doesn't matter which one. #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::cout << "Test" << std::endl; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/conflicts/main.cpp b/lldb/test/API/commands/expression/import-std-module/conflicts/main.cpp index ea48c73bc9d5b..bfc6806db0c27 100644 --- a/lldb/test/API/commands/expression/import-std-module/conflicts/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/conflicts/main.cpp @@ -2,7 +2,7 @@ #include #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::size_t f = argc; f = std::abs(argc); f = std::div(argc * 2, argc).quot; diff --git a/lldb/test/API/commands/expression/import-std-module/deque-basic/main.cpp b/lldb/test/API/commands/expression/import-std-module/deque-basic/main.cpp index 5bed55674bfb3..cd3733271ec34 100644 --- a/lldb/test/API/commands/expression/import-std-module/deque-basic/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/deque-basic/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::deque a = {3, 1, 2}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/main.cpp index f8fd1fb2dd9cb..129074c2711b5 100644 --- a/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/main.cpp @@ -4,7 +4,7 @@ struct Foo { int a; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::deque a = {{3}, {1}, {2}}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp index b1ffc4b24cd03..e3b34cd5d1f63 100644 --- a/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp @@ -4,7 +4,7 @@ struct Foo { int a; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::forward_list a = {{3}, {1}, {2}}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/forward_list/main.cpp b/lldb/test/API/commands/expression/import-std-module/forward_list/main.cpp index 4f5e30f062991..b74545cf18c9e 100644 --- a/lldb/test/API/commands/expression/import-std-module/forward_list/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/forward_list/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::forward_list a = {3, 1, 2}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/main.cpp index 3cfb35f8c6b4b..9ce094ac926df 100644 --- a/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/main.cpp @@ -4,7 +4,7 @@ struct Foo { int a; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::list a = {{3}, {1}, {2}}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/list/main.cpp b/lldb/test/API/commands/expression/import-std-module/list/main.cpp index e54719a02fb14..1e9d17ac75f24 100644 --- a/lldb/test/API/commands/expression/import-std-module/list/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/list/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::list a = {3, 1, 2}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/no-std-module/main.cpp b/lldb/test/API/commands/expression/import-std-module/no-std-module/main.cpp index c93e9d0ec8ac3..eaf0b64bd02de 100644 --- a/lldb/test/API/commands/expression/import-std-module/no-std-module/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/no-std-module/main.cpp @@ -1,5 +1,5 @@ // We don't import any std module here. -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/queue/main.cpp b/lldb/test/API/commands/expression/import-std-module/queue/main.cpp index 66e8f02c27328..12f68e836383e 100644 --- a/lldb/test/API/commands/expression/import-std-module/queue/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/queue/main.cpp @@ -8,7 +8,7 @@ struct C { int i; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; // std::deque is the default container. std::queue q_deque({{1}}); std::queue> q_list({{1}}); diff --git a/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp index 73664f1c83a41..b70ff4b2acf08 100644 --- a/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp @@ -4,7 +4,7 @@ struct Foo { int a; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::shared_ptr s(new Foo); s->a = 3; return s->a; // Set break point at this line. diff --git a/lldb/test/API/commands/expression/import-std-module/shared_ptr/main.cpp b/lldb/test/API/commands/expression/import-std-module/shared_ptr/main.cpp index cb81754087fd7..72c5aa7f965c6 100644 --- a/lldb/test/API/commands/expression/import-std-module/shared_ptr/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/shared_ptr/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::shared_ptr s(new int); *s = 3; return *s; // Set break point at this line. diff --git a/lldb/test/API/commands/expression/import-std-module/stack/main.cpp b/lldb/test/API/commands/expression/import-std-module/stack/main.cpp index 0ce9499073345..54330aa07e6bf 100644 --- a/lldb/test/API/commands/expression/import-std-module/stack/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/stack/main.cpp @@ -8,7 +8,7 @@ struct C { int i; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; // std::deque is the default container. std::stack s_deque({{1}, {2}, {3}}); std::stack> s_vector({{1}, {2}, {3}}); diff --git a/lldb/test/API/commands/expression/import-std-module/sysroot/main.cpp b/lldb/test/API/commands/expression/import-std-module/sysroot/main.cpp index c01fadc5d8e47..72e572de28ec1 100644 --- a/lldb/test/API/commands/expression/import-std-module/sysroot/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/sysroot/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; libc_struct s; std::vector v; return 0; // Set break point at this line. diff --git a/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp index 4e81e6beee858..b70ff4b2acf08 100644 --- a/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp @@ -4,8 +4,8 @@ struct Foo { int a; }; -int main(int argc, char **argv) { - std::unique_ptr s(new Foo); +int main() { int argc = 0; char **argv = (char **)0; + std::shared_ptr s(new Foo); s->a = 3; return s->a; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/unique_ptr/main.cpp b/lldb/test/API/commands/expression/import-std-module/unique_ptr/main.cpp index dd7dbe638aed8..72c5aa7f965c6 100644 --- a/lldb/test/API/commands/expression/import-std-module/unique_ptr/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/unique_ptr/main.cpp @@ -1,7 +1,7 @@ #include -int main(int argc, char **argv) { - std::unique_ptr s(new int); +int main() { int argc = 0; char **argv = (char **)0; + std::shared_ptr s(new int); *s = 3; return *s; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/vector-bool/main.cpp b/lldb/test/API/commands/expression/import-std-module/vector-bool/main.cpp index 9554401cf5085..77da4794eec7d 100644 --- a/lldb/test/API/commands/expression/import-std-module/vector-bool/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/vector-bool/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::vector a = {0, 1, 0, 1}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/vector-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/vector-dbg-info-content/main.cpp index 24c3fec75d2f5..a50c3084f51cc 100644 --- a/lldb/test/API/commands/expression/import-std-module/vector-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/vector-dbg-info-content/main.cpp @@ -4,7 +4,7 @@ struct Foo { int a; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::vector a = {{3}, {1}, {2}}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/main.cpp b/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/main.cpp index b5ada909e4397..8269f708eb4f4 100644 --- a/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::vector > a = {{1, 2, 3}, {3, 2, 1}}; return 0; // Set break point at this line. } diff --git a/lldb/test/API/commands/expression/import-std-module/vector/main.cpp b/lldb/test/API/commands/expression/import-std-module/vector/main.cpp index 668b59181d421..b4754b9f3d3db 100644 --- a/lldb/test/API/commands/expression/import-std-module/vector/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/vector/main.cpp @@ -1,7 +1,7 @@ #include typedef std::vector vector_long; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::vector a = {3, 1, 2}; vector_long b = {3, 1, 2}; return 0; // Set break point at this line. diff --git a/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp b/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp index d2c5a6258a5de..989f3c45db556 100644 --- a/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp @@ -4,7 +4,7 @@ struct Foo { int a; }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::shared_ptr s(new Foo); s->a = 3; std::weak_ptr w = s; diff --git a/lldb/test/API/commands/expression/import-std-module/weak_ptr/main.cpp b/lldb/test/API/commands/expression/import-std-module/weak_ptr/main.cpp index 13479eb94961e..6eaffc7320dda 100644 --- a/lldb/test/API/commands/expression/import-std-module/weak_ptr/main.cpp +++ b/lldb/test/API/commands/expression/import-std-module/weak_ptr/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::shared_ptr s(new int); *s = 3; std::weak_ptr w = s; diff --git a/lldb/test/API/commands/expression/inline-namespace/main.cpp b/lldb/test/API/commands/expression/inline-namespace/main.cpp index c10b361a0cd49..3a6fc797323b8 100644 --- a/lldb/test/API/commands/expression/inline-namespace/main.cpp +++ b/lldb/test/API/commands/expression/inline-namespace/main.cpp @@ -4,7 +4,7 @@ namespace A { }; } -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; // Set break point at this line. return A::f(); } diff --git a/lldb/test/API/commands/expression/options/main.cpp b/lldb/test/API/commands/expression/options/main.cpp index 0d30c79bd229e..db605f184ea99 100644 --- a/lldb/test/API/commands/expression/options/main.cpp +++ b/lldb/test/API/commands/expression/options/main.cpp @@ -10,8 +10,8 @@ bar() return static_value + id; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + bar(); // breakpoint_in_main return foo(); } diff --git a/lldb/test/API/commands/expression/pr35310/main.cpp b/lldb/test/API/commands/expression/pr35310/main.cpp index a8e8a5c737a01..65ff0f7d45898 100644 --- a/lldb/test/API/commands/expression/pr35310/main.cpp +++ b/lldb/test/API/commands/expression/pr35310/main.cpp @@ -10,7 +10,7 @@ class A { } }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; A a; // Break here a.test_abi_tag(); diff --git a/lldb/test/API/commands/expression/radar_8638051/main.c b/lldb/test/API/commands/expression/radar_8638051/main.c index dbfcefe802d2a..f3e93edeef1b7 100644 --- a/lldb/test/API/commands/expression/radar_8638051/main.c +++ b/lldb/test/API/commands/expression/radar_8638051/main.c @@ -31,8 +31,8 @@ int c(int val) return val + 3; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/commands/expression/scoped_enums/main.cpp b/lldb/test/API/commands/expression/scoped_enums/main.cpp index b0d67d23dc5e5..5c5aa709b5dba 100644 --- a/lldb/test/API/commands/expression/scoped_enums/main.cpp +++ b/lldb/test/API/commands/expression/scoped_enums/main.cpp @@ -7,7 +7,7 @@ enum Bar { BarBarBar = 42 }; -int main(int argc, const char **argv) { +int main() { int argc = 0; char **argv = (char **)0; Foo f = Foo::FooBar; Bar b = BarBar; bool b1 = f == Foo::FooBar; diff --git a/lldb/test/API/commands/expression/test/main.cpp b/lldb/test/API/commands/expression/test/main.cpp index 22208a87cb446..270b5b7021c34 100644 --- a/lldb/test/API/commands/expression/test/main.cpp +++ b/lldb/test/API/commands/expression/test/main.cpp @@ -9,8 +9,8 @@ a_function_to_call() return static_value; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + printf ("Hello world!\n"); puts ("hello"); // Please test many expressions while stopped at this line: diff --git a/lldb/test/API/commands/expression/timeout/wait-a-while.cpp b/lldb/test/API/commands/expression/timeout/wait-a-while.cpp index ac37c5d243b29..f5ce3728617bb 100644 --- a/lldb/test/API/commands/expression/timeout/wait-a-while.cpp +++ b/lldb/test/API/commands/expression/timeout/wait-a-while.cpp @@ -24,8 +24,8 @@ wait_a_while (int microseconds) } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + printf ("stop here in main.\n"); int num_times = wait_a_while (argc * 1000); printf ("Done, took %d times.\n", num_times); diff --git a/lldb/test/API/commands/expression/unwind_expression/main.cpp b/lldb/test/API/commands/expression/unwind_expression/main.cpp index 56b06f31eccae..574615b7ecaad 100644 --- a/lldb/test/API/commands/expression/unwind_expression/main.cpp +++ b/lldb/test/API/commands/expression/unwind_expression/main.cpp @@ -14,8 +14,8 @@ int second_function(int x){ return x; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + a_function_to_call(); // Set a breakpoint here to get started second_function(1); return 0; diff --git a/lldb/test/API/commands/expression/xvalue/main.cpp b/lldb/test/API/commands/expression/xvalue/main.cpp index 556c63f2b4499..95345c8a19ef5 100644 --- a/lldb/test/API/commands/expression/xvalue/main.cpp +++ b/lldb/test/API/commands/expression/xvalue/main.cpp @@ -5,8 +5,8 @@ struct Tmp Tmp foo() { return Tmp(); } -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int something = foo().data; return 0; // Break here } diff --git a/lldb/test/API/commands/frame/diagnose/inheritance/main.cpp b/lldb/test/API/commands/frame/diagnose/inheritance/main.cpp index 78cac2c89653b..ff3dd60d329cd 100644 --- a/lldb/test/API/commands/frame/diagnose/inheritance/main.cpp +++ b/lldb/test/API/commands/frame/diagnose/inheritance/main.cpp @@ -60,8 +60,8 @@ class D : public C, public B protected: int m_d; }; -int main (int argc, char const *argv[], char const *envp[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + D *good_d = new D(1, 2, 3, 4); D *d = nullptr; return d->get(); diff --git a/lldb/test/API/commands/frame/var-scope/main.c b/lldb/test/API/commands/frame/var-scope/main.c index 86af937807ffc..7e9ff1b8e426a 100644 --- a/lldb/test/API/commands/frame/var-scope/main.c +++ b/lldb/test/API/commands/frame/var-scope/main.c @@ -6,7 +6,11 @@ int foo(int x, int y) { //% self.expect("frame variable -s z", substrs=['LOCAL: (int) z = 0']) } -int main (int argc, char const *argv[]) +int __main(int argc, char **argv) { return foo(-3,0); //% self.expect("frame variable -s argc argv", substrs=['ARG: (int) argc =']) } + +int main() { + return __main(0, (char **)0); +} diff --git a/lldb/test/API/commands/log/basic/main.cpp b/lldb/test/API/commands/log/basic/main.cpp index c883ce82c92ba..59efff4680fca 100644 --- a/lldb/test/API/commands/log/basic/main.cpp +++ b/lldb/test/API/commands/log/basic/main.cpp @@ -40,8 +40,8 @@ foo (int i, int j) } int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + int array[3]; diff --git a/lldb/test/API/commands/process/attach-resume/main.cpp b/lldb/test/API/commands/process/attach-resume/main.cpp index 82aad70eed560..f48a4c9aca921 100644 --- a/lldb/test/API/commands/process/attach-resume/main.cpp +++ b/lldb/test/API/commands/process/attach-resume/main.cpp @@ -19,8 +19,8 @@ void *start(void *data) return 0; } -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + lldb_enable_attach(); static const size_t nthreads = 16; diff --git a/lldb/test/API/commands/process/attach/attach_denied/main.cpp b/lldb/test/API/commands/process/attach/attach_denied/main.cpp index ff1fccae4b1c5..fb4eb95d2f3c0 100644 --- a/lldb/test/API/commands/process/attach/attach_denied/main.cpp +++ b/lldb/test/API/commands/process/attach/attach_denied/main.cpp @@ -58,8 +58,8 @@ void signal_handler (int) { } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + if (argc < 2) { fprintf (stderr, "invalid number of command line arguments\n"); diff --git a/lldb/test/API/commands/process/attach/main.cpp b/lldb/test/API/commands/process/attach/main.cpp index a43ed8eac5b26..c9abd53a68977 100644 --- a/lldb/test/API/commands/process/attach/main.cpp +++ b/lldb/test/API/commands/process/attach/main.cpp @@ -5,7 +5,7 @@ volatile int g_val = 12345; -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; int temp; lldb_enable_attach(); diff --git a/lldb/test/API/commands/process/launch-with-shellexpand/main.cpp b/lldb/test/API/commands/process/launch-with-shellexpand/main.cpp index cbef8d1e6da1d..a965caf0f4188 100644 --- a/lldb/test/API/commands/process/launch-with-shellexpand/main.cpp +++ b/lldb/test/API/commands/process/launch-with-shellexpand/main.cpp @@ -1,5 +1,5 @@ int -main (int argc, char const **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + return 0; // break here } diff --git a/lldb/test/API/commands/process/launch/main.cpp b/lldb/test/API/commands/process/launch/main.cpp index f2035d5516795..f14fca678faa8 100644 --- a/lldb/test/API/commands/process/launch/main.cpp +++ b/lldb/test/API/commands/process/launch/main.cpp @@ -2,8 +2,8 @@ #include int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + char buffer[1024]; fgets (buffer, sizeof (buffer), stdin); diff --git a/lldb/test/API/commands/process/launch/print_cwd.cpp b/lldb/test/API/commands/process/launch/print_cwd.cpp index b4b073fbcb8de..2dba3b1b86df4 100644 --- a/lldb/test/API/commands/process/launch/print_cwd.cpp +++ b/lldb/test/API/commands/process/launch/print_cwd.cpp @@ -10,8 +10,8 @@ #endif int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + char buffer[1024]; fprintf(stdout, "stdout: %s\n", getcwd(buffer, 1024)); diff --git a/lldb/test/API/commands/process/launch/print_env.cpp b/lldb/test/API/commands/process/launch/print_env.cpp index 8c6df8ea01a4d..45c1cbab9f186 100644 --- a/lldb/test/API/commands/process/launch/print_env.cpp +++ b/lldb/test/API/commands/process/launch/print_env.cpp @@ -2,8 +2,8 @@ #include #include -int main (int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + char *evil = getenv("EVIL"); return 0; // Set breakpoint here. diff --git a/lldb/test/API/commands/register/register/intel_xtended_registers/main.cpp b/lldb/test/API/commands/register/register/intel_xtended_registers/main.cpp index 7c1b5d50a9a6a..4966eeb8b04f6 100644 --- a/lldb/test/API/commands/register/register/intel_xtended_registers/main.cpp +++ b/lldb/test/API/commands/register/register/intel_xtended_registers/main.cpp @@ -4,8 +4,8 @@ #include int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + // PR_MPX_ENABLE_MANAGEMENT won't be defined on linux kernel versions below 3.19 #ifndef PR_MPX_ENABLE_MANAGEMENT return -1; diff --git a/lldb/test/API/commands/register/register/intel_xtended_registers/mpx_bound_violation/main.cpp b/lldb/test/API/commands/register/register/intel_xtended_registers/mpx_bound_violation/main.cpp index b08977a3521e2..75cfc4d2caacf 100644 --- a/lldb/test/API/commands/register/register/intel_xtended_registers/mpx_bound_violation/main.cpp +++ b/lldb/test/API/commands/register/register/intel_xtended_registers/mpx_bound_violation/main.cpp @@ -16,8 +16,8 @@ static void violate_lower_bound (int *ptr, int size) } int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + unsigned int rax, rbx, rcx, rdx; int array[5]; diff --git a/lldb/test/API/commands/register/register/register_command/main.cpp b/lldb/test/API/commands/register/register/register_command/main.cpp index 860dfef0b3b97..87954e25031c7 100644 --- a/lldb/test/API/commands/register/register/register_command/main.cpp +++ b/lldb/test/API/commands/register/register/register_command/main.cpp @@ -5,8 +5,8 @@ long double outermost_return_long_double (long double my_long_double); -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + lldb_enable_attach(); char my_string[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}; diff --git a/lldb/test/API/commands/settings/main.cpp b/lldb/test/API/commands/settings/main.cpp index e18f0ae52a9b1..5161db4f9edb7 100644 --- a/lldb/test/API/commands/settings/main.cpp +++ b/lldb/test/API/commands/settings/main.cpp @@ -9,8 +9,8 @@ int numberfn() } int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + // The program writes its output to the following file: // // o "output1.txt" for test_pass_host_env_vars() test case diff --git a/lldb/test/API/commands/settings/quoting/main.c b/lldb/test/API/commands/settings/quoting/main.c index 2ebaa142bc5ca..16ec6668f3cf5 100644 --- a/lldb/test/API/commands/settings/quoting/main.c +++ b/lldb/test/API/commands/settings/quoting/main.c @@ -4,8 +4,8 @@ /* This program writes its arguments (separated by '\0') to stdout. */ int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + int i; FILE *output = fopen (argv[1], "w"); diff --git a/lldb/test/API/commands/target/basic/c.c b/lldb/test/API/commands/target/basic/c.c index 8fdb850a7f8a6..9084e689b6a02 100644 --- a/lldb/test/API/commands/target/basic/c.c +++ b/lldb/test/API/commands/target/basic/c.c @@ -1,7 +1,7 @@ #include -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + enum days { Monday = 10, Tuesday, diff --git a/lldb/test/API/commands/target/basic/globals.c b/lldb/test/API/commands/target/basic/globals.c index 85ae646ff8414..55d31ae4b371a 100644 --- a/lldb/test/API/commands/target/basic/globals.c +++ b/lldb/test/API/commands/target/basic/globals.c @@ -5,8 +5,8 @@ const char* my_global_str = "abc"; const char **my_global_str_ptr = &my_global_str; static int my_static_int = 228; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + printf("global char: %c\n", my_global_char); printf("global str: %s\n", my_global_str); diff --git a/lldb/test/API/commands/watchpoints/hello_watchlocation/main.cpp b/lldb/test/API/commands/watchpoints/hello_watchlocation/main.cpp index 02499efcfea34..c9ecac043a92a 100644 --- a/lldb/test/API/commands/watchpoints/hello_watchlocation/main.cpp +++ b/lldb/test/API/commands/watchpoints/hello_watchlocation/main.cpp @@ -71,8 +71,8 @@ thread_func (uint32_t thread_index) } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + g_count = 4; std::thread threads[3]; diff --git a/lldb/test/API/commands/watchpoints/hello_watchpoint/main.c b/lldb/test/API/commands/watchpoints/hello_watchpoint/main.c index f007fb5a4f59f..be4214c0e6888 100644 --- a/lldb/test/API/commands/watchpoints/hello_watchpoint/main.c +++ b/lldb/test/API/commands/watchpoints/hello_watchpoint/main.c @@ -5,7 +5,7 @@ int32_t global = 10; // Watchpoint variable declaration. char gchar1 = 'a'; char gchar2 = 'b'; -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int local = 0; printf("&global=%p\n", &global); printf("about to write to 'global'...\n"); // Set break point at this line. diff --git a/lldb/test/API/commands/watchpoints/multiple_threads/main.cpp b/lldb/test/API/commands/watchpoints/multiple_threads/main.cpp index ec41e8e8ebfff..5f4fec0351968 100644 --- a/lldb/test/API/commands/watchpoints/multiple_threads/main.cpp +++ b/lldb/test/API/commands/watchpoints/multiple_threads/main.cpp @@ -13,7 +13,7 @@ void thread_func() { g_val = i; } -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; printf("Before running the thread\n"); pseudo_barrier_init(g_barrier, 2); pseudo_barrier_init(g_barrier2, 2); diff --git a/lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp b/lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp index 7dfdd62d50bcc..008dd32bee726 100644 --- a/lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp +++ b/lldb/test/API/commands/watchpoints/watchpoint_commands/command/main.cpp @@ -8,7 +8,7 @@ static void modify(int32_t &var) { ++var; } -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int local = 0; printf("&global=%p\n", &global); printf("about to write to 'global'...\n"); // Set break point at this line. diff --git a/lldb/test/API/commands/watchpoints/watchpoint_commands/condition/main.cpp b/lldb/test/API/commands/watchpoints/watchpoint_commands/condition/main.cpp index f0d14f3840412..caf1a11893785 100644 --- a/lldb/test/API/commands/watchpoints/watchpoint_commands/condition/main.cpp +++ b/lldb/test/API/commands/watchpoints/watchpoint_commands/condition/main.cpp @@ -7,7 +7,7 @@ static void modify(int32_t &var) { ++var; } -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int local = 0; printf("&global=%p\n", &global); printf("about to write to 'global'...\n"); // Set break point at this line. diff --git a/lldb/test/API/commands/watchpoints/watchpoint_commands/main.c b/lldb/test/API/commands/watchpoints/watchpoint_commands/main.c index 6a3036d3ce979..094010fe1396e 100644 --- a/lldb/test/API/commands/watchpoints/watchpoint_commands/main.c +++ b/lldb/test/API/commands/watchpoints/watchpoint_commands/main.c @@ -3,7 +3,7 @@ int32_t global = 10; // Watchpoint variable declaration. -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int local = 0; printf("&global=%p\n", &global); printf("about to write to 'global'...\n"); // Set break point at this line. diff --git a/lldb/test/API/commands/watchpoints/watchpoint_events/main.c b/lldb/test/API/commands/watchpoints/watchpoint_events/main.c index 4b917536a1610..ff5a59c1f4fce 100644 --- a/lldb/test/API/commands/watchpoints/watchpoint_events/main.c +++ b/lldb/test/API/commands/watchpoints/watchpoint_events/main.c @@ -1,8 +1,8 @@ #include int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + int local_var = 10; printf ("local_var is: %d.\n", local_var++); // Put a breakpoint here. return local_var; diff --git a/lldb/test/API/commands/watchpoints/watchpoint_set_command/main.cpp b/lldb/test/API/commands/watchpoints/watchpoint_set_command/main.cpp index cca5690b9224e..7c36c49ecd8e0 100644 --- a/lldb/test/API/commands/watchpoints/watchpoint_set_command/main.cpp +++ b/lldb/test/API/commands/watchpoints/watchpoint_set_command/main.cpp @@ -77,8 +77,8 @@ thread_func (uint32_t thread_index) } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + g_count = 4; std::thread threads[3]; diff --git a/lldb/test/API/commands/watchpoints/watchpoint_size/main.c b/lldb/test/API/commands/watchpoints/watchpoint_size/main.c index 216c5e0428795..5c2f834212b25 100644 --- a/lldb/test/API/commands/watchpoints/watchpoint_size/main.c +++ b/lldb/test/API/commands/watchpoints/watchpoint_size/main.c @@ -8,7 +8,7 @@ uint16_t wordArray[4] = {0}; uint64_t pad2 = 0; uint32_t dwordArray[2] = {0}; -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int i; uint8_t localByte; diff --git a/lldb/test/API/driver/batch_mode/main.c b/lldb/test/API/driver/batch_mode/main.c index c85a0f272d2c1..07c02e50ca130 100644 --- a/lldb/test/API/driver/batch_mode/main.c +++ b/lldb/test/API/driver/batch_mode/main.c @@ -3,8 +3,8 @@ #include int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + lldb_enable_attach(); int do_crash = 0; diff --git a/lldb/test/API/functionalities/asan/main.c b/lldb/test/API/functionalities/asan/main.c index 85e7c5ec64edb..b22da8077a616 100644 --- a/lldb/test/API/functionalities/asan/main.c +++ b/lldb/test/API/functionalities/asan/main.c @@ -13,8 +13,8 @@ void f2() { free(pointer); // free line } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + f1(); f2(); diff --git a/lldb/test/API/functionalities/avoids-fd-leak/main.c b/lldb/test/API/functionalities/avoids-fd-leak/main.c index 5bdf227928edc..4d3b4918c12ef 100644 --- a/lldb/test/API/functionalities/avoids-fd-leak/main.c +++ b/lldb/test/API/functionalities/avoids-fd-leak/main.c @@ -5,8 +5,8 @@ #include int -main (int argc, char const **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + struct stat buf; int i, rv = 0; // Set breakpoint here. diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_conditions/main.c b/lldb/test/API/functionalities/breakpoint/breakpoint_conditions/main.c index abe769cbea481..8f414a917bdcc 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_conditions/main.c +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_conditions/main.c @@ -28,8 +28,8 @@ int c(int val) return val + 3; // Find the line number of function "c" here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_ids/main.cpp b/lldb/test/API/functionalities/breakpoint/breakpoint_ids/main.cpp index 2c70d81a2fef7..2938b55aca0af 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_ids/main.cpp +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_ids/main.cpp @@ -43,8 +43,8 @@ foo (int i, int j) } int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + int array[3]; diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c b/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c index 3f80f22fb2bba..cb8bdde15e5c3 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_ignore_count/main.c @@ -29,8 +29,8 @@ int c(int val) return val + 3; // Find the line number of function "c" here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/main.c b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/main.c index f6ccb031c7445..4e7616f2a29f0 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_locations/main.c +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_locations/main.c @@ -22,8 +22,8 @@ func_inlined (void) extern int func_inlined (void); int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + printf ("Starting...\n"); int (*func_ptr) (void); diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_names/main.c b/lldb/test/API/functionalities/breakpoint/breakpoint_names/main.c index 3f80f22fb2bba..cb8bdde15e5c3 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_names/main.c +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_names/main.c @@ -29,8 +29,8 @@ int c(int val) return val + 3; // Find the line number of function "c" here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_options/main.cpp b/lldb/test/API/functionalities/breakpoint/breakpoint_options/main.cpp index b2e8f523c84d4..2448f88c42520 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_options/main.cpp +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_options/main.cpp @@ -1,4 +1,4 @@ extern "C" int foo(void); -int main (int argc, char **argv) { // Set break point at this line. +int main() { int argc = 0; char **argv = (char **)0; // Set break point at this line. return foo(); } diff --git a/lldb/test/API/functionalities/breakpoint/cpp/main.cpp b/lldb/test/API/functionalities/breakpoint/cpp/main.cpp index f352084e74447..d50e6e70960d5 100644 --- a/lldb/test/API/functionalities/breakpoint/cpp/main.cpp +++ b/lldb/test/API/functionalities/breakpoint/cpp/main.cpp @@ -59,8 +59,8 @@ namespace c { }; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + a::c ac; b::c bc; c::d cd; diff --git a/lldb/test/API/functionalities/breakpoint/debugbreak/main.c b/lldb/test/API/functionalities/breakpoint/debugbreak/main.c index 5f936327e4eae..58c1164e71814 100644 --- a/lldb/test/API/functionalities/breakpoint/debugbreak/main.c +++ b/lldb/test/API/functionalities/breakpoint/debugbreak/main.c @@ -19,8 +19,8 @@ bar(int const *foo) } int -main(int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + int foo = 42; bar(&foo); return 0; diff --git a/lldb/test/API/functionalities/breakpoint/dummy_target_breakpoints/main.c b/lldb/test/API/functionalities/breakpoint/dummy_target_breakpoints/main.c index e1f03237cd119..424d586847207 100644 --- a/lldb/test/API/functionalities/breakpoint/dummy_target_breakpoints/main.c +++ b/lldb/test/API/functionalities/breakpoint/dummy_target_breakpoints/main.c @@ -1,8 +1,8 @@ #include int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + printf ("Set a breakpoint on this line.\n"); return 0; // Set another on this line. diff --git a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp index baafd12779226..67935067d52d1 100644 --- a/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp +++ b/lldb/test/API/functionalities/breakpoint/hardware_breakpoints/hardware_breakpoint_on_multiple_threads/main.cpp @@ -26,8 +26,8 @@ thread_func (uint32_t thread_index) { } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + std::thread threads[NUM_OF_THREADS]; printf ("Starting thread creation with hardware breakpoint set...\n"); diff --git a/lldb/test/API/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp b/lldb/test/API/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp index 75d2c3690c898..9aef9289b3744 100644 --- a/lldb/test/API/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp +++ b/lldb/test/API/functionalities/breakpoint/inlined_breakpoints/basic_type.cpp @@ -88,8 +88,8 @@ void Puts(char const *msg) } int -main (int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + T a = T_VALUE_1; T* a_ptr = &a; T& a_ref = a; diff --git a/lldb/test/API/functionalities/breakpoint/serialize/main.c b/lldb/test/API/functionalities/breakpoint/serialize/main.c index 3f80f22fb2bba..cb8bdde15e5c3 100644 --- a/lldb/test/API/functionalities/breakpoint/serialize/main.c +++ b/lldb/test/API/functionalities/breakpoint/serialize/main.c @@ -29,8 +29,8 @@ int c(int val) return val + 3; // Find the line number of function "c" here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/functionalities/breakpoint/source_regexp/a.c b/lldb/test/API/functionalities/breakpoint/source_regexp/a.c index 056583f1c42cd..79e66d03998f4 100644 --- a/lldb/test/API/functionalities/breakpoint/source_regexp/a.c +++ b/lldb/test/API/functionalities/breakpoint/source_regexp/a.c @@ -3,8 +3,8 @@ #include "a.h" static int -main_func(int input) -{ +main() { int argc = 0; char **argv = (char **)0; + return printf("Set B breakpoint here: %d", input); } diff --git a/lldb/test/API/functionalities/breakpoint/source_regexp/main.c b/lldb/test/API/functionalities/breakpoint/source_regexp/main.c index 9c8625e877f58..b91e0229df2cc 100644 --- a/lldb/test/API/functionalities/breakpoint/source_regexp/main.c +++ b/lldb/test/API/functionalities/breakpoint/source_regexp/main.c @@ -2,8 +2,8 @@ #include "a.h" int -main_func(int input) -{ +main() { int argc = 0; char **argv = (char **)0; + return printf("Set B breakpoint here: %d.\n", input); } diff --git a/lldb/test/API/functionalities/breakpoint/step_over_breakpoint/main.cpp b/lldb/test/API/functionalities/breakpoint/step_over_breakpoint/main.cpp index 8cfd34b73b55b..7feb52b780590 100644 --- a/lldb/test/API/functionalities/breakpoint/step_over_breakpoint/main.cpp +++ b/lldb/test/API/functionalities/breakpoint/step_over_breakpoint/main.cpp @@ -2,8 +2,8 @@ int func() { return 1; } int -main(int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + int a = 0; // breakpoint_1 int b = func(); // breakpoint_2 a = b + func(); // breakpoint_3 diff --git a/lldb/test/API/functionalities/conditional_break/main.c b/lldb/test/API/functionalities/conditional_break/main.c index dbfcefe802d2a..f3e93edeef1b7 100644 --- a/lldb/test/API/functionalities/conditional_break/main.c +++ b/lldb/test/API/functionalities/conditional_break/main.c @@ -31,8 +31,8 @@ int c(int val) return val + 3; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/functionalities/darwin_log/basic/main.c b/lldb/test/API/functionalities/darwin_log/basic/main.c index dedd49123cf2c..ad33e50df95fe 100644 --- a/lldb/test/API/functionalities/darwin_log/basic/main.c +++ b/lldb/test/API/functionalities/darwin_log/basic/main.c @@ -3,8 +3,8 @@ #include "../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger = os_log_create("org.llvm.lldb.test", "basic-test"); if (!logger) return 1; diff --git a/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity-chain/main.c b/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity-chain/main.c index 7b16428b72f5b..d1402ac6fc28c 100644 --- a/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity-chain/main.c +++ b/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity-chain/main.c @@ -4,8 +4,8 @@ #include "../../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity/main.c b/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity/main.c index 7b16428b72f5b..d1402ac6fc28c 100644 --- a/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity/main.c +++ b/lldb/test/API/functionalities/darwin_log/filter/exact_match/activity/main.c @@ -4,8 +4,8 @@ #include "../../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/filter/exact_match/category/main.c b/lldb/test/API/functionalities/darwin_log/filter/exact_match/category/main.c index 7b16428b72f5b..d1402ac6fc28c 100644 --- a/lldb/test/API/functionalities/darwin_log/filter/exact_match/category/main.c +++ b/lldb/test/API/functionalities/darwin_log/filter/exact_match/category/main.c @@ -4,8 +4,8 @@ #include "../../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/filter/exact_match/message/main.c b/lldb/test/API/functionalities/darwin_log/filter/exact_match/message/main.c index 6fb9e9c402ae3..d1e56853ef477 100644 --- a/lldb/test/API/functionalities/darwin_log/filter/exact_match/message/main.c +++ b/lldb/test/API/functionalities/darwin_log/filter/exact_match/message/main.c @@ -4,8 +4,8 @@ #include "../../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/filter/exact_match/subsystem/main.c b/lldb/test/API/functionalities/darwin_log/filter/exact_match/subsystem/main.c index 7b16428b72f5b..d1402ac6fc28c 100644 --- a/lldb/test/API/functionalities/darwin_log/filter/exact_match/subsystem/main.c +++ b/lldb/test/API/functionalities/darwin_log/filter/exact_match/subsystem/main.c @@ -4,8 +4,8 @@ #include "../../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/filter/regex/message/main.c b/lldb/test/API/functionalities/darwin_log/filter/regex/message/main.c index 7474344076e48..2372b0013adf4 100644 --- a/lldb/test/API/functionalities/darwin_log/filter/regex/message/main.c +++ b/lldb/test/API/functionalities/darwin_log/filter/regex/message/main.c @@ -4,8 +4,8 @@ #include "../../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/format/main.c b/lldb/test/API/functionalities/darwin_log/format/main.c index a29ecd16c9bae..905ee8328b0a4 100644 --- a/lldb/test/API/functionalities/darwin_log/format/main.c +++ b/lldb/test/API/functionalities/darwin_log/format/main.c @@ -4,8 +4,8 @@ #include "../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); if (!logger_sub1) return 1; diff --git a/lldb/test/API/functionalities/darwin_log/source/debug/main.c b/lldb/test/API/functionalities/darwin_log/source/debug/main.c index 5f841d8415e66..3e0ee2fc9e5cf 100644 --- a/lldb/test/API/functionalities/darwin_log/source/debug/main.c +++ b/lldb/test/API/functionalities/darwin_log/source/debug/main.c @@ -3,8 +3,8 @@ #include "../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/darwin_log/source/info/main.c b/lldb/test/API/functionalities/darwin_log/source/info/main.c index fc6159f5075cc..1617d2a015550 100644 --- a/lldb/test/API/functionalities/darwin_log/source/info/main.c +++ b/lldb/test/API/functionalities/darwin_log/source/info/main.c @@ -3,8 +3,8 @@ #include "../../common/darwin_log_common.h" -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + os_log_t logger_sub1 = os_log_create("org.llvm.lldb.test.sub1", "cat1"); os_log_t logger_sub2 = os_log_create("org.llvm.lldb.test.sub2", "cat2"); if (!logger_sub1 || !logger_sub2) diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-advanced/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-advanced/main.cpp index ac13113da4275..7e2d65deafd37 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-advanced/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-advanced/main.cpp @@ -124,8 +124,8 @@ struct VeryLong int z_2; }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int iAmInt = 9; diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-categories/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-categories/main.cpp index 197a9b6ae2413..54d719b991cd5 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-categories/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-categories/main.cpp @@ -19,8 +19,8 @@ struct Circle : public Shape { Circle(int R = 6) : r(R) {} }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Rectangle r1(5,6); Rectangle r2(9,16); Rectangle r3(4,4); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-cpp/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-cpp/main.cpp index b22a3d8c732ad..a91e6bf373770 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-cpp/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-cpp/main.cpp @@ -59,8 +59,8 @@ struct IUseCharStar IUseCharStar() : pointer("Hello world") {} }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int iAmInt = 1; const float& IAmFloat = float(2.45); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-named-summaries/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-named-summaries/main.cpp index 3ff641363bfa0..45e4cbc4171dc 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-named-summaries/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-named-summaries/main.cpp @@ -34,8 +34,8 @@ struct Third {} }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + First first(12,34); Second second(65,43.25); Third *third = new Third(96,'E'); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-script/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-script/main.cpp index 98ea9ca6028f4..d6d8b85d3fe9e 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-script/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-script/main.cpp @@ -25,8 +25,8 @@ struct i_am_cooler floating((F1 + F2)/2) {} }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + i_am_cool one(1,3.14,'E'); i_am_cool two(4,2.71,'G'); diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-smart-array/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-smart-array/main.cpp index 34bd5e2c0ef1e..671165a3baf5e 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-smart-array/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-smart-array/main.cpp @@ -36,8 +36,8 @@ struct SomeOtherData } }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + char strarr[32] = "Hello world!"; char *strptr = NULL; strptr = "Hello world!"; diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp index ef7c97470652f..54c798c84029b 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/libcxx/function/main.cpp @@ -28,8 +28,8 @@ int foo2() { return foo2_f(10); // Set break point at this line. } -int main (int argc, char *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int acc = 42; std::function f1 = foo; std::function f2 = [acc,f1] (int x) -> int { diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-synth/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-synth/main.cpp index 77b101dbf3832..1956ac70c223f 100644 --- a/lldb/test/API/functionalities/data-formatter/data-formatter-synth/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/data-formatter-synth/main.cpp @@ -57,8 +57,8 @@ struct Plenty } }; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + BagOfInts int_bag(6); BagOfFloats float_bag(2.71); diff --git a/lldb/test/API/functionalities/data-formatter/dump_dynamic/main.cpp b/lldb/test/API/functionalities/data-formatter/dump_dynamic/main.cpp index 68e3a58ad6015..a353e2fa066e9 100644 --- a/lldb/test/API/functionalities/data-formatter/dump_dynamic/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/dump_dynamic/main.cpp @@ -14,8 +14,8 @@ class Derived : public Base { virtual int func() { return m_derived_data; } }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Base *base = new Derived(); return 0; //% stream = lldb.SBStream() //% base = self.frame().FindVariable("base") diff --git a/lldb/test/API/functionalities/data-formatter/parray/main.cpp b/lldb/test/API/functionalities/data-formatter/parray/main.cpp index 63001eb3f9638..c096ce5710def 100644 --- a/lldb/test/API/functionalities/data-formatter/parray/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/parray/main.cpp @@ -10,8 +10,8 @@ ElemType* alloc(size_t count, std::function get) return elems; } -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int* data = alloc(5, [] (size_t idx) -> int { return 2 * idx + 1; }); diff --git a/lldb/test/API/functionalities/data-formatter/stringprinter/main.cpp b/lldb/test/API/functionalities/data-formatter/stringprinter/main.cpp index 670ed3db17483..d6e1a942459dd 100644 --- a/lldb/test/API/functionalities/data-formatter/stringprinter/main.cpp +++ b/lldb/test/API/functionalities/data-formatter/stringprinter/main.cpp @@ -1,7 +1,7 @@ #include -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + std::string stdstring("Hello\t\tWorld\nI am here\t\tto say hello\n"); //%self.addTearDownHook(lambda x: x.runCmd("setting set escape-non-printables true")) const char* constcharstar = stdstring.c_str(); std::string longstring( diff --git a/lldb/test/API/functionalities/dead-strip/main.c b/lldb/test/API/functionalities/dead-strip/main.c index aa92522c432e1..efbf1f8747421 100644 --- a/lldb/test/API/functionalities/dead-strip/main.c +++ b/lldb/test/API/functionalities/dead-strip/main.c @@ -37,8 +37,8 @@ int f3 (char *s) // We want main to start on line 50 -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + f1("carp"); f3("dong"); return 0; diff --git a/lldb/test/API/functionalities/deleted-executable/main.cpp b/lldb/test/API/functionalities/deleted-executable/main.cpp index af00ac263cc1b..c85a44af31ec9 100644 --- a/lldb/test/API/functionalities/deleted-executable/main.cpp +++ b/lldb/test/API/functionalities/deleted-executable/main.cpp @@ -2,7 +2,7 @@ #include #include -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; lldb_enable_attach(); { diff --git a/lldb/test/API/functionalities/dynamic_value_child_count/pass-to-base.cpp b/lldb/test/API/functionalities/dynamic_value_child_count/pass-to-base.cpp index d9dd3529821eb..671a5e62e7a8d 100644 --- a/lldb/test/API/functionalities/dynamic_value_child_count/pass-to-base.cpp +++ b/lldb/test/API/functionalities/dynamic_value_child_count/pass-to-base.cpp @@ -27,8 +27,8 @@ DerivedClass::DerivedClass() : BaseClass() } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + BaseClass *b = nullptr; // Break here and check b has 0 children b = new DerivedClass(); // Break here and check b still has 0 children b = nullptr; // Break here and check b has one child now diff --git a/lldb/test/API/functionalities/exec/main.cpp b/lldb/test/API/functionalities/exec/main.cpp index 51c67d5f232dc..5d9a03315609b 100644 --- a/lldb/test/API/functionalities/exec/main.cpp +++ b/lldb/test/API/functionalities/exec/main.cpp @@ -7,7 +7,7 @@ #include #include -int main(int argc, char const **argv) { +int main() { int argc = 0; char **argv = (char **)0; char *buf = strdup(argv[0]); // Set breakpoint 1 here std::string directory_name(::dirname(buf)); diff --git a/lldb/test/API/functionalities/inferior-crashing/recursive-inferior/main.c b/lldb/test/API/functionalities/inferior-crashing/recursive-inferior/main.c index 25e6e8df0b9b1..218b6d3b95c16 100644 --- a/lldb/test/API/functionalities/inferior-crashing/recursive-inferior/main.c +++ b/lldb/test/API/functionalities/inferior-crashing/recursive-inferior/main.c @@ -11,8 +11,8 @@ void recursive_function(int i) } } -int main(int argc, char *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + recursive_function(0); return 0; } diff --git a/lldb/test/API/functionalities/inline-stepping/calling.cpp b/lldb/test/API/functionalities/inline-stepping/calling.cpp index 49179ce7c9788..0aadf058fd6e9 100644 --- a/lldb/test/API/functionalities/inline-stepping/calling.cpp +++ b/lldb/test/API/functionalities/inline-stepping/calling.cpp @@ -112,8 +112,8 @@ max_value(const std::string& lhs, const std::string& rhs) } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + inline_value = 0; // Stop here and step over to set up stepping over. diff --git a/lldb/test/API/functionalities/memory-region/main.cpp b/lldb/test/API/functionalities/memory-region/main.cpp index 116c10a6c3eab..56edf0b00029b 100644 --- a/lldb/test/API/functionalities/memory-region/main.cpp +++ b/lldb/test/API/functionalities/memory-region/main.cpp @@ -1,6 +1,6 @@ #include -int main (int argc, char const **argv) { +int main() { int argc = 0; char **argv = (char **)0; std::cout << "Program with sections" << std::endl; return 0; // Run here before printing memory regions } diff --git a/lldb/test/API/functionalities/memory/read/main.cpp b/lldb/test/API/functionalities/memory/read/main.cpp index 5a33ac1343c28..9e8d019f8ccd8 100644 --- a/lldb/test/API/functionalities/memory/read/main.cpp +++ b/lldb/test/API/functionalities/memory/read/main.cpp @@ -1,8 +1,8 @@ #include #include -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + char my_string[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 0}; double my_double = 1234.5678; int my_ints[] = {2,4,6,8,10,12,14,16,18,20,22}; diff --git a/lldb/test/API/functionalities/non-overlapping-index-variable-i/main.cpp b/lldb/test/API/functionalities/non-overlapping-index-variable-i/main.cpp index 567b944f485b7..f3c4bca6af46a 100644 --- a/lldb/test/API/functionalities/non-overlapping-index-variable-i/main.cpp +++ b/lldb/test/API/functionalities/non-overlapping-index-variable-i/main.cpp @@ -18,7 +18,7 @@ class Data { {} }; -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; Data *data[1000]; Data **ptr = data; for (int i = 0; i < 1000; ++i) { diff --git a/lldb/test/API/functionalities/object-file/bin/hello.c b/lldb/test/API/functionalities/object-file/bin/hello.c index 8c804005afe3e..e33c9bbe09aeb 100644 --- a/lldb/test/API/functionalities/object-file/bin/hello.c +++ b/lldb/test/API/functionalities/object-file/bin/hello.c @@ -1,7 +1,7 @@ #include -int main(int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + printf("Hello, world\n"); return 0; } diff --git a/lldb/test/API/functionalities/object-file/bin/hello.cpp b/lldb/test/API/functionalities/object-file/bin/hello.cpp index 8c804005afe3e..e33c9bbe09aeb 100644 --- a/lldb/test/API/functionalities/object-file/bin/hello.cpp +++ b/lldb/test/API/functionalities/object-file/bin/hello.cpp @@ -1,7 +1,7 @@ #include -int main(int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + printf("Hello, world\n"); return 0; } diff --git a/lldb/test/API/functionalities/plugins/python_os_plugin/main.c b/lldb/test/API/functionalities/plugins/python_os_plugin/main.c index faa6dd58ecd62..52368b4083ade 100644 --- a/lldb/test/API/functionalities/plugins/python_os_plugin/main.c +++ b/lldb/test/API/functionalities/plugins/python_os_plugin/main.c @@ -1,7 +1,7 @@ #include -int main (int argc, char const *argv[], char const *envp[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + puts("stop here"); // Set breakpoint here return 0; } diff --git a/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c b/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c index fcbfa8a6b51c7..e81fde0ce3bb3 100644 --- a/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c +++ b/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_process_SIGSEGV.c @@ -22,7 +22,7 @@ static void lwp_main(void *unused) { foo(bar); // Frame lwp_main } -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; ucontext_t uc; lwpid_t lid; static const size_t ssize = 16 * 1024; diff --git a/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c b/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c index 1cd86631eddaf..32cb36c5657b4 100644 --- a/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c +++ b/lldb/test/API/functionalities/postmortem/netbsd-core/2lwp_t2_SIGSEGV.c @@ -17,7 +17,7 @@ void lwp_main(void *unused) { foo(0, bar); // Frame lwp_main } -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; ucontext_t uc; lwpid_t lid; static const size_t ssize = 16 * 1024; diff --git a/lldb/test/API/functionalities/process_group/main.c b/lldb/test/API/functionalities/process_group/main.c index 7e986bbac65de..59bacb93971cf 100644 --- a/lldb/test/API/functionalities/process_group/main.c +++ b/lldb/test/API/functionalities/process_group/main.c @@ -4,8 +4,8 @@ volatile int release_child_flag = 0; -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + pid_t child = fork(); if (child == -1) { diff --git a/lldb/test/API/functionalities/recursion/main.cpp b/lldb/test/API/functionalities/recursion/main.cpp index 3bd09a9a83806..da7538447b906 100644 --- a/lldb/test/API/functionalities/recursion/main.cpp +++ b/lldb/test/API/functionalities/recursion/main.cpp @@ -24,8 +24,8 @@ void make_tree(node* root, int count) } } -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + node root(1); make_tree(&root,25000); return 0; // Set break point at this line. diff --git a/lldb/test/API/functionalities/rerun/main.cpp b/lldb/test/API/functionalities/rerun/main.cpp index cbef8d1e6da1d..a965caf0f4188 100644 --- a/lldb/test/API/functionalities/rerun/main.cpp +++ b/lldb/test/API/functionalities/rerun/main.cpp @@ -1,5 +1,5 @@ int -main (int argc, char const **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + return 0; // break here } diff --git a/lldb/test/API/functionalities/signal/raise/main.c b/lldb/test/API/functionalities/signal/raise/main.c index 4203fe5d4c89e..d9d9a105e797f 100644 --- a/lldb/test/API/functionalities/signal/raise/main.c +++ b/lldb/test/API/functionalities/signal/raise/main.c @@ -8,8 +8,8 @@ void handler(int signo) _exit(signo); } -int main (int argc, char *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + if (signal(SIGTRAP, handler) == SIG_ERR) { perror("signal(SIGTRAP)"); diff --git a/lldb/test/API/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp b/lldb/test/API/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp index 0f484b341df36..e5f48285bfdef 100644 --- a/lldb/test/API/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp +++ b/lldb/test/API/functionalities/tail_call_frames/ambiguous_tail_call_seq1/main.cpp @@ -16,7 +16,7 @@ void __attribute__((noinline)) func1() { func3_amb(); /* tail */ } -int __attribute__((disable_tail_calls)) main(int argc, char **) { +int __attribute__((disable_tail_calls)) main() { int argc = 0; char **argv = (char **)0; // The sequences `main -> func1 -> f{2,3}_amb -> sink` are both plausible. Test // that lldb doesn't attempt to guess which one occurred. func1(); diff --git a/lldb/test/API/functionalities/tail_call_frames/disambiguate_call_site/main.cpp b/lldb/test/API/functionalities/tail_call_frames/disambiguate_call_site/main.cpp index 3d1567e87e461..8bde171c7cc68 100644 --- a/lldb/test/API/functionalities/tail_call_frames/disambiguate_call_site/main.cpp +++ b/lldb/test/API/functionalities/tail_call_frames/disambiguate_call_site/main.cpp @@ -13,7 +13,7 @@ void __attribute__((noinline)) func2() { void __attribute__((noinline)) func1() { sink(); /* tail */ } -int __attribute__((disable_tail_calls)) main(int argc, char **) { +int __attribute__((disable_tail_calls)) main() { int argc = 0; char **argv = (char **)0; // The sequences `main -> f{1,2} -> sink` are both plausible. Test that // return-pc call site info allows lldb to pick the correct sequence. func2(); diff --git a/lldb/test/API/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp b/lldb/test/API/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp index 7ed187667d5e3..0aac42f21feaf 100644 --- a/lldb/test/API/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp +++ b/lldb/test/API/functionalities/tail_call_frames/disambiguate_paths_to_common_sink/main.cpp @@ -21,7 +21,7 @@ void __attribute__((noinline)) sink(bool called_from_main) { void __attribute__((noinline)) func1() { sink(false); /* tail */ } -int __attribute__((disable_tail_calls)) main(int argc, char **) { +int __attribute__((disable_tail_calls)) main() { int argc = 0; char **argv = (char **)0; // When func1 tail-calls sink, make sure that the former appears in the // backtrace. sink(true); diff --git a/lldb/test/API/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp b/lldb/test/API/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp index 1350a29a0063e..68131549f0c7a 100644 --- a/lldb/test/API/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp +++ b/lldb/test/API/functionalities/tail_call_frames/disambiguate_tail_call_seq/main.cpp @@ -14,7 +14,7 @@ void __attribute__((noinline)) func2() { sink(); /* tail */ } void __attribute__((noinline)) func1() { func3(); /* tail */ } -int __attribute__((disable_tail_calls)) main(int argc, char **) { +int __attribute__((disable_tail_calls)) main() { int argc = 0; char **argv = (char **)0; // The sequences `main -> func1 -> f{2,3} -> sink` are both plausible. Test // that lldb picks the latter sequence. func1(); diff --git a/lldb/test/API/functionalities/thread/create_after_attach/main.cpp b/lldb/test/API/functionalities/thread/create_after_attach/main.cpp index d8f06e55a2dd9..2a4aef7c3dcc4 100644 --- a/lldb/test/API/functionalities/thread/create_after_attach/main.cpp +++ b/lldb/test/API/functionalities/thread/create_after_attach/main.cpp @@ -36,8 +36,8 @@ thread_2_func (void *input) return NULL; } -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + lldb_enable_attach(); // Create a new thread diff --git a/lldb/test/API/functionalities/thread/step_until/main.c b/lldb/test/API/functionalities/thread/step_until/main.c index e0b4d8ab951e5..009eefe5bbea4 100644 --- a/lldb/test/API/functionalities/thread/step_until/main.c +++ b/lldb/test/API/functionalities/thread/step_until/main.c @@ -11,8 +11,8 @@ void call_me(int argc) } int -main(int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + call_me(argc); printf("Back out in main.\n"); diff --git a/lldb/test/API/functionalities/tsan/basic/main.c b/lldb/test/API/functionalities/tsan/basic/main.c index a47806188697c..b4c9503968a65 100644 --- a/lldb/test/API/functionalities/tsan/basic/main.c +++ b/lldb/test/API/functionalities/tsan/basic/main.c @@ -14,8 +14,8 @@ void *f2(void *p) { return NULL; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + pointer = (char *)malloc(10); // malloc line pthread_t t1, t2; diff --git a/lldb/test/API/functionalities/tsan/cpp_global_location/main.cpp b/lldb/test/API/functionalities/tsan/cpp_global_location/main.cpp index 7c9fee297b30b..803f65a7b08bf 100644 --- a/lldb/test/API/functionalities/tsan/cpp_global_location/main.cpp +++ b/lldb/test/API/functionalities/tsan/cpp_global_location/main.cpp @@ -15,8 +15,8 @@ void *f2(void *p) { return NULL; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + pthread_t t1; pthread_create(&t1, NULL, f1, NULL); diff --git a/lldb/test/API/functionalities/tsan/global_location/main.c b/lldb/test/API/functionalities/tsan/global_location/main.c index 7c9fee297b30b..803f65a7b08bf 100644 --- a/lldb/test/API/functionalities/tsan/global_location/main.c +++ b/lldb/test/API/functionalities/tsan/global_location/main.c @@ -15,8 +15,8 @@ void *f2(void *p) { return NULL; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + pthread_t t1; pthread_create(&t1, NULL, f1, NULL); diff --git a/lldb/test/API/functionalities/tsan/thread_numbers/main.c b/lldb/test/API/functionalities/tsan/thread_numbers/main.c index af0b7a2678982..4203c52efb335 100644 --- a/lldb/test/API/functionalities/tsan/thread_numbers/main.c +++ b/lldb/test/API/functionalities/tsan/thread_numbers/main.c @@ -21,8 +21,8 @@ void *f2(void *p) { return NULL; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + pointer = (char *)malloc(10); for (int i = 0; i < 3; i++) { diff --git a/lldb/test/API/functionalities/tty/main.c b/lldb/test/API/functionalities/tty/main.c index 71c854b5bf40e..d8662d12c8154 100644 --- a/lldb/test/API/functionalities/tty/main.c +++ b/lldb/test/API/functionalities/tty/main.c @@ -1,8 +1,8 @@ #include int -main(int argc, char** argv) -{ +main() { int argc = 0; char **argv = (char **)0; + for (int i = 0; i < argc; i++) { printf("%d: %s.\n", i, argv[i]); } diff --git a/lldb/test/API/functionalities/type_completion/main.cpp b/lldb/test/API/functionalities/type_completion/main.cpp index 2154d5805c97f..8c1f43d0c4a49 100644 --- a/lldb/test/API/functionalities/type_completion/main.cpp +++ b/lldb/test/API/functionalities/type_completion/main.cpp @@ -50,8 +50,8 @@ class NameAndAddress typedef std::vector People; -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + People p; p.push_back(NameAndAddress("Enrico","123 Main Street")); p.push_back(NameAndAddress("Foo","10710 Johnson Avenue")); // Set break point at this line. diff --git a/lldb/test/API/functionalities/unwind/ehframe/main.c b/lldb/test/API/functionalities/unwind/ehframe/main.c index 46de1efe62656..a9aace093996d 100644 --- a/lldb/test/API/functionalities/unwind/ehframe/main.c +++ b/lldb/test/API/functionalities/unwind/ehframe/main.c @@ -52,7 +52,7 @@ void func() { #endif } -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + func(); } diff --git a/lldb/test/API/functionalities/unwind/noreturn/main.c b/lldb/test/API/functionalities/unwind/noreturn/main.c index 4f6525fbf52f6..86b5e594e7f46 100644 --- a/lldb/test/API/functionalities/unwind/noreturn/main.c +++ b/lldb/test/API/functionalities/unwind/noreturn/main.c @@ -27,8 +27,8 @@ func_a (void) } int -main (int argc, char *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + func_a (); return 0; diff --git a/lldb/test/API/iohandler/completion/main.c b/lldb/test/API/iohandler/completion/main.c index 03350dd8299a6..c1682b55992bf 100644 --- a/lldb/test/API/iohandler/completion/main.c +++ b/lldb/test/API/iohandler/completion/main.c @@ -1,4 +1,4 @@ -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; lldb_enable_attach(); int to_complete = 0; return to_complete; diff --git a/lldb/test/API/lang/c/array_types/main.c b/lldb/test/API/lang/c/array_types/main.c index 03a128dcb2533..87f6df1540590 100644 --- a/lldb/test/API/lang/c/array_types/main.c +++ b/lldb/test/API/lang/c/array_types/main.c @@ -1,5 +1,5 @@ -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + struct point_tag { int x; int y; diff --git a/lldb/test/API/lang/c/bitfields/main.c b/lldb/test/API/lang/c/bitfields/main.c index f3f4d6a2c6f79..22acfbce97c52 100644 --- a/lldb/test/API/lang/c/bitfields/main.c +++ b/lldb/test/API/lang/c/bitfields/main.c @@ -2,8 +2,8 @@ #include #include -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + struct Bits { uint32_t : 1, // Unnamed bitfield diff --git a/lldb/test/API/lang/c/enum_types/main.c b/lldb/test/API/lang/c/enum_types/main.c index 0aa73c970ec6f..92b63206d7b34 100644 --- a/lldb/test/API/lang/c/enum_types/main.c +++ b/lldb/test/API/lang/c/enum_types/main.c @@ -9,8 +9,7 @@ struct foo { ops *op; }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; enum bitfield { None = 0, A = 1 << 0, diff --git a/lldb/test/API/lang/c/forward/main.c b/lldb/test/API/lang/c/forward/main.c index 5a13f1d1ea2b6..9a0f592d6e588 100644 --- a/lldb/test/API/lang/c/forward/main.c +++ b/lldb/test/API/lang/c/forward/main.c @@ -7,8 +7,8 @@ struct bar }; int -main (int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + struct bar b= { 1, 2 }; foo (&b); diff --git a/lldb/test/API/lang/c/global_variables/main.c b/lldb/test/API/lang/c/global_variables/main.c index eb7720a6b0484..e0aee89e4dda8 100644 --- a/lldb/test/API/lang/c/global_variables/main.c +++ b/lldb/test/API/lang/c/global_variables/main.c @@ -8,8 +8,8 @@ static const char *g_file_static_cstr = "g_file_static_cstr"; int *g_ptr = &g_file_global_int; extern int g_a; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + g_common_1 = g_file_global_int / g_file_static_int; static const char *g_func_static_cstr = "g_func_static_cstr"; printf ("%s %s\n", g_file_global_cstr, g_file_static_cstr); diff --git a/lldb/test/API/lang/c/local_variables/main.c b/lldb/test/API/lang/c/local_variables/main.c index 2ab579a71a757..ea81e3124d2c6 100644 --- a/lldb/test/API/lang/c/local_variables/main.c +++ b/lldb/test/API/lang/c/local_variables/main.c @@ -13,7 +13,7 @@ void foo(unsigned j) bar(i); // Set break point at this line. } -int main(int argc, char** argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + foo(argc); } diff --git a/lldb/test/API/lang/c/recurse/main.c b/lldb/test/API/lang/c/recurse/main.c index 1159669ebf152..92060770c2615 100644 --- a/lldb/test/API/lang/c/recurse/main.c +++ b/lldb/test/API/lang/c/recurse/main.c @@ -10,8 +10,8 @@ recurse_crash (uint32_t depth) } int -main (int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + // If we have more than one argument, then it should a depth to recurse to. // If we have just the program name as an argument, use UINT32_MAX so we // eventually crash the program by overflowing the stack diff --git a/lldb/test/API/lang/c/set_values/main.c b/lldb/test/API/lang/c/set_values/main.c index 64474c275a091..56d9a3ff22c8e 100644 --- a/lldb/test/API/lang/c/set_values/main.c +++ b/lldb/test/API/lang/c/set_values/main.c @@ -89,8 +89,8 @@ void set_point (void) }; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + // Continue to the breakpoint in set_char() set_char(); //// continue; var i; val -set 99 1 set_uchar(); //// continue; var i; val -set 99 2 diff --git a/lldb/test/API/lang/c/step-target/main.c b/lldb/test/API/lang/c/step-target/main.c index 5e4a490aa90ba..290baadc086e3 100644 --- a/lldb/test/API/lang/c/step-target/main.c +++ b/lldb/test/API/lang/c/step-target/main.c @@ -17,8 +17,8 @@ modifyInt(int incoming) } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + if (argc > 0) { int var_makes_block = argc + 1; diff --git a/lldb/test/API/lang/c/stepping/main.c b/lldb/test/API/lang/c/stepping/main.c index 8237ebf984c93..a553daee26a88 100644 --- a/lldb/test/API/lang/c/stepping/main.c +++ b/lldb/test/API/lang/c/stepping/main.c @@ -35,8 +35,8 @@ int complex (int first, int second, int third) return first + second + third; // Step in targeting complex should stop here } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // frame select 2, thread step-out while stopped at "c(1)" int B2 = b(2); // assignment to B2 diff --git a/lldb/test/API/lang/c/struct_types/main.c b/lldb/test/API/lang/c/struct_types/main.c index 08ef0a703f22b..95f0306f5acd1 100644 --- a/lldb/test/API/lang/c/struct_types/main.c +++ b/lldb/test/API/lang/c/struct_types/main.c @@ -9,8 +9,8 @@ int sum_things(struct things_to_sum tts) return tts.a + tts.b + tts.c; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + struct point_tag { int x; int y; diff --git a/lldb/test/API/lang/c/tls_globals/main.c b/lldb/test/API/lang/c/tls_globals/main.c index bdfd78c1ac34b..f2e329e122f0c 100644 --- a/lldb/test/API/lang/c/tls_globals/main.c +++ b/lldb/test/API/lang/c/tls_globals/main.c @@ -20,8 +20,8 @@ void *fn_static(void *param) usleep(1); } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + pthread_t handle; pthread_create(&handle, NULL, &fn_static, NULL); touch_shared(); diff --git a/lldb/test/API/lang/c/typedef/main.c b/lldb/test/API/lang/c/typedef/main.c index ddfce61efad21..184b67cfff82a 100644 --- a/lldb/test/API/lang/c/typedef/main.c +++ b/lldb/test/API/lang/c/typedef/main.c @@ -3,8 +3,8 @@ void test() typedef double * a; a b = 0; // Set break point 4. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + typedef float a; int i = 0; // Set break point 1. i++; diff --git a/lldb/test/API/lang/cpp/char1632_t/main.cpp b/lldb/test/API/lang/cpp/char1632_t/main.cpp index dc37df27fceb5..353064f446915 100644 --- a/lldb/test/API/lang/cpp/char1632_t/main.cpp +++ b/lldb/test/API/lang/cpp/char1632_t/main.cpp @@ -13,8 +13,8 @@ void copy_char_seq (T (&arr)[N], const T* src) arr[src_len] = 0; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + char16_t as16[UASZ]; char32_t as32[UASZ]; auto cs16_zero = (char16_t)0; diff --git a/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp b/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp index 8bb0a42b58a3a..c4f31fc62f674 100644 --- a/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp +++ b/lldb/test/API/lang/cpp/class-template-parameter-pack/main.cpp @@ -26,7 +26,7 @@ template <> struct D : D { bool argsAre_Int_bool() { return true; } }; -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; C myC; C myLesserC; myC.member = 64; diff --git a/lldb/test/API/lang/cpp/class_static/main.cpp b/lldb/test/API/lang/cpp/class_static/main.cpp index e96443e865a8e..d156e6191b9a5 100644 --- a/lldb/test/API/lang/cpp/class_static/main.cpp +++ b/lldb/test/API/lang/cpp/class_static/main.cpp @@ -34,8 +34,8 @@ static PointType g_points[] = }; int -main (int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + const char *hello_world = "Hello, world!"; printf ("A::g_points[1].x = %i\n", A::g_points[1].x); // Set break point at this line. printf ("::g_points[1].x = %i\n", g_points[1].x); diff --git a/lldb/test/API/lang/cpp/class_types/main.cpp b/lldb/test/API/lang/cpp/class_types/main.cpp index 4eda69ba545a5..6998b3207bec5 100644 --- a/lldb/test/API/lang/cpp/class_types/main.cpp +++ b/lldb/test/API/lang/cpp/class_types/main.cpp @@ -105,8 +105,8 @@ class C : public B }; int -main (int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + A a(12); B b(22,33); C c(44,55,66); diff --git a/lldb/test/API/lang/cpp/diamond/main.cpp b/lldb/test/API/lang/cpp/diamond/main.cpp index 8f9714d33172c..b4426b1441c5d 100644 --- a/lldb/test/API/lang/cpp/diamond/main.cpp +++ b/lldb/test/API/lang/cpp/diamond/main.cpp @@ -65,8 +65,8 @@ class Joiner2 : public Derived2 int m_stuff[32]; }; -int main(int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Joiner1 j1; Joiner2 j2; j1.Print(); diff --git a/lldb/test/API/lang/cpp/dynamic-value/pass-to-base.cpp b/lldb/test/API/lang/cpp/dynamic-value/pass-to-base.cpp index 2bccf3303823c..f3e7070c36682 100644 --- a/lldb/test/API/lang/cpp/dynamic-value/pass-to-base.cpp +++ b/lldb/test/API/lang/cpp/dynamic-value/pass-to-base.cpp @@ -53,8 +53,8 @@ class B : public Extra, public virtual A static A* my_global_A_ptr; int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + my_global_A_ptr = new B (100, 200); B myB (10, 20, my_global_A_ptr); B *second_fake_A_ptr = new B (150, 250); diff --git a/lldb/test/API/lang/cpp/dynamic-value/sbvalue-cast.cpp b/lldb/test/API/lang/cpp/dynamic-value/sbvalue-cast.cpp index 8a95cf4d3903b..89d896152d6a1 100644 --- a/lldb/test/API/lang/cpp/dynamic-value/sbvalue-cast.cpp +++ b/lldb/test/API/lang/cpp/dynamic-value/sbvalue-cast.cpp @@ -57,8 +57,8 @@ class DerivedB : public VIRTUAL Base }; int -main(int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + DerivedA* dA = new DerivedA(10); DerivedB* dB = new DerivedB(12); Base *array[2] = {dA, dB}; diff --git a/lldb/test/API/lang/cpp/enum_types/main.cpp b/lldb/test/API/lang/cpp/enum_types/main.cpp index be895208c7d40..14d0de14161e8 100644 --- a/lldb/test/API/lang/cpp/enum_types/main.cpp +++ b/lldb/test/API/lang/cpp/enum_types/main.cpp @@ -24,5 +24,32 @@ DEFINE_UNSIGNED_ENUM(ul, unsigned long) DEFINE_SIGNED_ENUM(l, signed long) DEFINE_UNSIGNED_ENUM(ull, unsigned long long) DEFINE_SIGNED_ENUM(ll, signed long long) +#ifdef SIGNED_ENUM_CLASS_TYPE + typedef SIGNED_ENUM_CLASS_TYPE enum_integer_t; + enum class DayType : enum_integer_t { + Monday = -3, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday, + kNumDays + }; + enum_integer_t day_value; +#else + typedef UNSIGNED_ENUM_CLASS_TYPE enum_integer_t; + enum class DayType : enum_integer_t { + Monday = 200, + Tuesday, + Wednesday, + Thursday, + Friday, + Saturday, + Sunday, + kNumDays + }; + enum_integer_t day_value; +#endif -int main(int argc, char const *argv[]) { return 0; } +int main() { int argc = 0; char **argv = (char **)0; return 0; } diff --git a/lldb/test/API/lang/cpp/function-template-parameter-pack/main.cpp b/lldb/test/API/lang/cpp/function-template-parameter-pack/main.cpp index 407ba68be8a2c..8fbf599e6db01 100644 --- a/lldb/test/API/lang/cpp/function-template-parameter-pack/main.cpp +++ b/lldb/test/API/lang/cpp/function-template-parameter-pack/main.cpp @@ -6,8 +6,8 @@ template int staticSizeof() { return staticSizeof() + sizeof(T1); } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int sz = staticSizeof(); return staticSizeof() != sz; //% self.expect("expression -- sz == staticSizeof()", "staticSizeof worked", substrs = ["true"]) //% self.expect("expression -- sz == staticSizeof() + sizeof(char)", "staticSizeof worked", substrs = ["true"]) diff --git a/lldb/test/API/lang/cpp/function_refs/main.cpp b/lldb/test/API/lang/cpp/function_refs/main.cpp index a57b0867fb8a3..2108d151e385f 100644 --- a/lldb/test/API/lang/cpp/function_refs/main.cpp +++ b/lldb/test/API/lang/cpp/function_refs/main.cpp @@ -15,7 +15,7 @@ auto &ref3 = varargs; auto binp = &binary; auto &binr = binary; auto null = &nullary; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; //% self.expect("target var ref", substrs=["(void (&)(bool))", "ref = 0x", //% "&::ref = "]) //% self.expect("target var ref2", diff --git a/lldb/test/API/lang/cpp/gmodules-templates/main.cpp b/lldb/test/API/lang/cpp/gmodules-templates/main.cpp index df75261657006..bbefee0d6810b 100644 --- a/lldb/test/API/lang/cpp/gmodules-templates/main.cpp +++ b/lldb/test/API/lang/cpp/gmodules-templates/main.cpp @@ -1,7 +1,7 @@ #include "b.h" -int main(int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Module m; // Test that the type Module which contains a field that is a // template instantiation can be fully resolved. diff --git a/lldb/test/API/lang/cpp/gmodules/main.cpp b/lldb/test/API/lang/cpp/gmodules/main.cpp index 588a3a8e01fea..90597f3366226 100644 --- a/lldb/test/API/lang/cpp/gmodules/main.cpp +++ b/lldb/test/API/lang/cpp/gmodules/main.cpp @@ -1,7 +1,7 @@ class Foo::Bar { int i = 123; }; -int main(int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + IntContainer test(42); Foo::Bar bar; return 0; // break here diff --git a/lldb/test/API/lang/cpp/inlines/inlines.cpp b/lldb/test/API/lang/cpp/inlines/inlines.cpp index 822d88e22f9bc..3cd7d204ef4ce 100644 --- a/lldb/test/API/lang/cpp/inlines/inlines.cpp +++ b/lldb/test/API/lang/cpp/inlines/inlines.cpp @@ -36,8 +36,8 @@ outer_inline (int outer_input) } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + printf ("Starting...\n"); int (*func_ptr) (int); diff --git a/lldb/test/API/lang/cpp/llvm-style/main.cpp b/lldb/test/API/lang/cpp/llvm-style/main.cpp index 6df5c9276985c..6028f718b1753 100644 --- a/lldb/test/API/lang/cpp/llvm-style/main.cpp +++ b/lldb/test/API/lang/cpp/llvm-style/main.cpp @@ -19,8 +19,8 @@ int C::foo(D* D) { } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + D myD { D::anInt() }; C().foo(&myD); return 0; diff --git a/lldb/test/API/lang/cpp/modules-import/main.cpp b/lldb/test/API/lang/cpp/modules-import/main.cpp index a6acf9a1a6998..e76f7fd3740b0 100644 --- a/lldb/test/API/lang/cpp/modules-import/main.cpp +++ b/lldb/test/API/lang/cpp/modules-import/main.cpp @@ -1,6 +1,6 @@ #include "Foo.h" -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; Foo foo; // break here. return 0; diff --git a/lldb/test/API/lang/cpp/namespace/main.cpp b/lldb/test/API/lang/cpp/namespace/main.cpp index fc5dacdaf8f55..99ab028e8db6a 100644 --- a/lldb/test/API/lang/cpp/namespace/main.cpp +++ b/lldb/test/API/lang/cpp/namespace/main.cpp @@ -103,8 +103,8 @@ int Foo::myfunc(int a) } int -main (int argc, char const *argv[]) -{ +main() { int argc = 0; char **argv = (char **)0; + test_lookup_at_global_scope(); test_lookup_at_file_scope(); A::test_lookup_at_ns_scope(); diff --git a/lldb/test/API/lang/cpp/namespace_conflicts/main.cpp b/lldb/test/API/lang/cpp/namespace_conflicts/main.cpp index 525b45d37ef52..5986b3417c0fb 100644 --- a/lldb/test/API/lang/cpp/namespace_conflicts/main.cpp +++ b/lldb/test/API/lang/cpp/namespace_conflicts/main.cpp @@ -12,8 +12,8 @@ int foo(D* D) { return D->dump(); //% self.expect("expression -- D->dump()", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["int", "2"]) } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + D myD { D::anInt() }; foo(&myD); return 0; diff --git a/lldb/test/API/lang/cpp/signed_types/main.cpp b/lldb/test/API/lang/cpp/signed_types/main.cpp index a0f8f3f374f22..00c14cb172a19 100644 --- a/lldb/test/API/lang/cpp/signed_types/main.cpp +++ b/lldb/test/API/lang/cpp/signed_types/main.cpp @@ -1,7 +1,7 @@ #include -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + char the_char = 'c'; short the_short = 'c'; wchar_t the_wchar_t = 'c'; diff --git a/lldb/test/API/lang/cpp/std-function-step-into-callable/main.cpp b/lldb/test/API/lang/cpp/std-function-step-into-callable/main.cpp index ebbb05e6d1383..5fcb8b07b3ce8 100644 --- a/lldb/test/API/lang/cpp/std-function-step-into-callable/main.cpp +++ b/lldb/test/API/lang/cpp/std-function-step-into-callable/main.cpp @@ -12,8 +12,8 @@ struct Bar { int num_ = 0 ; } ; -int main (int argc, char *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int acc = 42; std::function f1 = foo; std::function f2 = [acc,f1] (int x) -> int { diff --git a/lldb/test/API/lang/cpp/stl/main.cpp b/lldb/test/API/lang/cpp/stl/main.cpp index 1d0a7fc045f0d..f7ac66de47994 100644 --- a/lldb/test/API/lang/cpp/stl/main.cpp +++ b/lldb/test/API/lang/cpp/stl/main.cpp @@ -2,8 +2,8 @@ #include #include #include -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + std::string hello_world ("Hello World!"); std::cout << hello_world << std::endl; std::cout << hello_world.length() << std::endl; diff --git a/lldb/test/API/lang/cpp/symbols/main.cpp b/lldb/test/API/lang/cpp/symbols/main.cpp index 81f00980e821d..70b339162cb10 100644 --- a/lldb/test/API/lang/cpp/symbols/main.cpp +++ b/lldb/test/API/lang/cpp/symbols/main.cpp @@ -24,8 +24,8 @@ const char getAChar() //% self.expect("expression -- D", DATA_TYPES_DISPLAYED_CORRECTLY, substrs = ["char", "Hello"]) } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int six = twice(3); return 0; } diff --git a/lldb/test/API/lang/cpp/template/main.cpp b/lldb/test/API/lang/cpp/template/main.cpp index f58cd30f371c3..fdc6979b12c8d 100644 --- a/lldb/test/API/lang/cpp/template/main.cpp +++ b/lldb/test/API/lang/cpp/template/main.cpp @@ -59,8 +59,8 @@ template struct T1 { FLOAT f = 1.5; }; template struct T2 { FLOAT f = 2.5; int i = 42; }; template class ...Args> class C { std::tuple...> V; }; -int main(int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + TestObj<1> testpos; TestObj<-1> testneg; EnumTemplate member(123); diff --git a/lldb/test/API/lang/cpp/type_lookup/main.cpp b/lldb/test/API/lang/cpp/type_lookup/main.cpp index d31720a25c390..5fabaf88595dc 100644 --- a/lldb/test/API/lang/cpp/type_lookup/main.cpp +++ b/lldb/test/API/lang/cpp/type_lookup/main.cpp @@ -40,7 +40,7 @@ struct contains_type { }; -int main (int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; nsp_a::namespace_only a_namespace_only = { 1 }; nsp_a::namespace_and_file a_namespace_and_file = { 2 }; nsp_a::contains_type::in_contains_type a_in_contains_type = { 3 }; diff --git a/lldb/test/API/lang/cpp/unicode-literals/main.cpp b/lldb/test/API/lang/cpp/unicode-literals/main.cpp index b6206c3595818..899d9ae444bbe 100644 --- a/lldb/test/API/lang/cpp/unicode-literals/main.cpp +++ b/lldb/test/API/lang/cpp/unicode-literals/main.cpp @@ -1,5 +1,5 @@ -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + auto cs16 = u"hello world ྒྙྐ"; auto cs32 = U"hello world ྒྙྐ"; char16_t *s16 = (char16_t *)u"ﺸﺵۻ"; diff --git a/lldb/test/API/lang/cpp/unique-types/main.cpp b/lldb/test/API/lang/cpp/unique-types/main.cpp index e419cf01a8459..c45a82dfe9d9b 100644 --- a/lldb/test/API/lang/cpp/unique-types/main.cpp +++ b/lldb/test/API/lang/cpp/unique-types/main.cpp @@ -3,8 +3,8 @@ #include #include -int main (int argc, char const *argv[], char const *envp[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + std::vector longs; std::vector shorts; for (int i=0; i<12; i++) diff --git a/lldb/test/API/lang/cpp/unsigned_types/main.cpp b/lldb/test/API/lang/cpp/unsigned_types/main.cpp index 921968650c66a..9378d822643ce 100644 --- a/lldb/test/API/lang/cpp/unsigned_types/main.cpp +++ b/lldb/test/API/lang/cpp/unsigned_types/main.cpp @@ -1,5 +1,5 @@ -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + typedef unsigned int uint32_t; unsigned char the_unsigned_char = 'c'; unsigned short the_unsigned_short = 'c'; diff --git a/lldb/test/API/lang/cpp/virtual-overload/main.cpp b/lldb/test/API/lang/cpp/virtual-overload/main.cpp index 79c482352f93b..6324b31b14d17 100644 --- a/lldb/test/API/lang/cpp/virtual-overload/main.cpp +++ b/lldb/test/API/lang/cpp/virtual-overload/main.cpp @@ -9,7 +9,7 @@ struct Derived : Base { virtual void f(int i, int j) {} }; -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; Derived obj; obj.f(1, 2); //% self.expect("fr var", "not crashing", substrs = ["obj"]) return 0; diff --git a/lldb/test/API/lang/cpp/wchar_t/main.cpp b/lldb/test/API/lang/cpp/wchar_t/main.cpp index 778642e0133f0..8222589520970 100644 --- a/lldb/test/API/lang/cpp/wchar_t/main.cpp +++ b/lldb/test/API/lang/cpp/wchar_t/main.cpp @@ -12,8 +12,8 @@ class Foo }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Foo foo_x('a'); Foo foo_y(L'a'); const wchar_t *mazeltov = L"מזל טוב"; diff --git a/lldb/test/API/lang/mixed/main.c b/lldb/test/API/lang/mixed/main.c index f5c5d19f2c892..e1655ef4ff9df 100644 --- a/lldb/test/API/lang/mixed/main.c +++ b/lldb/test/API/lang/mixed/main.c @@ -8,8 +8,8 @@ bar() return static_value; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + bar(); // breakpoint_in_main return foo(); } diff --git a/lldb/test/API/macosx/find-dsym/deep-bundle/main.c b/lldb/test/API/macosx/find-dsym/deep-bundle/main.c index 0a44b96068c2e..c00322dcf4cc2 100644 --- a/lldb/test/API/macosx/find-dsym/deep-bundle/main.c +++ b/lldb/test/API/macosx/find-dsym/deep-bundle/main.c @@ -5,8 +5,8 @@ int setup_is_complete = 0; -int main(int argc, const char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + char command[8192]; sprintf (command, "/bin/rm -rf %s/MyFramework %s/MyFramework.framework %s/MyFramework.framework.dSYM", diff --git a/lldb/test/API/macosx/function-starts/main.cpp b/lldb/test/API/macosx/function-starts/main.cpp index 188078a22ed91..5aefbd6eb1bae 100644 --- a/lldb/test/API/macosx/function-starts/main.cpp +++ b/lldb/test/API/macosx/function-starts/main.cpp @@ -20,8 +20,7 @@ static void *a_function() return 0; } -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; { // Create file to signal that this process has started up. std::ofstream f; diff --git a/lldb/test/API/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp b/lldb/test/API/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp index 3123542c2ac59..813fbfb9de885 100644 --- a/lldb/test/API/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp +++ b/lldb/test/API/macosx/lc-note/kern-ver-str/create-empty-corefile.cpp @@ -234,8 +234,8 @@ get_uuid_from_binary (const char *fn) return uuid; } -int main (int argc, char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + if (argc != 2 && argc != 3) { fprintf (stderr, "usage: create-empty-corefile [binary-to-copy-uuid-from]\n"); diff --git a/lldb/test/API/macosx/order/main.c b/lldb/test/API/macosx/order/main.c index 6c5a02f379cc6..53d4a227b2b00 100644 --- a/lldb/test/API/macosx/order/main.c +++ b/lldb/test/API/macosx/order/main.c @@ -37,8 +37,8 @@ int f3 (char *s) // We want main to start on line 50 -int main (int argc, const char * argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + f1("carp"); f2("ding"); f3("dong"); diff --git a/lldb/test/API/macosx/queues/main.c b/lldb/test/API/macosx/queues/main.c index 2bf390b1330a6..18f03076e083c 100644 --- a/lldb/test/API/macosx/queues/main.c +++ b/lldb/test/API/macosx/queues/main.c @@ -86,8 +86,8 @@ stopper () } -int main (int argc, const char **argv) -{ +int main() { int argc = 0; char **argv = (char **)0; + dispatch_queue_t work_submittor_1 = dispatch_queue_create ("com.apple.work_submittor_1", DISPATCH_QUEUE_SERIAL); dispatch_queue_t work_submittor_2 = dispatch_queue_create ("com.apple.work_submittor_and_quit_2", DISPATCH_QUEUE_SERIAL); dispatch_queue_t work_submittor_3 = dispatch_queue_create ("com.apple.work_submittor_3", DISPATCH_QUEUE_SERIAL); diff --git a/lldb/test/API/macosx/universal/main.c b/lldb/test/API/macosx/universal/main.c index 3edab51b1f6ad..0fe66cbe3747c 100644 --- a/lldb/test/API/macosx/universal/main.c +++ b/lldb/test/API/macosx/universal/main.c @@ -9,8 +9,8 @@ call_me() } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + printf ("Hello there!\n"); // Set break point at this line. if (argc == 2 && strcmp(argv[1], "keep_waiting") == 0) while (1) diff --git a/lldb/test/API/python_api/event/main.c b/lldb/test/API/python_api/event/main.c index f6dbff4be4da6..f09c3a3b45db0 100644 --- a/lldb/test/API/python_api/event/main.c +++ b/lldb/test/API/python_api/event/main.c @@ -26,8 +26,8 @@ int c(int val) return val + 3; // Find the line number of function "c" here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/python_api/formatters/main.cpp b/lldb/test/API/python_api/formatters/main.cpp index f21c956144c29..a5e1ee039abaf 100644 --- a/lldb/test/API/python_api/formatters/main.cpp +++ b/lldb/test/API/python_api/formatters/main.cpp @@ -30,7 +30,7 @@ struct Empty1 { void *data; }; struct Empty2 { void *data; }; -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; JustAStruct foo; foo.A = 1; foo.B = 3.14; diff --git a/lldb/test/API/python_api/frame/get-variables/main.c b/lldb/test/API/python_api/frame/get-variables/main.c index 5f6bd7de7819d..b51bec2edb2b9 100644 --- a/lldb/test/API/python_api/frame/get-variables/main.c +++ b/lldb/test/API/python_api/frame/get-variables/main.c @@ -3,7 +3,7 @@ int g_global_var = 123; static int g_static_var = 123; -int main (int argc, char const *argv[]) +int __main(int argc, char **argv) { static int static_var = 123; g_static_var = 123; // clang bug. Need to touch this variable, otherwise it disappears. @@ -19,3 +19,7 @@ int main (int argc, char const *argv[]) } return 0; } + +int main() { + return __main(0, (char **)0); +} diff --git a/lldb/test/API/python_api/frame/inlines/inlines.c b/lldb/test/API/python_api/frame/inlines/inlines.c index a2a8212278d00..d5342bba55c3d 100644 --- a/lldb/test/API/python_api/frame/inlines/inlines.c +++ b/lldb/test/API/python_api/frame/inlines/inlines.c @@ -36,8 +36,8 @@ outer_inline (int outer_input) } int -main (int argc, char **argv) -{ +main() { int argc = 0; char **argv = (char **)0; + printf ("Starting...\n"); int (*func_ptr) (int); diff --git a/lldb/test/API/python_api/frame/main.c b/lldb/test/API/python_api/frame/main.c index eb2b1a26d5610..048c8e8bae4dd 100644 --- a/lldb/test/API/python_api/frame/main.c +++ b/lldb/test/API/python_api/frame/main.c @@ -35,8 +35,8 @@ int c(int val, char ch) return val + 3 + ch; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1, 'A'); // a(1, 'A') -> b(2, 'B') -> c(3, 'C') printf("a(1, 'A') returns %d\n", A1); diff --git a/lldb/test/API/python_api/function_symbol/main.c b/lldb/test/API/python_api/function_symbol/main.c index d5f8cebc5a005..4943b425d8b4e 100644 --- a/lldb/test/API/python_api/function_symbol/main.c +++ b/lldb/test/API/python_api/function_symbol/main.c @@ -37,8 +37,8 @@ int c(int val) return val + 3; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/python_api/hello_world/main.c b/lldb/test/API/python_api/hello_world/main.c index c516f923614f1..b4706ddb78f5a 100644 --- a/lldb/test/API/python_api/hello_world/main.c +++ b/lldb/test/API/python_api/hello_world/main.c @@ -6,8 +6,8 @@ #include #endif -int main(int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + lldb_enable_attach(); printf("Hello world.\n"); // Set break point at this line. diff --git a/lldb/test/API/python_api/interpreter/main.c b/lldb/test/API/python_api/interpreter/main.c index 277aa54a4eea5..e96507ef83ae0 100644 --- a/lldb/test/API/python_api/interpreter/main.c +++ b/lldb/test/API/python_api/interpreter/main.c @@ -1,6 +1,6 @@ #include -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; printf("Hello world.\n"); return 0; } diff --git a/lldb/test/API/python_api/lldbutil/frame/main.c b/lldb/test/API/python_api/lldbutil/frame/main.c index 6244a38a5c572..10cb792f588f7 100644 --- a/lldb/test/API/python_api/lldbutil/frame/main.c +++ b/lldb/test/API/python_api/lldbutil/frame/main.c @@ -24,8 +24,8 @@ int c(int val) return val + 3; // Find the line number here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/python_api/lldbutil/iter/main.cpp b/lldb/test/API/python_api/lldbutil/iter/main.cpp index 38658e3d287ad..9dd6156aa7b3f 100644 --- a/lldb/test/API/python_api/lldbutil/iter/main.cpp +++ b/lldb/test/API/python_api/lldbutil/iter/main.cpp @@ -69,8 +69,8 @@ thread_func (void *arg) } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + uint32_t thread_index_1 = 1; uint32_t thread_index_2 = 2; uint32_t thread_index_3 = 3; diff --git a/lldb/test/API/python_api/name_lookup/main.cpp b/lldb/test/API/python_api/name_lookup/main.cpp index b38208ce2a355..f05578f654e42 100644 --- a/lldb/test/API/python_api/name_lookup/main.cpp +++ b/lldb/test/API/python_api/name_lookup/main.cpp @@ -45,8 +45,8 @@ class g } }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + g g; g.unique_function_name(); g.unique_function_name(argc); diff --git a/lldb/test/API/python_api/process/io/main.c b/lldb/test/API/python_api/process/io/main.c index c9a5707f0e175..f21b0926b8962 100644 --- a/lldb/test/API/python_api/process/io/main.c +++ b/lldb/test/API/python_api/process/io/main.c @@ -1,6 +1,6 @@ #include -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; printf("Hello world.\n"); // Set breakpoint here char line[100]; if (fgets(line, sizeof(line), stdin)) { diff --git a/lldb/test/API/python_api/process/main.cpp b/lldb/test/API/python_api/process/main.cpp index f3cc7e12d3357..0228b8895f9f2 100644 --- a/lldb/test/API/python_api/process/main.cpp +++ b/lldb/test/API/python_api/process/main.cpp @@ -9,8 +9,8 @@ char *my_char_ptr = (char *)"Does it work?"; uint32_t my_uint32 = 12345; int my_int = 0; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + for (int i = 0; i < 3; ++i) { printf("my_char='%c'\n", my_char); ++my_char; diff --git a/lldb/test/API/python_api/sbdata/main.cpp b/lldb/test/API/python_api/sbdata/main.cpp index 526e8cfbbd571..7be73d5c896fa 100644 --- a/lldb/test/API/python_api/sbdata/main.cpp +++ b/lldb/test/API/python_api/sbdata/main.cpp @@ -13,8 +13,8 @@ struct foo {} }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + foo* foobar = new foo[2]; foobar[0].a = 1; diff --git a/lldb/test/API/python_api/sbvalue_const_addrof/main.cpp b/lldb/test/API/python_api/sbvalue_const_addrof/main.cpp index 318a45bc21a85..dbb8b62dd9363 100644 --- a/lldb/test/API/python_api/sbvalue_const_addrof/main.cpp +++ b/lldb/test/API/python_api/sbvalue_const_addrof/main.cpp @@ -19,9 +19,9 @@ struct ThreadInfo { RegisterContext regs; ThreadInfo *next; }; -int main (int argc, char const *argv[], char const *envp[]); +int main() { int argc = 0; char **argv = (char **)0;; -ThreadInfo g_thread2 = { 0x2222, "thread2", { 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, (uintptr_t)&main, 0x2006, 0x2007 }, NULL }; +ThreadInfo g_thread2 = 0x2222, "thread2", { 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, (uintptr_t)&main, 0x2006, 0x2007 }, NULL }; ThreadInfo g_thread1 = { 0x1111, "thread1", { 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, (uintptr_t)&main, 0x1006, 0x1007 }, &g_thread2 }; ThreadInfo *g_thread_list_ptr = &g_thread1; diff --git a/lldb/test/API/python_api/section/main.c b/lldb/test/API/python_api/section/main.c index 9d73ac724cd3e..4575aa2f96ac8 100644 --- a/lldb/test/API/python_api/section/main.c +++ b/lldb/test/API/python_api/section/main.c @@ -7,8 +7,8 @@ char my_global_var_of_char_type = 'X'; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + // this code just "does something" with the global so that it is not // optimised away if (argc > 1 && strlen(argv[1])) diff --git a/lldb/test/API/python_api/signals/main.cpp b/lldb/test/API/python_api/signals/main.cpp index ef29e91685c88..7e213cc027d02 100644 --- a/lldb/test/API/python_api/signals/main.cpp +++ b/lldb/test/API/python_api/signals/main.cpp @@ -9,8 +9,8 @@ // This simple program is to test the lldb Python API related to process. -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + #if defined(_WIN32) ::ExitProcess(1); #else diff --git a/lldb/test/API/python_api/symbol-context/main.c b/lldb/test/API/python_api/symbol-context/main.c index b6d3ee3386230..991d96d4e7fb4 100644 --- a/lldb/test/API/python_api/symbol-context/main.c +++ b/lldb/test/API/python_api/symbol-context/main.c @@ -28,8 +28,8 @@ int c(int val) return val + 3; // Find the line number of function "c" here. } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/python_api/target/main.c b/lldb/test/API/python_api/target/main.c index 0949c1550a9f9..3ce8e278223d8 100644 --- a/lldb/test/API/python_api/target/main.c +++ b/lldb/test/API/python_api/target/main.c @@ -36,8 +36,8 @@ int c(int val) return val + 3; } -int main (int argc, char const *argv[], char** env) -{ +int main() { int argc = 0; char **argv = (char **)0; + // Set a break at entry to main. int A1 = a(1); // a(1) -> b(1) -> c(1) printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/python_api/thread/main.cpp b/lldb/test/API/python_api/thread/main.cpp index dde740a1b6bf6..6a654aa38151a 100644 --- a/lldb/test/API/python_api/thread/main.cpp +++ b/lldb/test/API/python_api/thread/main.cpp @@ -5,8 +5,8 @@ char my_char = 'u'; int my_int = 0; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + for (int i = 0; i < 3; ++i) { printf("my_char='%c'\n", my_char); ++my_char; diff --git a/lldb/test/API/python_api/thread/main2.cpp b/lldb/test/API/python_api/thread/main2.cpp index b07841ccc682d..ac6872b1c6fd1 100644 --- a/lldb/test/API/python_api/thread/main2.cpp +++ b/lldb/test/API/python_api/thread/main2.cpp @@ -31,8 +31,8 @@ int c(int val) return val + 3; } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + int A1 = a(1); printf("a(1) returns %d\n", A1); diff --git a/lldb/test/API/python_api/type/main.cpp b/lldb/test/API/python_api/type/main.cpp index b1ef625283855..ea8964fa26dab 100644 --- a/lldb/test/API/python_api/type/main.cpp +++ b/lldb/test/API/python_api/type/main.cpp @@ -33,8 +33,8 @@ enum EnumType {}; enum class ScopedEnumType {}; enum class EnumUChar : unsigned char {}; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Task *task_head = new Task(-1, NULL); Task *task1 = new Task(1, NULL); Task *task2 = new Task(2, NULL); diff --git a/lldb/test/API/python_api/value/linked_list/main.cpp b/lldb/test/API/python_api/value/linked_list/main.cpp index 13982bfe9818f..e1e880ef2b17e 100644 --- a/lldb/test/API/python_api/value/linked_list/main.cpp +++ b/lldb/test/API/python_api/value/linked_list/main.cpp @@ -11,8 +11,8 @@ class Task { }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + Task *task_head = NULL; Task *task1 = new Task(1, NULL); Task *task2 = new Task(2, NULL); diff --git a/lldb/test/API/python_api/value/main.c b/lldb/test/API/python_api/value/main.c index c2e0dc8c12ddc..fc59f0a2d19da 100644 --- a/lldb/test/API/python_api/value/main.c +++ b/lldb/test/API/python_api/value/main.c @@ -29,8 +29,8 @@ struct MyStruct int b; }; -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + uint32_t uinthex = 0xE0A35F10; int32_t sinthex = 0xE0A35F10; diff --git a/lldb/test/API/python_api/watchpoint/condition/main.cpp b/lldb/test/API/python_api/watchpoint/condition/main.cpp index f0d14f3840412..caf1a11893785 100644 --- a/lldb/test/API/python_api/watchpoint/condition/main.cpp +++ b/lldb/test/API/python_api/watchpoint/condition/main.cpp @@ -7,7 +7,7 @@ static void modify(int32_t &var) { ++var; } -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int local = 0; printf("&global=%p\n", &global); printf("about to write to 'global'...\n"); // Set break point at this line. diff --git a/lldb/test/API/python_api/watchpoint/main.c b/lldb/test/API/python_api/watchpoint/main.c index 80d35a920d67a..43e8d5cd5b8a9 100644 --- a/lldb/test/API/python_api/watchpoint/main.c +++ b/lldb/test/API/python_api/watchpoint/main.c @@ -3,7 +3,7 @@ int32_t global = 10; // Watchpoint variable declaration. -int main(int argc, char** argv) { +int main() { int argc = 0; char **argv = (char **)0; int local = 0; printf("&global=%p\n", &global); printf("about to write to 'global'...\n"); // Set break point at this line. diff --git a/lldb/test/API/python_api/watchpoint/watchlocation/main.cpp b/lldb/test/API/python_api/watchpoint/watchlocation/main.cpp index 0c5f5a6c836f8..f8cf07559961c 100644 --- a/lldb/test/API/python_api/watchpoint/watchlocation/main.cpp +++ b/lldb/test/API/python_api/watchpoint/watchlocation/main.cpp @@ -71,8 +71,8 @@ thread_func (uint32_t thread_index) } -int main (int argc, char const *argv[]) -{ +int main() { int argc = 0; char **argv = (char **)0; + g_count = 4; std::thread threads[3]; diff --git a/lldb/test/API/source-manager/main.c b/lldb/test/API/source-manager/main.c index 9f62166357ce3..6dc0b1f46a0bd 100644 --- a/lldb/test/API/source-manager/main.c +++ b/lldb/test/API/source-manager/main.c @@ -1,6 +1,6 @@ #include -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; printf("Hello world.\n"); // Set break point at this line. return 0; } diff --git a/lldb/test/API/tools/lldb-server/inferior-crash/main.cpp b/lldb/test/API/tools/lldb-server/inferior-crash/main.cpp index ced7f7125088e..651c4a17599e7 100644 --- a/lldb/test/API/tools/lldb-server/inferior-crash/main.cpp +++ b/lldb/test/API/tools/lldb-server/inferior-crash/main.cpp @@ -7,7 +7,7 @@ const char *const SEGFAULT_COMMAND = "segfault"; const char *const ABORT_COMMAND = "abort"; } -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; if (argc < 2) { std::cout << "expected at least one command provided on the command line" << std::endl; diff --git a/lldb/test/API/tools/lldb-server/main.cpp b/lldb/test/API/tools/lldb-server/main.cpp index 4a877deaafbdc..d48665f1dbf80 100644 --- a/lldb/test/API/tools/lldb-server/main.cpp +++ b/lldb/test/API/tools/lldb-server/main.cpp @@ -241,7 +241,7 @@ static void *thread_func(void *arg) { return nullptr; } -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; lldb_enable_attach(); std::vector threads; diff --git a/lldb/test/API/tools/lldb-server/platform-process-connect/main.cpp b/lldb/test/API/tools/lldb-server/platform-process-connect/main.cpp index c7ebe0759a403..7d21b27914a8a 100644 --- a/lldb/test/API/tools/lldb-server/platform-process-connect/main.cpp +++ b/lldb/test/API/tools/lldb-server/platform-process-connect/main.cpp @@ -1,6 +1,6 @@ #include -int main(int argc, char **argv) { +int main() { int argc = 0; char **argv = (char **)0; printf("argc: %d\n", argc); return argv[0][0]; } diff --git a/lldb/test/API/tools/lldb-vscode/attach/main.c b/lldb/test/API/tools/lldb-vscode/attach/main.c index 64d86583ada69..8870539c34c87 100644 --- a/lldb/test/API/tools/lldb-vscode/attach/main.c +++ b/lldb/test/API/tools/lldb-vscode/attach/main.c @@ -1,7 +1,7 @@ #include #include -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; lldb_enable_attach(); if (argc >= 2) { diff --git a/lldb/test/API/tools/lldb-vscode/breakpoint/main.cpp b/lldb/test/API/tools/lldb-vscode/breakpoint/main.cpp index 04deb9482c5fb..9d5e4f9e657d6 100644 --- a/lldb/test/API/tools/lldb-vscode/breakpoint/main.cpp +++ b/lldb/test/API/tools/lldb-vscode/breakpoint/main.cpp @@ -15,7 +15,7 @@ namespace a { return 14 + i; // break 14 } } -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; #if defined(__APPLE__) const char *libother_name = "libother.dylib"; #else diff --git a/lldb/test/API/tools/lldb-vscode/launch/main.c b/lldb/test/API/tools/lldb-vscode/launch/main.c index aed2af9828f34..57db4a31427e8 100644 --- a/lldb/test/API/tools/lldb-vscode/launch/main.c +++ b/lldb/test/API/tools/lldb-vscode/launch/main.c @@ -2,7 +2,7 @@ #include #include -int main(int argc, char const *argv[], char const *envp[]) { +int main() { int argc = 0; char **argv = (char **)0; for (int i=0; i= 7): + return False + try: + # We skip this test for debug builds because it takes too long parsing lldb's own + # debug info. Release builds are fine. + # Checking the size of the lldb-vscode binary seems to be a decent proxy for a quick + # detection. It should be far less than 1 MB in Release builds. + if os.path.getsize(os.environ["LLDBVSCODE_EXEC"]) < 1000000: + return True + except: + return False + @skipIfWindows @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_runInTerminal(self): + if not self.isTestSupported(): + return ''' Tests the "runInTerminal" reverse request. It makes sure that the IDE can launch the inferior with the correct environment variables and arguments. ''' - if "debug" in str(os.environ["LLDBVSCODE_EXEC"]).lower(): - # We skip this test for debug builds because it takes too long parsing lldb's own - # debug info. Release builds are fine. - # Checking this environment variable seems to be a decent proxy for a quick - # detection - return program = self.getBuildArtifact("a.out") source = 'main.c' self.build_and_launch( @@ -77,6 +87,8 @@ def test_runInTerminal(self): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_runInTerminalInvalidTarget(self): + if not self.isTestSupported(): + return self.build_and_create_debug_adaptor() response = self.launch( "INVALIDPROGRAM", stopOnEntry=True, runInTerminal=True, args=["foobar"], env=["FOO=bar"], expectFailure=True) @@ -88,6 +100,8 @@ def test_runInTerminalInvalidTarget(self): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_missingArgInRunInTerminalLauncher(self): + if not self.isTestSupported(): + return proc = subprocess.run([self.lldbVSCodeExec, "--launch-target", "INVALIDPROGRAM"], capture_output=True, universal_newlines=True) self.assertTrue(proc.returncode != 0) @@ -97,6 +111,8 @@ def test_missingArgInRunInTerminalLauncher(self): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_FakeAttachedRunInTerminalLauncherWithInvalidProgram(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -115,6 +131,8 @@ def test_FakeAttachedRunInTerminalLauncherWithInvalidProgram(self): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_FakeAttachedRunInTerminalLauncherWithValidProgram(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -132,6 +150,8 @@ def test_FakeAttachedRunInTerminalLauncherWithValidProgram(self): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_FakeAttachedRunInTerminalLauncherAndCheckEnvironment(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) @@ -150,6 +170,8 @@ def test_FakeAttachedRunInTerminalLauncherAndCheckEnvironment(self): @skipIfRemote @skipIf(archs=no_match(['x86_64'])) def test_NonAttachedRunInTerminalLauncher(self): + if not self.isTestSupported(): + return comm_file = os.path.join(self.getBuildDir(), "comm-file") os.mkfifo(comm_file) diff --git a/lldb/test/API/tools/lldb-vscode/stackTrace/main.c b/lldb/test/API/tools/lldb-vscode/stackTrace/main.c index 85b41c492817f..7242a3af3c3e3 100644 --- a/lldb/test/API/tools/lldb-vscode/stackTrace/main.c +++ b/lldb/test/API/tools/lldb-vscode/stackTrace/main.c @@ -7,7 +7,7 @@ int recurse(int x) { return recurse(x-1) + x; // recurse call } -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; recurse(20); // recurse invocation return 0; } diff --git a/lldb/test/API/tools/lldb-vscode/step/main.cpp b/lldb/test/API/tools/lldb-vscode/step/main.cpp index 3027551972fcc..56d3b1c85507d 100644 --- a/lldb/test/API/tools/lldb-vscode/step/main.cpp +++ b/lldb/test/API/tools/lldb-vscode/step/main.cpp @@ -5,6 +5,6 @@ int function(int x) { return x; } -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; return function(2); } diff --git a/lldb/test/API/tools/lldb-vscode/variables/main.cpp b/lldb/test/API/tools/lldb-vscode/variables/main.cpp index 0223bd0a75ea8..8562f20024230 100644 --- a/lldb/test/API/tools/lldb-vscode/variables/main.cpp +++ b/lldb/test/API/tools/lldb-vscode/variables/main.cpp @@ -9,7 +9,7 @@ struct PointType { int g_global = 123; static int s_global = 234; -int main(int argc, char const *argv[]) { +int main() { int argc = 0; char **argv = (char **)0; static float s_local = 2.25; PointType pt = { 11,22, {0}}; for (int i=0; i #include #include @@ -21,8 +23,6 @@ #include "lldb/lldb-defines.h" -#include "FifoFiles.h" - using namespace llvm; namespace lldb_vscode { @@ -30,13 +30,13 @@ namespace lldb_vscode { FifoFile::FifoFile(StringRef path) : m_path(path) {} FifoFile::~FifoFile() { -#if !defined(WIN32) +#if !defined(_WIN32) unlink(m_path.c_str()); #endif }; Expected> CreateFifoFile(StringRef path) { -#if defined(WIN32) +#if defined(_WIN32) return createStringError(inconvertibleErrorCode(), "Unimplemented"); #else if (int err = mkfifo(path.data(), 0600)) diff --git a/lldb/tools/lldb-vscode/FifoFiles.h b/lldb/tools/lldb-vscode/FifoFiles.h index 891b6f5746010..f186f65e86c43 100644 --- a/lldb/tools/lldb-vscode/FifoFiles.h +++ b/lldb/tools/lldb-vscode/FifoFiles.h @@ -9,6 +9,7 @@ #ifndef LLDB_TOOLS_LLDB_VSCODE_FIFOFILES_H #define LLDB_TOOLS_LLDB_VSCODE_FIFOFILES_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX #include "llvm/Support/Error.h" #include "JSONUtils.h" diff --git a/lldb/tools/lldb-vscode/IOStream.cpp b/lldb/tools/lldb-vscode/IOStream.cpp index 4b11b90b4c2e8..cd22d906c14c6 100644 --- a/lldb/tools/lldb-vscode/IOStream.cpp +++ b/lldb/tools/lldb-vscode/IOStream.cpp @@ -8,7 +8,7 @@ #include "IOStream.h" -#if defined(_WIN32) +#if defined(_WIN32) #include #else #include diff --git a/lldb/tools/lldb-vscode/IOStream.h b/lldb/tools/lldb-vscode/IOStream.h index 603ae9adcc2a1..0eb9b6fefb0dc 100644 --- a/lldb/tools/lldb-vscode/IOStream.h +++ b/lldb/tools/lldb-vscode/IOStream.h @@ -9,6 +9,8 @@ #ifndef LLDB_TOOLS_LLDB_VSCODE_IOSTREAM_H #define LLDB_TOOLS_LLDB_VSCODE_IOSTREAM_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX + #if defined(_WIN32) // We need to #define NOMINMAX in order to skip `min()` and `max()` macro // definitions that conflict with other system headers. diff --git a/lldb/tools/lldb-vscode/RunInTerminal.cpp b/lldb/tools/lldb-vscode/RunInTerminal.cpp index 4db2806924ca0..2126563d9e961 100644 --- a/lldb/tools/lldb-vscode/RunInTerminal.cpp +++ b/lldb/tools/lldb-vscode/RunInTerminal.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// -#if !defined(WIN32) +#include "RunInTerminal.h" + +#if !defined(_WIN32) #include #include #include @@ -21,8 +23,6 @@ #include "lldb/lldb-defines.h" -#include "RunInTerminal.h" - using namespace llvm; namespace lldb_vscode { diff --git a/lldb/tools/lldb-vscode/VSCode.h b/lldb/tools/lldb-vscode/VSCode.h index 8e7dfc0789344..a2e1cac8ecf91 100644 --- a/lldb/tools/lldb-vscode/VSCode.h +++ b/lldb/tools/lldb-vscode/VSCode.h @@ -9,6 +9,8 @@ #ifndef LLDB_TOOLS_LLDB_VSCODE_VSCODE_H #define LLDB_TOOLS_LLDB_VSCODE_VSCODE_H +#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX + #include #include #include diff --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp b/lldb/tools/lldb-vscode/lldb-vscode.cpp index c581b9b4a9a0d..9469690cd7db5 100644 --- a/lldb/tools/lldb-vscode/lldb-vscode.cpp +++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#include "VSCode.h" + #include #include #include @@ -52,7 +54,6 @@ #include "JSONUtils.h" #include "LLDBUtils.h" -#include "VSCode.h" #if defined(_WIN32) #ifndef PATH_MAX @@ -3002,8 +3003,8 @@ static void printHelp(LLDBVSCodeOptTable &table, llvm::StringRef tool_name) { // emitted to the debug adaptor. void LaunchRunInTerminalTarget(llvm::opt::Arg &target_arg, llvm::StringRef comm_file, char *argv[]) { -#if defined(WIN_32) - llvm::errs() << "runInTerminal is not supported on Windows\n"; +#if defined(_WIN32) + llvm::errs() << "runInTerminal is only supported on POSIX systems\n"; exit(EXIT_FAILURE); #else RunInTerminalLauncherCommChannel comm_channel(comm_file); diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 454ec561af9a4..aabd816479ce7 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -2,6 +2,10 @@ cmake_minimum_required(VERSION 3.13.4) +set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake) +include(${LLVM_COMMON_CMAKE_UTILS}/Modules/CMakePolicy.cmake + NO_POLICY_SCOPE) + set(CMAKE_BUILD_WITH_INSTALL_NAME_DIR ON) if(NOT DEFINED LLVM_VERSION_MAJOR) @@ -14,7 +18,7 @@ if(NOT DEFINED LLVM_VERSION_PATCH) set(LLVM_VERSION_PATCH 0) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX git) + set(LLVM_VERSION_SUFFIX "") endif() if (NOT PACKAGE_VERSION) @@ -294,6 +298,7 @@ set(LLVM_ALL_TARGETS ARM AVR BPF + DPU Hexagon Lanai Mips diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index de8431fe3908e..3982b80244fcd 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -31,6 +31,10 @@ LLVM web page, this document applies to the *next* release, not the current one. To see the release notes for a specific release, please see the `releases page `_. +Deprecated and Removed Features/APIs +================================================= +* BG/Q support, including QPX, will be removed in the 12.0.0 release. + Non-comprehensive list of changes in this release ================================================= .. NOTE @@ -92,6 +96,29 @@ Changes to TableGen uses the "`...`" range punctuation (e.g., ``{0...9}``). The hyphen syntax is deprecated. +Changes to the AArch64 Backend +-------------------------- + +During this release ... + +* Lots of improvements to generation of Windows unwind data; the unwind + data is optimized and written in packed form where possible, reducing + the size of unwind data (pdata and xdata sections) by around 60% + compared with LLVM 11. The generation of prologs/epilogs is tweaked + when targeting Windows, to increase the chances of being able to use + the packed unwind info format. + +* Support for creating Windows unwind data using ``.seh_*`` assembler + directives. + +* Produce proper assembly output for the Windows target, including + ``:lo12:`` relocation specifiers, to allow the assembly output + to actually be assembled. + +* Changed the assembly comment string for MSVC targets to ``//`` (consistent + with the MinGW and ELF targets), freeing up ``;`` to be used as + statement separator. + Changes to the ARM Backend -------------------------- @@ -102,11 +129,97 @@ Changes to the MIPS Target During this release ... +* The Machine Outliner is now supported for ARM and Thumb2, it is not + turned on by default and can be enabled with the ``-moutline`` clang flag. + Changes to the PowerPC Target ----------------------------- -During this release ... +Optimization: + +* Made improvements to loop unroll-and-jam including fix to respect user + provided #pragma unroll-and-jam for loops on targets other than ARM. +* Improved PartialInliner allowing it to handle code regions in a switch + statements. +* Improved PGO support on AIX by building and linking with compiler-rt profile + library. +* Add support for Epilogue Vectorization and enabled it by default. + +CodeGen: + +* POWER10 support + * Implementation of PC Relative addressing in LLD including the associated + linker optimizations. + * Add support for the new matrix multiplication (MMA) instructions to Clang + and LLVM. + * Implementation of Power10 builtins. + +* Scheduling enhancements + * Add a new algorithm to cluster more loads/stores if the DAG is not too + complicated. + * Enable the PowerPC scheduling heuristic for Power10. + +* Target dependent passes tuning + * Enhance LoopStrengthReduce/PPCLoopInstrFormPrep pass for PowerPC, + especially for P10 intrinsics. + * Enhance machine combiner pass to reduce register pressure for PowerPC. + * Improve MachineSink to do more sinking based on register pressure and alias + analysis. + +* General improvements + * Complete the constrained floating point operations support. + * Improve the llvm-exegesis support. + * Improve the stack clash protection to probe the gap between stackptr and + realigned stackptr. + * Improve the IEEE long double support for Power8. + * Enable MemorySSA for LoopSink. + * Enhance LLVM debugging functionality via options such as -print-changed and + -print-before-changed. + * Add builtins for Power9 (i.e. darn, xvtdiv, xvtsqrt etc). + * Add options to disable all or part of LoopIdiomRecognizePass. + * Add support for printing the DDG in DOT form allowing for visual inspection + of the Data Dependence Graph. + * Remove the QPX support. + * Significant number of bug fixes including all the fixes necessary to + achieve a clean test run for Julia. + +AIX Support: + +* Compiler-rt support + * Add support for building compiler-rt for AIX and 32-bit Power targets. + * Made compiler-rt the default rtlib for AIX. + +* General Improvements + * Enable the AIX extended AltiVec ABI under option -mabi=vec-extabi. + * Add partial C99 complex type support. + * Implemente traceback table for functions (encodes vector information, + emits exception handling). + * Implemente code generation for C++ dynamic initialization and finalization. + of non-local variables for use with the -bcdtors option of the AIX linker. + * Add new option -mignore-xcoff-visibility. + * Enable explicit sections on AIX. + * Enable -f[no-]data-sections on AIX and set -fdata-sections to be the default + on AIX. + * Enable -f[no-]function-sections. + * Add support for relocation generation using the large code model. + * Add pragma align natural and sorted out pragma pack stack effect. + +Changes to the SystemZ Target +----------------------------- + +* Added support for the MemorySanitizer and the LeakSanitizer. +* Added support for the ``-fstack-clash-protection`` command line option. +* Enhanced the assembler parser to allow using `%r0` even in an address + register context, and to allow specifying registers using plain integer + numbers instead of register names everywhere. +* Fixed wrong code generation violating the platform ABI when passing + a C++ class (not struct) type having only a single member of + floating-point type. +* Fixed wrong code generation when using the `vec_store_len_r` or + `vec_load_len_r` intrinsics with an immediate length argument of + 16 or larger. +* Miscellaneous codegen enhancements, in particular to improve vector code. Changes to the X86 Target ------------------------- @@ -205,6 +318,21 @@ External Open Source Projects Using LLVM 12 * A project... +External Open Source Projects Using LLVM 11 +=========================================== + +Zig Programming Language +------------------------ + +`Zig `_ is a general-purpose programming language and +toolchain for maintaining robust, optimal, and reusable software. In addition +to supporting LLVM as an optional backend, Zig links Clang and LLD to provide +an out-of-the-box cross compilation experience, not only for Zig code but for +C and C++ code as well. Using a sophisticated caching system, Zig lazily builds +from source compiler-rt, mingw-w64, musl, glibc, libcxx, libcxxabi, and +libunwind for the selected target - a "batteries included" drop-in for GCC/Clang +that works the same on every platform. + Additional Information ====================== diff --git a/llvm/docs/index.rst b/llvm/docs/index.rst index 7e0bc8c4552b9..0df1ea79b4f1c 100644 --- a/llvm/docs/index.rst +++ b/llvm/docs/index.rst @@ -1,10 +1,5 @@ About -======== - -.. warning:: - - If you are using a released version of LLVM, see `the download page - `_ to find your documentation. +===== The LLVM compiler infrastructure supports a wide range of projects, from industrial strength compilers to specialized JIT applications to small diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h index 8274213aa839b..a78df16ca404c 100644 --- a/llvm/include/llvm-c/Core.h +++ b/llvm/include/llvm-c/Core.h @@ -160,10 +160,10 @@ typedef enum { LLVMVectorTypeKind, /**< Fixed width SIMD vector type */ LLVMMetadataTypeKind, /**< Metadata */ LLVMX86_MMXTypeKind, /**< X86 MMX */ - LLVMX86_AMXTypeKind, /**< X86 AMX */ LLVMTokenTypeKind, /**< Tokens */ LLVMScalableVectorTypeKind, /**< Scalable SIMD vector type */ - LLVMBFloatTypeKind /**< 16 bit brain floating point type */ + LLVMBFloatTypeKind, /**< 16 bit brain floating point type */ + LLVMX86_AMXTypeKind /**< X86 AMX */ } LLVMTypeKind; typedef enum { @@ -270,7 +270,6 @@ typedef enum { LLVMConstantVectorValueKind, LLVMUndefValueValueKind, - LLVMPoisonValueValueKind, LLVMConstantAggregateZeroValueKind, LLVMConstantDataArrayValueKind, LLVMConstantDataVectorValueKind, @@ -283,6 +282,7 @@ typedef enum { LLVMInlineAsmValueKind, LLVMInstructionValueKind, + LLVMPoisonValueValueKind } LLVMValueKind; typedef enum { diff --git a/llvm/include/llvm-c/Orc.h b/llvm/include/llvm-c/Orc.h index 183107c148a6d..9beef44c89dd5 100644 --- a/llvm/include/llvm-c/Orc.h +++ b/llvm/include/llvm-c/Orc.h @@ -339,8 +339,7 @@ LLVMErrorRef LLVMOrcResourceTrackerRemove(LLVMOrcResourceTrackerRef RT); * ownership has not been passed to a JITDylib (e.g. because some error * prevented the client from calling LLVMOrcJITDylibAddGenerator). */ -void LLVMOrcDisposeDefinitionGenerator( - LLVMOrcDefinitionGeneratorRef DG); +void LLVMOrcDisposeDefinitionGenerator(LLVMOrcDefinitionGeneratorRef DG); /** * Dispose of a MaterializationUnit. @@ -388,7 +387,9 @@ LLVMOrcExecutionSessionCreateJITDylib(LLVMOrcExecutionSessionRef ES, * Returns the JITDylib with the given name, or NULL if no such JITDylib * exists. */ -LLVMOrcJITDylibRef LLVMOrcExecutionSessionGetJITDylibByName(const char *Name); +LLVMOrcJITDylibRef +LLVMOrcExecutionSessionGetJITDylibByName(LLVMOrcExecutionSessionRef ES, + const char *Name); /** * Return a reference to a newly created resource tracker associated with JD. diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index eed315c929adf..0235349e4e71e 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -97,6 +97,7 @@ class Triple { lanai, // Lanai: Lanai 32-bit wasm32, // WebAssembly with 32-bit pointers wasm64, // WebAssembly with 64-bit pointers + dpu, // UPMEM DPU renderscript32, // 32-bit RenderScript renderscript64, // 64-bit RenderScript ve, // NEC SX-Aurora Vector Engine @@ -133,6 +134,9 @@ class Triple { AArch64SubArch_arm64e, + DPUSubArch_v1a, + DPUSubArch_v1b, + KalimbaSubArch_v3, KalimbaSubArch_v4, KalimbaSubArch_v5, @@ -157,6 +161,7 @@ class Triple { AMD, Mesa, SUSE, + UPMEM, OpenEmbedded, LastVendorType = OpenEmbedded }; @@ -193,6 +198,7 @@ class Triple { WatchOS, // Apple watchOS Mesa3D, Contiki, + DPURTe, // UPMEM DPU Runtime Environment AMDPAL, // AMD PAL Runtime HermitCore, // HermitCore Unikernel/Multikernel Hurd, // GNU/Hurd diff --git a/llvm/include/llvm/Analysis/AssumptionCache.h b/llvm/include/llvm/Analysis/AssumptionCache.h index 0ef63dc68e1ca..c4602d3449c0c 100644 --- a/llvm/include/llvm/Analysis/AssumptionCache.h +++ b/llvm/include/llvm/Analysis/AssumptionCache.h @@ -45,7 +45,7 @@ class AssumptionCache { enum : unsigned { ExprResultIdx = std::numeric_limits::max() }; struct ResultElem { - WeakTrackingVH Assume; + WeakVH Assume; /// contains either ExprResultIdx or the index of the operand bundle /// containing the knowledge. diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 1552303b610ca..f1c2669e42256 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -314,6 +314,7 @@ enum { EM_AMDGPU = 224, // AMD GPU architecture EM_RISCV = 243, // RISC-V EM_LANAI = 244, // Lanai 32-bit processor + EM_DPU = 245, // DPU architecture EM_BPF = 247, // Linux kernel bpf virtual machine EM_VE = 251, // NEC SX-Aurora VE EM_CSKY = 252, // C-SKY 32-bit processor @@ -699,35 +700,35 @@ enum : unsigned { EF_AMDGPU_MACH_R600_LAST = EF_AMDGPU_MACH_R600_TURKS, // AMDGCN-based processors. - EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, - EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, - EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, - EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, - EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, - EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, - EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, + EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020, + EF_AMDGPU_MACH_AMDGCN_GFX601 = 0x021, + EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022, + EF_AMDGPU_MACH_AMDGCN_GFX701 = 0x023, + EF_AMDGPU_MACH_AMDGCN_GFX702 = 0x024, + EF_AMDGPU_MACH_AMDGCN_GFX703 = 0x025, + EF_AMDGPU_MACH_AMDGCN_GFX704 = 0x026, EF_AMDGPU_MACH_AMDGCN_RESERVED_0X27 = 0x027, - EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, - EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, - EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, - EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, - EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, - EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, - EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, - EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, - EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, - EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, - EF_AMDGPU_MACH_AMDGCN_GFX90C = 0x032, - EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, - EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, - EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, - EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036, - EF_AMDGPU_MACH_AMDGCN_GFX1031 = 0x037, - EF_AMDGPU_MACH_AMDGCN_GFX1032 = 0x038, - EF_AMDGPU_MACH_AMDGCN_GFX1033 = 0x039, - EF_AMDGPU_MACH_AMDGCN_GFX602 = 0x03a, - EF_AMDGPU_MACH_AMDGCN_GFX705 = 0x03b, - EF_AMDGPU_MACH_AMDGCN_GFX805 = 0x03c, + EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028, + EF_AMDGPU_MACH_AMDGCN_GFX802 = 0x029, + EF_AMDGPU_MACH_AMDGCN_GFX803 = 0x02a, + EF_AMDGPU_MACH_AMDGCN_GFX810 = 0x02b, + EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c, + EF_AMDGPU_MACH_AMDGCN_GFX902 = 0x02d, + EF_AMDGPU_MACH_AMDGCN_GFX904 = 0x02e, + EF_AMDGPU_MACH_AMDGCN_GFX906 = 0x02f, + EF_AMDGPU_MACH_AMDGCN_GFX908 = 0x030, + EF_AMDGPU_MACH_AMDGCN_GFX909 = 0x031, + EF_AMDGPU_MACH_AMDGCN_GFX90C = 0x032, + EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033, + EF_AMDGPU_MACH_AMDGCN_GFX1011 = 0x034, + EF_AMDGPU_MACH_AMDGCN_GFX1012 = 0x035, + EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036, + EF_AMDGPU_MACH_AMDGCN_GFX1031 = 0x037, + EF_AMDGPU_MACH_AMDGCN_GFX1032 = 0x038, + EF_AMDGPU_MACH_AMDGCN_GFX1033 = 0x039, + EF_AMDGPU_MACH_AMDGCN_GFX602 = 0x03a, + EF_AMDGPU_MACH_AMDGCN_GFX705 = 0x03b, + EF_AMDGPU_MACH_AMDGCN_GFX805 = 0x03c, // First/last AMDGCN-based processors. EF_AMDGPU_MACH_AMDGCN_FIRST = EF_AMDGPU_MACH_AMDGCN_GFX600, @@ -788,12 +789,32 @@ enum { #include "ELFRelocs/VE.def" }; - // ELF Relocation types for CSKY enum { #include "ELFRelocs/CSKY.def" }; +// UPMEM +// ELF Relocation types for DPU +enum { +#include "ELFRelocs/DPU.def" +}; + +// DPU Specific e_flags +enum : unsigned { + EF_DPU_EABI_SET = 0x00800000U, + EF_DPU_EABIMASK = 0xFF000000U, +}; + +#define EF_EABI_DPU_SET(e_flags, eabi) \ + ((((e_flags) | llvm::ELF::EF_DPU_EABI_SET) & \ + (~llvm::ELF::EF_DPU_EABIMASK)) | \ + (((eabi) << __builtin_ctz(llvm::ELF::EF_DPU_EABIMASK)) & \ + llvm::ELF::EF_DPU_EABIMASK)) +#define EF_EABI_DPU_GET(e_flags) \ + (((e_flags)&llvm::ELF::EF_DPU_EABIMASK) >> \ + __builtin_ctz(llvm::ELF::EF_DPU_EABIMASK)) + #undef ELF_RELOC // Section header. @@ -895,6 +916,7 @@ enum : unsigned { SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, + SHT_DPU_ATTRIBUTES = 0x70000003U, SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in // this section based on their sizes SHT_X86_64_UNWIND = 0x70000001, // Unwind information diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/DPU.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/DPU.def new file mode 100644 index 0000000000000..bb58519314122 --- /dev/null +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/DPU.def @@ -0,0 +1,28 @@ +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +// No relocation +ELF_RELOC(R_DPU_NONE , 0) +ELF_RELOC(R_DPU_32 , 1) +ELF_RELOC(R_DPU_8 , 2) +ELF_RELOC(R_DPU_16 , 3) +ELF_RELOC(R_DPU_64 , 4) +ELF_RELOC(R_DPU_PC , 128) +ELF_RELOC(R_DPU_IMM5 , 129) +ELF_RELOC(R_DPU_IMM8_DMA , 130) +ELF_RELOC(R_DPU_IMM24_PC , 131) +ELF_RELOC(R_DPU_IMM27_PC , 132) +ELF_RELOC(R_DPU_IMM28_PC_OPC8 , 133) +ELF_RELOC(R_DPU_IMM8_STR , 134) +ELF_RELOC(R_DPU_IMM12_STR , 135) +ELF_RELOC(R_DPU_IMM16_STR , 136) +ELF_RELOC(R_DPU_IMM16_ATM , 137) +ELF_RELOC(R_DPU_IMM24 , 138) +ELF_RELOC(R_DPU_IMM24_RB , 139) +ELF_RELOC(R_DPU_IMM27 , 140) +ELF_RELOC(R_DPU_IMM28 , 141) +ELF_RELOC(R_DPU_IMM32 , 142) +ELF_RELOC(R_DPU_IMM32_ZERO_RB , 143) +ELF_RELOC(R_DPU_IMM17_24 , 144) +ELF_RELOC(R_DPU_IMM32_DUS_RB , 145) diff --git a/llvm/include/llvm/CodeGen/FastISel.h b/llvm/include/llvm/CodeGen/FastISel.h index 81c1d6aad49a1..26bf4ab2618ce 100644 --- a/llvm/include/llvm/CodeGen/FastISel.h +++ b/llvm/include/llvm/CodeGen/FastISel.h @@ -490,7 +490,10 @@ class FastISel { /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - /// Test whether the given value has exactly one use. + /// Test whether the register associated with this value has exactly one use, + /// in which case that single use is killing. Note that multiple IR values + /// may map onto the same register, in which case this is not the same as + /// checking that an IR value has one use. bool hasTrivialKill(const Value *V); /// Create a machine mem operand from the given instruction. diff --git a/llvm/include/llvm/CodeGen/MachineInstr.h b/llvm/include/llvm/CodeGen/MachineInstr.h index 6bbe2d03f9e58..f8d97c2c07a6f 100644 --- a/llvm/include/llvm/CodeGen/MachineInstr.h +++ b/llvm/include/llvm/CodeGen/MachineInstr.h @@ -1156,6 +1156,10 @@ class MachineInstr return getOpcode() == TargetOpcode::CFI_INSTRUCTION; } + bool isPseudoProbe() const { + return getOpcode() == TargetOpcode::PSEUDO_PROBE; + } + // True if the instruction represents a position in the function. bool isPosition() const { return isLabel() || isCFIInstruction(); } @@ -1165,6 +1169,9 @@ class MachineInstr bool isDebugInstr() const { return isDebugValue() || isDebugLabel() || isDebugRef(); } + bool isDebugOrPseudoInstr() const { + return isDebugInstr() || isPseudoProbe(); + } bool isDebugOffsetImm() const { return getDebugOffset().isImm(); } diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index c3221aac8eea4..40115fbd2f158 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -2785,6 +2785,10 @@ class TargetLoweringBase { return false; } + /// Does this target require the clearing of high-order bits in a register + /// passed to the fp16 to fp conversion library function. + virtual bool shouldKeepZExtForFP16Conv() const { return false; } + //===--------------------------------------------------------------------===// // Runtime Library hooks // diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index 6bfc02d153796..e5fca98f92717 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -96,7 +96,6 @@ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ - X(UUIDOfExpr) \ X(BoolExpr) \ X(StringLiteral) \ X(LambdaExpr) \ @@ -2035,21 +2034,6 @@ class ThrowExpr : public Node { } }; -// MSVC __uuidof extension, generated by clang in -fms-extensions mode. -class UUIDOfExpr : public Node { - Node *Operand; -public: - UUIDOfExpr(Node *Operand_) : Node(KUUIDOfExpr), Operand(Operand_) {} - - template void match(Fn F) const { F(Operand); } - - void printLeft(OutputStream &S) const override { - S << "__uuidof("; - Operand->print(S); - S << ")"; - } -}; - class BoolExpr : public Node { bool Value; @@ -5013,6 +4997,43 @@ Node *AbstractManglingParser::parseExpr() { } } return nullptr; + case 'u': { + ++First; + Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); + if (!Name) + return nullptr; + // Special case legacy __uuidof mangling. The 't' and 'z' appear where the + // standard encoding expects a , and would be otherwise be + // interpreted as node 'short' or 'ellipsis'. However, neither + // __uuidof(short) nor __uuidof(...) can actually appear, so there is no + // actual conflict here. + if (Name->getBaseName() == "__uuidof") { + if (numLeft() < 2) + return nullptr; + if (*First == 't') { + ++First; + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + return make(Name, makeNodeArray(&Ty, &Ty + 1)); + } + if (*First == 'z') { + ++First; + Node *Ex = getDerived().parseExpr(); + if (!Ex) + return nullptr; + return make(Name, makeNodeArray(&Ex, &Ex + 1)); + } + } + size_t ExprsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseTemplateArg(); + if (E == nullptr) + return E; + Names.push_back(E); + } + return make(Name, popTrailingNodeArray(ExprsBegin)); + } case '1': case '2': case '3': @@ -5024,21 +5045,6 @@ Node *AbstractManglingParser::parseExpr() { case '9': return getDerived().parseUnresolvedName(); } - - if (consumeIf("u8__uuidoft")) { - Node *Ty = getDerived().parseType(); - if (!Ty) - return nullptr; - return make(Ty); - } - - if (consumeIf("u8__uuidofz")) { - Node *Ex = getDerived().parseExpr(); - if (!Ex) - return nullptr; - return make(Ex); - } - return nullptr; } diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def index 8440461679759..75d360bf4237a 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def +++ b/llvm/include/llvm/Frontend/OpenMP/OMPKinds.def @@ -375,7 +375,7 @@ __OMP_RTL(__kmpc_init_allocator, false, /* omp_allocator_handle_t */ VoidPtr, __OMP_RTL(__kmpc_destroy_allocator, false, Void, /* Int */ Int32, /* omp_allocator_handle_t */ VoidPtr) -__OMP_RTL(__kmpc_push_target_tripcount, false, Void, IdentPtr, Int64, Int64) +__OMP_RTL(__kmpc_push_target_tripcount_mapper, false, Void, IdentPtr, Int64, Int64) __OMP_RTL(__tgt_target_mapper, false, Int32, IdentPtr, Int64, VoidPtr, Int32, VoidPtrPtr, VoidPtrPtr, Int64Ptr, Int64Ptr, VoidPtrPtr, VoidPtrPtr) __OMP_RTL(__tgt_target_nowait_mapper, false, Int32, IdentPtr, Int64, VoidPtr, Int32, @@ -844,7 +844,7 @@ __OMP_RTL_ATTRS(__kmpc_free, AllocAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__kmpc_init_allocator, DefaultAttrs, ReturnPtrAttrs, {}) __OMP_RTL_ATTRS(__kmpc_destroy_allocator, AllocAttrs, AttributeSet(), {}) -__OMP_RTL_ATTRS(__kmpc_push_target_tripcount, SetterAttrs, AttributeSet(), {}) +__OMP_RTL_ATTRS(__kmpc_push_target_tripcount_mapper, SetterAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__tgt_target_mapper, ForkAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__tgt_target_nowait_mapper, ForkAttrs, AttributeSet(), {}) __OMP_RTL_ATTRS(__tgt_target_teams_mapper, ForkAttrs, AttributeSet(), {}) diff --git a/llvm/include/llvm/IR/CMakeLists.txt b/llvm/include/llvm/IR/CMakeLists.txt index 0498fc269b634..e53f2420a5518 100644 --- a/llvm/include/llvm/IR/CMakeLists.txt +++ b/llvm/include/llvm/IR/CMakeLists.txt @@ -8,6 +8,7 @@ tablegen(LLVM IntrinsicsAArch64.h -gen-intrinsic-enums -intrinsic-prefix=aarch64 tablegen(LLVM IntrinsicsAMDGPU.h -gen-intrinsic-enums -intrinsic-prefix=amdgcn) tablegen(LLVM IntrinsicsARM.h -gen-intrinsic-enums -intrinsic-prefix=arm) tablegen(LLVM IntrinsicsBPF.h -gen-intrinsic-enums -intrinsic-prefix=bpf) +tablegen(LLVM IntrinsicsDPU.h -gen-intrinsic-enums -intrinsic-prefix=dpu) tablegen(LLVM IntrinsicsHexagon.h -gen-intrinsic-enums -intrinsic-prefix=hexagon) tablegen(LLVM IntrinsicsMips.h -gen-intrinsic-enums -intrinsic-prefix=mips) tablegen(LLVM IntrinsicsNVPTX.h -gen-intrinsic-enums -intrinsic-prefix=nvvm) diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index f42ef48de6b3c..955ac8e537fe1 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1757,9 +1757,6 @@ class CallBase : public Instruction { return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } - /// Returns true if this function is guaranteed to return. - bool willReturn() const { return hasFnAttr(Attribute::WillReturn); } - void setOnlyReadsMemory() { addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly); } diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h index d2a55f89fac98..b99dc62bbb9de 100644 --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -633,6 +633,10 @@ class Instruction : public User, /// generated program. bool isSafeToRemove() const; + /// Return true if the instruction will return (unwinding is considered as + /// a form of returning control flow here). + bool willReturn() const; + /// Return true if the instruction is a variety of EH-block. bool isEHPad() const { switch (getOpcode()) { @@ -650,6 +654,9 @@ class Instruction : public User, /// llvm.lifetime.end marker. bool isLifetimeStartOrEnd() const; + /// Return true if the instruction is a DbgInfoIntrinsic or PseudoProbeInst. + bool isDebugOrPseudoInst() const; + /// Return a pointer to the next non-debug instruction in the same basic /// block as 'this', or nullptr if no such instruction exists. Skip any pseudo /// operations if \c SkipPseudoOp is true. diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h index 9d68f3fdde6c2..df3a1d5687567 100644 --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -981,12 +981,16 @@ class PseudoProbeInst : public IntrinsicInst { return cast(const_cast(getArgOperand(0))); } + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(1))); + } + ConstantInt *getAttributes() const { return cast(const_cast(getArgOperand(2))); } - ConstantInt *getIndex() const { - return cast(const_cast(getArgOperand(1))); + ConstantInt *getFactor() const { + return cast(const_cast(getArgOperand(3))); } }; diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index b2bfc6e6f9e6a..35b605821b15e 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1298,7 +1298,7 @@ def int_sideeffect : DefaultAttrsIntrinsic<[], [], [IntrInaccessibleMemOnly, Int // Like the sideeffect intrinsic defined above, this intrinsic is treated by the // optimizer as having opaque side effects so that it won't be get rid of or moved // out of the block it probes. -def int_pseudoprobe : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], +def int_pseudoprobe : Intrinsic<[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty, llvm_i64_ty], [IntrInaccessibleMemOnly, IntrWillReturn]>; // Intrinsics to support half precision floating point format @@ -1664,3 +1664,4 @@ include "llvm/IR/IntrinsicsSystemZ.td" include "llvm/IR/IntrinsicsWebAssembly.td" include "llvm/IR/IntrinsicsRISCV.td" include "llvm/IR/IntrinsicsVE.td" +include "llvm/IR/IntrinsicsDPU.td" diff --git a/llvm/include/llvm/IR/IntrinsicsDPU.td b/llvm/include/llvm/IR/IntrinsicsDPU.td new file mode 100644 index 0000000000000..0efeb1ecf43ee --- /dev/null +++ b/llvm/include/llvm/IR/IntrinsicsDPU.td @@ -0,0 +1,25 @@ +//===- IntrinsicsDPU.td - Defines DPU intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the DPU-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +def llvm_mram_ptr_ty : LLVMQualPointerType; +def llvm_wram_ptr_ty : LLVMQualPointerType; + +let TargetPrefix = "dpu" in { + +def int_dpu_tid : Intrinsic<[llvm_anyint_ty], [], [IntrNoMem]>; +def int_dpu_sdma : Intrinsic<[], [llvm_wram_ptr_ty, llvm_mram_ptr_ty, llvm_i32_ty], [IntrHasSideEffects, ReadOnly>, WriteOnly>, Throws]>; +def int_dpu_ldma : Intrinsic<[], [llvm_wram_ptr_ty, llvm_mram_ptr_ty, llvm_i32_ty], [IntrHasSideEffects, ReadOnly>, WriteOnly>, Throws]>; +def int_dpu_sdma_unchecked : Intrinsic<[], [llvm_wram_ptr_ty, llvm_wram_ptr_ty, llvm_i32_ty], [IntrHasSideEffects, ReadOnly>, WriteOnly>, Throws]>; +def int_dpu_ldma_unchecked : Intrinsic<[], [llvm_wram_ptr_ty, llvm_wram_ptr_ty, llvm_i32_ty], [IntrHasSideEffects, ReadOnly>, WriteOnly>, Throws]>; + +} diff --git a/llvm/include/llvm/IR/IntrinsicsRISCV.td b/llvm/include/llvm/IR/IntrinsicsRISCV.td index ab5b09b72ac33..c4056895f68e6 100644 --- a/llvm/include/llvm/IR/IntrinsicsRISCV.td +++ b/llvm/include/llvm/IR/IntrinsicsRISCV.td @@ -790,6 +790,9 @@ let TargetPrefix = "riscv" in { defm vsoxei : RISCVIStore; defm vsuxei : RISCVIStore; + def int_riscv_vle1 : RISCVUSLoad; + def int_riscv_vse1 : RISCVUSStore; + defm vamoswap : RISCVAMO; defm vamoadd : RISCVAMO; defm vamoxor : RISCVAMO; @@ -940,8 +943,8 @@ let TargetPrefix = "riscv" in { defm vfwnmsac : RISCVTernaryWide; defm vfsqrt : RISCVUnaryAA; - defm vfrsqrte7 : RISCVUnaryAA; - defm vfrece7 : RISCVUnaryAA; + defm vfrsqrt7 : RISCVUnaryAA; + defm vfrec7 : RISCVUnaryAA; defm vfmin : RISCVBinaryAAX; defm vfmax : RISCVBinaryAAX; diff --git a/llvm/include/llvm/IR/Metadata.h b/llvm/include/llvm/IR/Metadata.h index 0b87416befe92..9a4480b75a30f 100644 --- a/llvm/include/llvm/IR/Metadata.h +++ b/llvm/include/llvm/IR/Metadata.h @@ -667,6 +667,12 @@ struct AAMDNodes { /// The tag specifying the noalias scope. MDNode *NoAlias = nullptr; + // Shift tbaa Metadata node to start off bytes later + static MDNode *ShiftTBAA(MDNode *M, size_t off); + + // Shift tbaa.struct Metadata node to start off bytes later + static MDNode *ShiftTBAAStruct(MDNode *M, size_t off); + /// Given two sets of AAMDNodes that apply to the same pointer, /// give the best AAMDNodes that are compatible with both (i.e. a set of /// nodes whose allowable aliasing conclusions are a subset of those @@ -680,6 +686,18 @@ struct AAMDNodes { Result.NoAlias = Other.NoAlias == NoAlias ? NoAlias : nullptr; return Result; } + + /// Create a new AAMDNode that describes this AAMDNode after applying a + /// constant offset to the start of the pointer + AAMDNodes shift(size_t Offset) { + AAMDNodes Result; + Result.TBAA = TBAA ? ShiftTBAA(TBAA, Offset) : nullptr; + Result.TBAAStruct = + TBAAStruct ? ShiftTBAAStruct(TBAAStruct, Offset) : nullptr; + Result.Scope = Scope; + Result.NoAlias = NoAlias; + return Result; + } }; // Specialize DenseMapInfo for AAMDNodes. diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h index acfacbd6c74e6..945f7e46e142d 100644 --- a/llvm/include/llvm/IR/Operator.h +++ b/llvm/include/llvm/IR/Operator.h @@ -568,6 +568,11 @@ class GEPOperator bool accumulateConstantOffset( const DataLayout &DL, APInt &Offset, function_ref ExternalAnalysis = nullptr) const; + + static bool accumulateConstantOffset( + Type *SourceType, ArrayRef Index, const DataLayout &DL, + APInt &Offset, + function_ref ExternalAnalysis = nullptr); }; class PtrToIntOperator diff --git a/llvm/include/llvm/IR/PseudoProbe.h b/llvm/include/llvm/IR/PseudoProbe.h index e0370c2641023..5165e80caa2d3 100644 --- a/llvm/include/llvm/IR/PseudoProbe.h +++ b/llvm/include/llvm/IR/PseudoProbe.h @@ -16,28 +16,39 @@ #include "llvm/ADT/Optional.h" #include #include +#include namespace llvm { class Instruction; +class BasicBlock; constexpr const char *PseudoProbeDescMetadataName = "llvm.pseudo_probe_desc"; enum class PseudoProbeType { Block = 0, IndirectCall, DirectCall }; +// The saturated distrution factor representing 100% for block probes. +constexpr static uint64_t PseudoProbeFullDistributionFactor = + std::numeric_limits::max(); + struct PseudoProbeDwarfDiscriminator { +public: // The following APIs encodes/decodes per-probe information to/from a // 32-bit integer which is organized as: // [2:0] - 0x7, this is reserved for regular discriminator, // see DWARF discriminator encoding rule // [18:3] - probe id - // [25:19] - reserved + // [25:19] - probe distribution factor // [28:26] - probe type, see PseudoProbeType // [31:29] - reserved for probe attributes - static uint32_t packProbeData(uint32_t Index, uint32_t Type) { + static uint32_t packProbeData(uint32_t Index, uint32_t Type, uint32_t Flags, + uint32_t Factor) { assert(Index <= 0xFFFF && "Probe index too big to encode, exceeding 2^16"); assert(Type <= 0x7 && "Probe type too big to encode, exceeding 7"); - return (Index << 3) | (Type << 26) | 0x7; + assert(Flags <= 0x7); + assert(Factor <= 100 && + "Probe distribution factor too big to encode, exceeding 100"); + return (Index << 3) | (Factor << 19) | (Type << 26) | 0x7; } static uint32_t extractProbeIndex(uint32_t Value) { @@ -51,16 +62,26 @@ struct PseudoProbeDwarfDiscriminator { static uint32_t extractProbeAttributes(uint32_t Value) { return (Value >> 29) & 0x7; } + + static uint32_t extractProbeFactor(uint32_t Value) { + return (Value >> 19) & 0x7F; + } + + // The saturated distrution factor representing 100% for callsites. + constexpr static uint8_t FullDistributionFactor = 100; }; struct PseudoProbe { uint32_t Id; uint32_t Type; uint32_t Attr; + float Factor; }; Optional extractProbe(const Instruction &Inst); +void setProbeDistributionFactor(Instruction &Inst, float Factor); + } // end namespace llvm #endif // LLVM_IR_PSEUDOPROBE_H diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index fed53eef68c3d..f301d49def20c 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -369,7 +369,8 @@ template class ELFObjectFile : public ELFObjectFileBase { for (const Elf_Shdr &Sec : *SectionsOrErr) { if (Sec.sh_type == ELF::SHT_ARM_ATTRIBUTES || - Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES) { + Sec.sh_type == ELF::SHT_RISCV_ATTRIBUTES || + Sec.sh_type == ELF::SHT_DPU_ATTRIBUTES) { auto ErrorOrContents = EF.getSectionContents(Sec); if (!ErrorOrContents) return ErrorOrContents.takeError(); @@ -1170,6 +1171,8 @@ StringRef ELFObjectFile::getFileFormatName() const { return "elf32-sparc"; case ELF::EM_AMDGPU: return "elf32-amdgpu"; + case ELF::EM_DPU: + return "elf32-dpu"; default: return "elf32-unknown"; } @@ -1251,6 +1254,8 @@ template Triple::ArchType ELFObjectFile::getArch() const { case ELF::EM_S390: return Triple::systemz; + case ELF::EM_DPU: + return Triple::dpu; case ELF::EM_SPARC: case ELF::EM_SPARC32PLUS: return IsLittleEndian ? Triple::sparcel : Triple::sparc; diff --git a/llvm/include/llvm/Passes/StandardInstrumentations.h b/llvm/include/llvm/Passes/StandardInstrumentations.h index 795a980878e26..61c86b0468f22 100644 --- a/llvm/include/llvm/Passes/StandardInstrumentations.h +++ b/llvm/include/llvm/Passes/StandardInstrumentations.h @@ -22,6 +22,7 @@ #include "llvm/IR/PassTimingInfo.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Transforms/IPO/SampleProfileProbe.h" #include #include @@ -273,6 +274,7 @@ class StandardInstrumentations { OptBisectInstrumentation OptBisect; PreservedCFGCheckerInstrumentation PreservedCFGChecker; IRChangedPrinter PrintChangedIR; + PseudoProbeVerifier PseudoProbeVerification; VerifyInstrumentation Verify; bool VerifyEach; diff --git a/llvm/include/llvm/ProfileData/ProfileCommon.h b/llvm/include/llvm/ProfileData/ProfileCommon.h index 6bb5825339ae1..55b94b2e690de 100644 --- a/llvm/include/llvm/ProfileData/ProfileCommon.h +++ b/llvm/include/llvm/ProfileData/ProfileCommon.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/ProfileSummary.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Error.h" #include #include @@ -89,6 +90,8 @@ class SampleProfileSummaryBuilder final : public ProfileSummaryBuilder { void addRecord(const sampleprof::FunctionSamples &FS, bool isCallsiteSample = false); + std::unique_ptr computeSummaryForProfiles( + const StringMap &Profiles); std::unique_ptr getSummary(); }; diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index c45ace9e68c16..25d5b2376c114 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -347,6 +347,16 @@ class SampleRecord { return SortedTargets; } + /// Prorate call targets by a distribution factor. + static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets, + float DistributionFactor) { + CallTargetMap AdjustedTargets; + for (const auto &I : Targets) { + AdjustedTargets[I.first()] = I.second * DistributionFactor; + } + return AdjustedTargets; + } + /// Merge the samples in \p Other into this record. /// Optionally scale sample counts by \p Weight. sampleprof_error merge(const SampleRecord &Other, uint64_t Weight = 1) { @@ -439,9 +449,11 @@ class SampleContext { void clearState(ContextStateMask S) { State &= (uint32_t)~S; } bool hasContext() const { return State != UnknownContext; } bool isBaseContext() const { return CallingContext.empty(); } - StringRef getName() const { return Name; } + StringRef getNameWithoutContext() const { return Name; } StringRef getCallingContext() const { return CallingContext; } - StringRef getNameWithContext() const { return FullContext; } + StringRef getNameWithContext(bool WithBracket = false) const { + return WithBracket ? InputContext : FullContext; + } private: // Give a context string, decode and populate internal states like @@ -449,6 +461,7 @@ class SampleContext { // `ContextStr`: `[main:3 @ _Z5funcAi:1 @ _Z8funcLeafi]` void setContext(StringRef ContextStr, ContextStateMask CState) { assert(!ContextStr.empty()); + InputContext = ContextStr; // Note that `[]` wrapped input indicates a full context string, otherwise // it's treated as context-less function name only. bool HasContext = ContextStr.startswith("["); @@ -480,6 +493,9 @@ class SampleContext { } } + // Input context string including bracketed calling context and leaf function + // name + StringRef InputContext; // Full context string including calling context and leaf function name StringRef FullContext; // Function name for the associated sample profile @@ -676,7 +692,8 @@ class FunctionSamples { Name = Other.getName(); if (!GUIDToFuncNameMap) GUIDToFuncNameMap = Other.GUIDToFuncNameMap; - + if (Context.getNameWithContext(true).empty()) + Context = Other.getContext(); if (FunctionHash == 0) { // Set the function hash code for the target profile. FunctionHash = Other.getFunctionHash(); @@ -743,8 +760,10 @@ class FunctionSamples { StringRef getName() const { return Name; } /// Return function name with context. - StringRef getNameWithContext() const { - return FunctionSamples::ProfileIsCS ? Context.getNameWithContext() : Name; + StringRef getNameWithContext(bool WithBracket = false) const { + return FunctionSamples::ProfileIsCS + ? Context.getNameWithContext(WithBracket) + : Name; } /// Return the original function name. diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h index 3f52a2f6163b7..999e75eddffac 100644 --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -488,8 +488,12 @@ class SampleProfileReader { /// \brief Whether samples are collected based on pseudo probes. bool ProfileIsProbeBased = false; + /// Whether function profiles are context-sensitive. bool ProfileIsCS = false; + /// Number of context-sensitive profiles. + uint32_t CSProfileCount = 0; + /// \brief The format of sample. SampleProfileFormat Format = SPF_None; }; diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h index 38f3e188be553..0706aa226c0e3 100644 --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -369,9 +369,22 @@ class Option { virtual void setDefault() = 0; + // Prints the help string for an option. + // + // This maintains the Indent for multi-line descriptions. + // FirstLineIndentedBy is the count of chars of the first line + // i.e. the one containing the --