diff --git a/.ci/metrics/metrics.py b/.ci/metrics/metrics.py index 70b787665a8b9..d219c9e55169e 100644 --- a/.ci/metrics/metrics.py +++ b/.ci/metrics/metrics.py @@ -43,40 +43,60 @@ def get_sampled_workflow_metrics(github_repo: github.Repository): Returns a list of GaugeMetric objects, containing the relevant metrics about the workflow """ + queued_job_counts = {} + running_job_counts = {} # Other states are available (pending, waiting, etc), but the meaning # is not documented (See #70540). # "queued" seems to be the info we want. - queued_workflow_count = len( - [ - x - for x in github_repo.get_workflow_runs(status="queued") - if x.name in WORKFLOWS_TO_TRACK - ] - ) - running_workflow_count = len( - [ - x - for x in github_repo.get_workflow_runs(status="in_progress") - if x.name in WORKFLOWS_TO_TRACK - ] - ) + for queued_workflow in github_repo.get_workflow_runs(status="queued"): + if queued_workflow.name not in WORKFLOWS_TO_TRACK: + continue + for queued_workflow_job in queued_workflow.jobs(): + job_name = queued_workflow_job.name + # Workflows marked as queued can potentially only have some jobs + # queued, so make sure to also count jobs currently in progress. + if queued_workflow_job.status == "queued": + if job_name not in queued_job_counts: + queued_job_counts[job_name] = 1 + else: + queued_job_counts[job_name] += 1 + elif queued_workflow_job.status == "in_progress": + if job_name not in running_job_counts: + running_job_counts[job_name] = 1 + else: + running_job_counts[job_name] += 1 + + for running_workflow in github_repo.get_workflow_runs(status="in_progress"): + if running_workflow.name not in WORKFLOWS_TO_TRACK: + continue + for running_workflow_job in running_workflow.jobs(): + job_name = running_workflow_job.name + if running_workflow_job.status != "in_progress": + continue + + if job_name not in running_job_counts: + running_job_counts[job_name] = 1 + else: + running_job_counts[job_name] += 1 workflow_metrics = [] - workflow_metrics.append( - GaugeMetric( - "workflow_queue_size", - queued_workflow_count, - time.time_ns(), + for queued_job in queued_job_counts: + workflow_metrics.append( + GaugeMetric( + f"workflow_queue_size_{queued_job}", + queued_job_counts[queued_job], + time.time_ns(), + ) ) - ) - workflow_metrics.append( - GaugeMetric( - "running_workflow_count", - running_workflow_count, - time.time_ns(), + for running_job in running_job_counts: + workflow_metrics.append( + GaugeMetric( + f"running_workflow_count_{running_job}", + running_job_counts[running_job], + time.time_ns(), + ) ) - ) # Always send a hearbeat metric so we can monitor is this container is still able to log to Grafana. workflow_metrics.append( GaugeMetric("metrics_container_heartbeat", 1, time.time_ns()) @@ -157,7 +177,7 @@ def get_per_workflow_metrics( # longer in a testing state and we can directly assert the workflow # result. for step in workflow_job.steps: - if step.conclusion != "success": + if step.conclusion != "success" and step.conclusion != "skipped": job_result = 0 break @@ -235,8 +255,6 @@ def upload_metrics(workflow_metrics, metrics_userid, api_key): def main(): # Authenticate with Github auth = Auth.Token(os.environ["GITHUB_TOKEN"]) - github_object = Github(auth=auth) - github_repo = github_object.get_repo("llvm/llvm-project") grafana_api_key = os.environ["GRAFANA_API_KEY"] grafana_metrics_userid = os.environ["GRAFANA_METRICS_USERID"] @@ -248,12 +266,11 @@ def main(): # Enter the main loop. Every five minutes we wake up and dump metrics for # the relevant jobs. while True: + github_object = Github(auth=auth) + github_repo = github_object.get_repo("llvm/llvm-project") + current_metrics = get_per_workflow_metrics(github_repo, workflows_to_track) current_metrics += get_sampled_workflow_metrics(github_repo) - # Always send a hearbeat metric so we can monitor is this container is still able to log to Grafana. - current_metrics.append( - GaugeMetric("metrics_container_heartbeat", 1, time.time_ns()) - ) upload_metrics(current_metrics, grafana_metrics_userid, grafana_api_key) print(f"Uploaded {len(current_metrics)} metrics", file=sys.stderr) diff --git a/.github/workflows/build-ci-container-windows.yml b/.github/workflows/build-ci-container-windows.yml index bba34066a97cd..068cb58301080 100644 --- a/.github/workflows/build-ci-container-windows.yml +++ b/.github/workflows/build-ci-container-windows.yml @@ -27,7 +27,7 @@ jobs: container-filename: ${{ steps.vars.outputs.container-filename }} steps: - name: Checkout LLVM - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout: .github/workflows/containers/github-action-ci-windows - name: Write Variables @@ -46,7 +46,7 @@ jobs: run: | docker save ${{ steps.vars.outputs.container-name-tag }} > ${{ steps.vars.outputs.container-filename }} - name: Upload container image - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: container path: ${{ steps.vars.outputs.container-filename }} @@ -63,7 +63,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Download container - uses: actions/download-artifact@v4 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 with: name: container - name: Push Container diff --git a/.github/workflows/build-ci-container.yml b/.github/workflows/build-ci-container.yml index 8272c8f6e266f..1921a3675166d 100644 --- a/.github/workflows/build-ci-container.yml +++ b/.github/workflows/build-ci-container.yml @@ -32,7 +32,7 @@ jobs: runs-on: depot-ubuntu-22.04-arm-16 steps: - name: Checkout LLVM - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout: .github/workflows/containers/github-action-ci/ # podman is not installed by default on the ARM64 images. @@ -66,7 +66,7 @@ jobs: podman save ${{ steps.vars.outputs.container-name-agent-tag }} > ${{ steps.vars.outputs.container-agent-filename }} - name: Upload container image - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 with: name: container-${{ matrix.arch }} path: "*.tar" @@ -90,7 +90,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Download container - uses: actions/download-artifact@v4 + uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - name: Push Container run: | diff --git a/.github/workflows/premerge.yaml b/.github/workflows/premerge.yaml index 178ab191a58be..49753c0746cbe 100644 --- a/.github/workflows/premerge.yaml +++ b/.github/workflows/premerge.yaml @@ -33,11 +33,11 @@ jobs: runs-on: llvm-premerge-linux-runners steps: - name: Checkout LLVM - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - name: Setup ccache - uses: hendrikmuhs/ccache-action@v1.2.14 + uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 with: max-size: "2000M" - name: Build and Test @@ -94,11 +94,11 @@ jobs: shell: bash steps: - name: Checkout LLVM - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - name: Setup ccache - uses: hendrikmuhs/ccache-action@v1.2.14 + uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 with: variant: "sccache" max-size: "2000M" @@ -144,7 +144,7 @@ jobs: call C:\\BuildTools\\Common7\\Tools\\VsDevCmd.bat -arch=amd64 -host_arch=amd64 bash .ci/monolithic-windows.sh "${{ steps.vars.outputs.windows-projects }}" "${{ steps.vars.outputs.windows-check-targets }}" - permerge-check-macos: + premerge-check-macos: runs-on: macos-14 if: >- github.repository_owner == 'llvm' && @@ -153,11 +153,11 @@ jobs: (github.event_name != 'pull_request' || github.event.action != 'closed') steps: - name: Checkout LLVM - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: fetch-depth: 2 - name: Setup ccache - uses: hendrikmuhs/ccache-action@v1.2.14 + uses: hendrikmuhs/ccache-action@a1209f81afb8c005c13b4296c32e363431bffea5 # v1.2.17 with: max-size: "2000M" - name: Install Ninja diff --git a/.github/workflows/release-asset-audit.py b/.github/workflows/release-asset-audit.py index cf6ad7fbbe143..0ff1ce81b28dd 100644 --- a/.github/workflows/release-asset-audit.py +++ b/.github/workflows/release-asset-audit.py @@ -1,4 +1,5 @@ import github +import re import sys _SPECIAL_CASE_BINARIES = { @@ -16,38 +17,73 @@ def _is_valid(uploader_name, valid_uploaders, asset_name): return False +def _get_uploaders(release_version): + # Until llvm 18, assets were uploaded by community members, the release managers + # and the GitHub Actions bot. + if release_version <= 18: + return set( + [ + "DimitryAndric", + "stefanp-ibm", + "lei137", + "omjavaid", + "nicolerabjohn", + "amy-kwan", + "mandlebug", + "zmodem", + "androm3da", + "tru", + "rovka", + "rorth", + "quinnlp", + "kamaub", + "abrisco", + "jakeegan", + "maryammo", + "tstellar", + "github-actions[bot]", + ] + ) + # llvm 19 and beyond, only the release managers, bot and a much smaller + # number of community members. + elif release_version >= 19: + return set( + [ + "zmodem", + "omjavaid", + "tru", + "tstellar", + "github-actions[bot]", + ] + ) + + +def _get_major_release_version(release_title): + # All release titles are of the form "LLVM X.Y.Z(-rcN)". + match = re.match("LLVM ([0-9]+)\.", release_title) + if match is None: + _write_comment_and_exit_with_error( + f'Could not parse release version from release title "{release_title}".' + ) + else: + return int(match.groups()[0]) + + +def _write_comment_and_exit_with_error(comment): + with open("comment", "w") as file: + file.write(comment) + sys.exit(1) + + def main(): token = sys.argv[1] gh = github.Github(login_or_token=token) repo = gh.get_repo("llvm/llvm-project") - uploaders = set( - [ - "DimitryAndric", - "stefanp-ibm", - "lei137", - "omjavaid", - "nicolerabjohn", - "amy-kwan", - "mandlebug", - "zmodem", - "androm3da", - "tru", - "rovka", - "rorth", - "quinnlp", - "kamaub", - "abrisco", - "jakeegan", - "maryammo", - "tstellar", - "github-actions[bot]", - ] - ) - for release in repo.get_releases(): print("Release:", release.title) + uploaders = _get_uploaders(_get_major_release_version(release.title)) for asset in release.get_assets(): created_at = asset.created_at updated_at = ( @@ -57,9 +93,9 @@ def main(): f"{asset.name} : {asset.uploader.login} [{created_at} {updated_at}] ( {asset.download_count} )" ) if not _is_valid(asset.uploader.login, uploaders, asset.name): - with open('comment', 'w') as file: - file.write(f'@{asset.uploader.login} is not a valid uploader.') - sys.exit(1) + _write_comment_and_exit_with_error( + f"@{asset.uploader.login} is not a valid uploader." + ) if __name__ == "__main__": diff --git a/.github/workflows/release-binaries-all.yml b/.github/workflows/release-binaries-all.yml index d18b9b0b5c2ff..fd4694ebea32d 100644 --- a/.github/workflows/release-binaries-all.yml +++ b/.github/workflows/release-binaries-all.yml @@ -27,6 +27,10 @@ on: required: true default: false type: boolean + secrets: + RELEASE_TASKS_USER_TOKEN: + description: "Secret used to check user permissions." + required: false pull_request: types: diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 204ee6405382f..398734c1a366d 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -133,13 +133,13 @@ jobs: # add extra CMake args to disable them. # See https://github.com/llvm/llvm-project/issues/99767 if [ "$RUNNER_OS" = "macOS" ]; then - target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_COMPILER_RT_ENABLE_IOS=OFF" + target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_BOOTSTRAP_COMPILER_RT_ENABLE_IOS=OFF" if [ "$RUNNER_ARCH" = "ARM64" ]; then arches=arm64 else arches=x86_64 fi - target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_DARWIN_osx_ARCHS=$arches -DBOOTSTRAP_DARWIN_osx_BUILTIN_ARCHS=$arches" + target_cmake_flags="$target_cmake_flags -DBOOTSTRAP_BOOTSTRAP_DARWIN_osx_ARCHS=$arches -DBOOTSTRAP_BOOTSTRAP_DARWIN_osx_BUILTIN_ARCHS=$arches" fi build_flang="true" diff --git a/.mailmap b/.mailmap index 851394b3e9dca..f5b220f892fce 100644 --- a/.mailmap +++ b/.mailmap @@ -38,6 +38,8 @@ Jianjian GUAN Jon Roelofs Jon Roelofs Jonathan Thackray +klensy +klensy LLVM GN Syncbot Martin Storsjö Med Ismail Bennani diff --git a/bolt/include/bolt/Core/BinarySection.h b/bolt/include/bolt/Core/BinarySection.h index 1093f6ad78a99..9c252c3675951 100644 --- a/bolt/include/bolt/Core/BinarySection.h +++ b/bolt/include/bolt/Core/BinarySection.h @@ -359,15 +359,9 @@ class BinarySection { /// Add a new relocation at the given /p Offset. void addRelocation(uint64_t Offset, MCSymbol *Symbol, uint64_t Type, - uint64_t Addend, uint64_t Value = 0, - bool Pending = false) { + uint64_t Addend, uint64_t Value = 0) { assert(Offset < getSize() && "offset not within section bounds"); - if (!Pending) { - Relocations.emplace(Relocation{Offset, Symbol, Type, Addend, Value}); - } else { - PendingRelocations.emplace_back( - Relocation{Offset, Symbol, Type, Addend, Value}); - } + Relocations.emplace(Relocation{Offset, Symbol, Type, Addend, Value}); } /// Add a dynamic relocation at the given /p Offset. diff --git a/bolt/include/bolt/Profile/DataAggregator.h b/bolt/include/bolt/Profile/DataAggregator.h index aa83d7f9b13ab..56eb463fc98fc 100644 --- a/bolt/include/bolt/Profile/DataAggregator.h +++ b/bolt/include/bolt/Profile/DataAggregator.h @@ -94,7 +94,7 @@ class DataAggregator : public DataReader { /// Used for parsing specific pre-aggregated input files. struct AggregatedLBREntry { - enum Type : char { BRANCH = 0, FT, FT_EXTERNAL_ORIGIN }; + enum Type : char { BRANCH = 0, FT, FT_EXTERNAL_ORIGIN, TRACE }; Location From; Location To; uint64_t Count; @@ -197,6 +197,10 @@ class DataAggregator : public DataReader { BoltAddressTranslation *BAT{nullptr}; + /// Whether pre-aggregated profile needs to convert branch profile into call + /// to continuation fallthrough profile. + bool NeedsConvertRetProfileToCallCont{false}; + /// Update function execution profile with a recorded trace. /// A trace is region of code executed between two LBR entries supplied in /// execution order. @@ -268,8 +272,7 @@ class DataAggregator : public DataReader { uint64_t Mispreds); /// Register a \p Branch. - bool doBranch(uint64_t From, uint64_t To, uint64_t Count, uint64_t Mispreds, - bool IsPreagg); + bool doBranch(uint64_t From, uint64_t To, uint64_t Count, uint64_t Mispreds); /// Register a trace between two LBR entries supplied in execution order. bool doTrace(const LBREntry &First, const LBREntry &Second, @@ -298,7 +301,7 @@ class DataAggregator : public DataReader { ErrorOr parseMemSample(); /// Parse pre-aggregated LBR samples created by an external tool - ErrorOr parseAggregatedLBREntry(); + std::error_code parseAggregatedLBREntry(); /// Parse either buildid:offset or just offset, representing a location in the /// binary. Used exclusively for pre-aggregated LBR samples. @@ -384,14 +387,15 @@ class DataAggregator : public DataReader { /// memory. /// /// File format syntax: - /// {B|F|f} [:] [:] - /// [] + /// {B|F|f|T} [:] [:] [] + /// [] /// /// B - indicates an aggregated branch /// F - an aggregated fall-through /// f - an aggregated fall-through with external origin - used to disambiguate /// between a return hitting a basic block head and a regular internal /// jump to the block + /// T - an aggregated trace: branch with a fall-through (from, to, ft_end) /// /// - build id of the object containing the start address. We can /// skip it for the main binary and use "X" for an unknown object. This will @@ -402,6 +406,8 @@ class DataAggregator : public DataReader { /// /// , - same for the end address. /// + /// - same for the fallthrough_end address. + /// /// - total aggregated count of the branch or a fall-through. /// /// - the number of times the branch was mispredicted. diff --git a/bolt/lib/Profile/DataAggregator.cpp b/bolt/lib/Profile/DataAggregator.cpp index de9ec6c1723d5..a859f27569385 100644 --- a/bolt/lib/Profile/DataAggregator.cpp +++ b/bolt/lib/Profile/DataAggregator.cpp @@ -711,7 +711,7 @@ bool DataAggregator::doInterBranch(BinaryFunction *FromFunc, } bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count, - uint64_t Mispreds, bool IsPreagg) { + uint64_t Mispreds) { // Returns whether \p Offset in \p Func contains a return instruction. auto checkReturn = [&](const BinaryFunction &Func, const uint64_t Offset) { auto isReturn = [&](auto MI) { return MI && BC->MIB->isReturn(*MI); }; @@ -772,7 +772,8 @@ bool DataAggregator::doBranch(uint64_t From, uint64_t To, uint64_t Count, return false; // Record call to continuation trace. - if (IsPreagg && FromFunc != ToFunc && (IsReturn || IsCallCont)) { + if (NeedsConvertRetProfileToCallCont && FromFunc != ToFunc && + (IsReturn || IsCallCont)) { LBREntry First{ToOrig - 1, ToOrig - 1, false}; LBREntry Second{ToOrig, ToOrig, false}; return doTrace(First, Second, Count); @@ -1216,23 +1217,30 @@ ErrorOr DataAggregator::parseLocationOrOffset() { return Location(true, BuildID.get(), Offset.get()); } -ErrorOr -DataAggregator::parseAggregatedLBREntry() { +std::error_code DataAggregator::parseAggregatedLBREntry() { while (checkAndConsumeFS()) { } ErrorOr TypeOrErr = parseString(FieldSeparator); if (std::error_code EC = TypeOrErr.getError()) return EC; + // Pre-aggregated profile with branches and fallthroughs needs to convert + // return profile into call to continuation fall-through. auto Type = AggregatedLBREntry::BRANCH; if (TypeOrErr.get() == "B") { + NeedsConvertRetProfileToCallCont = true; Type = AggregatedLBREntry::BRANCH; } else if (TypeOrErr.get() == "F") { + NeedsConvertRetProfileToCallCont = true; Type = AggregatedLBREntry::FT; } else if (TypeOrErr.get() == "f") { + NeedsConvertRetProfileToCallCont = true; Type = AggregatedLBREntry::FT_EXTERNAL_ORIGIN; + } else if (TypeOrErr.get() == "T") { + // Trace is expanded into B and [Ff] + Type = AggregatedLBREntry::TRACE; } else { - reportError("expected B, F or f"); + reportError("expected T, B, F or f"); return make_error_code(llvm::errc::io_error); } @@ -1248,6 +1256,15 @@ DataAggregator::parseAggregatedLBREntry() { if (std::error_code EC = To.getError()) return EC; + ErrorOr TraceFtEnd = std::error_code(); + if (Type == AggregatedLBREntry::TRACE) { + while (checkAndConsumeFS()) { + } + TraceFtEnd = parseLocationOrOffset(); + if (std::error_code EC = TraceFtEnd.getError()) + return EC; + } + while (checkAndConsumeFS()) { } ErrorOr Frequency = @@ -1270,9 +1287,24 @@ DataAggregator::parseAggregatedLBREntry() { return make_error_code(llvm::errc::io_error); } - return AggregatedLBREntry{From.get(), To.get(), - static_cast(Frequency.get()), Mispreds, - Type}; + BinaryFunction *FromFunc = getBinaryFunctionContainingAddress(From->Offset); + BinaryFunction *ToFunc = getBinaryFunctionContainingAddress(To->Offset); + + for (BinaryFunction *BF : {FromFunc, ToFunc}) + if (BF) + BF->setHasProfileAvailable(); + + uint64_t Count = static_cast(Frequency.get()); + AggregatedLBREntry Entry{From.get(), To.get(), Count, Mispreds, Type}; + AggregatedLBRs.emplace_back(Entry); + if (Type == AggregatedLBREntry::TRACE) { + auto FtType = (FromFunc == ToFunc) ? AggregatedLBREntry::FT + : AggregatedLBREntry::FT_EXTERNAL_ORIGIN; + AggregatedLBREntry TraceFt{To.get(), TraceFtEnd.get(), Count, 0, FtType}; + AggregatedLBRs.emplace_back(TraceFt); + } + + return std::error_code(); } bool DataAggregator::ignoreKernelInterrupt(LBREntry &LBR) const { @@ -1585,8 +1617,7 @@ void DataAggregator::processBranchEvents() { for (const auto &AggrLBR : BranchLBRs) { const Trace &Loc = AggrLBR.first; const TakenBranchInfo &Info = AggrLBR.second; - doBranch(Loc.From, Loc.To, Info.TakenCount, Info.MispredCount, - /*IsPreagg*/ false); + doBranch(Loc.From, Loc.To, Info.TakenCount, Info.MispredCount); } } @@ -1722,18 +1753,10 @@ std::error_code DataAggregator::parsePreAggregatedLBRSamples() { outs() << "PERF2BOLT: parsing pre-aggregated profile...\n"; NamedRegionTimer T("parseAggregated", "Parsing aggregated branch events", TimerGroupName, TimerGroupDesc, opts::TimeAggregator); - while (hasData()) { - ErrorOr AggrEntry = parseAggregatedLBREntry(); - if (std::error_code EC = AggrEntry.getError()) + while (hasData()) + if (std::error_code EC = parseAggregatedLBREntry()) return EC; - for (const uint64_t Addr : {AggrEntry->From.Offset, AggrEntry->To.Offset}) - if (BinaryFunction *BF = getBinaryFunctionContainingAddress(Addr)) - BF->setHasProfileAvailable(); - - AggregatedLBRs.emplace_back(std::move(AggrEntry.get())); - } - return std::error_code(); } @@ -1746,8 +1769,9 @@ void DataAggregator::processPreAggregated() { for (const AggregatedLBREntry &AggrEntry : AggregatedLBRs) { switch (AggrEntry.EntryType) { case AggregatedLBREntry::BRANCH: + case AggregatedLBREntry::TRACE: doBranch(AggrEntry.From.Offset, AggrEntry.To.Offset, AggrEntry.Count, - AggrEntry.Mispreds, /*IsPreagg*/ true); + AggrEntry.Mispreds); break; case AggregatedLBREntry::FT: case AggregatedLBREntry::FT_EXTERNAL_ORIGIN: { diff --git a/bolt/test/X86/callcont-fallthru.s b/bolt/test/X86/callcont-fallthru.s index d76f869c971fd..95cb4c5fc2df4 100644 --- a/bolt/test/X86/callcont-fallthru.s +++ b/bolt/test/X86/callcont-fallthru.s @@ -4,19 +4,21 @@ # RUN: %clang %cflags -fpic -shared -xc /dev/null -o %t.so ## Link against a DSO to ensure PLT entries. # RUN: %clangxx %cxxflags %s %t.so -o %t -Wl,-q -nostdlib -# RUN: link_fdata %s %t %t.pa1 PREAGG +# RUN: link_fdata %s %t %t.pa1 PREAGG1 # RUN: link_fdata %s %t %t.pa2 PREAGG2 # RUN: link_fdata %s %t %t.pa3 PREAGG3 -# RUN: link_fdata %s %t %t.pa4 PREAGG4 +# RUN: link_fdata %s %t %t.pat PREAGGT1 +# RUN: link_fdata %s %t %t.pat2 PREAGGT2 ## Check normal case: fallthrough is not LP or secondary entry. -# RUN: llvm-strip --strip-unneeded %t -o %t.exe -# RUN: llvm-bolt %t.exe --pa -p %t.pa1 -o %t.out \ +# RUN: llvm-strip --strip-unneeded %t -o %t.strip +# RUN: llvm-objcopy --remove-section=.eh_frame %t.strip %t.noeh +# RUN: llvm-bolt %t.strip --pa -p %t.pa1 -o %t.out \ # RUN: --print-cfg --print-only=main | FileCheck %s ## Check that getFallthroughsInTrace correctly handles a trace starting at plt ## call continuation -# RUN: llvm-bolt %t.exe --pa -p %t.pa2 -o %t.out2 \ +# RUN: llvm-bolt %t.strip --pa -p %t.pa2 -o %t.out2 \ # RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK2 ## Check that we don't treat secondary entry points as call continuation sites. @@ -24,8 +26,21 @@ # RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK3 ## Check fallthrough to a landing pad case. -# RUN: llvm-bolt %t.exe --pa -p %t.pa4 -o %t.out \ -# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK4 +# RUN: llvm-bolt %t.strip --pa -p %t.pa3 -o %t.out \ +# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK3 + +## Check pre-aggregated traces attach call continuation fallthrough count +# RUN: llvm-bolt %t.noeh --pa -p %t.pat -o %t.out \ +# RUN: --print-cfg --print-only=main | FileCheck %s + +## Check pre-aggregated traces don't attach call continuation fallthrough count +## to secondary entry point (unstripped) +# RUN: llvm-bolt %t --pa -p %t.pat2 -o %t.out \ +# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK3 +## Check pre-aggregated traces don't attach call continuation fallthrough count +## to landing pad (stripped, LP) +# RUN: llvm-bolt %t.strip --pa -p %t.pat2 -o %t.out \ +# RUN: --print-cfg --print-only=main | FileCheck %s --check-prefix=CHECK3 .globl foo .type foo, %function @@ -51,8 +66,9 @@ main: movl %edi, -0x8(%rbp) movq %rsi, -0x10(%rbp) callq puts@PLT -## Target is a call continuation -# PREAGG: B X:0 #Ltmp1# 2 0 +## Target is an external-origin call continuation +# PREAGG1: B X:0 #Ltmp1# 2 0 +# PREAGGT1: T X:0 #Ltmp1# #Ltmp4_br# 2 # CHECK: callq puts@PLT # CHECK-NEXT: count: 2 @@ -63,14 +79,16 @@ Ltmp1: Ltmp4: cmpl $0x0, -0x14(%rbp) +Ltmp4_br: je Ltmp0 # CHECK2: je .Ltmp0 # CHECK2-NEXT: count: 3 movl $0xa, -0x18(%rbp) callq foo -## Target is a call continuation -# PREAGG: B #Lfoo_ret# #Ltmp3# 1 0 +## Target is a binary-local call continuation +# PREAGG1: B #Lfoo_ret# #Ltmp3# 1 0 +# PREAGGT1: T #Lfoo_ret# #Ltmp3# #Ltmp3_br# 1 # CHECK: callq foo # CHECK-NEXT: count: 1 @@ -79,16 +97,12 @@ Ltmp4: # CHECK2: callq foo # CHECK2-NEXT: count: 3 -## Target is a secondary entry point +## Target is a secondary entry point (unstripped) or a landing pad (stripped) # PREAGG3: B X:0 #Ltmp3# 2 0 +# PREAGGT2: T X:0 #Ltmp3# #Ltmp3_br# 2 # CHECK3: callq foo # CHECK3-NEXT: count: 0 -## Target is a landing pad -# PREAGG4: B X:0 #Ltmp3# 2 0 -# CHECK4: callq puts@PLT -# CHECK4-NEXT: count: 0 - Ltmp3: cmpl $0x0, -0x18(%rbp) Ltmp3_br: diff --git a/bolt/test/link_fdata.py b/bolt/test/link_fdata.py index 3837e394ccc87..028823a69ce00 100755 --- a/bolt/test/link_fdata.py +++ b/bolt/test/link_fdata.py @@ -34,9 +34,9 @@ fdata_pat = re.compile(r"([01].*) (?P\d+) (?P\d+)") # Pre-aggregated profile: -# {B|F|f} [:] [:] -# [] -preagg_pat = re.compile(r"(?P[BFf]) (?P.*)") +# {T|B|F|f} [:] [:] [] +# [] +preagg_pat = re.compile(r"(?P[TBFf]) (?P.*)") # No-LBR profile: # diff --git a/bolt/tools/driver/llvm-bolt.cpp b/bolt/tools/driver/llvm-bolt.cpp index efa06cd68cb99..f151cf5f63fc5 100644 --- a/bolt/tools/driver/llvm-bolt.cpp +++ b/bolt/tools/driver/llvm-bolt.cpp @@ -173,16 +173,6 @@ void boltMode(int argc, char **argv) { } } -static std::string GetExecutablePath(const char *Argv0) { - SmallString<256> ExecutablePath(Argv0); - // Do a PATH lookup if Argv0 isn't a valid path. - if (!llvm::sys::fs::exists(ExecutablePath)) - if (llvm::ErrorOr P = - llvm::sys::findProgramByName(ExecutablePath)) - ExecutablePath = *P; - return std::string(ExecutablePath); -} - int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); @@ -190,7 +180,7 @@ int main(int argc, char **argv) { llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - std::string ToolPath = GetExecutablePath(argv[0]); + std::string ToolPath = llvm::sys::fs::getMainExecutable(argv[0], nullptr); // Initialize targets and assembly printers/parsers. llvm::InitializeAllTargetInfos(); diff --git a/bolt/unittests/Core/BinaryContext.cpp b/bolt/unittests/Core/BinaryContext.cpp index 9819a8c2b777b..0fefa1b83c3c2 100644 --- a/bolt/unittests/Core/BinaryContext.cpp +++ b/bolt/unittests/Core/BinaryContext.cpp @@ -93,12 +93,13 @@ TEST_P(BinaryContextTester, FlushPendingRelocCALL26) { DataSize, 4); MCSymbol *RelSymbol1 = BC->getOrCreateGlobalSymbol(4, "Func1"); ASSERT_TRUE(RelSymbol1); - BS.addRelocation(8, RelSymbol1, ELF::R_AARCH64_CALL26, 0, 0, true); + BS.addPendingRelocation( + Relocation{8, RelSymbol1, ELF::R_AARCH64_CALL26, 0, 0}); MCSymbol *RelSymbol2 = BC->getOrCreateGlobalSymbol(16, "Func2"); ASSERT_TRUE(RelSymbol2); - BS.addRelocation(12, RelSymbol2, ELF::R_AARCH64_CALL26, 0, 0, true); + BS.addPendingRelocation( + Relocation{12, RelSymbol2, ELF::R_AARCH64_CALL26, 0, 0}); - std::error_code EC; SmallVector Vect(DataSize); raw_svector_ostream OS(Vect); @@ -134,12 +135,13 @@ TEST_P(BinaryContextTester, FlushPendingRelocJUMP26) { (uint8_t *)Data, Size, 4); MCSymbol *RelSymbol1 = BC->getOrCreateGlobalSymbol(4, "Func1"); ASSERT_TRUE(RelSymbol1); - BS.addRelocation(8, RelSymbol1, ELF::R_AARCH64_JUMP26, 0, 0, true); + BS.addPendingRelocation( + Relocation{8, RelSymbol1, ELF::R_AARCH64_JUMP26, 0, 0}); MCSymbol *RelSymbol2 = BC->getOrCreateGlobalSymbol(16, "Func2"); ASSERT_TRUE(RelSymbol2); - BS.addRelocation(12, RelSymbol2, ELF::R_AARCH64_JUMP26, 0, 0, true); + BS.addPendingRelocation( + Relocation{12, RelSymbol2, ELF::R_AARCH64_JUMP26, 0, 0}); - std::error_code EC; SmallVector Vect(Size); raw_svector_ostream OS(Vect); diff --git a/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp b/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp index aeb7fe90f2175..ea0207619fb2b 100644 --- a/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp +++ b/clang-tools-extra/clang-reorder-fields/ReorderFieldsAction.cpp @@ -70,11 +70,12 @@ getNewFieldsOrder(const RecordDecl *Definition, } SmallVector NewFieldsOrder; for (const auto &Name : DesiredFieldsOrder) { - if (!NameToIndex.count(Name)) { + auto It = NameToIndex.find(Name); + if (It == NameToIndex.end()) { llvm::errs() << "Field " << Name << " not found in definition.\n"; return {}; } - NewFieldsOrder.push_back(NameToIndex[Name]); + NewFieldsOrder.push_back(It->second); } assert(NewFieldsOrder.size() == NameToIndex.size()); return NewFieldsOrder; diff --git a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp index 43b69a24bdb16..07071a1f6d2fe 100644 --- a/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/NonConstParameterCheck.cpp @@ -119,13 +119,12 @@ void NonConstParameterCheck::addParm(const ParmVarDecl *Parm) { T->getPointeeType()->isFloatingType())) return; - if (Parameters.find(Parm) != Parameters.end()) + auto [It, Inserted] = Parameters.try_emplace(Parm); + if (!Inserted) return; - ParmInfo PI; - PI.IsReferenced = false; - PI.CanBeConst = true; - Parameters[Parm] = PI; + It->second.IsReferenced = false; + It->second.CanBeConst = true; } void NonConstParameterCheck::setReferenced(const DeclRefExpr *Ref) { diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp index 4a9426ee7e8bb..0637d0eff688c 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp @@ -14,13 +14,14 @@ namespace clang::tidy::utils { ExceptionSpecAnalyzer::State ExceptionSpecAnalyzer::analyze(const FunctionDecl *FuncDecl) { - // Check if the function has already been analyzed and reuse that result. - const auto CacheEntry = FunctionCache.find(FuncDecl); - if (CacheEntry == FunctionCache.end()) { + // Check if function exist in cache or add temporary value to cache to protect + // against endless recursion. + const auto [CacheEntry, NotFound] = + FunctionCache.try_emplace(FuncDecl, State::NotThrowing); + if (NotFound) { ExceptionSpecAnalyzer::State State = analyzeImpl(FuncDecl); - - // Cache the result of the analysis. - FunctionCache.try_emplace(FuncDecl, State); + // Update result with calculated value + FunctionCache[FuncDecl] = State; return State; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp index 347a1e3220061..4df0927b62af5 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp @@ -1,4 +1,6 @@ // RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t -- -- -fexceptions +// RUN: %check_clang_tidy -std=c++17 -check-suffixes=,ERR %s performance-noexcept-move-constructor %t \ +// RUN: -- --fix-errors -- -fexceptions -DENABLE_ERROR namespace std { @@ -397,3 +399,18 @@ namespace gh68101 Container(Container&&) noexcept(std::is_nothrow_move_constructible::value); }; } // namespace gh68101 + +namespace gh111436 +{ + +template class set { + set(set &&) = default; + +#ifdef ENABLE_ERROR + set(initializer_list __l) {}; + // CHECK-MESSAGES-ERR: :[[@LINE-1]]:7: error: member 'initializer_list' cannot have template arguments [clang-diagnostic-error] + // CHECK-MESSAGES-ERR: :[[@LINE-2]]:36: error: expected ')' [clang-diagnostic-error] +#endif +}; + +} // namespace gh111436 diff --git a/clang/docs/HLSL/FunctionCalls.rst b/clang/docs/HLSL/FunctionCalls.rst index 6d65fe6e3fb20..ea6dc2ad8a4df 100644 --- a/clang/docs/HLSL/FunctionCalls.rst +++ b/clang/docs/HLSL/FunctionCalls.rst @@ -248,13 +248,14 @@ which is a term made up for HLSL. A cx-value is a temporary value which may be the result of a cast, and stores its value back to an lvalue when the value expires. -To represent this concept in Clang we introduce a new ``HLSLOutParamExpr``. An -``HLSLOutParamExpr`` has two forms, one with a single sub-expression and one -with two sub-expressions. +To represent this concept in Clang we introduce a new ``HLSLOutArgExpr``. An +``HLSLOutArgExpr`` has three sub-expressions: -The single sub-expression form is used when the argument expression and the -function parameter are the same type, so no cast is required. As in this -example: +* An OpaqueValueExpr of the argument lvalue expression. +* An OpaqueValueExpr of the copy-initialized parameter temporary. +* A BinaryOpExpr assigning the first with the value of the second. + +Given this example: .. code-block:: c++ @@ -267,23 +268,36 @@ example: Init(V); } -The expected AST formulation for this code would be something like: +The expected AST formulation for this code would be something like the example +below. Due to the nature of OpaqueValueExpr nodes, the nodes repeat in the AST +dump. The fake addresses ``0xSOURCE`` and ``0xTEMPORARY`` denote the source +lvalue and argument temporary lvalue expressions. .. code-block:: text CallExpr 'void' |-ImplicitCastExpr 'void (*)(int &)' | `-DeclRefExpr 'void (int &)' lvalue Function 'Init' 'void (int &)' - |-HLSLOutParamExpr 'int' lvalue inout - `-DeclRefExpr 'int' lvalue Var 'V' 'int' - -The ``HLSLOutParamExpr`` captures that the value is ``inout`` vs ``out`` to -denote whether or not the temporary is initialized from the sub-expression. If -no casting is required the sub-expression denotes the lvalue expression that the -cx-value will be copied to when the value expires. - -The two sub-expression form of the AST node is required when the argument type -is not the same as the parameter type. Given this example: + `-HLSLOutArgExpr 'int' lvalue inout + |-OpaqueValueExpr 0xSOURCE 'int' lvalue + | `-DeclRefExpr 'int' lvalue Var 'V' 'int' + |-OpaqueValueExpr 0xTEMPORARY 'int' lvalue + | `-ImplicitCastExpr 'int' + | `-OpaqueValueExpr 0xSOURCE 'int' lvalue + | `-DeclRefExpr 'int' lvalue Var 'V' 'int' + `-BinaryOperator 'int' lvalue '=' + |-OpaqueValueExpr 0xSOURCE 'int' lvalue + | `-DeclRefExpr 'int' lvalue Var 'V' 'int' + `-ImplicitCastExpr 'int' + `-OpaqueValueExpr 0xTEMPORARY 'int' lvalue + `-ImplicitCastExpr 'int' + `-OpaqueValueExpr 0xSOURCE 'int' lvalue + `-DeclRefExpr 'int' lvalue Var 'V' 'int' + +The ``HLSLOutArgExpr`` captures that the value is ``inout`` vs ``out`` to +denote whether or not the temporary is initialized from the sub-expression. + +The example below demonstrates argument casting: .. code-block:: c++ @@ -295,7 +309,7 @@ is not the same as the parameter type. Given this example: Trunc(F); } -For this case the ``HLSLOutParamExpr`` will have sub-expressions to record both +For this case the ``HLSLOutArgExpr`` will have sub-expressions to record both casting expression sequences for the initialization and write back: .. code-block:: text @@ -303,20 +317,31 @@ casting expression sequences for the initialization and write back: -CallExpr 'void' |-ImplicitCastExpr 'void (*)(int3 &)' | `-DeclRefExpr 'void (int3 &)' lvalue Function 'inc_i32' 'void (int3 &)' - `-HLSLOutParamExpr 'int3' lvalue inout - |-ImplicitCastExpr 'float3' - | `-ImplicitCastExpr 'int3' - | `-OpaqueValueExpr 'int3' lvalue - `-ImplicitCastExpr 'int3' - `-ImplicitCastExpr 'float3' - `-DeclRefExpr 'float3' lvalue 'F' 'float3' - -In this formation the write-back casts are captured as the first sub-expression -and they cast from an ``OpaqueValueExpr``. In IR generation we can use the -``OpaqueValueExpr`` as a placeholder for the ``HLSLOutParamExpr``'s temporary -value on function return. - -In code generation this can be implemented with some targeted extensions to the -Objective-C write-back support. Specifically extending CGCall.cpp's -``EmitWriteback`` function to support casting expressions and emission of -aggregate lvalues. + `-HLSLOutArgExpr 'int3':'vector' lvalue inout + |-OpaqueValueExpr 0xSOURCE 'float3':'vector' lvalue + | `-DeclRefExpr 'float3':'vector' lvalue Var 'F' 'float3':'vector' + |-OpaqueValueExpr 0xTEMPORARY 'int3':'vector' lvalue + | `-ImplicitCastExpr 'vector' + | `-ImplicitCastExpr 'float3':'vector' + | `-OpaqueValueExpr 0xSOURCE 'float3':'vector' lvalue + | `-DeclRefExpr 'float3':'vector' lvalue Var 'F' 'float3':'vector' + `-BinaryOperator 'float3':'vector' lvalue '=' + |-OpaqueValueExpr 0xSOURCE 'float3':'vector' lvalue + | `-DeclRefExpr 'float3':'vector' lvalue Var 'F' 'float3':'vector' + `-ImplicitCastExpr 'vector' + `-ImplicitCastExpr 'int3':'vector' + `-OpaqueValueExpr 0xTEMPORARY 'int3':'vector' lvalue + `-ImplicitCastExpr 'vector' + `-ImplicitCastExpr 'float3':'vector' + `-OpaqueValueExpr 0xSOURCE 'float3':'vector' lvalue + `-DeclRefExpr 'float3':'vector' lvalue Var 'F' 'float3':'vector' + +The AST representation is the same whether casting is required or not, which +simplifies the code generation. IR generation does the following: + +* Emit the argument lvalue expression. +* Initialize the argument: + * For ``inout`` arguments, emit the copy-initialization expression. + * For ``out`` arguments, emit an uninitialized temporary. +* Emit the call +* Emit the write-back BinaryOperator expression. diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 973cf8f9d091c..2a956ad5b2909 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2866,6 +2866,47 @@ etc.). Query for this feature with ``__has_builtin(__builtin_assume_separate_storage)``. +``__builtin_assume_dereferenceable`` +------------------------------------- + +``__builtin_assume_dereferenceable`` is used to provide the optimizer with the +knowledge that the pointer argument P is dereferenceable up to at least the +specified number of bytes. + +**Syntax**: + +.. code-block:: c++ + + __builtin_assume_dereferenceable(const void *, size_t) + +**Example of Use**: + +.. code-block:: c++ + + int foo(int *x, int y) { + __builtin_assume_dereferenceable(x, sizeof(int)); + int z = 0; + if (y == 1) { + // The optimizer may execute the load of x unconditionally due to + // __builtin_assume_dereferenceable guaranteeing sizeof(int) bytes can + // be loaded speculatively without trapping. + z = *x; + } + return z; + } + +**Description**: + +The arguments to this function provide a start pointer ``P`` and a size ``S``. +``S`` must be at least 1 and a constant. The optimizer may assume that ``S`` +bytes are dereferenceable starting at ``P``. Note that this does not necessarily +imply that ``P`` is non-null as ``nullptr`` can be dereferenced in some cases. +The assumption also does not imply that ``P`` is not dereferenceable past ``S`` +bytes. + + +Query for this feature with ``__has_builtin(__builtin_assume_dereferenceable)``. + ``__builtin_offsetof`` ---------------------- diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b8a04167b9ca8..efaacdf18d50a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -54,6 +54,8 @@ ABI Changes in This Version AST Dumping Potentially Breaking Changes ---------------------------------------- +- Added support for dumping template arguments of structural value kinds. + Clang Frontend Potentially Breaking Changes ------------------------------------------- @@ -91,6 +93,7 @@ C Language Changes - Clang now allows an ``inline`` specifier on a typedef declaration of a function type in Microsoft compatibility mode. #GH124869 +- Clang now allows ``restrict`` qualifier for array types with pointer elements (#GH92847). C2y Feature Support ^^^^^^^^^^^^^^^^^^^ @@ -122,6 +125,10 @@ Attribute Changes in Clang - The ``no_sanitize`` attribute now accepts both ``gnu`` and ``clang`` names. - Clang now diagnoses use of declaration attributes on void parameters. (#GH108819) +- Clang now allows ``__attribute__((model("small")))`` and + ``__attribute__((model("large")))`` on non-TLS globals in x86-64 compilations. + This forces the global to be considered small or large in regards to the + x86-64 code model, regardless of the code model specified for the compilation. Improvements to Clang's diagnostics ----------------------------------- @@ -145,6 +152,9 @@ Improvements to Coverage Mapping Bug Fixes in This Version ------------------------- +- Clang now outputs correct values when #embed data contains bytes with negative + signed char values (#GH102798). + Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -212,6 +222,8 @@ LoongArch Support RISC-V Support ^^^^^^^^^^^^^^ +- Add support for `-mtune=generic-ooo` (a generic out-of-order model). + CUDA/HIP Language Changes ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/AST/JSONNodeDumper.h b/clang/include/clang/AST/JSONNodeDumper.h index 9422c8fceccfb..660a05435003d 100644 --- a/clang/include/clang/AST/JSONNodeDumper.h +++ b/clang/include/clang/AST/JSONNodeDumper.h @@ -345,6 +345,7 @@ class JSONNodeDumper void VisitDeclarationTemplateArgument(const TemplateArgument &TA); void VisitNullPtrTemplateArgument(const TemplateArgument &TA); void VisitIntegralTemplateArgument(const TemplateArgument &TA); + void VisitStructuralValueTemplateArgument(const TemplateArgument &TA); void VisitTemplateTemplateArgument(const TemplateArgument &TA); void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA); void VisitExpressionTemplateArgument(const TemplateArgument &TA); diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index d5f6c0f6cc67d..6134a70c04bd3 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -22,32 +22,29 @@ #include namespace llvm { - class raw_ostream; +class raw_ostream; } namespace clang { - class ASTContext; - class BlockDecl; - class CXXConstructorDecl; - class CXXDestructorDecl; - class CXXMethodDecl; - class FunctionDecl; - struct MethodVFTableLocation; - class NamedDecl; - class ObjCMethodDecl; - class StringLiteral; - struct ThisAdjustment; - struct ThunkInfo; - class VarDecl; +class ASTContext; +class BlockDecl; +class CXXConstructorDecl; +class CXXDestructorDecl; +class CXXMethodDecl; +class FunctionDecl; +struct MethodVFTableLocation; +class NamedDecl; +class ObjCMethodDecl; +class StringLiteral; +struct ThisAdjustment; +struct ThunkInfo; +class VarDecl; /// MangleContext - Context for tracking state which persists across multiple /// calls to the C++ name mangler. class MangleContext { public: - enum ManglerKind { - MK_Itanium, - MK_Microsoft - }; + enum ManglerKind { MK_Itanium, MK_Microsoft }; private: virtual void anchor(); @@ -59,10 +56,10 @@ class MangleContext { /// ASTContext. bool IsAux = false; - llvm::DenseMap GlobalBlockIds; - llvm::DenseMap LocalBlockIds; - llvm::DenseMap AnonStructIds; - llvm::DenseMap FuncAnonStructSize; + llvm::DenseMap GlobalBlockIds; + llvm::DenseMap LocalBlockIds; + llvm::DenseMap AnonStructIds; + llvm::DenseMap FuncAnonStructSize; public: ManglerKind getKind() const { return Kind; } @@ -73,7 +70,7 @@ class MangleContext { ManglerKind Kind, bool IsAux = false) : Context(Context), Diags(Diags), Kind(Kind), IsAux(IsAux) {} - virtual ~MangleContext() { } + virtual ~MangleContext() {} ASTContext &getASTContext() const { return Context; } @@ -82,10 +79,10 @@ class MangleContext { virtual void startNewFunction() { LocalBlockIds.clear(); } unsigned getBlockId(const BlockDecl *BD, bool Local) { - llvm::DenseMap &BlockIds - = Local? LocalBlockIds : GlobalBlockIds; + llvm::DenseMap &BlockIds = + Local ? LocalBlockIds : GlobalBlockIds; std::pair::iterator, bool> - Result = BlockIds.insert(std::make_pair(BD, BlockIds.size())); + Result = BlockIds.insert(std::make_pair(BD, BlockIds.size())); return Result.first->second; } @@ -125,7 +122,7 @@ class MangleContext { return false; } - virtual void needsUniqueInternalLinkageNames() { } + virtual void needsUniqueInternalLinkageNames() {} // FIXME: consider replacing raw_ostream & with something like SmallString &. void mangleName(GlobalDecl GD, raw_ostream &); @@ -143,10 +140,9 @@ class MangleContext { virtual void mangleCXXRTTIName(QualType T, raw_ostream &, bool NormalizeIntegers = false) = 0; virtual void mangleStringLiteral(const StringLiteral *SL, raw_ostream &) = 0; - virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream&); + virtual void mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &); - void mangleGlobalBlock(const BlockDecl *BD, - const NamedDecl *ID, + void mangleGlobalBlock(const BlockDecl *BD, const NamedDecl *ID, raw_ostream &Out); void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, raw_ostream &Out); @@ -314,6 +310,6 @@ class ASTNameGenerator { class Implementation; std::unique_ptr Impl; }; -} +} // namespace clang #endif diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def index b3dc7c3d8dc77..790dd572a7c99 100644 --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -370,6 +370,9 @@ CAST_OPERATION(HLSLArrayRValue) // Aggregate by Value cast (HLSL only). CAST_OPERATION(HLSLElementwiseCast) +// Splat cast for Aggregates (HLSL only). +CAST_OPERATION(HLSLAggregateSplatCast) + //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. // Note that additions to this should also update the StmtVisitor class, diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index b4d866d855323..736bcabbad1f7 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/include/clang/AST/StmtOpenMP.h @@ -996,7 +996,6 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective { return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass || C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass || C == OMPStripeDirectiveClass; - ; } }; @@ -5675,7 +5674,6 @@ class OMPStripeDirective final : public OMPLoopTransformationDirective { /// \param NumLoops Number of associated loops to allocate. static OMPStripeDirective * CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned NumLoops); - /// Gets/sets the associated loops after striping. /// /// This is in de-sugared format stored as a CompoundStmt. diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index bfd205ffb0d99..4b5ad2b5fa74c 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -249,6 +249,7 @@ class TextNodeDumper void VisitDeclarationTemplateArgument(const TemplateArgument &TA); void VisitNullPtrTemplateArgument(const TemplateArgument &TA); void VisitIntegralTemplateArgument(const TemplateArgument &TA); + void VisitStructuralValueTemplateArgument(const TemplateArgument &TA); void VisitTemplateTemplateArgument(const TemplateArgument &TA); void VisitTemplateExpansionTemplateArgument(const TemplateArgument &TA); void VisitExpressionTemplateArgument(const TemplateArgument &TA); diff --git a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h index aaf89f4e94d4a..78b03d325efd9 100644 --- a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h +++ b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h @@ -63,23 +63,6 @@ template class CachedConstAccessorsLattice : public Base { getOrCreateConstMethodReturnValue(const RecordStorageLocation &RecordLoc, const CallExpr *CE, Environment &Env); - /// Creates or returns a previously created `StorageLocation` associated with - /// a const method call `obj.getFoo()` where `RecordLoc` is the - /// `RecordStorageLocation` of `obj`. - /// - /// The callback `Initialize` runs on the storage location if newly created. - /// Returns nullptr if unable to find or create a value. - /// - /// Requirements: - /// - /// - `CE` should return a location (GLValue or a record type). - /// - /// DEPRECATED: switch users to the below overload which takes Callee and Type - /// directly. - StorageLocation *getOrCreateConstMethodReturnStorageLocation( - const RecordStorageLocation &RecordLoc, const CallExpr *CE, - Environment &Env, llvm::function_ref Initialize); - /// Creates or returns a previously created `StorageLocation` associated with /// a const method call `obj.getFoo()` where `RecordLoc` is the /// `RecordStorageLocation` of `obj`, `Callee` is the decl for `getFoo`. @@ -208,29 +191,6 @@ Value *CachedConstAccessorsLattice::getOrCreateConstMethodReturnValue( return Val; } -template -StorageLocation * -CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation( - const RecordStorageLocation &RecordLoc, const CallExpr *CE, - Environment &Env, llvm::function_ref Initialize) { - assert(!CE->getType().isNull()); - assert(CE->isGLValue() || CE->getType()->isRecordType()); - auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc]; - const FunctionDecl *DirectCallee = CE->getDirectCallee(); - if (DirectCallee == nullptr) - return nullptr; - auto it = ObjMap.find(DirectCallee); - if (it != ObjMap.end()) - return it->second; - - StorageLocation &Loc = - Env.createStorageLocation(CE->getType().getNonReferenceType()); - Initialize(Loc); - - ObjMap.insert({DirectCallee, &Loc}); - return &Loc; -} - template StorageLocation & CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation( diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 4384a98d63eb3..65c91ccd75ecc 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -459,6 +459,7 @@ class TargetArch arches> : TargetSpec { } def TargetARM : TargetArch<["arm", "thumb", "armeb", "thumbeb"]>; def TargetAArch64 : TargetArch<["aarch64", "aarch64_be", "aarch64_32"]>; +def TargetAMDGPU : TargetArch<["amdgcn", "r600"]>; def TargetAnyArm : TargetArch; def TargetAVR : TargetArch<["avr"]>; def TargetBPF : TargetArch<["bpfel", "bpfeb"]>; @@ -469,7 +470,9 @@ def TargetMSP430 : TargetArch<["msp430"]>; def TargetM68k : TargetArch<["m68k"]>; def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; def TargetX86 : TargetArch<["x86"]>; +def TargetX86_64 : TargetArch<["x86_64"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; +def TargetSPIRV : TargetArch<["spirv", "spirv32", "spirv64"]>; def TargetWebAssembly : TargetArch<["wasm32", "wasm64"]>; def TargetNVPTX : TargetArch<["nvptx", "nvptx64"]>; def TargetWindows : TargetSpec { @@ -3124,11 +3127,20 @@ def PragmaClangTextSection : InheritableAttr { let Documentation = [InternalOnly]; } -def CodeModel : InheritableAttr, TargetSpecificAttr { +// The code model attribute only applies to LoongArch and x86-64, but for NVPTX +// compilations that share code with the host, we want to ignore the attribute +// rather than warn on it. +def CodeModel + : InheritableAttr, + TargetSpecificAttr> { let Spellings = [GCC<"model">]; - let Args = [EnumArgument<"Model", "llvm::CodeModel::Model", /*is_string=*/1, - ["normal", "medium", "extreme"], ["Small", "Medium", "Large"], - /*opt=*/0, /*fake=*/0, /*isExternalType=*/1, /*isCovered=*/0>]; + let Args = [EnumArgument< + "Model", "llvm::CodeModel::Model", + /*is_string=*/1, ["small", "normal", "medium", "large", "extreme"], + ["Small", "Small", "Medium", "Large", "Large"], + /*opt=*/0, /*fake=*/0, /*isExternalType=*/1, /*isCovered=*/0>]; let Subjects = SubjectList<[NonTLSGlobalVar], ErrorDiag>; let Documentation = [CodeModelDocs]; } diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 0ad4c958d0983..f5362b4d59142 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -62,6 +62,16 @@ def CodeModelDocs : Documentation { let Content = [{ The ``model`` attribute allows overriding the translation unit's code model (specified by ``-mcmodel``) for a specific global variable. + +On LoongArch, allowed values are "normal", "medium", "extreme". + +On x86-64, allowed values are ``"small"`` and ``"large"``. ``"small"`` is +roughly equivalent to ``-mcmodel=small``, meaning the global is considered +"small" placed closer to the ``.text`` section relative to "large" globals, and +to prefer using 32-bit relocations to access the global. ``"large"`` is roughly +equivalent to ``-mcmodel=large``, meaning the global is considered "large" and +placed further from the ``.text`` section relative to "small" globals, and +64-bit relocations must be used to access the global. }]; let Heading = "model"; } @@ -8482,7 +8492,7 @@ that is a pointer to the type with the attribute. } The above example will result in a call to ``bar`` being passed the address of -`y`` when ``y`` goes out of scope, then a call to ``foo`` being passed the +``y`` when ``y`` goes out of scope, then a call to ``foo`` being passed the address of ``x`` when ``x`` goes out of scope. If two or more variables share the same scope, their ``cleanup`` callbacks are invoked in the reverse order the variables were declared in. It is not possible to check the return value diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 29939242596ba..0e5df338dd2e5 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -839,6 +839,12 @@ def BuiltinAssumeAligned : Builtin { let Prototype = "void*(void const*, size_t, ...)"; } +def BuiltinAssumeDereferenceable : Builtin { + let Spellings = ["__builtin_assume_dereferenceable"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(void const*, _Constant size_t)"; +} + def BuiltinFree : Builtin { let Spellings = ["__builtin_free"]; let Attributes = [FunctionWithBuiltinPrefix, NoThrow]; diff --git a/clang/include/clang/Basic/BuiltinsNVPTX.td b/clang/include/clang/Basic/BuiltinsNVPTX.td index 9d24a992563a4..327dc88cffdb4 100644 --- a/clang/include/clang/Basic/BuiltinsNVPTX.td +++ b/clang/include/clang/Basic/BuiltinsNVPTX.td @@ -669,6 +669,14 @@ def __nvvm_redux_sync_umax : NVPTXBuiltinSMAndPTX<"unsigned int(unsigned int, in def __nvvm_redux_sync_and : NVPTXBuiltinSMAndPTX<"int(int, int)", SM_80, PTX70>; def __nvvm_redux_sync_xor : NVPTXBuiltinSMAndPTX<"int(int, int)", SM_80, PTX70>; def __nvvm_redux_sync_or : NVPTXBuiltinSMAndPTX<"int(int, int)", SM_80, PTX70>; +def __nvvm_redux_sync_fmin : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmin_abs : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmin_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmin_abs_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmax : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmax_abs : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmax_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; +def __nvvm_redux_sync_fmax_abs_NaN : NVPTXBuiltinSMAndPTX<"float(float, int)", SM_100a, PTX86>; // Membar diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2fce5e88ba8a0..c4f0fc55b4a38 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7413,6 +7413,11 @@ def warn_c23_compat_utf8_string : Warning< def note_cxx20_c23_compat_utf8_string_remove_u8 : Note< "remove 'u8' prefix to avoid a change of behavior; " "Clang encodes unprefixed narrow string literals as UTF-8">; +def warn_c23_compat_restrict_on_array_of_pointers : Warning< + "'restrict' qualifier on an array of pointers is incompatible with C standards before C23">, + InGroup, DefaultIgnore; +def ext_restrict_on_array_of_pointers_c23 : Extension< + "'restrict' qualifier on an array of pointers is a C23 extension">, InGroup; def err_array_init_different_type : Error< "cannot initialize array %diff{of type $ with array of type $|" "with different type of array}0,1">; diff --git a/clang/include/clang/Basic/FPOptions.def b/clang/include/clang/Basic/FPOptions.def index 79f04c89c9fed..90428c3c73c8b 100644 --- a/clang/include/clang/Basic/FPOptions.def +++ b/clang/include/clang/Basic/FPOptions.def @@ -28,5 +28,5 @@ OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) OPTION(Float16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, FPEvalMethod) OPTION(BFloat16ExcessPrecision, LangOptions::ExcessPrecisionKind, 2, Float16ExcessPrecision) OPTION(MathErrno, bool, 1, BFloat16ExcessPrecision) -OPTION(ComplexRange, LangOptions::ComplexRangeKind, 2, MathErrno) +OPTION(ComplexRange, LangOptions::ComplexRangeKind, 3, MathErrno) #undef OPTION diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index cb55f09acc076..bfab0baa089cf 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -238,7 +238,7 @@ BENIGN_LANGOPT(NoSignedZero , 1, 0, "Permit Floating Point optimization wit BENIGN_LANGOPT(AllowRecip , 1, 0, "Permit Floating Point reciprocal") BENIGN_LANGOPT(ApproxFunc , 1, 0, "Permit Floating Point approximation") -ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 2, CX_None, "Enable use of range reduction for complex arithmetics.") +ENUM_LANGOPT(ComplexRange, ComplexRangeKind, 3, CX_None, "Enable use of range reduction for complex arithmetics.") BENIGN_LANGOPT(ObjCGCBitmapPrint , 1, 0, "printing of GC's bitmap layout for __weak/__strong ivars") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index f58a719a45a84..651b3b67b1058 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -648,9 +648,12 @@ class LangOptions : public LangOptionsBase { // Define accessors/mutators for language options of enumeration type. #define LANGOPT(Name, Bits, Default, Description) -#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - Type get##Name() const { return static_cast(Name); } \ - void set##Name(Type Value) { Name = static_cast(Value); } +#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + Type get##Name() const { return static_cast(Name); } \ + void set##Name(Type Value) { \ + assert(static_cast(Value) < (1u << Bits)); \ + Name = static_cast(Value); \ + } #include "clang/Basic/LangOptions.def" /// Are we compiling a module? @@ -959,11 +962,14 @@ class FPOptions { void applyChanges(FPOptionsOverride FPO); // We can define most of the accessors automatically: + // TODO: consider enforcing the assertion that value fits within bits + // statically. #define OPTION(NAME, TYPE, WIDTH, PREVIOUS) \ TYPE get##NAME() const { \ return static_cast((Value & NAME##Mask) >> NAME##Shift); \ } \ void set##NAME(TYPE value) { \ + assert(storage_type(value) < (1u << WIDTH)); \ Value = (Value & ~NAME##Mask) | (storage_type(value) << NAME##Shift); \ } #include "clang/Basic/FPOptions.def" diff --git a/clang/include/clang/CodeGen/CGFunctionInfo.h b/clang/include/clang/CodeGen/CGFunctionInfo.h index 9d785d878b61d..040ee025afaa8 100644 --- a/clang/include/clang/CodeGen/CGFunctionInfo.h +++ b/clang/include/clang/CodeGen/CGFunctionInfo.h @@ -206,8 +206,8 @@ class ABIArgInfo { static ABIArgInfo getIgnore() { return ABIArgInfo(Ignore); } - static ABIArgInfo getIndirect(CharUnits Alignment, bool ByVal = true, - bool Realign = false, + static ABIArgInfo getIndirect(CharUnits Alignment, unsigned AddrSpace, + bool ByVal = true, bool Realign = false, llvm::Type *Padding = nullptr) { auto AI = ABIArgInfo(Indirect); AI.setIndirectAlign(Alignment); @@ -215,6 +215,7 @@ class ABIArgInfo { AI.setIndirectRealign(Realign); AI.setSRetAfterThis(false); AI.setPaddingType(Padding); + AI.setIndirectAddrSpace(AddrSpace); return AI; } @@ -232,7 +233,7 @@ class ABIArgInfo { static ABIArgInfo getIndirectInReg(CharUnits Alignment, bool ByVal = true, bool Realign = false) { - auto AI = getIndirect(Alignment, ByVal, Realign); + auto AI = getIndirect(Alignment, 0, ByVal, Realign); AI.setInReg(true); return AI; } @@ -422,12 +423,12 @@ class ABIArgInfo { } unsigned getIndirectAddrSpace() const { - assert(isIndirectAliased() && "Invalid kind!"); + assert((isIndirect() || isIndirectAliased()) && "Invalid kind!"); return IndirectAttr.AddrSpace; } void setIndirectAddrSpace(unsigned AddrSpace) { - assert(isIndirectAliased() && "Invalid kind!"); + assert((isIndirect() || isIndirectAliased()) && "Invalid kind!"); IndirectAttr.AddrSpace = AddrSpace; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 1cf62ab466134..5ad187926e710 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3397,7 +3397,7 @@ def fno_objc_weak : Flag<["-"], "fno-objc-weak">, Group, def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group, Visibility<[ClangOption, FlangOption]>; defm operator_names : BoolFOption<"operator-names", - LangOpts<"CXXOperatorNames">, Default, + LangOpts<"CXXOperatorNames">, Default, NegFlag, PosFlag>; @@ -5618,10 +5618,18 @@ def nogpuinc : Flag<["-"], "nogpuinc">, Group, def nohipwrapperinc : Flag<["-"], "nohipwrapperinc">, Group, HelpText<"Do not include the default HIP wrapper headers and include paths">; def : Flag<["-"], "nocudainc">, Alias; -def nogpulib : Flag<["-"], "nogpulib">, MarshallingInfoFlag>, - Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, - HelpText<"Do not link device library for CUDA/HIP device compilation">; -def : Flag<["-"], "nocudalib">, Alias; +def no_offloadlib + : Flag<["--"], "no-offloadlib">, + MarshallingInfoFlag>, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, + HelpText<"Do not link device library for CUDA/HIP device compilation">; +def offloadlib : Flag<["--"], "offloadlib">, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, + HelpText<"Link device libraries for GPU device compilation">; +def : Flag<["-"], "nogpulib">, + Alias, + Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; +def : Flag<["-"], "nocudalib">, Alias; def gpulibc : Flag<["-"], "gpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>, HelpText<"Link the LLVM C Library for GPUs">; def nogpulibc : Flag<["-"], "nogpulibc">, Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>; diff --git a/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def new file mode 100644 index 0000000000000..e6df763920430 --- /dev/null +++ b/clang/include/clang/Lex/HLSLRootSignatureTokenKinds.def @@ -0,0 +1,123 @@ +//===--- HLSLRootSignature.def - Tokens and Enum Database -------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the TokenKinds used in the Root Signature DSL. This +// includes keywords, enums and a small subset of punctuators. Users of this +// file must optionally #define the TOK, KEYWORD, ENUM or specific ENUM macros +// to make use of this file. +// +//===----------------------------------------------------------------------===// + +#ifndef TOK +#define TOK(X) +#endif +#ifndef PUNCTUATOR +#define PUNCTUATOR(X,Y) TOK(pu_ ## X) +#endif +#ifndef KEYWORD +#define KEYWORD(X) TOK(kw_ ## X) +#endif +#ifndef ENUM +#define ENUM(NAME, LIT) TOK(en_ ## NAME) +#endif + +// Defines the various types of enum +#ifndef DESCRIPTOR_RANGE_OFFSET_ENUM +#define DESCRIPTOR_RANGE_OFFSET_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif +#ifndef ROOT_DESCRIPTOR_FLAG_ENUM +#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif +// Note: ON denotes that the flag is unique from the above Root Descriptor +// Flags. This is required to avoid token kind enum conflicts. +#ifndef DESCRIPTOR_RANGE_FLAG_ENUM_OFF +#define DESCRIPTOR_RANGE_FLAG_ENUM_OFF(NAME, LIT) +#endif +#ifndef DESCRIPTOR_RANGE_FLAG_ENUM_ON +#define DESCRIPTOR_RANGE_FLAG_ENUM_ON(NAME, LIT) ENUM(NAME, LIT) +#endif +#ifndef DESCRIPTOR_RANGE_FLAG_ENUM +#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) DESCRIPTOR_RANGE_FLAG_ENUM_##ON(NAME, LIT) +#endif +#ifndef SHADER_VISIBILITY_ENUM +#define SHADER_VISIBILITY_ENUM(NAME, LIT) ENUM(NAME, LIT) +#endif + +// General Tokens: +TOK(invalid) +TOK(end_of_stream) +TOK(int_literal) + +// Register Tokens: +TOK(bReg) +TOK(tReg) +TOK(uReg) +TOK(sReg) + +// Punctuators: +PUNCTUATOR(l_paren, '(') +PUNCTUATOR(r_paren, ')') +PUNCTUATOR(comma, ',') +PUNCTUATOR(or, '|') +PUNCTUATOR(equal, '=') +PUNCTUATOR(plus, '+') +PUNCTUATOR(minus, '-') + +// RootElement Keywords: +KEYWORD(DescriptorTable) + +// DescriptorTable Keywords: +KEYWORD(CBV) +KEYWORD(SRV) +KEYWORD(UAV) +KEYWORD(Sampler) + +// General Parameter Keywords: +KEYWORD(space) +KEYWORD(visibility) +KEYWORD(flags) + +// View Parameter Keywords: +KEYWORD(numDescriptors) +KEYWORD(offset) + +// Descriptor Range Offset Enum: +DESCRIPTOR_RANGE_OFFSET_ENUM(DescriptorRangeOffsetAppend, "DESCRIPTOR_RANGE_OFFSET_APPEND") + +// Root Descriptor Flag Enums: +ROOT_DESCRIPTOR_FLAG_ENUM(DataVolatile, "DATA_VOLATILE") +ROOT_DESCRIPTOR_FLAG_ENUM(DataStaticWhileSetAtExecute, "DATA_STATIC_WHILE_SET_AT_EXECUTE") +ROOT_DESCRIPTOR_FLAG_ENUM(DataStatic, "DATA_STATIC") + +// Descriptor Range Flag Enums: +DESCRIPTOR_RANGE_FLAG_ENUM(DescriptorsVolatile, "DESCRIPTORS_VOLATILE", ON) +DESCRIPTOR_RANGE_FLAG_ENUM(DataVolatile, "DATA_VOLATILE", OFF) +DESCRIPTOR_RANGE_FLAG_ENUM(DataStaticWhileSetAtExecute, "DATA_STATIC_WHILE_SET_AT_EXECUTE", OFF) +DESCRIPTOR_RANGE_FLAG_ENUM(DataStatic, "DATA_STATIC", OFF) +DESCRIPTOR_RANGE_FLAG_ENUM(DescriptorsStaticKeepingBufferBoundsChecks, "DESCRIPTORS_STATIC_KEEPING_BUFFER_BOUNDS_CHECKS", ON) + +// Shader Visibiliy Enums: +SHADER_VISIBILITY_ENUM(All, "SHADER_VISIBILITY_ALL") +SHADER_VISIBILITY_ENUM(Vertex, "SHADER_VISIBILITY_VERTEX") +SHADER_VISIBILITY_ENUM(Hull, "SHADER_VISIBILITY_HULL") +SHADER_VISIBILITY_ENUM(Domain, "SHADER_VISIBILITY_DOMAIN") +SHADER_VISIBILITY_ENUM(Geometry, "SHADER_VISIBILITY_GEOMETRY") +SHADER_VISIBILITY_ENUM(Pixel, "SHADER_VISIBILITY_PIXEL") +SHADER_VISIBILITY_ENUM(Amplification, "SHADER_VISIBILITY_AMPLIFICATION") +SHADER_VISIBILITY_ENUM(Mesh, "SHADER_VISIBILITY_MESH") + +#undef SHADER_VISIBILITY_ENUM +#undef DESCRIPTOR_RANGE_FLAG_ENUM +#undef DESCRIPTOR_RANGE_FLAG_ENUM_OFF +#undef DESCRIPTOR_RANGE_FLAG_ENUM_ON +#undef ROOT_DESCRIPTOR_FLAG_ENUM +#undef DESCRIPTOR_RANGE_OFFSET_ENUM +#undef ENUM +#undef KEYWORD +#undef PUNCTUATOR +#undef TOK diff --git a/clang/include/clang/Lex/LexHLSLRootSignature.h b/clang/include/clang/Lex/LexHLSLRootSignature.h new file mode 100644 index 0000000000000..21c44e0351d9e --- /dev/null +++ b/clang/include/clang/Lex/LexHLSLRootSignature.h @@ -0,0 +1,86 @@ +//===--- LexHLSLRootSignature.h ---------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// This file defines the LexHLSLRootSignature interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LEX_LEXHLSLROOTSIGNATURE_H +#define LLVM_CLANG_LEX_LEXHLSLROOTSIGNATURE_H + +#include "clang/Basic/SourceLocation.h" + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" + +namespace clang { +namespace hlsl { + +struct RootSignatureToken { + enum Kind { +#define TOK(X) X, +#include "clang/Lex/HLSLRootSignatureTokenKinds.def" + }; + + Kind Kind = Kind::invalid; + + // Retain the SouceLocation of the token for diagnostics + clang::SourceLocation TokLoc; + + // Retain spelling of an numeric constant to be parsed later + StringRef NumSpelling; + + // Constructors + RootSignatureToken(clang::SourceLocation TokLoc) : TokLoc(TokLoc) {} + RootSignatureToken(enum Kind Kind, clang::SourceLocation TokLoc) + : Kind(Kind), TokLoc(TokLoc) {} +}; +using TokenKind = enum RootSignatureToken::Kind; + +class RootSignatureLexer { +public: + RootSignatureLexer(StringRef Signature, clang::SourceLocation SourceLoc) + : Buffer(Signature), SourceLoc(SourceLoc) {} + + /// Consumes and returns the next token. + RootSignatureToken ConsumeToken(); + + /// Returns the token that proceeds CurToken + RootSignatureToken PeekNextToken(); + + bool EndOfBuffer() { + AdvanceBuffer(Buffer.take_while(isspace).size()); + return Buffer.empty(); + } + +private: + // Internal buffer to iterate over + StringRef Buffer; + + // Current peek state + std::optional NextToken = std::nullopt; + + // Passed down parameters from Sema + clang::SourceLocation SourceLoc; + + /// Consumes the buffer and returns the lexed token. + RootSignatureToken LexToken(); + + /// Advance the buffer by the specified number of characters. + /// Updates the SourceLocation appropriately. + void AdvanceBuffer(unsigned NumCharacters = 1) { + Buffer = Buffer.drop_front(NumCharacters); + SourceLoc = SourceLoc.getLocWithOffset(NumCharacters); + } +}; + +} // namespace hlsl +} // namespace clang + +#endif // LLVM_CLANG_LEX_PARSEHLSLROOTSIGNATURE_H diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 1870d1271c556..a501b901862b6 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3669,6 +3669,7 @@ class Sema final : public SemaBase { /// cause problems if the variable is mutable, its initialization is /// effectful, or its address is taken. bool GloballyUniqueObjectMightBeAccidentallyDuplicated(const VarDecl *Dcl); + void DiagnoseUniqueObjectDuplication(const VarDecl *Dcl); /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 6e8ca2e4710de..c9266ea50e4bf 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -144,6 +144,7 @@ class SemaHLSL : public SemaBase { bool CanPerformScalarCast(QualType SrcTy, QualType DestTy); bool ContainsBitField(QualType BaseTy); bool CanPerformElementwiseCast(Expr *Src, QualType DestType); + bool CanPerformAggregateSplatCast(Expr *Src, QualType DestType); ExprResult ActOnOutParamExpr(ParmVarDecl *Param, Expr *Arg); QualType getInoutParameterType(QualType Ty); diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def index 34bb7a809162b..a9b8d0753673b 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.def @@ -294,6 +294,16 @@ ANALYZER_OPTION( bool, ShouldUnrollLoops, "unroll-loops", "Whether the analysis should try to unroll loops with known bounds.", false) +ANALYZER_OPTION( + bool, ShouldAssumeAtLeastOneIteration, "assume-at-least-one-iteration", + "Whether the analyzer should always assume at least one iteration in " + "loops where the loop condition is opaque (i.e. the analyzer cannot " + "determine if it's true or false). Setting this to true eliminates some " + "false positives (where e.g. a structure is nonempty, but the analyzer " + "does not notice this); but it also eliminates some true positives (e.g. " + "cases where a structure can be empty and this causes buggy behavior).", + false) + ANALYZER_OPTION( bool, ShouldDisplayNotesAsEvents, "notes-as-events", "Whether the bug reporter should transparently treat extra note diagnostic " diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 0e586725b5869..55ac41736344d 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1683,7 +1683,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, assert(!ElemT); // Structs etc. const Descriptor *Desc = S.P.createDescriptor( - Call, ElemType.getTypePtr(), Descriptor::InlineDescMD, + NewCall, ElemType.getTypePtr(), Descriptor::InlineDescMD, /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, /*Init=*/nullptr); diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index c22aa66ba2cfb..460167c1b9a3d 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1645,11 +1645,22 @@ SourceLocation CallExpr::getBeginLoc() const { if (const auto *OCE = dyn_cast(this)) return OCE->getBeginLoc(); - if (const auto *Method = - dyn_cast_if_present(getCalleeDecl()); - Method && Method->isExplicitObjectMemberFunction()) { - assert(getNumArgs() > 0 && getArg(0)); - return getArg(0)->getBeginLoc(); + // A non-dependent call to a member function with an explicit object parameter + // is modelled with the object expression being the first argument, e.g. in + // `o.f(x)`, the callee will be just `f`, and `o` will be the first argument. + // Since the first argument is written before the callee, the expression's + // begin location should come from the first argument. + // This does not apply to dependent calls, which are modelled with `o.f` + // being the callee. + if (!isTypeDependent()) { + if (const auto *Method = + dyn_cast_if_present(getCalleeDecl()); + Method && Method->isExplicitObjectMemberFunction()) { + bool HasFirstArg = getNumArgs() > 0 && getArg(0); + assert(HasFirstArg); + if (HasFirstArg) + return getArg(0)->getBeginLoc(); + } } SourceLocation begin = getCallee()->getBeginLoc(); @@ -1957,6 +1968,7 @@ bool CastExpr::CastConsistency() const { case CK_HLSLArrayRValue: case CK_HLSLVectorTruncation: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: CheckNoBasePath: assert(path_empty() && "Cast kind should not have a base path!"); break; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5c6ca4c9ee4de..043974fb41443 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -15025,6 +15025,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointCast: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_HLSLAggregateSplatCast: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -15903,6 +15904,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_MatrixCast: case CK_HLSLVectorTruncation: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index 169e3ee94c221..27fd214dcee3b 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -1705,6 +1705,10 @@ void JSONNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &TA) { void JSONNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { JOS.attribute("value", TA.getAsIntegral().getSExtValue()); } +void JSONNodeDumper::VisitStructuralValueTemplateArgument( + const TemplateArgument &TA) { + Visit(TA.getAsStructuralValue(), TA.getStructuralValueType()); +} void JSONNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) { // FIXME: cannot just call dump() on the argument, as that doesn't specify // the output format. diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp index f23647ef12404..4f8b50e179e30 100644 --- a/clang/lib/AST/StmtOpenMP.cpp +++ b/clang/lib/AST/StmtOpenMP.cpp @@ -417,6 +417,14 @@ OMPTileDirective::Create(const ASTContext &C, SourceLocation StartLoc, return Dir; } +OMPTileDirective *OMPTileDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned NumLoops) { + return createEmptyDirective( + C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1, + SourceLocation(), SourceLocation(), NumLoops); +} + OMPStripeDirective * OMPStripeDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef Clauses, @@ -438,14 +446,6 @@ OMPStripeDirective *OMPStripeDirective::CreateEmpty(const ASTContext &C, SourceLocation(), SourceLocation(), NumLoops); } -OMPTileDirective *OMPTileDirective::CreateEmpty(const ASTContext &C, - unsigned NumClauses, - unsigned NumLoops) { - return createEmptyDirective( - C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1, - SourceLocation(), SourceLocation(), NumLoops); -} - OMPUnrollDirective * OMPUnrollDirective::Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef Clauses, diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 6da1f776b4b63..08efcda46b8f9 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -1226,6 +1226,12 @@ void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) { dumpTemplateArgument(TA); } +void TextNodeDumper::VisitStructuralValueTemplateArgument( + const TemplateArgument &TA) { + OS << " structural value"; + dumpTemplateArgument(TA); +} + void TextNodeDumper::dumpTemplateName(TemplateName TN, StringRef Label) { AddChild(Label, [=] { { diff --git a/clang/lib/Analysis/LiveVariables.cpp b/clang/lib/Analysis/LiveVariables.cpp index 481932ee59c8e..af563702b77bf 100644 --- a/clang/lib/Analysis/LiveVariables.cpp +++ b/clang/lib/Analysis/LiveVariables.cpp @@ -16,7 +16,9 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/FlowSensitive/DataflowWorklist.h" +#include "clang/Basic/SourceManager.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -662,12 +664,19 @@ void LiveVariables::dumpExprLiveness(const SourceManager &M) { } void LiveVariablesImpl::dumpExprLiveness(const SourceManager &M) { + auto ByBeginLoc = [&M](const Expr *L, const Expr *R) { + return M.isBeforeInTranslationUnit(L->getBeginLoc(), R->getBeginLoc()); + }; + // Don't iterate over blockEndsToLiveness directly because it's not sorted. for (const CFGBlock *B : *analysisContext.getCFG()) { llvm::errs() << "\n[ B" << B->getBlockID() << " (live expressions at block exit) ]\n"; - for (const Expr *E : blocksEndToLiveness[B].liveExprs) { + std::vector LiveExprs; + llvm::append_range(LiveExprs, blocksEndToLiveness[B].liveExprs); + llvm::sort(LiveExprs, ByBeginLoc); + for (const Expr *E : LiveExprs) { llvm::errs() << "\n"; E->dump(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index d60a6b38b0c12..74ff89346f3c4 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -157,9 +157,9 @@ void CIRToLLVMGlobalOpLowering::setupRegionInitializedLLVMGlobalOp( op, llvmType, isConst, linkage, symbol, nullptr, alignment, addrSpace, isDsoLocal, isThreadLocal, /*comdat=*/mlir::SymbolRefAttr(), attributes); - newGlobalOp.getRegion().push_back(new mlir::Block()); + newGlobalOp.getRegion().emplaceBlock(); rewriter.setInsertionPointToEnd(newGlobalOp.getInitializerBlock()); -}; +} mlir::LogicalResult CIRToLLVMGlobalOpLowering::matchAndRewriteRegionInitializedGlobal( diff --git a/clang/lib/CodeGen/ABIInfo.cpp b/clang/lib/CodeGen/ABIInfo.cpp index cda8a494f6c27..d981d69913632 100644 --- a/clang/lib/CodeGen/ABIInfo.cpp +++ b/clang/lib/CodeGen/ABIInfo.cpp @@ -171,11 +171,11 @@ bool ABIInfo::isPromotableIntegerTypeForABI(QualType Ty) const { return false; } -ABIArgInfo ABIInfo::getNaturalAlignIndirect(QualType Ty, bool ByVal, - bool Realign, +ABIArgInfo ABIInfo::getNaturalAlignIndirect(QualType Ty, unsigned AddrSpace, + bool ByVal, bool Realign, llvm::Type *Padding) const { - return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty), ByVal, - Realign, Padding); + return ABIArgInfo::getIndirect(getContext().getTypeAlignInChars(Ty), + AddrSpace, ByVal, Realign, Padding); } ABIArgInfo ABIInfo::getNaturalAlignIndirectInReg(QualType Ty, diff --git a/clang/lib/CodeGen/ABIInfo.h b/clang/lib/CodeGen/ABIInfo.h index 213e7879c3162..9c7029c99bd44 100644 --- a/clang/lib/CodeGen/ABIInfo.h +++ b/clang/lib/CodeGen/ABIInfo.h @@ -110,7 +110,8 @@ class ABIInfo { /// A convenience method to return an indirect ABIArgInfo with an /// expected alignment equal to the ABI alignment of the given type. CodeGen::ABIArgInfo - getNaturalAlignIndirect(QualType Ty, bool ByVal = true, bool Realign = false, + getNaturalAlignIndirect(QualType Ty, unsigned AddrSpace, bool ByVal = true, + bool Realign = false, llvm::Type *Padding = nullptr) const; CodeGen::ABIArgInfo getNaturalAlignIndirectInReg(QualType Ty, diff --git a/clang/lib/CodeGen/ABIInfoImpl.cpp b/clang/lib/CodeGen/ABIInfoImpl.cpp index 795874059bda7..68887cd7916c7 100644 --- a/clang/lib/CodeGen/ABIInfoImpl.cpp +++ b/clang/lib/CodeGen/ABIInfoImpl.cpp @@ -21,9 +21,10 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); } // Treat an enum type as its underlying type. @@ -36,7 +37,7 @@ ABIArgInfo DefaultABIInfo::classifyArgumentType(QualType Ty) const { Context.getTypeSize(Context.getTargetInfo().hasInt128Type() ? Context.Int128Ty : Context.LongLongTy)) - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) @@ -48,7 +49,7 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy)) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) @@ -59,7 +60,8 @@ ABIArgInfo DefaultABIInfo::classifyReturnType(QualType RetTy) const { getContext().getTypeSize(getContext().getTargetInfo().hasInt128Type() ? getContext().Int128Ty : getContext().LongLongTy)) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect()); @@ -126,7 +128,8 @@ bool CodeGen::classifyReturnType(const CGCXXABI &CXXABI, CGFunctionInfo &FI, if (const auto *RT = Ty->getAs()) if (!isa(RT->getDecl()) && !RT->getDecl()->canPassInRegisters()) { - FI.getReturnInfo() = Info.getNaturalAlignIndirect(Ty); + FI.getReturnInfo() = Info.getNaturalAlignIndirect( + Ty, Info.getDataLayout().getAllocaAddrSpace()); return true; } diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 361e4c4bf2e2e..d57f491a20c8e 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -3839,6 +3839,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, AlignmentCI, OffsetValue); return RValue::get(PtrValue); } + case Builtin::BI__builtin_assume_dereferenceable: { + const Expr *Ptr = E->getArg(0); + const Expr *Size = E->getArg(1); + Value *PtrValue = EmitScalarExpr(Ptr); + Value *SizeValue = EmitScalarExpr(Size); + if (SizeValue->getType() != IntPtrTy) + SizeValue = + Builder.CreateIntCast(SizeValue, IntPtrTy, false, "casted.size"); + Builder.CreateDereferenceableAssumption(PtrValue, SizeValue); + return RValue::get(nullptr); + } case Builtin::BI__assume: case Builtin::BI__builtin_assume: { if (E->getArg(0)->HasSideEffects(getContext())) @@ -21011,6 +21022,8 @@ Value *CodeGenFunction::EmitSystemZBuiltinExpr(unsigned BuiltinID, CI = Intrinsic::experimental_constrained_nearbyint; break; case 1: ID = Intrinsic::round; CI = Intrinsic::experimental_constrained_round; break; + case 4: ID = Intrinsic::roundeven; + CI = Intrinsic::experimental_constrained_roundeven; break; case 5: ID = Intrinsic::trunc; CI = Intrinsic::experimental_constrained_trunc; break; case 6: ID = Intrinsic::ceil; diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 2dce86410db85..e6c2ac939eb88 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1671,10 +1671,8 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { // Add type for sret argument. if (IRFunctionArgs.hasSRetArg()) { - QualType Ret = FI.getReturnType(); - unsigned AddressSpace = CGM.getTypes().getTargetAddressSpace(Ret); - ArgTypes[IRFunctionArgs.getSRetArgNo()] = - llvm::PointerType::get(getLLVMContext(), AddressSpace); + ArgTypes[IRFunctionArgs.getSRetArgNo()] = llvm::PointerType::get( + getLLVMContext(), FI.getReturnInfo().getIndirectAddrSpace()); } // Add type for inalloca argument. @@ -5144,7 +5142,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // If the call returns a temporary with struct return, create a temporary // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); - RawAddress SRetAlloca = RawAddress::invalid(); llvm::Value *UnusedReturnSizePtr = nullptr; if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { // For virtual function pointer thunks and musttail calls, we must always @@ -5158,11 +5155,11 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } else if (!ReturnValue.isNull()) { SRetPtr = ReturnValue.getAddress(); } else { - SRetPtr = CreateMemTemp(RetTy, "tmp", &SRetAlloca); + SRetPtr = CreateMemTempWithoutCast(RetTy, "tmp"); if (HaveInsertPoint() && ReturnValue.isUnused()) { llvm::TypeSize size = CGM.getDataLayout().getTypeAllocSize(ConvertTypeForMem(RetTy)); - UnusedReturnSizePtr = EmitLifetimeStart(size, SRetAlloca.getPointer()); + UnusedReturnSizePtr = EmitLifetimeStart(size, SRetPtr.getBasePointer()); } } if (IRFunctionArgs.hasSRetArg()) { @@ -5397,11 +5394,22 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, V->getType()->isIntegerTy()) V = Builder.CreateZExt(V, ArgInfo.getCoerceToType()); - // If the argument doesn't match, perform a bitcast to coerce it. This - // can happen due to trivial type mismatches. + // The only plausible mismatch here would be for pointer address spaces, + // which can happen e.g. when passing a sret arg that is in the AllocaAS + // to a function that takes a pointer to and argument in the DefaultAS. + // We assume that the target has a reasonable mapping for the DefaultAS + // (it can be casted to from incoming specific ASes), and insert an AS + // cast to address the mismatch. if (FirstIRArg < IRFuncTy->getNumParams() && - V->getType() != IRFuncTy->getParamType(FirstIRArg)) - V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg)); + V->getType() != IRFuncTy->getParamType(FirstIRArg)) { + assert(V->getType()->isPointerTy() && "Only pointers can mismatch!"); + auto FormalAS = CallInfo.arguments()[ArgNo] + .type.getQualifiers() + .getAddressSpace(); + auto ActualAS = I->Ty.getAddressSpace(); + V = getTargetHooks().performAddrSpaceCast( + *this, V, ActualAS, FormalAS, IRFuncTy->getParamType(FirstIRArg)); + } if (ArgHasMaybeUndefAttr) V = Builder.CreateFreeze(V); @@ -5737,7 +5745,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // pop this cleanup later on. Being eager about this is OK, since this // temporary is 'invisible' outside of the callee. if (UnusedReturnSizePtr) - pushFullExprCleanup(NormalEHLifetimeMarker, SRetAlloca, + pushFullExprCleanup(NormalEHLifetimeMarker, SRetPtr, UnusedReturnSizePtr); llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index d5b584ec0f2e9..46ad11e64c4d5 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -5122,7 +5122,7 @@ void CGDebugInfo::EmitLabel(const LabelDecl *D, CGBuilderTy &Builder) { DBuilder.insertLabel(L, llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, Scope, CurInlinedAt), - Builder.GetInsertBlock()); + Builder.GetInsertBlock()->end()); } llvm::DIType *CGDebugInfo::CreateSelfType(const QualType &QualTy, @@ -5200,7 +5200,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable( LexicalBlockStack.back(), CurInlinedAt); auto *Expr = DBuilder.createExpression(addr); if (InsertPoint) - DBuilder.insertDeclare(Storage, D, Expr, DL, InsertPoint); + DBuilder.insertDeclare(Storage, D, Expr, DL, InsertPoint->getIterator()); else DBuilder.insertDeclare(Storage, D, Expr, DL, Builder.GetInsertBlock()); } @@ -5865,7 +5865,7 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, if (auto InsertPoint = Value->getInsertionPointAfterDef()) { DBuilder.insertDbgValueIntrinsic(Value, D, DBuilder.createExpression(), DIL, - &**InsertPoint); + *InsertPoint); } } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 2bbc0791c6587..0b0ffd2db853f 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5339,6 +5339,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_HLSLVectorTruncation: case CK_HLSLArrayRValue: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index c3f1cbed6b39f..d25d0f2c2133c 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -296,18 +296,25 @@ void AggExprEmitter::withReturnValueSlot( (RequiresDestruction && Dest.isIgnored()); Address RetAddr = Address::invalid(); - RawAddress RetAllocaAddr = RawAddress::invalid(); EHScopeStack::stable_iterator LifetimeEndBlock; llvm::Value *LifetimeSizePtr = nullptr; llvm::IntrinsicInst *LifetimeStartInst = nullptr; if (!UseTemp) { - RetAddr = Dest.getAddress(); + // It is possible for the existing slot we are using directly to have been + // allocated in the correct AS for an indirect return, and then cast to + // the default AS (this is the behaviour of CreateMemTemp), however we know + // that the return address is expected to point to the uncasted AS, hence we + // strip possible pointer casts here. + if (Dest.getAddress().isValid()) + RetAddr = Dest.getAddress().withPointer( + Dest.getAddress().getBasePointer()->stripPointerCasts(), + Dest.getAddress().isKnownNonNull()); } else { - RetAddr = CGF.CreateMemTemp(RetTy, "tmp", &RetAllocaAddr); + RetAddr = CGF.CreateMemTempWithoutCast(RetTy, "tmp"); llvm::TypeSize Size = CGF.CGM.getDataLayout().getTypeAllocSize(CGF.ConvertTypeForMem(RetTy)); - LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAllocaAddr.getPointer()); + LifetimeSizePtr = CGF.EmitLifetimeStart(Size, RetAddr.getBasePointer()); if (LifetimeSizePtr) { LifetimeStartInst = cast(std::prev(Builder.GetInsertPoint())); @@ -316,7 +323,7 @@ void AggExprEmitter::withReturnValueSlot( "Last insertion wasn't a lifetime.start?"); CGF.pushFullExprCleanup( - NormalEHLifetimeMarker, RetAllocaAddr, LifetimeSizePtr); + NormalEHLifetimeMarker, RetAddr, LifetimeSizePtr); LifetimeEndBlock = CGF.EHStack.stable_begin(); } } @@ -337,7 +344,7 @@ void AggExprEmitter::withReturnValueSlot( // Since we're not guaranteed to be in an ExprWithCleanups, clean up // eagerly. CGF.DeactivateCleanupBlock(LifetimeEndBlock, LifetimeStartInst); - CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAllocaAddr.getPointer()); + CGF.EmitLifetimeEnd(LifetimeSizePtr, RetAddr.getBasePointer()); } } @@ -491,6 +498,31 @@ static bool isTrivialFiller(Expr *E) { return false; } +static void EmitHLSLAggregateSplatCast(CodeGenFunction &CGF, Address DestVal, + QualType DestTy, llvm::Value *SrcVal, + QualType SrcTy, SourceLocation Loc) { + // Flatten our destination + SmallVector DestTypes; // Flattened type + SmallVector, 16> StoreGEPList; + // ^^ Flattened accesses to DestVal we want to store into + CGF.FlattenAccessAndType(DestVal, DestTy, StoreGEPList, DestTypes); + + assert(SrcTy->isScalarType() && "Invalid HLSL Aggregate splat cast."); + for (unsigned I = 0, Size = StoreGEPList.size(); I < Size; ++I) { + llvm::Value *Cast = + CGF.EmitScalarConversion(SrcVal, SrcTy, DestTypes[I], Loc); + + // store back + llvm::Value *Idx = StoreGEPList[I].second; + if (Idx) { + llvm::Value *V = + CGF.Builder.CreateLoad(StoreGEPList[I].first, "load.for.insert"); + Cast = CGF.Builder.CreateInsertElement(V, Cast, Idx); + } + CGF.Builder.CreateStore(Cast, StoreGEPList[I].first); + } +} + // emit a flat cast where the RHS is a scalar, including vector static void EmitHLSLScalarFlatCast(CodeGenFunction &CGF, Address DestVal, QualType DestTy, llvm::Value *SrcVal, @@ -963,6 +995,19 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_HLSLArrayRValue: Visit(E->getSubExpr()); break; + case CK_HLSLAggregateSplatCast: { + Expr *Src = E->getSubExpr(); + QualType SrcTy = Src->getType(); + RValue RV = CGF.EmitAnyExpr(Src); + QualType DestTy = E->getType(); + Address DestVal = Dest.getAddress(); + SourceLocation Loc = E->getExprLoc(); + + assert(RV.isScalar() && "RHS of HLSL splat cast must be a scalar."); + llvm::Value *SrcVal = RV.getScalarVal(); + EmitHLSLAggregateSplatCast(CGF, DestVal, DestTy, SrcVal, SrcTy, Loc); + break; + } case CK_HLSLElementwiseCast: { Expr *Src = E->getSubExpr(); QualType SrcTy = Src->getType(); @@ -1553,6 +1598,7 @@ static bool castPreservesZero(const CastExpr *CE) { case CK_AtomicToNonAtomic: case CK_HLSLVectorTruncation: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: return true; case CK_BaseToDerivedMemberPointer: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index c2679ea92dc97..ff7c55be246cc 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -611,6 +611,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_HLSLVectorTruncation: case CK_HLSLArrayRValue: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index ef11798869d3b..ee5874b26f534 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1336,6 +1336,7 @@ class ConstExprEmitter case CK_HLSLVectorTruncation: case CK_HLSLArrayRValue: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: return nullptr; } llvm_unreachable("Invalid CastKind"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 80daed7e53951..30f01496ba221 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2643,6 +2643,11 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { return EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc()); } + // CK_HLSLAggregateSplatCast only handles splatting to vectors from a vec1 + // Casts were inserted in Sema to Cast the Src Expr to a Scalar and + // To perform any necessary Scalar Cast, so this Cast can be handled + // by the regular Vector Splat cast code. + case CK_HLSLAggregateSplatCast: case CK_VectorSplat: { llvm::Type *DstTy = ConvertType(DestTy); Value *Elt = Visit(const_cast(E)); @@ -2800,7 +2805,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { SourceLocation Loc = CE->getExprLoc(); QualType SrcTy = E->getType(); - assert(RV.isAggregate() && "Not a valid HLSL Flat Cast."); + assert(RV.isAggregate() && "Not a valid HLSL Elementwise Cast."); // RHS is an aggregate Address SrcVal = RV.getAggregateAddress(); return EmitHLSLElementwiseCast(CGF, SrcVal, SrcTy, DestTy, Loc); diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 6cccd353cff96..03ddc87d8d3df 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -54,10 +54,6 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { auto *DXILValMD = M.getOrInsertNamedMetadata(DXILValKey); DXILValMD->addOperand(Val); } -void addDisableOptimizations(llvm::Module &M) { - StringRef Key = "dx.disable_optimizations"; - M.addModuleFlag(llvm::Module::ModFlagBehavior::Override, Key, 1); -} // cbuffer will be translated into global variable in special address space. // If translate into C, // cbuffer A { @@ -171,8 +167,6 @@ void CGHLSLRuntime::finishCodeGen() { addDxilValVersion(TargetOpts.DxilValidatorVersion, M); generateGlobalCtorDtorCalls(); - if (CGM.getCodeGenOpts().OptimizationLevel == 0) - addDisableOptimizations(M); const DataLayout &DL = M.getDataLayout(); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 6c929a6431c0f..16986de96bdbc 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -63,7 +63,7 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getMessageSendFn() const { // Add the non-lazy-bind attribute, since objc_msgSend is likely to // be called a lot. - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; + llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy}; return CGM.CreateRuntimeFunction( llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend", llvm::AttributeList::get(CGM.getLLVMContext(), @@ -77,10 +77,10 @@ class ObjCCommonTypesHelper { /// by indirect reference in the first argument, and therefore the /// self and selector parameters are shifted over by one. llvm::FunctionCallee getMessageSendStretFn() const { - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, - params, true), - "objc_msgSend_stret"); + llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(CGM.VoidTy, params, true), + "objc_msgSend_stret"); } /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...) @@ -89,10 +89,10 @@ class ObjCCommonTypesHelper { /// floating-point stack; without a special entrypoint, the nil case /// would be unbalanced. llvm::FunctionCallee getMessageSendFpretFn() const { - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.DoubleTy, - params, true), - "objc_msgSend_fpret"); + llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(CGM.DoubleTy, params, true), + "objc_msgSend_fpret"); } /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...) @@ -101,14 +101,14 @@ class ObjCCommonTypesHelper { /// x87 floating point stack; without a special entrypoint, the nil case /// would be unbalanced. Only used on 64-bit X86. llvm::FunctionCallee getMessageSendFp2retFn() const { - llvm::Type *params[] = { ObjectPtrTy, SelectorPtrTy }; + llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy}; llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext); llvm::Type *resultType = llvm::StructType::get(longDoubleType, longDoubleType); - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(resultType, - params, true), - "objc_msgSend_fp2ret"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(resultType, params, true), + "objc_msgSend_fp2ret"); } /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...) @@ -117,10 +117,10 @@ class ObjCCommonTypesHelper { /// semantics. The class passed is the superclass of the current /// class. llvm::FunctionCallee getMessageSendSuperFn() const { - llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper"); + llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSendSuper"); } /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...) @@ -128,10 +128,10 @@ class ObjCCommonTypesHelper { /// A slightly different messenger used for super calls. The class /// passed is the current class. llvm::FunctionCallee getMessageSendSuperFn2() const { - llvm::Type *params[] = { SuperPtrTy, SelectorPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper2"); + llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSendSuper2"); } /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super, @@ -139,10 +139,10 @@ class ObjCCommonTypesHelper { /// /// The messenger used for super calls which return an aggregate indirectly. llvm::FunctionCallee getMessageSendSuperStretFn() const { - llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; + llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy}; return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, true), - "objc_msgSendSuper_stret"); + llvm::FunctionType::get(CGM.VoidTy, params, true), + "objc_msgSendSuper_stret"); } /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super, @@ -150,10 +150,10 @@ class ObjCCommonTypesHelper { /// /// objc_msgSendSuper_stret with the super2 semantics. llvm::FunctionCallee getMessageSendSuperStretFn2() const { - llvm::Type *params[] = { Int8PtrTy, SuperPtrTy, SelectorPtrTy }; + llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy}; return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, true), - "objc_msgSendSuper2_stret"); + llvm::FunctionType::get(CGM.VoidTy, params, true), + "objc_msgSendSuper2_stret"); } llvm::FunctionCallee getMessageSendSuperFpretFn() const { @@ -240,9 +240,8 @@ class ObjCCommonTypesHelper { CanQualType Params[] = { IdType, SelType, Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy}; - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(IdType, Params)); + llvm::FunctionType *FTy = Types.GetFunctionType( + Types.arrangeBuiltinFunctionDeclaration(IdType, Params)); return CGM.CreateRuntimeFunction(FTy, "objc_getProperty"); } @@ -259,9 +258,8 @@ class ObjCCommonTypesHelper { IdType, Ctx.BoolTy, Ctx.BoolTy}; - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); + llvm::FunctionType *FTy = Types.GetFunctionType( + Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); return CGM.CreateRuntimeFunction(FTy, "objc_setProperty"); } @@ -277,16 +275,15 @@ class ObjCCommonTypesHelper { // void objc_setProperty_nonatomic_copy(id self, SEL _cmd, // id newValue, ptrdiff_t offset); - SmallVector Params; + SmallVector Params; CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType()); CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType()); Params.push_back(IdType); Params.push_back(SelType); Params.push_back(IdType); Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified()); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); + llvm::FunctionType *FTy = Types.GetFunctionType( + Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); const char *name; if (atomic && copy) name = "objc_setProperty_atomic_copy"; @@ -304,15 +301,14 @@ class ObjCCommonTypesHelper { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // void objc_copyStruct (void *, const void *, size_t, bool, bool) - SmallVector Params; + SmallVector Params; Params.push_back(Ctx.VoidPtrTy); Params.push_back(Ctx.VoidPtrTy); Params.push_back(Ctx.getSizeType()); Params.push_back(Ctx.BoolTy); Params.push_back(Ctx.BoolTy); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); + llvm::FunctionType *FTy = Types.GetFunctionType( + Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct"); } @@ -323,14 +319,14 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getCppAtomicObjectFunction() { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); - /// void objc_copyCppObjectAtomic(void *dest, const void *src, void *helper); - SmallVector Params; + /// void objc_copyCppObjectAtomic(void *dest, const void *src, void + /// *helper); + SmallVector Params; Params.push_back(Ctx.VoidPtrTy); Params.push_back(Ctx.VoidPtrTy); Params.push_back(Ctx.VoidPtrTy); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); + llvm::FunctionType *FTy = Types.GetFunctionType( + Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic"); } @@ -338,11 +334,10 @@ class ObjCCommonTypesHelper { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // void objc_enumerationMutation (id) - SmallVector Params; + SmallVector Params; Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType())); - llvm::FunctionType *FTy = - Types.GetFunctionType( - Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); + llvm::FunctionType *FTy = Types.GetFunctionType( + Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params)); return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation"); } @@ -350,13 +345,12 @@ class ObjCCommonTypesHelper { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); // Class objc_lookUpClass (const char *) - SmallVector Params; + SmallVector Params; Params.push_back( - Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst()))); + Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst()))); llvm::FunctionType *FTy = Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration( - Ctx.getCanonicalType(Ctx.getObjCClassType()), - Params)); + Ctx.getCanonicalType(Ctx.getObjCClassType()), Params)); return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass"); } @@ -364,8 +358,7 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getGcReadWeakFn() { // id objc_read_weak (id *) llvm::Type *args[] = {CGM.UnqualPtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); + llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_read_weak"); } @@ -373,8 +366,7 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getGcAssignWeakFn() { // id objc_assign_weak (id, id *) llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); + llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak"); } @@ -382,8 +374,7 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getGcAssignGlobalFn() { // id objc_assign_global(id, id *) llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); + llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_global"); } @@ -391,8 +382,7 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getGcAssignThreadLocalFn() { // id objc_assign_threadlocal(id src, id * dest) llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); + llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal"); } @@ -400,15 +390,14 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getGcAssignIvarFn() { // id objc_assign_ivar(id, id *, ptrdiff_t) llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy, CGM.PtrDiffTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); + llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar"); } /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function. llvm::FunctionCallee GcMemmoveCollectableFn() { // void *objc_memmove_collectable(void *dst, const void *src, size_t size) - llvm::Type *args[] = { Int8PtrTy, Int8PtrTy, LongTy }; + llvm::Type *args[] = {Int8PtrTy, Int8PtrTy, LongTy}; llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable"); } @@ -417,17 +406,15 @@ class ObjCCommonTypesHelper { llvm::FunctionCallee getGcAssignStrongCastFn() { // id objc_assign_strongCast(id, id *) llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy}; - llvm::FunctionType *FTy = - llvm::FunctionType::get(ObjectPtrTy, args, false); + llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast"); } /// ExceptionThrowFn - LLVM objc_exception_throw function. llvm::FunctionCallee getExceptionThrowFn() { // void objc_exception_throw(id) - llvm::Type *args[] = { ObjectPtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, args, false); + llvm::Type *args[] = {ObjectPtrTy}; + llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw"); } @@ -441,18 +428,16 @@ class ObjCCommonTypesHelper { /// SyncEnterFn - LLVM object_sync_enter function. llvm::FunctionCallee getSyncEnterFn() { // int objc_sync_enter (id) - llvm::Type *args[] = { ObjectPtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.IntTy, args, false); + llvm::Type *args[] = {ObjectPtrTy}; + llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); } /// SyncExitFn - LLVM object_sync_exit function. llvm::FunctionCallee getSyncExitFn() { // int objc_sync_exit (id) - llvm::Type *args[] = { ObjectPtrTy }; - llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.IntTy, args, false); + llvm::Type *args[] = {ObjectPtrTy}; + llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); } @@ -553,32 +538,32 @@ class ObjCTypesHelper : public ObjCCommonTypesHelper { llvm::FunctionCallee getExceptionTryEnterFn() { llvm::Type *params[] = {CGM.UnqualPtrTy}; return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, false), - "objc_exception_try_enter"); + llvm::FunctionType::get(CGM.VoidTy, params, false), + "objc_exception_try_enter"); } /// ExceptionTryExitFn - LLVM objc_exception_try_exit function. llvm::FunctionCallee getExceptionTryExitFn() { llvm::Type *params[] = {CGM.UnqualPtrTy}; return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.VoidTy, params, false), - "objc_exception_try_exit"); + llvm::FunctionType::get(CGM.VoidTy, params, false), + "objc_exception_try_exit"); } /// ExceptionExtractFn - LLVM objc_exception_extract function. llvm::FunctionCallee getExceptionExtractFn() { llvm::Type *params[] = {CGM.UnqualPtrTy}; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, false), - "objc_exception_extract"); + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, false), + "objc_exception_extract"); } /// ExceptionMatchFn - LLVM objc_exception_match function. llvm::FunctionCallee getExceptionMatchFn() { - llvm::Type *params[] = { ClassPtrTy, ObjectPtrTy }; + llvm::Type *params[] = {ClassPtrTy, ObjectPtrTy}; return CGM.CreateRuntimeFunction( - llvm::FunctionType::get(CGM.Int32Ty, params, false), - "objc_exception_match"); + llvm::FunctionType::get(CGM.Int32Ty, params, false), + "objc_exception_match"); } /// SetJmpFn - LLVM _setjmp function. @@ -670,44 +655,44 @@ class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { llvm::FunctionCallee getMessageSendFixupFn() { // id objc_msgSend_fixup(id, struct message_ref_t*, ...) - llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSend_fixup"); + llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSend_fixup"); } llvm::FunctionCallee getMessageSendFpretFixupFn() { // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...) - llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSend_fpret_fixup"); + llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSend_fpret_fixup"); } llvm::FunctionCallee getMessageSendStretFixupFn() { // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...) - llvm::Type *params[] = { ObjectPtrTy, MessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSend_stret_fixup"); + llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSend_stret_fixup"); } llvm::FunctionCallee getMessageSendSuper2FixupFn() { // id objc_msgSendSuper2_fixup (struct objc_super *, // struct _super_message_ref_t*, ...) - llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper2_fixup"); + llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSendSuper2_fixup"); } llvm::FunctionCallee getMessageSendSuper2StretFixupFn() { // id objc_msgSendSuper2_stret_fixup(struct objc_super *, // struct _super_message_ref_t*, ...) - llvm::Type *params[] = { SuperPtrTy, SuperMessageRefPtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, - params, true), - "objc_msgSendSuper2_stret_fixup"); + llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(ObjectPtrTy, params, true), + "objc_msgSendSuper2_stret_fixup"); } llvm::FunctionCallee getObjCEndCatchFn() { @@ -716,10 +701,9 @@ class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { } llvm::FunctionCallee getObjCBeginCatchFn() { - llvm::Type *params[] = { Int8PtrTy }; - return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy, - params, false), - "objc_begin_catch"); + llvm::Type *params[] = {Int8PtrTy}; + return CGM.CreateRuntimeFunction( + llvm::FunctionType::get(Int8PtrTy, params, false), "objc_begin_catch"); } /// Class objc_loadClassref (void *) @@ -733,21 +717,23 @@ class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper { // // Also it is safe to make it readnone, since we never load or store the // classref except by calling this function. - llvm::Type *params[] = { Int8PtrPtrTy }; + llvm::Type *params[] = {Int8PtrPtrTy}; llvm::LLVMContext &C = CGM.getLLVMContext(); - llvm::AttributeSet AS = llvm::AttributeSet::get(C, { - llvm::Attribute::get(C, llvm::Attribute::NonLazyBind), - llvm::Attribute::getWithMemoryEffects(C, llvm::MemoryEffects::none()), - llvm::Attribute::get(C, llvm::Attribute::NoUnwind), - }); + llvm::AttributeSet AS = llvm::AttributeSet::get( + C, { + llvm::Attribute::get(C, llvm::Attribute::NonLazyBind), + llvm::Attribute::getWithMemoryEffects( + C, llvm::MemoryEffects::none()), + llvm::Attribute::get(C, llvm::Attribute::NoUnwind), + }); llvm::FunctionCallee F = CGM.CreateRuntimeFunction( llvm::FunctionType::get(ClassnfABIPtrTy, params, false), "objc_loadClassref", llvm::AttributeList::get(CGM.getLLVMContext(), llvm::AttributeList::FunctionIndex, AS)); if (!CGM.getTriple().isOSBinFormatCOFF()) - cast(F.getCallee())->setLinkage( - llvm::Function::ExternalWeakLinkage); + cast(F.getCallee()) + ->setLinkage(llvm::Function::ExternalWeakLinkage); return F; } @@ -772,9 +758,10 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { unsigned skip; unsigned scan; SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0) - : skip(_skip), scan(_scan) {} + : skip(_skip), scan(_scan) {} }; + // clang-format off /// opcode for captured block variables layout 'instructions'. /// In the following descriptions, 'I' is the value of the immediate field. /// (field following the opcode). @@ -821,11 +808,12 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { /// /// This is included so that older tools can at least continue /// processing the layout past such things. - //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10, + // BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10, /// All other opcodes are reserved. Halt interpretation and /// treat everything else as opaque. }; + // clang-format on class RUN_SKIP { public: @@ -835,7 +823,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR, CharUnits BytePos = CharUnits::Zero(), CharUnits Size = CharUnits::Zero()) - : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} + : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} // Allow sorting based on byte pos. bool operator<(const RUN_SKIP &b) const { @@ -853,70 +841,71 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { /// LazySymbols - Symbols to generate a lazy reference for. See /// DefinedSymbols and FinishModule(). - llvm::SetVector LazySymbols; + llvm::SetVector LazySymbols; /// DefinedSymbols - External symbols which are defined by this /// module. The symbols in this list and LazySymbols are used to add /// special linker symbols which ensure that Objective-C modules are /// linked properly. - llvm::SetVector DefinedSymbols; + llvm::SetVector DefinedSymbols; /// ClassNames - uniqued class names. - llvm::StringMap ClassNames; + llvm::StringMap ClassNames; /// MethodVarNames - uniqued method variable names. - llvm::DenseMap MethodVarNames; + llvm::DenseMap MethodVarNames; /// DefinedCategoryNames - list of category names in form Class_Category. llvm::SmallSetVector DefinedCategoryNames; /// MethodVarTypes - uniqued method type signatures. We have to use /// a StringMap here because have no other unique reference. - llvm::StringMap MethodVarTypes; + llvm::StringMap MethodVarTypes; /// MethodDefinitions - map of methods which have been defined in /// this translation unit. - llvm::DenseMap MethodDefinitions; + llvm::DenseMap MethodDefinitions; /// DirectMethodDefinitions - map of direct methods which have been defined in /// this translation unit. - llvm::DenseMap DirectMethodDefinitions; + llvm::DenseMap + DirectMethodDefinitions; /// PropertyNames - uniqued method variable names. - llvm::DenseMap PropertyNames; + llvm::DenseMap PropertyNames; /// ClassReferences - uniqued class references. - llvm::DenseMap ClassReferences; + llvm::DenseMap ClassReferences; /// SelectorReferences - uniqued selector references. - llvm::DenseMap SelectorReferences; + llvm::DenseMap SelectorReferences; /// Protocols - Protocols for which an objc_protocol structure has /// been emitted. Forward declarations are handled by creating an /// empty structure whose initializer is filled in when/if defined. - llvm::DenseMap Protocols; + llvm::DenseMap Protocols; /// DefinedProtocols - Protocols which have actually been /// defined. We should not need this, see FIXME in GenerateProtocol. - llvm::DenseSet DefinedProtocols; + llvm::DenseSet DefinedProtocols; /// DefinedClasses - List of defined classes. - SmallVector DefinedClasses; + SmallVector DefinedClasses; /// ImplementedClasses - List of @implemented classes. - SmallVector ImplementedClasses; + SmallVector ImplementedClasses; /// DefinedNonLazyClasses - List of defined "non-lazy" classes. - SmallVector DefinedNonLazyClasses; + SmallVector DefinedNonLazyClasses; /// DefinedCategories - List of defined categories. - SmallVector DefinedCategories; + SmallVector DefinedCategories; /// DefinedStubCategories - List of defined categories on class stubs. - SmallVector DefinedStubCategories; + SmallVector DefinedStubCategories; /// DefinedNonLazyCategories - List of defined "non-lazy" categories. - SmallVector DefinedNonLazyCategories; + SmallVector DefinedNonLazyCategories; /// Cached reference to the class for constant strings. This value has type /// int * but is actually an Obj-C class pointer. @@ -963,10 +952,8 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { /// building a weak layout. Does not guarantee that the layout will /// actually have any entries, because the ivar might be under-aligned. llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, - CharUnits beginOffset, - CharUnits endOffset, - bool forStrongLayout, - bool hasMRCWeakIvars); + CharUnits beginOffset, CharUnits endOffset, + bool forStrongLayout, bool hasMRCWeakIvars); llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI, CharUnits beginOffset, @@ -981,22 +968,19 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars); } - Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, bool ByrefLayout); + Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT, + bool ByrefLayout); - void UpdateRunSkipBlockVars(bool IsByref, - Qualifiers::ObjCLifetime LifeTime, - CharUnits FieldOffset, - CharUnits FieldSize); + void UpdateRunSkipBlockVars(bool IsByref, Qualifiers::ObjCLifetime LifeTime, + CharUnits FieldOffset, CharUnits FieldSize); - void BuildRCBlockVarRecordLayout(const RecordType *RT, - CharUnits BytePos, bool &HasUnion, - bool ByrefLayout=false); + void BuildRCBlockVarRecordLayout(const RecordType *RT, CharUnits BytePos, + bool &HasUnion, bool ByrefLayout = false); void BuildRCRecordLayout(const llvm::StructLayout *RecLayout, const RecordDecl *RD, - ArrayRef RecFields, - CharUnits BytePos, bool &HasUnion, - bool ByrefLayout); + ArrayRef RecFields, + CharUnits BytePos, bool &HasUnion, bool ByrefLayout); uint64_t InlineLayoutInstruction(SmallVectorImpl &Layout); @@ -1009,17 +993,16 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { /// EmitPropertyList - Emit the given property list. The return /// value has type PropertyListPtrTy. - llvm::Constant *EmitPropertyList(Twine Name, - const Decl *Container, + llvm::Constant *EmitPropertyList(Twine Name, const Decl *Container, const ObjCContainerDecl *OCD, const ObjCCommonTypesHelper &ObjCTypes, bool IsClassProperty); /// EmitProtocolMethodTypes - Generate the array of extended method type /// strings. The return value has type Int8PtrPtrTy. - llvm::Constant *EmitProtocolMethodTypes(Twine Name, - ArrayRef MethodTypes, - const ObjCCommonTypesHelper &ObjCTypes); + llvm::Constant * + EmitProtocolMethodTypes(Twine Name, ArrayRef MethodTypes, + const ObjCCommonTypesHelper &ObjCTypes); /// GetProtocolRef - Return a reference to the internal protocol /// description, creating an empty one if it has not been @@ -1053,8 +1036,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { ConstantStructBuilder &Init, StringRef Section, CharUnits Align, bool AddToUsed); - llvm::GlobalVariable *CreateMetadataVar(Twine Name, - llvm::Constant *Init, + llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *Init, StringRef Section, CharUnits Align, bool AddToUsed); @@ -1065,12 +1047,9 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { protected: CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Arg0, - QualType Arg0Ty, - bool IsSuper, + ReturnValueSlot Return, QualType ResultType, + Selector Sel, llvm::Value *Arg0, + QualType Arg0Ty, bool IsSuper, const CallArgList &CallArgs, const ObjCMethodDecl *OMD, const ObjCInterfaceDecl *ClassReceiver, @@ -1084,15 +1063,14 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {} - bool isNonFragileABI() const { - return ObjCABI == 2; - } + bool isNonFragileABI() const { return ObjCABI == 2; } ConstantAddress GenerateConstantString(const StringLiteral *SL) override; ConstantAddress GenerateConstantNSString(const StringLiteral *SL); - llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, - const ObjCContainerDecl *CD=nullptr) override; + llvm::Function * + GenerateMethod(const ObjCMethodDecl *OMD, + const ObjCContainerDecl *CD = nullptr) override; llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD); @@ -1107,7 +1085,7 @@ class CGObjCCommonMac : public CodeGen::CGObjCRuntime { /// object for the given declaration, emitting it if needed. These /// forward references will be filled in with empty bodies if no /// definition is seen. The return value has type ProtocolPtrTy. - virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; + virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) = 0; virtual llvm::Constant *getNSConstantStringClassRef() = 0; @@ -1148,9 +1126,7 @@ class ProtocolMethodLists { OptionalInstanceMethods, OptionalClassMethods }; - enum { - NumProtocolMethodLists = 4 - }; + enum { NumProtocolMethodLists = 4 }; static MethodListType getMethodListKind(Kind kind) { switch (kind) { @@ -1172,8 +1148,8 @@ class ProtocolMethodLists { ProtocolMethodLists result; for (auto *MD : PD->methods()) { - size_t index = (2 * size_t(MD->isOptional())) - + (size_t(MD->isClassMethod())); + size_t index = + (2 * size_t(MD->isOptional())) + (size_t(MD->isClassMethod())); result.Methods[index].push_back(MD); } @@ -1181,14 +1157,14 @@ class ProtocolMethodLists { } template - SmallVector emitExtendedTypesArray(Self *self) const { + SmallVector emitExtendedTypesArray(Self *self) const { // In both ABIs, the method types list is parallel with the // concatenation of the methods arrays in the following order: // instance methods // class methods // optional instance methods // optional class methods - SmallVector result; + SmallVector result; // Methods is already in the correct order for both ABIs. for (auto &list : Methods) { @@ -1233,16 +1209,13 @@ class CGObjCMac : public CGObjCCommonMac { /// has type ClassExtensionPtrTy. llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID, CharUnits instanceSize, - bool hasMRCWeakIvars, - bool isMetaclass); + bool hasMRCWeakIvars, bool isMetaclass); /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class. - llvm::Value *EmitClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID); + llvm::Value *EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID); - llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II); + llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II); llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; @@ -1254,8 +1227,7 @@ class CGObjCMac : public CGObjCCommonMac { /// (i.e. metaclass ivars) is emitted, otherwise the list of /// interface ivars will be emitted. The return value has type /// IvarListPtrTy. - llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, - bool ForClass); + llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, bool ForClass); /// EmitMetaClass - Emit a forward reference to the class structure /// for the metaclass of the given interface. The return value has @@ -1294,9 +1266,8 @@ class CGObjCMac : public CGObjCCommonMac { /// structure used to store optional instance and class methods, and /// protocol properties. The return value has type /// ProtocolExtensionPtrTy. - llvm::Constant * - EmitProtocolExtension(const ObjCProtocolDecl *PD, - const ProtocolMethodLists &methodLists); + llvm::Constant *EmitProtocolExtension(const ObjCProtocolDecl *PD, + const ProtocolMethodLists &methodLists); /// EmitProtocolList - Generate the list of referenced /// protocols. The return value has type ProtocolListPtrTy. @@ -1318,19 +1289,17 @@ class CGObjCMac : public CGObjCCommonMac { CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, - QualType ResultType, - Selector Sel, llvm::Value *Receiver, + QualType ResultType, Selector Sel, + llvm::Value *Receiver, const CallArgList &CallArgs, const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) override; - CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, QualType ResultType, - Selector Sel, const ObjCInterfaceDecl *Class, - bool isCategoryImpl, llvm::Value *Receiver, - bool IsClassMessage, const CallArgList &CallArgs, - const ObjCMethodDecl *Method) override; + CodeGen::RValue GenerateMessageSendSuper( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, + QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, + const CallArgList &CallArgs, const ObjCMethodDecl *Method) override; llvm::Value *GetClass(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) override; @@ -1370,22 +1339,19 @@ class CGObjCMac : public CGObjCCommonMac { const ObjCAtSynchronizedStmt &S) override; void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S); void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) override; - llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) override; - void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) override; - void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - bool threadlocal = false) override; - void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - llvm::Value *ivarOffset) override; - void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest) override; - void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address dest, Address src, - llvm::Value *size) override; + bool ClearInsertionPoint = true) override; + llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, + Address AddrWeakObj) override; + void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dst) override; + void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dest, bool threadlocal = false) override; + void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dest, llvm::Value *ivarOffset) override; + void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dest) override; + void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest, + Address src, llvm::Value *size) override; LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, @@ -1399,24 +1365,24 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { private: friend ProtocolMethodLists; ObjCNonFragileABITypesHelper ObjCTypes; - llvm::GlobalVariable* ObjCEmptyCacheVar; - llvm::Constant* ObjCEmptyVtableVar; + llvm::GlobalVariable *ObjCEmptyCacheVar; + llvm::Constant *ObjCEmptyVtableVar; /// SuperClassReferences - uniqued super class references. - llvm::DenseMap SuperClassReferences; + llvm::DenseMap SuperClassReferences; /// MetaClassReferences - uniqued meta class references. - llvm::DenseMap MetaClassReferences; + llvm::DenseMap MetaClassReferences; /// EHTypeReferences - uniqued class ehtype references. - llvm::DenseMap EHTypeReferences; + llvm::DenseMap EHTypeReferences; /// VTableDispatchMethods - List of methods for which we generate /// vtable-based message dispatch. llvm::DenseSet VTableDispatchMethods; /// DefinedMetaClasses - List of defined meta-classes. - std::vector DefinedMetaClasses; + std::vector DefinedMetaClasses; /// isVTableDispatchedSelector - Returns true if SEL is a /// vtable-based selector. @@ -1431,20 +1397,17 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { void AddModuleClassList(ArrayRef Container, StringRef SymbolName, StringRef SectionName); - llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, - unsigned InstanceStart, - unsigned InstanceSize, - const ObjCImplementationDecl *ID); - llvm::GlobalVariable *BuildClassObject(const ObjCInterfaceDecl *CI, - bool isMetaclass, - llvm::Constant *IsAGV, - llvm::Constant *SuperClassGV, - llvm::Constant *ClassRoGV, - bool HiddenVisibility); + llvm::GlobalVariable * + BuildClassRoTInitializer(unsigned flags, unsigned InstanceStart, + unsigned InstanceSize, + const ObjCImplementationDecl *ID); + llvm::GlobalVariable * + BuildClassObject(const ObjCInterfaceDecl *CI, bool isMetaclass, + llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, + llvm::Constant *ClassRoGV, bool HiddenVisibility); void emitMethodConstant(ConstantArrayBuilder &builder, - const ObjCMethodDecl *MD, - bool forProtocol); + const ObjCMethodDecl *MD, bool forProtocol); /// Emit the method list for the given implementation. The return value /// has type MethodListnfABITy. @@ -1479,23 +1442,17 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { ObjCProtocolDecl::protocol_iterator begin, ObjCProtocolDecl::protocol_iterator end); - CodeGen::RValue EmitVTableMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method); + CodeGen::RValue EmitVTableMessageSend( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, + QualType ResultType, Selector Sel, llvm::Value *Receiver, QualType Arg0Ty, + bool IsSuper, const CallArgList &CallArgs, const ObjCMethodDecl *Method); /// GetClassGlobal - Return the global variable for the Objective-C /// class of the given name. llvm::Constant *GetClassGlobal(StringRef Name, ForDefinition_t IsForDefinition, bool Weak = false, bool DLLImport = false); - llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID, - bool isMetaclass, + llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID, bool isMetaclass, ForDefinition_t isForDefinition); llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID); @@ -1506,11 +1463,9 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy, /// for the given class reference. - llvm::Value *EmitClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID); + llvm::Value *EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID); - llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II, + llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID); llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; @@ -1528,9 +1483,8 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { /// ObjCIvarOffsetVariable - Returns the ivar offset variable for /// the given ivar. /// - llvm::GlobalVariable * ObjCIvarOffsetVariable( - const ObjCInterfaceDecl *ID, - const ObjCIvarDecl *Ivar); + llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, + const ObjCIvarDecl *Ivar); /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy, /// for the given selector. @@ -1547,16 +1501,15 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; } void GetClassSizeInfo(const ObjCImplementationDecl *OID, - uint32_t &InstanceStart, - uint32_t &InstanceSize); + uint32_t &InstanceStart, uint32_t &InstanceSize); // Shamelessly stolen from Analysis/CFRefCount.cpp - Selector GetNullarySelector(const char* name) const { + Selector GetNullarySelector(const char *name) const { const IdentifierInfo *II = &CGM.getContext().Idents.get(name); return CGM.getContext().Selectors.getSelector(0, &II); } - Selector GetUnarySelector(const char* name) const { + Selector GetUnarySelector(const char *name) const { const IdentifierInfo *II = &CGM.getContext().Idents.get(name); return CGM.getContext().Selectors.getSelector(1, &II); } @@ -1582,7 +1535,7 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { // and that the method may be inlined, this optimization actually // can't be performed. if (const ObjCMethodDecl *MD = - dyn_cast_or_null(CGF.CurFuncDecl)) + dyn_cast_or_null(CGF.CurFuncDecl)) if (MD->isInstanceMethod() && !MD->isDirectMethod()) if (const ObjCInterfaceDecl *ID = MD->getClassInterface()) return IV->getContainingInterface()->isSuperClassOf(ID); @@ -1621,27 +1574,28 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) override; - CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, QualType ResultType, - Selector Sel, const ObjCInterfaceDecl *Class, - bool isCategoryImpl, llvm::Value *Receiver, - bool IsClassMessage, const CallArgList &CallArgs, - const ObjCMethodDecl *Method) override; + CodeGen::RValue GenerateMessageSendSuper( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, + QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage, + const CallArgList &CallArgs, const ObjCMethodDecl *Method) override; llvm::Value *GetClass(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) override; - llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override - { return EmitSelector(CGF, Sel); } - Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override - { return EmitSelectorAddr(Sel); } + llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override { + return EmitSelector(CGF, Sel); + } + Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override { + return EmitSelectorAddr(Sel); + } /// The NeXT/Apple runtimes do not support typed selectors; just emit an /// untyped one. llvm::Value *GetSelector(CodeGenFunction &CGF, - const ObjCMethodDecl *Method) override - { return EmitSelector(CGF, Method->getSelector()); } + const ObjCMethodDecl *Method) override { + return EmitSelector(CGF, Method->getSelector()); + } void GenerateCategory(const ObjCCategoryImplDecl *CMD) override; @@ -1691,22 +1645,19 @@ class CGObjCNonFragileABIMac : public CGObjCCommonMac { void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) override; void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) override; - llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) override; - void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address edst) override; - void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - bool threadlocal = false) override; - void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest, - llvm::Value *ivarOffset) override; - void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dest) override; - void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address dest, Address src, - llvm::Value *size) override; + bool ClearInsertionPoint = true) override; + llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, + Address AddrWeakObj) override; + void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address edst) override; + void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dest, bool threadlocal = false) override; + void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dest, llvm::Value *ivarOffset) override; + void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, + Address dest) override; + void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest, + Address src, llvm::Value *size) override; LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) override; @@ -1740,14 +1691,12 @@ struct NullReturnState { /// Complete the null-return operation. It is valid to call this /// regardless of whether 'init' has been called. - RValue complete(CodeGenFunction &CGF, - ReturnValueSlot returnSlot, - RValue result, - QualType resultType, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method) { + RValue complete(CodeGenFunction &CGF, ReturnValueSlot returnSlot, + RValue result, QualType resultType, + const CallArgList &CallArgs, const ObjCMethodDecl *Method) { // If we never had to do a null-check, just use the raw result. - if (!NullBB) return result; + if (!NullBB) + return result; // The continuation block. This will be left null if we don't have an // IP, which can happen if the method we're calling is marked noreturn. @@ -1774,7 +1723,8 @@ struct NullReturnState { // If we've got a void return, just jump to the continuation block. if (result.isScalar() && resultType->isVoidType()) { // No jumps required if the message-send was noreturn. - if (contBB) CGF.EmitBlock(contBB); + if (contBB) + CGF.EmitBlock(contBB); return result; } @@ -1785,7 +1735,8 @@ struct NullReturnState { CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(resultType), resultType); // If no join is necessary, just flow out. - if (!contBB) return RValue::get(null); + if (!contBB) + return RValue::get(null); // Otherwise, build a phi. CGF.EmitBlock(contBB); @@ -1803,7 +1754,8 @@ struct NullReturnState { assert(result.isAggregate() && "null init of non-aggregate result?"); if (!returnSlot.isUnused()) CGF.EmitNullInitialization(result.getAggregateAddress(), resultType); - if (contBB) CGF.EmitBlock(contBB); + if (contBB) + CGF.EmitBlock(contBB); return result; } @@ -1835,9 +1787,8 @@ static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext, llvm::GlobalVariable *C, unsigned idx0, unsigned idx1) { llvm::Value *Idxs[] = { - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), - llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1) - }; + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0), + llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)}; return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs); } @@ -1863,7 +1814,7 @@ getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) { /// A helper function to create an internal or private global variable. static llvm::GlobalVariable * finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, - const llvm::Twine &Name, CodeGenModule &CGM) { + const llvm::Twine &Name, CodeGenModule &CGM) { std::string SectionName; if (CGM.getTriple().isOSBinFormatMachO()) SectionName = "__DATA, __objc_const"; @@ -1876,8 +1827,8 @@ finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder, /* *** CGObjCMac Public Interface *** */ -CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), - ObjCTypes(cgm) { +CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) + : CGObjCCommonMac(cgm), ObjCTypes(cgm) { ObjCABI = 1; EmitImageInfo(); } @@ -1896,24 +1847,22 @@ llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) { Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) { return EmitSelectorAddr(Sel); } -llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, const ObjCMethodDecl - *Method) { +llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, + const ObjCMethodDecl *Method) { return EmitSelector(CGF, Method->getSelector()); } llvm::Constant *CGObjCMac::GetEHType(QualType T) { - if (T->isObjCIdType() || - T->isObjCQualifiedIdType()) { + if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { return CGM.GetAddrOfRTTIDescriptor( - CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true); + CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true); } - if (T->isObjCClassType() || - T->isObjCQualifiedClassType()) { + if (T->isObjCClassType() || T->isObjCQualifiedClassType()) { return CGM.GetAddrOfRTTIDescriptor( - CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true); + CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true); } if (T->isObjCObjectPointerType()) - return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true); + return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true); llvm_unreachable("asking for catch type for ObjC type in fragile runtime"); } @@ -1940,8 +1889,8 @@ llvm::Constant *CGObjCMac::GetEHType(QualType T) { ConstantAddress CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) { return (!CGM.getLangOpts().NoConstantCFStrings - ? CGM.GetAddrOfConstantCFString(SL) - : GenerateConstantNSString(SL)); + ? CGM.GetAddrOfConstantCFString(SL) + : GenerateConstantNSString(SL)); } static llvm::StringMapEntry & @@ -1957,9 +1906,8 @@ llvm::Constant *CGObjCMac::getNSConstantStringClassRef() { return cast(V); auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; - std::string str = - StringClass.empty() ? "_NSConstantStringClassReference" - : "_" + StringClass + "ClassReference"; + std::string str = StringClass.empty() ? "_NSConstantStringClassReference" + : "_" + StringClass + "ClassReference"; llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0); auto GV = CGM.CreateRuntimeVariable(PTy, str); @@ -1972,9 +1920,8 @@ llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() { return cast(V); auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass; - std::string str = - StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" - : "OBJC_CLASS_$_" + StringClass; + std::string str = StringClass.empty() ? "OBJC_CLASS_$_NSConstantString" + : "OBJC_CLASS_$_" + StringClass; llvm::Constant *GV = GetClassGlobal(str, NotForDefinition); ConstantStringClassRef = GV; return GV; @@ -1984,11 +1931,11 @@ ConstantAddress CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { unsigned StringLength = 0; llvm::StringMapEntry &Entry = - GetConstantStringEntry(NSConstantStringMap, Literal, StringLength); + GetConstantStringEntry(NSConstantStringMap, Literal, StringLength); if (auto *C = Entry.second) - return ConstantAddress( - C, C->getValueType(), CharUnits::fromQuantity(C->getAlignment())); + return ConstantAddress(C, C->getValueType(), + CharUnits::fromQuantity(C->getAlignment())); // If we don't already have it, get _NSConstantStringClassReference. llvm::Constant *Class = getNSConstantStringClassRef(); @@ -2008,7 +1955,7 @@ CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { // String pointer. llvm::Constant *C = - llvm::ConstantDataArray::getString(VMContext, Entry.first()); + llvm::ConstantDataArray::getString(VMContext, Entry.first()); llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage; bool isConstant = !CGM.getLangOpts().WritableStrings; @@ -2041,30 +1988,22 @@ CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) { return ConstantAddress(GV, GV->getValueType(), Alignment); } -enum { - kCFTaggedObjectID_Integer = (1 << 1) + 1 -}; +enum { kCFTaggedObjectID_Integer = (1 << 1) + 1 }; /// Generates a message send where the super is the receiver. This is /// a message send to self with special delivery semantics indicating /// which class's method should be called. -CodeGen::RValue -CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Receiver, - bool IsClassMessage, - const CodeGen::CallArgList &CallArgs, - const ObjCMethodDecl *Method) { +CodeGen::RValue CGObjCMac::GenerateMessageSendSuper( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, + Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl, + llvm::Value *Receiver, bool IsClassMessage, + const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) { // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. RawAddress ObjCSuper = CGF.CreateTempAlloca( ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = - CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); + CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); @@ -2102,7 +2041,7 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // FIXME: We shouldn't need to do this cast, rectify the ASTContext and // ObjCTypes types. llvm::Type *ClassTy = - CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); + CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); Target = CGF.Builder.CreateBitCast(Target, ClassTy); CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(), @@ -2111,31 +2050,21 @@ CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, } /// Generate code for a message send expression. -CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) { +CodeGen::RValue CGObjCMac::GenerateMessageSend( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, + Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs, + const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) { return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver, CGF.getContext().getObjCIdType(), false, CallArgs, Method, Class, ObjCTypes); } -CodeGen::RValue -CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Arg0, - QualType Arg0Ty, - bool IsSuper, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method, - const ObjCInterfaceDecl *ClassReceiver, - const ObjCCommonTypesHelper &ObjCTypes) { +CodeGen::RValue CGObjCCommonMac::EmitMessageSend( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, + Selector Sel, llvm::Value *Arg0, QualType Arg0Ty, bool IsSuper, + const CallArgList &CallArgs, const ObjCMethodDecl *Method, + const ObjCInterfaceDecl *ClassReceiver, + const ObjCCommonTypesHelper &ObjCTypes) { CodeGenTypes &Types = CGM.getTypes(); auto selTy = CGF.getContext().getObjCSelType(); llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy)); @@ -2157,7 +2086,7 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, "Result type mismatch!"); bool ReceiverCanBeNull = - canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0); + canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0); bool RequiresNullCheck = false; bool RequiresSelValue = true; @@ -2170,22 +2099,23 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, // so just don't bother with setting the `_cmd` argument. RequiresSelValue = false; } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) { - if (ReceiverCanBeNull) RequiresNullCheck = true; - Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) - : ObjCTypes.getSendStretFn(IsSuper); + if (ReceiverCanBeNull) + RequiresNullCheck = true; + Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper) + : ObjCTypes.getSendStretFn(IsSuper); } else if (CGM.ReturnTypeUsesFPRet(ResultType)) { Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper) - : ObjCTypes.getSendFpretFn(IsSuper); + : ObjCTypes.getSendFpretFn(IsSuper); } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) { Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper) - : ObjCTypes.getSendFp2retFn(IsSuper); + : ObjCTypes.getSendFp2retFn(IsSuper); } else { // arm64 uses objc_msgSend for stret methods and yet null receiver check // must be made for it. if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo)) RequiresNullCheck = true; Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper) - : ObjCTypes.getSendFn(IsSuper); + : ObjCTypes.getSendFn(IsSuper); } // Cast function to proper signature @@ -2214,8 +2144,8 @@ CGObjCCommonMac::EmitMessageSend(CodeGen::CodeGenFunction &CGF, llvm::CallBase *CallSite; CGCallee Callee = CGCallee::forDirect(BitcastFn); - RValue rvalue = CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, - &CallSite); + RValue rvalue = + CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite); // Mark the call as noreturn if the method is marked noreturn and the // receiver cannot be null. @@ -2240,13 +2170,19 @@ static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT, if (auto ownership = FQT.getObjCLifetime()) { // Ownership does not apply recursively to C pointer types. - if (pointee) return Qualifiers::GCNone; + if (pointee) + return Qualifiers::GCNone; switch (ownership) { - case Qualifiers::OCL_Weak: return Qualifiers::Weak; - case Qualifiers::OCL_Strong: return Qualifiers::Strong; - case Qualifiers::OCL_ExplicitNone: return Qualifiers::GCNone; - case Qualifiers::OCL_Autoreleasing: llvm_unreachable("autoreleasing ivar?"); - case Qualifiers::OCL_None: llvm_unreachable("known nonzero"); + case Qualifiers::OCL_Weak: + return Qualifiers::Weak; + case Qualifiers::OCL_Strong: + return Qualifiers::Strong; + case Qualifiers::OCL_ExplicitNone: + return Qualifiers::GCNone; + case Qualifiers::OCL_Autoreleasing: + llvm_unreachable("autoreleasing ivar?"); + case Qualifiers::OCL_None: + llvm_unreachable("known nonzero"); } llvm_unreachable("bad objc ownership"); } @@ -2265,76 +2201,73 @@ static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT, } namespace { - struct IvarInfo { - CharUnits Offset; - uint64_t SizeInWords; - IvarInfo(CharUnits offset, uint64_t sizeInWords) +struct IvarInfo { + CharUnits Offset; + uint64_t SizeInWords; + IvarInfo(CharUnits offset, uint64_t sizeInWords) : Offset(offset), SizeInWords(sizeInWords) {} - // Allow sorting based on byte pos. - bool operator<(const IvarInfo &other) const { - return Offset < other.Offset; - } - }; + // Allow sorting based on byte pos. + bool operator<(const IvarInfo &other) const { return Offset < other.Offset; } +}; - /// A helper class for building GC layout strings. - class IvarLayoutBuilder { - CodeGenModule &CGM; +/// A helper class for building GC layout strings. +class IvarLayoutBuilder { + CodeGenModule &CGM; - /// The start of the layout. Offsets will be relative to this value, - /// and entries less than this value will be silently discarded. - CharUnits InstanceBegin; + /// The start of the layout. Offsets will be relative to this value, + /// and entries less than this value will be silently discarded. + CharUnits InstanceBegin; - /// The end of the layout. Offsets will never exceed this value. - CharUnits InstanceEnd; + /// The end of the layout. Offsets will never exceed this value. + CharUnits InstanceEnd; - /// Whether we're generating the strong layout or the weak layout. - bool ForStrongLayout; + /// Whether we're generating the strong layout or the weak layout. + bool ForStrongLayout; - /// Whether the offsets in IvarsInfo might be out-of-order. - bool IsDisordered = false; + /// Whether the offsets in IvarsInfo might be out-of-order. + bool IsDisordered = false; - llvm::SmallVector IvarsInfo; + llvm::SmallVector IvarsInfo; - public: - IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin, - CharUnits instanceEnd, bool forStrongLayout) +public: + IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin, + CharUnits instanceEnd, bool forStrongLayout) : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd), - ForStrongLayout(forStrongLayout) { - } + ForStrongLayout(forStrongLayout) {} - void visitRecord(const RecordType *RT, CharUnits offset); + void visitRecord(const RecordType *RT, CharUnits offset); - template - void visitAggregate(Iterator begin, Iterator end, - CharUnits aggrOffset, - const GetOffsetFn &getOffset); + template + void visitAggregate(Iterator begin, Iterator end, CharUnits aggrOffset, + const GetOffsetFn &getOffset); - void visitField(const FieldDecl *field, CharUnits offset); + void visitField(const FieldDecl *field, CharUnits offset); - /// Add the layout of a block implementation. - void visitBlock(const CGBlockInfo &blockInfo); + /// Add the layout of a block implementation. + void visitBlock(const CGBlockInfo &blockInfo); - /// Is there any information for an interesting bitmap? - bool hasBitmapData() const { return !IvarsInfo.empty(); } + /// Is there any information for an interesting bitmap? + bool hasBitmapData() const { return !IvarsInfo.empty(); } - llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC, - llvm::SmallVectorImpl &buffer); + llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC, + llvm::SmallVectorImpl &buffer); - static void dump(ArrayRef buffer) { - const unsigned char *s = buffer.data(); - for (unsigned i = 0, e = buffer.size(); i < e; i++) - if (!(s[i] & 0xf0)) - printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); - else - printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); - printf("\n"); - } - }; + static void dump(ArrayRef buffer) { + const unsigned char *s = buffer.data(); + for (unsigned i = 0, e = buffer.size(); i < e; i++) + if (!(s[i] & 0xf0)) + printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); + else + printf("0x%x%s", s[i], s[i] != 0 ? ", " : ""); + printf("\n"); + } +}; } // end anonymous namespace -llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, - const CGBlockInfo &blockInfo) { +llvm::Constant * +CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, + const CGBlockInfo &blockInfo) { llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); if (CGM.getLangOpts().getGC() == LangOptions::NonGC) @@ -2378,7 +2311,8 @@ void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) { const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); // Ignore constant captures. - if (capture.isConstant()) continue; + if (capture.isConstant()) + continue; CharUnits fieldOffset = capture.getOffset(); @@ -2413,8 +2347,8 @@ void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) { /// getBlockCaptureLifetime - This routine returns life time of the captured /// block variable for the purpose of block layout meta-data generation. FQT is /// the type of the variable captured in the block. -Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT, - bool ByrefLayout) { +Qualifiers::ObjCLifetime +CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT, bool ByrefLayout) { // If it has an ownership qualifier, we're done. if (auto lifetime = FQT.getObjCLifetime()) return lifetime; @@ -2436,26 +2370,25 @@ void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, CharUnits FieldSize) { // __block variables are passed by their descriptor address. if (IsByref) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, - FieldSize)); + RunSkipBlockVars.push_back( + RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, FieldSize)); else if (LifeTime == Qualifiers::OCL_Strong) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, - FieldSize)); + RunSkipBlockVars.push_back( + RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, FieldSize)); else if (LifeTime == Qualifiers::OCL_Weak) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, - FieldSize)); + RunSkipBlockVars.push_back( + RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, FieldSize)); else if (LifeTime == Qualifiers::OCL_ExplicitNone) - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, - FieldSize)); + RunSkipBlockVars.push_back( + RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, FieldSize)); else - RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, - FieldOffset, - FieldSize)); + RunSkipBlockVars.push_back( + RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, FieldOffset, FieldSize)); } void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, const RecordDecl *RD, - ArrayRef RecFields, + ArrayRef RecFields, CharUnits BytePos, bool &HasUnion, bool ByrefLayout) { bool IsUnion = (RD && RD->isUnion()); @@ -2475,7 +2408,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, // although this dependency is hidden. const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); CharUnits FieldOffset = - CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i)); + CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i)); // Skip over unnamed or bitfields if (!Field->getIdentifier() || Field->isBitField()) { @@ -2513,13 +2446,14 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, // Replicate layout information for each array element. Note that // one element is already done. uint64_t ElIx = 1; - for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) { + for (int FirstIndex = RunSkipBlockVars.size() - 1; ElIx < ElCount; + ElIx++) { CharUnits Size = CGM.getContext().getTypeSizeInChars(RT); - for (int i = OldIndex+1; i <= FirstIndex; ++i) + for (int i = OldIndex + 1; i <= FirstIndex; ++i) RunSkipBlockVars.push_back( - RUN_SKIP(RunSkipBlockVars[i].opcode, - RunSkipBlockVars[i].block_var_bytepos + Size*ElIx, - RunSkipBlockVars[i].block_var_size)); + RUN_SKIP(RunSkipBlockVars[i].opcode, + RunSkipBlockVars[i].block_var_bytepos + Size * ElIx, + RunSkipBlockVars[i].block_var_size)); } continue; } @@ -2533,10 +2467,8 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, MaxFieldOffset = FieldOffset; } } else { - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(FQT, ByrefLayout), - BytePos + FieldOffset, - FieldSize); + UpdateRunSkipBlockVars(false, getBlockCaptureLifetime(FQT, ByrefLayout), + BytePos + FieldOffset, FieldSize); } } @@ -2545,32 +2477,32 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, // Last field was a bitfield. Must update the info. uint64_t BitFieldSize = LastFieldBitfieldOrUnnamed->getBitWidthValue(); unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + - ((BitFieldSize % ByteSizeInBits) != 0); + ((BitFieldSize % ByteSizeInBits) != 0); CharUnits Size = CharUnits::fromQuantity(UnsSize); Size += LastBitfieldOrUnnamedOffset; - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), - ByrefLayout), - BytePos + LastBitfieldOrUnnamedOffset, - Size); + UpdateRunSkipBlockVars( + false, + getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), + ByrefLayout), + BytePos + LastBitfieldOrUnnamedOffset, Size); } else { - assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); + assert(!LastFieldBitfieldOrUnnamed->getIdentifier() && + "Expected unnamed"); // Last field was unnamed. Must update skip info. - CharUnits FieldSize - = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType()); - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), - ByrefLayout), - BytePos + LastBitfieldOrUnnamedOffset, - FieldSize); + CharUnits FieldSize = CGM.getContext().getTypeSizeInChars( + LastFieldBitfieldOrUnnamed->getType()); + UpdateRunSkipBlockVars( + false, + getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(), + ByrefLayout), + BytePos + LastBitfieldOrUnnamedOffset, FieldSize); } } if (MaxField) - UpdateRunSkipBlockVars(false, - getBlockCaptureLifetime(MaxField->getType(), ByrefLayout), - BytePos + MaxFieldOffset, - MaxUnionSize); + UpdateRunSkipBlockVars( + false, getBlockCaptureLifetime(MaxField->getType(), ByrefLayout), + BytePos + MaxFieldOffset, MaxUnionSize); } void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, @@ -2578,105 +2510,104 @@ void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, bool &HasUnion, bool ByrefLayout) { const RecordDecl *RD = RT->getDecl(); - SmallVector Fields(RD->fields()); + SmallVector Fields(RD->fields()); llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); const llvm::StructLayout *RecLayout = - CGM.getDataLayout().getStructLayout(cast(Ty)); + CGM.getDataLayout().getStructLayout(cast(Ty)); BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout); } /// InlineLayoutInstruction - This routine produce an inline instruction for the /// block variable layout if it can. If not, it returns 0. Rules are as follow: -/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world, -/// an inline layout of value 0x0000000000000xyz is interpreted as follows: -/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by -/// y captured object of BLOCK_LAYOUT_BYREF. Followed by -/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero -/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no -/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured. +/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit +/// world, an inline layout of value 0x0000000000000xyz is interpreted as +/// follows: x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by y +/// captured object of BLOCK_LAYOUT_BYREF. Followed by z captured object of +/// BLOCK_LAYOUT_WEAK. If any of the above is missing, zero replaces it. For +/// example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no BLOCK_LAYOUT_BYREF +/// and no BLOCK_LAYOUT_WEAK objects are captured. uint64_t CGObjCCommonMac::InlineLayoutInstruction( - SmallVectorImpl &Layout) { + SmallVectorImpl &Layout) { uint64_t Result = 0; if (Layout.size() <= 3) { unsigned size = Layout.size(); - unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0; + unsigned strong_word_count = 0, byref_word_count = 0, weak_word_count = 0; unsigned char inst; - enum BLOCK_LAYOUT_OPCODE opcode ; + enum BLOCK_LAYOUT_OPCODE opcode; switch (size) { - case 3: - inst = Layout[0]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_STRONG) - strong_word_count = (inst & 0xF)+1; - else - return 0; + case 3: + inst = Layout[0]; + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); + if (opcode == BLOCK_LAYOUT_STRONG) + strong_word_count = (inst & 0xF) + 1; + else + return 0; + inst = Layout[1]; + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); + if (opcode == BLOCK_LAYOUT_BYREF) + byref_word_count = (inst & 0xF) + 1; + else + return 0; + inst = Layout[2]; + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); + if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF) + 1; + else + return 0; + break; + + case 2: + inst = Layout[0]; + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); + if (opcode == BLOCK_LAYOUT_STRONG) { + strong_word_count = (inst & 0xF) + 1; inst = Layout[1]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); if (opcode == BLOCK_LAYOUT_BYREF) - byref_word_count = (inst & 0xF)+1; + byref_word_count = (inst & 0xF) + 1; + else if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF) + 1; else return 0; - inst = Layout[2]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + } else if (opcode == BLOCK_LAYOUT_BYREF) { + byref_word_count = (inst & 0xF) + 1; + inst = Layout[1]; + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - break; - - case 2: - inst = Layout[0]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_STRONG) { - strong_word_count = (inst & 0xF)+1; - inst = Layout[1]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_BYREF) - byref_word_count = (inst & 0xF)+1; - else if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - } - else if (opcode == BLOCK_LAYOUT_BYREF) { - byref_word_count = (inst & 0xF)+1; - inst = Layout[1]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; - else - return 0; - } - else - return 0; - break; - - case 1: - inst = Layout[0]; - opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_STRONG) - strong_word_count = (inst & 0xF)+1; - else if (opcode == BLOCK_LAYOUT_BYREF) - byref_word_count = (inst & 0xF)+1; - else if (opcode == BLOCK_LAYOUT_WEAK) - weak_word_count = (inst & 0xF)+1; + weak_word_count = (inst & 0xF) + 1; else return 0; - break; + } else + return 0; + break; - default: + case 1: + inst = Layout[0]; + opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); + if (opcode == BLOCK_LAYOUT_STRONG) + strong_word_count = (inst & 0xF) + 1; + else if (opcode == BLOCK_LAYOUT_BYREF) + byref_word_count = (inst & 0xF) + 1; + else if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF) + 1; + else return 0; + break; + + default: + return 0; } // Cannot inline when any of the word counts is 15. Because this is one less // than the actual work count (so 15 means 16 actual word counts), // and we can only display 0 thru 15 word counts. - if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16) + if (strong_word_count == 16 || byref_word_count == 16 || + weak_word_count == 16) return 0; - unsigned count = - (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0); + unsigned count = (strong_word_count != 0) + (byref_word_count != 0) + + (weak_word_count != 0); if (size == count) { if (strong_word_count) @@ -2698,7 +2629,7 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { return nullPtr; unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(LangAS::Default); unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); - unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; + unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits; // Sort on byte position; captures might not be allocated in order, // and unions can do funny things. @@ -2710,21 +2641,20 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode; CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos; CharUnits end_byte_pos = start_byte_pos; - unsigned j = i+1; + unsigned j = i + 1; while (j < size) { if (opcode == RunSkipBlockVars[j].opcode) { end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos; i++; - } - else + } else break; } CharUnits size_in_bytes = - end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size; + end_byte_pos - start_byte_pos + RunSkipBlockVars[j - 1].block_var_size; if (j < size) { - CharUnits gap = - RunSkipBlockVars[j].block_var_bytepos - - RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size; + CharUnits gap = RunSkipBlockVars[j].block_var_bytepos - + RunSkipBlockVars[j - 1].block_var_bytepos - + RunSkipBlockVars[j - 1].block_var_size; size_in_bytes += gap; } CharUnits residue_in_bytes = CharUnits::Zero(); @@ -2745,20 +2675,21 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { if (size_in_words > 0) { // Note that value in imm. is one less that the actual // value. So, we subtract 1 away! - unsigned char inst = (opcode << 4) | (size_in_words-1); + unsigned char inst = (opcode << 4) | (size_in_words - 1); Layout.push_back(inst); } if (residue_in_bytes > CharUnits::Zero()) { - unsigned char inst = - (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1); + unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | + (residue_in_bytes.getQuantity() - 1); Layout.push_back(inst); } } while (!Layout.empty()) { unsigned char inst = Layout.back(); - enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); - if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS) + enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); + if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || + opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS) Layout.pop_back(); else break; @@ -2774,11 +2705,11 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { printf("\n Inline block variable layout: "); printf("0x0%" PRIx64 "", Result); if (auto numStrong = (Result & 0xF00) >> 8) - printf(", BL_STRONG:%d", (int) numStrong); + printf(", BL_STRONG:%d", (int)numStrong); if (auto numByref = (Result & 0x0F0) >> 4) - printf(", BL_BYREF:%d", (int) numByref); + printf(", BL_BYREF:%d", (int)numByref); if (auto numWeak = (Result & 0x00F) >> 0) - printf(", BL_WEAK:%d", (int) numWeak); + printf(", BL_WEAK:%d", (int)numWeak); printf(", BL_OPERATOR:0\n"); } return llvm::ConstantInt::get(CGM.IntPtrTy, Result); @@ -2797,36 +2728,36 @@ llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) { printf("\n Block variable layout: "); for (unsigned i = 0, e = BitMap.size(); i != e; i++) { unsigned char inst = BitMap[i]; - enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4); unsigned delta = 1; switch (opcode) { - case BLOCK_LAYOUT_OPERATOR: - printf("BL_OPERATOR:"); - delta = 0; - break; - case BLOCK_LAYOUT_NON_OBJECT_BYTES: - printf("BL_NON_OBJECT_BYTES:"); - break; - case BLOCK_LAYOUT_NON_OBJECT_WORDS: - printf("BL_NON_OBJECT_WORD:"); - break; - case BLOCK_LAYOUT_STRONG: - printf("BL_STRONG:"); - break; - case BLOCK_LAYOUT_BYREF: - printf("BL_BYREF:"); - break; - case BLOCK_LAYOUT_WEAK: - printf("BL_WEAK:"); - break; - case BLOCK_LAYOUT_UNRETAINED: - printf("BL_UNRETAINED:"); - break; + case BLOCK_LAYOUT_OPERATOR: + printf("BL_OPERATOR:"); + delta = 0; + break; + case BLOCK_LAYOUT_NON_OBJECT_BYTES: + printf("BL_NON_OBJECT_BYTES:"); + break; + case BLOCK_LAYOUT_NON_OBJECT_WORDS: + printf("BL_NON_OBJECT_WORD:"); + break; + case BLOCK_LAYOUT_STRONG: + printf("BL_STRONG:"); + break; + case BLOCK_LAYOUT_BYREF: + printf("BL_BYREF:"); + break; + case BLOCK_LAYOUT_WEAK: + printf("BL_WEAK:"); + break; + case BLOCK_LAYOUT_UNRETAINED: + printf("BL_UNRETAINED:"); + break; } // Actual value of word count is one more that what is in the imm. // field of the instruction printf("%d", (inst & 0xf) + delta); - if (i < e-1) + if (i < e - 1) printf(", "); else printf("\n"); @@ -2884,13 +2815,13 @@ void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM, unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(LangAS::Default); unsigned ByteSizeInBits = CGM.getTarget().getCharWidth(); - unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; + unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits; const BlockDecl *blockDecl = blockInfo.getBlockDecl(); // Calculate the basic layout of the block structure. const llvm::StructLayout *layout = - CGM.getDataLayout().getStructLayout(blockInfo.StructureType); + CGM.getDataLayout().getStructLayout(blockInfo.StructureType); // Ignore the optional 'this' capture: C++ objects are not assumed // to be GC'ed. @@ -2906,10 +2837,11 @@ void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); // Ignore constant captures. - if (capture.isConstant()) continue; + if (capture.isConstant()) + continue; CharUnits fieldOffset = - CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex())); + CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex())); assert(!type->isArrayType() && "array variable should not be caught"); if (!CI.isByRef()) @@ -2948,7 +2880,8 @@ llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM, RunSkipBlockVars.clear(); bool hasUnion = false; if (const RecordType *record = T->getAs()) { - BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, true /*ByrefLayout */); + BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion, + true /*ByrefLayout */); llvm::Constant *Result = getBitmapBlockLayout(true); if (isa(Result)) Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy); @@ -2986,10 +2919,10 @@ llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) { return GetOrEmitProtocolRef(PD); } -llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime( - CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID, - ObjCCommonTypesHelper &ObjCTypes) { +llvm::Value * +CGObjCCommonMac::EmitClassRefViaRuntime(CodeGenFunction &CGF, + const ObjCInterfaceDecl *ID, + ObjCCommonTypesHelper &ObjCTypes) { llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn(); llvm::Value *className = CGF.CGM @@ -2997,10 +2930,8 @@ llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime( ID->getObjCRuntimeNameAsString())) .getPointer(); ASTContext &ctx = CGF.CGM.getContext(); - className = - CGF.Builder.CreateBitCast(className, - CGF.ConvertType( - ctx.getPointerType(ctx.CharTy.withConst()))); + className = CGF.Builder.CreateBitCast( + className, CGF.ConvertType(ctx.getPointerType(ctx.CharTy.withConst()))); llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className); call->setDoesNotThrow(); return call; @@ -3042,20 +2973,19 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { values.add(GetClassName(PD->getObjCRuntimeNameAsString())); values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(), PD->protocol_begin(), PD->protocol_end())); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredInstanceMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredClassMethods)); + values.add(methodLists.emitMethodList( + this, PD, ProtocolMethodLists::RequiredInstanceMethods)); + values.add(methodLists.emitMethodList( + this, PD, ProtocolMethodLists::RequiredClassMethods)); if (Entry) { // Already created, update the initializer. assert(Entry->hasPrivateLinkage()); values.finishAndSetAsInitializer(Entry); } else { - Entry = values.finishAndCreateGlobal("OBJC_PROTOCOL_" + PD->getName(), - CGM.getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::PrivateLinkage); + Entry = values.finishAndCreateGlobal( + "OBJC_PROTOCOL_" + PD->getName(), CGM.getPointerAlign(), + /*constant*/ false, llvm::GlobalValue::PrivateLinkage); Entry->setSection("__OBJC,__protocol,regular,no_dead_strip"); Protocols[PD->getIdentifier()] = Entry; @@ -3096,36 +3026,30 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { llvm::Constant * CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, const ProtocolMethodLists &methodLists) { - auto optInstanceMethods = - methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalInstanceMethods); - auto optClassMethods = - methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalClassMethods); - - auto extendedMethodTypes = - EmitProtocolMethodTypes("OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(), - methodLists.emitExtendedTypesArray(this), - ObjCTypes); - - auto instanceProperties = - EmitPropertyList("OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD, - ObjCTypes, false); + auto optInstanceMethods = methodLists.emitMethodList( + this, PD, ProtocolMethodLists::OptionalInstanceMethods); + auto optClassMethods = methodLists.emitMethodList( + this, PD, ProtocolMethodLists::OptionalClassMethods); + + auto extendedMethodTypes = EmitProtocolMethodTypes( + "OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(), + methodLists.emitExtendedTypesArray(this), ObjCTypes); + + auto instanceProperties = EmitPropertyList( + "OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD, ObjCTypes, false); auto classProperties = - EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr, - PD, ObjCTypes, true); + EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr, + PD, ObjCTypes, true); // Return null if no extension bits are used. - if (optInstanceMethods->isNullValue() && - optClassMethods->isNullValue() && - extendedMethodTypes->isNullValue() && - instanceProperties->isNullValue() && + if (optInstanceMethods->isNullValue() && optClassMethods->isNullValue() && + extendedMethodTypes->isNullValue() && instanceProperties->isNullValue() && classProperties->isNullValue()) { return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); } uint64_t size = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy); @@ -3187,11 +3111,10 @@ CGObjCMac::EmitProtocolList(Twine name, return GV; } -static void -PushProtocolProperties(llvm::SmallPtrSet &PropertySet, - SmallVectorImpl &Properties, - const ObjCProtocolDecl *Proto, - bool IsClassProperty) { +static void PushProtocolProperties( + llvm::SmallPtrSet &PropertySet, + SmallVectorImpl &Properties, + const ObjCProtocolDecl *Proto, bool IsClassProperty) { for (const auto *PD : Proto->properties()) { if (IsClassProperty != PD->isClassProperty()) continue; @@ -3216,11 +3139,9 @@ PushProtocolProperties(llvm::SmallPtrSet &PropertySet, struct _objc_property[prop_count]; }; */ -llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, - const Decl *Container, - const ObjCContainerDecl *OCD, - const ObjCCommonTypesHelper &ObjCTypes, - bool IsClassProperty) { +llvm::Constant *CGObjCCommonMac::EmitPropertyList( + Twine Name, const Decl *Container, const ObjCContainerDecl *OCD, + const ObjCCommonTypesHelper &ObjCTypes, bool IsClassProperty) { if (IsClassProperty) { // Make this entry NULL for OS X with deployment target < 10.11, for iOS // with deployment target < 9.0. @@ -3231,7 +3152,7 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, } SmallVector Properties; - llvm::SmallPtrSet PropertySet; + llvm::SmallPtrSet PropertySet; if (const ObjCInterfaceDecl *OID = dyn_cast(OCD)) for (const ObjCCategoryDecl *ClassExt : OID->known_extensions()) @@ -3259,8 +3180,7 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, if (const ObjCInterfaceDecl *OID = dyn_cast(OCD)) { for (const auto *P : OID->all_referenced_protocols()) PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); - } - else if (const ObjCCategoryDecl *CD = dyn_cast(OCD)) { + } else if (const ObjCCategoryDecl *CD = dyn_cast(OCD)) { for (const auto *P : CD->protocols()) PushProtocolProperties(PropertySet, Properties, P, IsClassProperty); } @@ -3270,7 +3190,7 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); unsigned propertySize = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy); ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(); @@ -3295,16 +3215,15 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, return GV; } -llvm::Constant * -CGObjCCommonMac::EmitProtocolMethodTypes(Twine Name, - ArrayRef MethodTypes, - const ObjCCommonTypesHelper &ObjCTypes) { +llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes( + Twine Name, ArrayRef MethodTypes, + const ObjCCommonTypesHelper &ObjCTypes) { // Return null for empty list. if (MethodTypes.empty()) return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy); - llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.Int8PtrTy, - MethodTypes.size()); + llvm::ArrayType *AT = + llvm::ArrayType::get(ObjCTypes.Int8PtrTy, MethodTypes.size()); llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes); StringRef Section; @@ -3337,20 +3256,16 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // @implementation so everyone else can live life under a clear blue sky. const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); const ObjCCategoryDecl *Category = - Interface->FindCategoryDeclaration(OCD->getIdentifier()); + Interface->FindCategoryDeclaration(OCD->getIdentifier()); SmallString<256> ExtName; - llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' - << OCD->getName(); + llvm::raw_svector_ostream(ExtName) + << Interface->getName() << '_' << OCD->getName(); ConstantInitBuilder Builder(CGM); auto Values = Builder.beginStruct(ObjCTypes.CategoryTy); - enum { - InstanceMethods, - ClassMethods, - NumMethodLists - }; + enum { InstanceMethods, ClassMethods, NumMethodLists }; SmallVector Methods[NumMethodLists]; for (const auto *MD : OCD->methods()) { if (!MD->isDirectMethod()) @@ -3366,9 +3281,9 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods, Methods[ClassMethods])); if (Category) { - Values.add( - EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), - Category->protocol_begin(), Category->protocol_end())); + Values.add(EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(), + Category->protocol_begin(), + Category->protocol_end())); } else { Values.addNullPointer(ObjCTypes.ProtocolListPtrTy); } @@ -3376,25 +3291,25 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { // If there is no category @interface then there can be no properties. if (Category) { - Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), - OCD, Category, ObjCTypes, false)); - Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), - OCD, Category, ObjCTypes, true)); + Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), OCD, + Category, ObjCTypes, false)); + Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD, + Category, ObjCTypes, true)); } else { Values.addNullPointer(ObjCTypes.PropertyListPtrTy); Values.addNullPointer(ObjCTypes.PropertyListPtrTy); } - llvm::GlobalVariable *GV = - CreateMetadataVar("OBJC_CATEGORY_" + ExtName.str(), Values, - "__OBJC,__category,regular,no_dead_strip", - CGM.getPointerAlign(), true); + llvm::GlobalVariable *GV = CreateMetadataVar( + "OBJC_CATEGORY_" + ExtName.str(), Values, + "__OBJC,__category,regular,no_dead_strip", CGM.getPointerAlign(), true); DefinedCategories.push_back(GV); DefinedCategoryNames.insert(llvm::CachedHashString(ExtName)); // method definition entries must be clear for next implementation. MethodDefinitions.clear(); } +// clang-format off enum FragileClassFlags { /// Apparently: is not a meta-class. FragileABI_Class_Factory = 0x00001, @@ -3445,6 +3360,7 @@ enum NonFragileClassFlags { /// Exclusive with CompiledByARC. NonFragileABI_Class_HasMRCWeakIvars = 0x00200, }; +// clang-format on static bool hasWeakMember(QualType type) { if (type.getObjCLifetime() == Qualifiers::OCL_Weak) { @@ -3466,11 +3382,12 @@ static bool hasWeakMember(QualType type) { /// __weak ivars. static bool hasMRCWeakIvars(CodeGenModule &CGM, const ObjCImplementationDecl *ID) { - if (!CGM.getLangOpts().ObjCWeak) return false; + if (!CGM.getLangOpts().ObjCWeak) + return false; assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); for (const ObjCIvarDecl *ivar = - ID->getClassInterface()->all_declared_ivar_begin(); + ID->getClassInterface()->all_declared_ivar_begin(); ivar; ivar = ivar->getNextIvar()) { if (hasWeakMember(ivar->getType())) return true; @@ -3506,7 +3423,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { std::string ClassName = ID->getNameAsString(); // FIXME: Gross ObjCInterfaceDecl *Interface = - const_cast(ID->getClassInterface()); + const_cast(ID->getClassInterface()); llvm::Constant *Protocols = EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(), Interface->all_referenced_protocol_begin(), @@ -3523,17 +3440,13 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { Flags |= FragileABI_Class_HasMRCWeakIvars; CharUnits Size = - CGM.getContext().getASTObjCImplementationLayout(ID).getSize(); + CGM.getContext().getASTObjCImplementationLayout(ID).getSize(); // FIXME: Set CXX-structors flag. if (ID->getClassInterface()->getVisibility() == HiddenVisibility) Flags |= FragileABI_Class_Hidden; - enum { - InstanceMethods, - ClassMethods, - NumMethodLists - }; + enum { InstanceMethods, ClassMethods, NumMethodLists }; SmallVector Methods[NumMethodLists]; for (const auto *MD : ID->methods()) { if (!MD->isDirectMethod()) @@ -3599,9 +3512,10 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { MethodDefinitions.clear(); } -llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, - llvm::Constant *Protocols, - ArrayRef Methods) { +llvm::Constant * +CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, + llvm::Constant *Protocols, + ArrayRef Methods) { unsigned Flags = FragileABI_Class_Meta; unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy); @@ -3629,16 +3543,16 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, values.addInt(ObjCTypes.LongTy, Flags); values.addInt(ObjCTypes.LongTy, Size); values.add(EmitIvarList(ID, true)); - values.add(emitMethodList(ID->getName(), MethodListType::ClassMethods, - Methods)); + values.add( + emitMethodList(ID->getName(), MethodListType::ClassMethods, Methods)); // cache is always NULL. values.addNullPointer(ObjCTypes.CachePtrTy); values.add(Protocols); // ivar_layout for metaclass is always NULL. values.addNullPointer(ObjCTypes.Int8PtrTy); // The class extension is used to store class properties for metaclasses. - values.add(EmitClassExtension(ID, CharUnits::Zero(), false/*hasMRCWeak*/, - /*isMetaclass*/true)); + values.add(EmitClassExtension(ID, CharUnits::Zero(), false /*hasMRCWeak*/, + /*isMetaclass*/ true)); std::string Name("OBJC_METACLASS_"); Name += ID->getName(); @@ -3707,10 +3621,10 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { struct _objc_property_list *properties; }; */ -llvm::Constant * -CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, - CharUnits InstanceSize, bool hasMRCWeakIvars, - bool isMetaclass) { +llvm::Constant *CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, + CharUnits InstanceSize, + bool hasMRCWeakIvars, + bool isMetaclass) { // Weak ivar layout. llvm::Constant *layout; if (isMetaclass) { @@ -3722,10 +3636,10 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, // Properties. llvm::Constant *propertyList = - EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_") - : Twine("_OBJC_$_PROP_LIST_")) - + ID->getName(), - ID, ID->getClassInterface(), ObjCTypes, isMetaclass); + EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_") + : Twine("_OBJC_$_PROP_LIST_")) + + ID->getName(), + ID, ID->getClassInterface(), ObjCTypes, isMetaclass); // Return null if no extension bits are used. if (layout->isNullValue() && propertyList->isNullValue()) { @@ -3733,7 +3647,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID, } uint64_t size = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy); ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy); @@ -3775,8 +3689,8 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID, auto countSlot = ivarList.addPlaceholder(); auto ivars = ivarList.beginArray(ObjCTypes.IvarTy); - for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) { + for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD; + IVD = IVD->getNextIvar()) { // Ignore unnamed bit-fields. if (!IVD->getDeclName()) continue; @@ -3852,8 +3766,9 @@ void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder, /// int count; /// struct objc_method_description list[count]; /// }; -llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT, - ArrayRef methods) { +llvm::Constant * +CGObjCMac::emitMethodList(Twine name, MethodListType MLT, + ArrayRef methods) { StringRef prefix; StringRef section; bool forProtocol = false; @@ -3902,9 +3817,9 @@ llvm::Constant *CGObjCMac::emitMethodList(Twine name, MethodListType MLT, // Return null for empty list. if (methods.empty()) - return llvm::Constant::getNullValue(forProtocol - ? ObjCTypes.MethodDescriptionListPtrTy - : ObjCTypes.MethodListPtrTy); + return llvm::Constant::getNullValue( + forProtocol ? ObjCTypes.MethodDescriptionListPtrTy + : ObjCTypes.MethodListPtrTy); // For protocols, this is an objc_method_description_list, which has // a slightly different structure. @@ -3952,9 +3867,8 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD, CodeGenTypes &Types = CGM.getTypes(); llvm::FunctionType *MethodTy = Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); - Method = - llvm::Function::Create(MethodTy, llvm::GlobalValue::InternalLinkage, - Name, &CGM.getModule()); + Method = llvm::Function::Create( + MethodTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); } MethodDefinitions.insert(std::make_pair(OMD, Method)); @@ -3986,7 +3900,7 @@ CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD, CodeGenTypes &Types = CGM.getTypes(); llvm::FunctionType *MethodTy = - Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); + Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD)); if (OldFn) { Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage, @@ -4096,11 +4010,10 @@ void CGObjCCommonMac::GenerateDirectMethodPrologue( } } -llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name, - ConstantStructBuilder &Init, - StringRef Section, - CharUnits Align, - bool AddToUsed) { +llvm::GlobalVariable * +CGObjCCommonMac::CreateMetadataVar(Twine Name, ConstantStructBuilder &Init, + StringRef Section, CharUnits Align, + bool AddToUsed) { llvm::GlobalValue::LinkageTypes LT = getLinkageTypeForObjCMetadata(CGM, Section); llvm::GlobalVariable *GV = @@ -4136,10 +4049,18 @@ CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type, bool NullTerminate) { StringRef Label; switch (Type) { - case ObjCLabelType::ClassName: Label = "OBJC_CLASS_NAME_"; break; - case ObjCLabelType::MethodVarName: Label = "OBJC_METH_VAR_NAME_"; break; - case ObjCLabelType::MethodVarType: Label = "OBJC_METH_VAR_TYPE_"; break; - case ObjCLabelType::PropertyName: Label = "OBJC_PROP_NAME_ATTR_"; break; + case ObjCLabelType::ClassName: + Label = "OBJC_CLASS_NAME_"; + break; + case ObjCLabelType::MethodVarName: + Label = "OBJC_METH_VAR_NAME_"; + break; + case ObjCLabelType::MethodVarType: + Label = "OBJC_METH_VAR_TYPE_"; + break; + case ObjCLabelType::PropertyName: + Label = "OBJC_PROP_NAME_ATTR_"; + break; } bool NonFragile = ForceNonFragileABI || isNonFragileABI(); @@ -4166,10 +4087,9 @@ CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type, llvm::Constant *Value = llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate); - llvm::GlobalVariable *GV = - new llvm::GlobalVariable(CGM.getModule(), Value->getType(), - /*isConstant=*/true, - llvm::GlobalValue::PrivateLinkage, Value, Label); + llvm::GlobalVariable *GV = new llvm::GlobalVariable( + CGM.getModule(), Value->getType(), + /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Value, Label); if (CGM.getTriple().isOSBinFormatMachO()) GV->setSection(Section); GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); @@ -4228,85 +4148,84 @@ void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF, } namespace { - struct PerformFragileFinally final : EHScopeStack::Cleanup { - const Stmt &S; - Address SyncArgSlot; - Address CallTryExitVar; - Address ExceptionData; - ObjCTypesHelper &ObjCTypes; - PerformFragileFinally(const Stmt *S, - Address SyncArgSlot, - Address CallTryExitVar, - Address ExceptionData, - ObjCTypesHelper *ObjCTypes) +struct PerformFragileFinally final : EHScopeStack::Cleanup { + const Stmt &S; + Address SyncArgSlot; + Address CallTryExitVar; + Address ExceptionData; + ObjCTypesHelper &ObjCTypes; + PerformFragileFinally(const Stmt *S, Address SyncArgSlot, + Address CallTryExitVar, Address ExceptionData, + ObjCTypesHelper *ObjCTypes) : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar), ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - // Check whether we need to call objc_exception_try_exit. - // In optimized code, this branch will always be folded. - llvm::BasicBlock *FinallyCallExit = + void Emit(CodeGenFunction &CGF, Flags flags) override { + // Check whether we need to call objc_exception_try_exit. + // In optimized code, this branch will always be folded. + llvm::BasicBlock *FinallyCallExit = CGF.createBasicBlock("finally.call_exit"); - llvm::BasicBlock *FinallyNoCallExit = + llvm::BasicBlock *FinallyNoCallExit = CGF.createBasicBlock("finally.no_call_exit"); - CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), - FinallyCallExit, FinallyNoCallExit); + CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar), + FinallyCallExit, FinallyNoCallExit); - CGF.EmitBlock(FinallyCallExit); - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), - ExceptionData.emitRawPointer(CGF)); + CGF.EmitBlock(FinallyCallExit); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(), + ExceptionData.emitRawPointer(CGF)); - CGF.EmitBlock(FinallyNoCallExit); + CGF.EmitBlock(FinallyNoCallExit); - if (isa(S)) { - if (const ObjCAtFinallyStmt* FinallyStmt = + if (isa(S)) { + if (const ObjCAtFinallyStmt *FinallyStmt = cast(S).getFinallyStmt()) { - // Don't try to do the @finally if this is an EH cleanup. - if (flags.isForEHCleanup()) return; + // Don't try to do the @finally if this is an EH cleanup. + if (flags.isForEHCleanup()) + return; - // Save the current cleanup destination in case there's - // control flow inside the finally statement. - llvm::Value *CurCleanupDest = + // Save the current cleanup destination in case there's + // control flow inside the finally statement. + llvm::Value *CurCleanupDest = CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot()); - CGF.EmitStmt(FinallyStmt->getFinallyBody()); + CGF.EmitStmt(FinallyStmt->getFinallyBody()); - if (CGF.HaveInsertPoint()) { - CGF.Builder.CreateStore(CurCleanupDest, - CGF.getNormalCleanupDestSlot()); - } else { - // Currently, the end of the cleanup must always exist. - CGF.EnsureInsertPoint(); - } + if (CGF.HaveInsertPoint()) { + CGF.Builder.CreateStore(CurCleanupDest, + CGF.getNormalCleanupDestSlot()); + } else { + // Currently, the end of the cleanup must always exist. + CGF.EnsureInsertPoint(); } - } else { - // Emit objc_sync_exit(expr); as finally's sole statement for - // @synchronized. - llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot); - CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg); } + } else { + // Emit objc_sync_exit(expr); as finally's sole statement for + // @synchronized. + llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg); } - }; + } +}; - class FragileHazards { - CodeGenFunction &CGF; - SmallVector Locals; - llvm::DenseSet BlocksBeforeTry; +class FragileHazards { + CodeGenFunction &CGF; + SmallVector Locals; + llvm::DenseSet BlocksBeforeTry; - llvm::InlineAsm *ReadHazard; - llvm::InlineAsm *WriteHazard; + llvm::InlineAsm *ReadHazard; + llvm::InlineAsm *WriteHazard; - llvm::FunctionType *GetAsmFnType(); + llvm::FunctionType *GetAsmFnType(); - void collectLocals(); - void emitReadHazard(CGBuilderTy &Builder); + void collectLocals(); + void emitReadHazard(CGBuilderTy &Builder); - public: - FragileHazards(CodeGenFunction &CGF); +public: + FragileHazards(CodeGenFunction &CGF); - void emitWriteHazard(); - void emitHazardsInNewBlocks(); - }; + void emitWriteHazard(); + void emitHazardsInNewBlocks(); +}; } // end anonymous namespace /// Create the fragile-ABI read and write hazards based on the current @@ -4317,11 +4236,12 @@ namespace { FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { collectLocals(); - if (Locals.empty()) return; + if (Locals.empty()) + return; // Collect all the blocks in the function. - for (llvm::Function::iterator - I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I) + for (llvm::Function::iterator I = CGF.CurFn->begin(), E = CGF.CurFn->end(); + I != E; ++I) BlocksBeforeTry.insert(&*I); llvm::FunctionType *AsmFnTy = GetAsmFnType(); @@ -4334,7 +4254,8 @@ FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { { std::string Constraint; for (unsigned I = 0, E = Locals.size(); I != E; ++I) { - if (I) Constraint += ','; + if (I) + Constraint += ','; Constraint += "*m"; } @@ -4348,7 +4269,8 @@ FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { { std::string Constraint; for (unsigned I = 0, E = Locals.size(); I != E; ++I) { - if (I) Constraint += ','; + if (I) + Constraint += ','; Constraint += "=*m"; } @@ -4358,13 +4280,16 @@ FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) { /// Emit a write hazard at the current location. void FragileHazards::emitWriteHazard() { - if (Locals.empty()) return; + if (Locals.empty()) + return; llvm::CallInst *Call = CGF.EmitNounwindRuntimeCall(WriteHazard, Locals); for (auto Pair : llvm::enumerate(Locals)) - Call->addParamAttr(Pair.index(), llvm::Attribute::get( - CGF.getLLVMContext(), llvm::Attribute::ElementType, - cast(Pair.value())->getAllocatedType())); + Call->addParamAttr( + Pair.index(), + llvm::Attribute::get( + CGF.getLLVMContext(), llvm::Attribute::ElementType, + cast(Pair.value())->getAllocatedType())); } void FragileHazards::emitReadHazard(CGBuilderTy &Builder) { @@ -4373,27 +4298,31 @@ void FragileHazards::emitReadHazard(CGBuilderTy &Builder) { call->setDoesNotThrow(); call->setCallingConv(CGF.getRuntimeCC()); for (auto Pair : llvm::enumerate(Locals)) - call->addParamAttr(Pair.index(), llvm::Attribute::get( - Builder.getContext(), llvm::Attribute::ElementType, - cast(Pair.value())->getAllocatedType())); + call->addParamAttr( + Pair.index(), + llvm::Attribute::get( + Builder.getContext(), llvm::Attribute::ElementType, + cast(Pair.value())->getAllocatedType())); } /// Emit read hazards in all the protected blocks, i.e. all the blocks /// which have been inserted since the beginning of the try. void FragileHazards::emitHazardsInNewBlocks() { - if (Locals.empty()) return; + if (Locals.empty()) + return; CGBuilderTy Builder(CGF, CGF.getLLVMContext()); // Iterate through all blocks, skipping those prior to the try. - for (llvm::Function::iterator - FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) { + for (llvm::Function::iterator FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); + FI != FE; ++FI) { llvm::BasicBlock &BB = *FI; - if (BlocksBeforeTry.count(&BB)) continue; + if (BlocksBeforeTry.count(&BB)) + continue; // Walk through all the calls in the block. - for (llvm::BasicBlock::iterator - BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) { + for (llvm::BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE; + ++BI) { llvm::Instruction &I = *BI; // Ignore instructions that aren't non-intrinsic calls. @@ -4419,7 +4348,7 @@ void FragileHazards::emitHazardsInNewBlocks() { } } -static void addIfPresent(llvm::DenseSet &S, Address V) { +static void addIfPresent(llvm::DenseSet &S, Address V) { if (V.isValid()) if (llvm::Value *Ptr = V.getBasePointer()) S.insert(Ptr); @@ -4427,15 +4356,15 @@ static void addIfPresent(llvm::DenseSet &S, Address V) { void FragileHazards::collectLocals() { // Compute a set of allocas to ignore. - llvm::DenseSet AllocasToIgnore; + llvm::DenseSet AllocasToIgnore; addIfPresent(AllocasToIgnore, CGF.ReturnValue); addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest); // Collect all the allocas currently in the function. This is // probably way too aggressive. llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock(); - for (llvm::BasicBlock::iterator - I = Entry.begin(), E = Entry.end(); I != E; ++I) + for (llvm::BasicBlock::iterator I = Entry.begin(), E = Entry.end(); I != E; + ++I) if (isa(*I) && !AllocasToIgnore.count(&*I)) Locals.push_back(&*I); } @@ -4562,12 +4491,12 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // A destination for the fall-through edges of the catch handlers to // jump to. CodeGenFunction::JumpDest FinallyEnd = - CGF.getJumpDestInCurrentScope("finally.end"); + CGF.getJumpDestInCurrentScope("finally.end"); // A destination for the rethrow edge of the catch handlers to jump // to. CodeGenFunction::JumpDest FinallyRethrow = - CGF.getJumpDestInCurrentScope("finally.rethrow"); + CGF.getJumpDestInCurrentScope("finally.rethrow"); // For @synchronized, call objc_sync_enter(sync.expr). The // evaluation of the expression must occur before we enter the @@ -4577,7 +4506,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, Address SyncArgSlot = Address::invalid(); if (!isTry) { llvm::Value *SyncArg = - CGF.EmitScalarExpr(cast(S).getSynchExpr()); + CGF.EmitScalarExpr(cast(S).getSynchExpr()); SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy); CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg); @@ -4588,9 +4517,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Allocate memory for the setjmp buffer. This needs to be kept // live throughout the try and catch blocks. - Address ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy, - CGF.getPointerAlign(), - "exceptiondata.ptr"); + Address ExceptionData = CGF.CreateTempAlloca( + ObjCTypes.ExceptionDataTy, CGF.getPointerAlign(), "exceptiondata.ptr"); // Create the fragile hazards. Note that this will not capture any // of the allocas required for exception processing, but will @@ -4606,9 +4534,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // The setjmp-safety rule here is that we should always store to this // variable in a place that dominates the branch through the cleanup // without passing through any setjmps. - Address CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), - CharUnits::One(), - "_call_try_exit"); + Address CallTryExitVar = CGF.CreateTempAlloca( + CGF.Builder.getInt1Ty(), CharUnits::One(), "_call_try_exit"); // A slot containing the exception to rethrow. Only needed when we // have both a @catch and a @finally. @@ -4616,10 +4543,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Push a normal cleanup to leave the try scope. CGF.EHStack.pushCleanup(NormalAndEHCleanup, &S, - SyncArgSlot, - CallTryExitVar, - ExceptionData, - &ObjCTypes); + SyncArgSlot, CallTryExitVar, + ExceptionData, &ObjCTypes); // Enter a try block: // - Call objc_exception_try_enter to push ExceptionData on top of @@ -4629,7 +4554,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // - Call setjmp on the exception data buffer. llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0); - llvm::Value *GEPIndexes[] = { Zero, Zero, Zero }; + llvm::Value *GEPIndexes[] = {Zero, Zero, Zero}; llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP( ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes, "setjmp_buffer"); @@ -4642,7 +4567,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); llvm::Value *DidCatch = - CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); + CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock); // Emit the protected block. @@ -4678,7 +4603,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // benefit of any @throws in the handlers. CGF.ObjCEHValueStack.push_back(Caught); - const ObjCAtTryStmt* AtTryStmt = cast(&S); + const ObjCAtTryStmt *AtTryStmt = cast(&S); bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr); @@ -4687,9 +4612,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, if (HasFinally) { // Save the currently-propagating exception before // objc_exception_try_enter clears the exception slot. - PropagatingExnVar = CGF.CreateTempAlloca(Caught->getType(), - CGF.getPointerAlign(), - "propagating_exception"); + PropagatingExnVar = CGF.CreateTempAlloca( + Caught->getType(), CGF.getPointerAlign(), "propagating_exception"); CGF.Builder.CreateStore(Caught, PropagatingExnVar); // Enter a new exception try block (in case a @catch block @@ -4697,13 +4621,12 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData.emitRawPointer(CGF)); - llvm::CallInst *SetJmpResult = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getSetJmpFn(), - SetJmpBuffer, "setjmp.result"); + llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp.result"); SetJmpResult->setCanReturnTwice(); llvm::Value *Threw = - CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); + CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); CatchBlock = CGF.createBasicBlock("catch"); CatchHandler = CGF.createBasicBlock("catch_for_catch"); @@ -4767,10 +4690,9 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Check if the @catch block matches the exception object. llvm::Value *Class = EmitClassRef(CGF, IDecl); - llvm::Value *matchArgs[] = { Class, Caught }; - llvm::CallInst *Match = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionMatchFn(), - matchArgs, "match"); + llvm::Value *matchArgs[] = {Class, Caught}; + llvm::CallInst *Match = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getExceptionMatchFn(), matchArgs, "match"); llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match"); llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next"); @@ -4789,9 +4711,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?"); // Initialize the catch variable. - llvm::Value *Tmp = - CGF.Builder.CreateBitCast(Caught, - CGF.ConvertType(CatchParam->getType())); + llvm::Value *Tmp = CGF.Builder.CreateBitCast( + Caught, CGF.ConvertType(CatchParam->getType())); EmitInitOfCatchParam(CGF, Tmp, CatchParam); CGF.EmitStmt(CatchStmt->getCatchBody()); @@ -4821,7 +4742,7 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // In theory we might now need a write hazard, but actually it's // unnecessary because there's no local-accessing code between // the try's write hazard and here. - //Hazards.emitWriteHazard(); + // Hazards.emitWriteHazard(); // Extract the new exception and save it to the // propagating-exception slot. @@ -4879,7 +4800,7 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, if (const Expr *ThrowExpr = S.getThrowExpr()) { llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr); ExceptionAsObject = - CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); + CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy); } else { assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) && "Unexpected rethrow outside @catch block."); @@ -4887,7 +4808,7 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, } CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject) - ->setDoesNotReturn(); + ->setDoesNotReturn(); CGF.Builder.CreateUnreachable(); // Clear the insertion point to indicate we are in unreachable code. @@ -4898,14 +4819,13 @@ void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, /// EmitObjCWeakRead - Code gen for loading value of a __weak /// object: objc_read_weak (id *src) /// -llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) { - llvm::Type* DestTy = AddrWeakObj.getElementType(); +llvm::Value *CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, + Address AddrWeakObj) { + llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); - llvm::Value *read_weak = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), - AddrWeakObjVal, "weakread"); + llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); return read_weak; } @@ -4915,7 +4835,7 @@ llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, /// void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); @@ -4926,9 +4846,9 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); - llvm::Value *args[] = { src, dstVal }; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), - args, "weakassign"); + llvm::Value *args[] = {src, dstVal}; + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, + "weakassign"); } /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. @@ -4937,7 +4857,7 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst, bool threadlocal) { - llvm::Type * SrcTy = src->getType(); + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); @@ -4950,11 +4870,11 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), - args, "globalassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args, + "globalassign"); else - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), - args, "threadlocalassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args, + "threadlocalassign"); } /// EmitObjCIvarAssign - Code gen for assigning to a __strong object. @@ -4964,7 +4884,7 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst, llvm::Value *ivarOffset) { assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); - llvm::Type * SrcTy = src->getType(); + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); @@ -4984,7 +4904,7 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, /// void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); @@ -4996,8 +4916,8 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), - args, "strongassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, + "strongassign"); } void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, @@ -5016,7 +4936,7 @@ LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { const ObjCInterfaceDecl *ID = - ObjectTy->castAs()->getInterface(); + ObjectTy->castAs()->getInterface(); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, EmitIvarOffset(CGF, ID, Ivar)); } @@ -5026,8 +4946,7 @@ llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, const ObjCIvarDecl *Ivar) { uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar); return llvm::ConstantInt::get( - CGM.getTypes().ConvertType(CGM.getContext().LongTy), - Offset); + CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset); } /* *** Private Interface *** */ @@ -5060,6 +4979,7 @@ std::string CGObjCCommonMac::GetSectionName(StringRef Section, llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum"); } +// clang-format off /// EmitImageInfo - Emit the image info marker used to encode some module /// level information. /// @@ -5081,6 +5001,7 @@ enum ImageInfoFlags { eImageInfo_ImageIsSimulated = (1 << 5), eImageInfo_ClassProperties = (1 << 6) }; +// clang-format on void CGObjCCommonMac::EmitImageInfo() { unsigned version = 0; // Version is unused? @@ -5103,15 +5024,13 @@ void CGObjCCommonMac::EmitImageInfo() { auto Int8Ty = llvm::Type::getInt8Ty(VMContext); if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { // Non-GC overrides those files which specify GC. - Mod.addModuleFlag(llvm::Module::Error, - "Objective-C Garbage Collection", - llvm::ConstantInt::get(Int8Ty,0)); + Mod.addModuleFlag(llvm::Module::Error, "Objective-C Garbage Collection", + llvm::ConstantInt::get(Int8Ty, 0)); } else { // Add the ObjC garbage collection value. - Mod.addModuleFlag(llvm::Module::Error, - "Objective-C Garbage Collection", - llvm::ConstantInt::get(Int8Ty, - (uint8_t)eImageInfo_GarbageCollected)); + Mod.addModuleFlag( + llvm::Module::Error, "Objective-C Garbage Collection", + llvm::ConstantInt::get(Int8Ty, (uint8_t)eImageInfo_GarbageCollected)); if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) { // Add the ObjC GC Only value. @@ -5121,8 +5040,8 @@ void CGObjCCommonMac::EmitImageInfo() { // Require that GC be specified and set to eImageInfo_GarbageCollected. llvm::Metadata *Ops[2] = { llvm::MDString::get(VMContext, "Objective-C Garbage Collection"), - llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - Int8Ty, eImageInfo_GarbageCollected))}; + llvm::ConstantAsMetadata::get( + llvm::ConstantInt::get(Int8Ty, eImageInfo_GarbageCollected))}; Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only", llvm::MDNode::get(VMContext, Ops)); } @@ -5181,7 +5100,7 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() { // The runtime expects exactly the list of defined classes followed // by the list of defined categories, in a single array. auto array = values.beginArray(ObjCTypes.Int8PtrTy); - for (unsigned i=0; igetImplementation()) @@ -5191,7 +5110,7 @@ llvm::Constant *CGObjCMac::EmitModuleSymbols() { array.add(DefinedClasses[i]); } - for (unsigned i=0; igetDecl(); // If this is a union, remember that we had one, because it might mess @@ -5284,11 +5203,12 @@ void IvarLayoutBuilder::visitRecord(const RecordType *RT, const ASTRecordLayout *recLayout = nullptr; visitAggregate(RD->field_begin(), RD->field_end(), offset, [&](const FieldDecl *field) -> CharUnits { - if (!recLayout) - recLayout = &CGM.getContext().getASTRecordLayout(RD); - auto offsetInBits = recLayout->getFieldOffset(field->getFieldIndex()); - return CGM.getContext().toCharUnitsFromBits(offsetInBits); - }); + if (!recLayout) + recLayout = &CGM.getContext().getASTRecordLayout(RD); + auto offsetInBits = + recLayout->getFieldOffset(field->getFieldIndex()); + return CGM.getContext().toCharUnitsFromBits(offsetInBits); + }); } template @@ -5331,7 +5251,8 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field, // If we ended up with a zero-sized array, we've done what we can do within // the limits of this layout encoding. - if (numElts == 0) return; + if (numElts == 0) + return; // Recurse if the base element type is a record type. if (auto recType = fieldType->getAs()) { @@ -5361,10 +5282,10 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field, Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType); // If it matches what we're looking for, add an entry. - if ((ForStrongLayout && GCAttr == Qualifiers::Strong) - || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { - assert(CGM.getContext().getTypeSizeInChars(fieldType) - == CGM.getPointerSize()); + if ((ForStrongLayout && GCAttr == Qualifiers::Strong) || + (!ForStrongLayout && GCAttr == Qualifiers::Weak)) { + assert(CGM.getContext().getTypeSizeInChars(fieldType) == + CGM.getPointerSize()); IvarsInfo.push_back(IvarInfo(fieldOffset, numElts)); } } @@ -5372,8 +5293,9 @@ void IvarLayoutBuilder::visitField(const FieldDecl *field, /// buildBitmap - This routine does the horsework of taking the offsets of /// strong/weak references and creating a bitmap. The bitmap is also /// returned in the given buffer, suitable for being passed to \c dump(). -llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, - llvm::SmallVectorImpl &buffer) { +llvm::Constant * +IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, + llvm::SmallVectorImpl &buffer) { // The bitmap is a series of skip/scan instructions, aligned to word // boundaries. The skip is performed first. const unsigned char MaxNibble = 0xF; @@ -5454,7 +5376,8 @@ llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, // Ignore scan requests that don't start at an even multiple of the // word size. We can't encode them. - if ((beginOfScan % WordSize) != 0) continue; + if ((beginOfScan % WordSize) != 0) + continue; // Ignore scan requests that start before the instance start. // This assumes that scans never span that boundary. The boundary @@ -5479,7 +5402,8 @@ llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, beginOfScanInWords = endOfLastScanInWords; // If that leaves us with nothing to scan, ignore this request. - if (beginOfScanInWords >= endOfScanInWords) continue; + if (beginOfScanInWords >= endOfScanInWords) + continue; } // Scan to the end of the request. @@ -5496,7 +5420,7 @@ llvm::Constant *IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC, // or necessary for the ARC-style layout strings. if (CGM.getLangOpts().getGC() != LangOptions::NonGC) { unsigned lastOffsetInWords = - (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize; + (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize; if (lastOffsetInWords > endOfLastScanInWords) { skip(lastOffsetInWords - endOfLastScanInWords); } @@ -5539,7 +5463,7 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, return llvm::Constant::getNullValue(PtrTy); const ObjCInterfaceDecl *OI = OMD->getClassInterface(); - SmallVector ivars; + SmallVector ivars; // GC layout strings include the complete object layout, possibly // inaccurately in the non-fragile ABI; the runtime knows how to fix this @@ -5553,22 +5477,21 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, // MRC weak layout strings follow the ARC style. CharUnits baseOffset; if (CGM.getLangOpts().getGC() == LangOptions::NonGC) { - for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) + for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); IVD; + IVD = IVD->getNextIvar()) ivars.push_back(IVD); if (isNonFragileABI()) { baseOffset = beginOffset; // InstanceStart } else if (!ivars.empty()) { baseOffset = - CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0])); + CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0])); } else { baseOffset = CharUnits::Zero(); } baseOffset = baseOffset.alignTo(CGM.getPointerAlign()); - } - else { + } else { CGM.getContext().DeepCollectObjCIvars(OI, true, ivars); baseOffset = CharUnits::Zero(); @@ -5581,8 +5504,9 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(), [&](const ObjCIvarDecl *ivar) -> CharUnits { - return CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivar)); - }); + return CharUnits::fromQuantity( + ComputeIvarBaseOffset(CGM, OMD, ivar)); + }); if (!builder.hasBitmapData()) return llvm::Constant::getNullValue(PtrTy); @@ -5590,7 +5514,7 @@ CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD, llvm::SmallVector buffer; llvm::Constant *C = builder.buildBitmap(*this, buffer); - if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) { + if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) { printf("\n%s ivar layout for class '%s': ", ForStrongLayout ? "strong" : "weak", OMD->getClassInterface()->getName().str().c_str()); @@ -5603,7 +5527,8 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) { llvm::GlobalVariable *&Entry = MethodVarNames[Sel]; // FIXME: Avoid std::string in "Sel.getAsString()" if (!Entry) - Entry = CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName); + Entry = + CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName); return getConstantGEP(VMContext, Entry, 0, 0); } @@ -5625,7 +5550,7 @@ llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) { llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D, bool Extended) { std::string TypeStr = - CGM.getContext().getObjCEncodingForMethodDecl(D, Extended); + CGM.getContext().getObjCEncodingForMethodDecl(D, Extended); llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr]; if (!Entry) @@ -5647,7 +5572,7 @@ llvm::Constant * CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD, const Decl *Container) { std::string TypeStr = - CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container); + CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container); return GetPropertyName(&CGM.getContext().Idents.get(TypeStr)); } @@ -5707,8 +5632,8 @@ CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm) /* *** */ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) - : VMContext(cgm.getLLVMContext()), CGM(cgm), ExternalProtocolPtrTy(nullptr) -{ + : VMContext(cgm.getLLVMContext()), CGM(cgm), + ExternalProtocolPtrTy(nullptr) { CodeGen::CodeGenTypes &Types = CGM.getTypes(); ASTContext &Ctx = CGM.getContext(); unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace(); @@ -5727,12 +5652,10 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) else IvarOffsetVarTy = LongTy; - ObjectPtrTy = - cast(Types.ConvertType(Ctx.getObjCIdType())); - PtrObjectPtrTy = - llvm::PointerType::getUnqual(ObjectPtrTy); + ObjectPtrTy = cast(Types.ConvertType(Ctx.getObjCIdType())); + PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy); SelectorPtrTy = - cast(Types.ConvertType(Ctx.getObjCSelType())); + cast(Types.ConvertType(Ctx.getObjCSelType())); // I'm not sure I like this. The implicit coordination is a bit // gross. We should solve this in a reasonable fashion because this @@ -5793,7 +5716,7 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) } ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) - : ObjCCommonTypesHelper(cgm) { + : ObjCCommonTypesHelper(cgm) { // struct _objc_method_description { // SEL name; // char *types; @@ -5811,7 +5734,7 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) // struct _objc_method_description_list * MethodDescriptionListPtrTy = - llvm::PointerType::getUnqual(MethodDescriptionListTy); + llvm::PointerType::getUnqual(MethodDescriptionListTy); // Protocol description structures @@ -5867,13 +5790,12 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) IntTy); // struct _objc_ivar_list * - IvarListTy = - llvm::StructType::create(VMContext, "struct._objc_ivar_list"); + IvarListTy = llvm::StructType::create(VMContext, "struct._objc_ivar_list"); IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy); // struct _objc_method_list * MethodListTy = - llvm::StructType::create(VMContext, "struct._objc_method_list"); + llvm::StructType::create(VMContext, "struct._objc_method_list"); MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy); // struct _objc_class_extension * @@ -5954,8 +5876,9 @@ ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm) llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy); } -ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm) - : ObjCCommonTypesHelper(cgm) { +ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper( + CodeGen::CodeGenModule &cgm) + : ObjCCommonTypesHelper(cgm) { // struct _method_list_t { // uint32_t entsize; // sizeof(struct _objc_method) // uint32_t method_count; @@ -6122,7 +6045,6 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t* SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy); - // struct objc_typeinfo { // const void** vtable; // objc_ehtype_vtable + 2 // const char* name; // c++ typeinfo string @@ -6148,14 +6070,12 @@ void CGObjCNonFragileABIMac::AddModuleClassList( if (!NumClasses) return; - SmallVector Symbols(NumClasses); - for (unsigned i=0; i Symbols(NumClasses); + for (unsigned i = 0; i < NumClasses; i++) Symbols[i] = Container[i]; - llvm::Constant *Init = - llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy, - Symbols.size()), - Symbols); + llvm::Constant *Init = llvm::ConstantArray::get( + llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Symbols.size()), Symbols); // Section name is obtained by calling GetSectionName, which returns // sections in the __DATA segment on MachO. @@ -6176,36 +6096,37 @@ void CGObjCNonFragileABIMac::FinishNonFragileABIModule() { // Build list of all implemented class addresses in array // L_OBJC_LABEL_CLASS_$. - for (unsigned i=0, NumClasses=ImplementedClasses.size(); igetImplementation()) // We are implementing a weak imported interface. Give it external linkage if (ID->isWeakImported() && !IMP->isWeakImported()) { DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); - DefinedMetaClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage); + DefinedMetaClasses[i]->setLinkage( + llvm::GlobalVariable::ExternalLinkage); } } - AddModuleClassList(DefinedClasses, "OBJC_LABEL_CLASS_$", - GetSectionName("__objc_classlist", - "regular,no_dead_strip")); + AddModuleClassList( + DefinedClasses, "OBJC_LABEL_CLASS_$", + GetSectionName("__objc_classlist", "regular,no_dead_strip")); - AddModuleClassList(DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$", - GetSectionName("__objc_nlclslist", - "regular,no_dead_strip")); + AddModuleClassList( + DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$", + GetSectionName("__objc_nlclslist", "regular,no_dead_strip")); // Build list of all implemented category addresses in array // L_OBJC_LABEL_CATEGORY_$. AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$", - GetSectionName("__objc_catlist", - "regular,no_dead_strip")); - AddModuleClassList(DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$", - GetSectionName("__objc_catlist2", - "regular,no_dead_strip")); - AddModuleClassList(DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$", - GetSectionName("__objc_nlcatlist", - "regular,no_dead_strip")); + GetSectionName("__objc_catlist", "regular,no_dead_strip")); + AddModuleClassList( + DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$", + GetSectionName("__objc_catlist2", "regular,no_dead_strip")); + AddModuleClassList( + DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$", + GetSectionName("__objc_nlcatlist", "regular,no_dead_strip")); EmitImageInfo(); } @@ -6264,7 +6185,7 @@ bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) { &CGM.getContext().Idents.get("objects"), &CGM.getContext().Idents.get("count")}; VTableDispatchMethods.insert( - CGM.getContext().Selectors.getSelector(3, KeyIdents)); + CGM.getContext().Selectors.getSelector(3, KeyIdents)); } } @@ -6286,11 +6207,9 @@ bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) { /// const struct _prop_list_t * const properties; /// } /// -llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( - unsigned flags, - unsigned InstanceStart, - unsigned InstanceSize, - const ObjCImplementationDecl *ID) { +llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer( + unsigned flags, unsigned InstanceStart, unsigned InstanceSize, + const ObjCImplementationDecl *ID) { std::string ClassName = std::string(ID->getObjCRuntimeNameAsString()); CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart); @@ -6309,12 +6228,12 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( values.addInt(ObjCTypes.IntTy, InstanceStart); values.addInt(ObjCTypes.IntTy, InstanceSize); values.add((flags & NonFragileABI_Class_Meta) - ? GetIvarLayoutName(nullptr, ObjCTypes) - : BuildStrongIvarLayout(ID, beginInstance, endInstance)); + ? GetIvarLayoutName(nullptr, ObjCTypes) + : BuildStrongIvarLayout(ID, beginInstance, endInstance)); values.add(GetClassName(ID->getObjCRuntimeNameAsString())); // const struct _method_list_t * const baseMethods; - SmallVector methods; + SmallVector methods; if (flags & NonFragileABI_Class_Meta) { for (const auto *MD : ID->class_methods()) if (!MD->isDirectMethod()) @@ -6327,29 +6246,29 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( values.add(emitMethodList(ID->getObjCRuntimeNameAsString(), (flags & NonFragileABI_Class_Meta) - ? MethodListType::ClassMethods - : MethodListType::InstanceMethods, + ? MethodListType::ClassMethods + : MethodListType::InstanceMethods, methods)); const ObjCInterfaceDecl *OID = ID->getClassInterface(); assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); - values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_" - + OID->getObjCRuntimeNameAsString(), + values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_" + + OID->getObjCRuntimeNameAsString(), OID->all_referenced_protocol_begin(), OID->all_referenced_protocol_end())); if (flags & NonFragileABI_Class_Meta) { values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy); values.add(GetIvarLayoutName(nullptr, ObjCTypes)); - values.add(EmitPropertyList( - "_OBJC_$_CLASS_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), - ID, ID->getClassInterface(), ObjCTypes, true)); + values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + + ID->getObjCRuntimeNameAsString(), + ID, ID->getClassInterface(), ObjCTypes, true)); } else { values.add(EmitIvarList(ID)); values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak)); - values.add(EmitPropertyList( - "_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), - ID, ID->getClassInterface(), ObjCTypes, false)); + values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + + ID->getObjCRuntimeNameAsString(), + ID, ID->getClassInterface(), ObjCTypes, false)); } llvm::SmallString<64> roLabel; @@ -6371,13 +6290,10 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( /// struct class_ro_t *ro; /// } /// -llvm::GlobalVariable * -CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI, - bool isMetaclass, - llvm::Constant *IsAGV, - llvm::Constant *SuperClassGV, - llvm::Constant *ClassRoGV, - bool HiddenVisibility) { +llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassObject( + const ObjCInterfaceDecl *CI, bool isMetaclass, llvm::Constant *IsAGV, + llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV, + bool HiddenVisibility) { ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(ObjCTypes.ClassnfABITy); values.add(IsAGV); @@ -6390,8 +6306,8 @@ CGObjCNonFragileABIMac::BuildClassObject(const ObjCInterfaceDecl *CI, values.add(ObjCEmptyVtableVar); values.add(ClassRoGV); - llvm::GlobalVariable *GV = - cast(GetClassGlobal(CI, isMetaclass, ForDefinition)); + llvm::GlobalVariable *GV = cast( + GetClassGlobal(CI, isMetaclass, ForDefinition)); values.finishAndSetAsInitializer(GV); if (CGM.getTriple().isOSBinFormatMachO()) @@ -6414,7 +6330,7 @@ void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, uint32_t &InstanceStart, uint32_t &InstanceSize) { const ASTRecordLayout &RL = - CGM.getContext().getASTObjCImplementationLayout(OID); + CGM.getContext().getASTObjCImplementationLayout(OID); // InstanceSize is really instance end. InstanceSize = RL.getDataSize().getQuantity(); @@ -6448,27 +6364,26 @@ static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM, void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { if (!ObjCEmptyCacheVar) { - ObjCEmptyCacheVar = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "_objc_empty_cache"); + ObjCEmptyCacheVar = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.CacheTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_cache"); if (CGM.getTriple().isOSBinFormatCOFF()) - ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache")); + ObjCEmptyCacheVar->setDLLStorageClass( + getStorage(CGM, "_objc_empty_cache")); // Only OS X with deployment version <10.9 use the empty vtable symbol const llvm::Triple &Triple = CGM.getTarget().getTriple(); if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9)) - ObjCEmptyVtableVar = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "_objc_empty_vtable"); + ObjCEmptyVtableVar = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.ImpnfABITy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable"); else ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.UnqualPtrTy); } // FIXME: Is this correct (that meta class size is never computed)? uint32_t InstanceStart = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); uint32_t InstanceSize = InstanceStart; uint32_t flags = NonFragileABI_Class_Meta; @@ -6512,9 +6427,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID); - llvm::GlobalVariable *MetaTClass = - BuildClassObject(CI, /*metaclass*/ true, - IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden); + llvm::GlobalVariable *MetaTClass = BuildClassObject( + CI, /*metaclass*/ true, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden); CGM.setGVProperties(MetaTClass, CI); DefinedMetaClasses.push_back(MetaTClass); @@ -6553,8 +6467,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID); llvm::GlobalVariable *ClassMD = - BuildClassObject(CI, /*metaclass*/ false, - MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden); + BuildClassObject(CI, /*metaclass*/ false, MetaTClass, SuperClassGV, + CLASS_RO_GV, classIsHidden); CGM.setGVProperties(ClassMD, CI); DefinedClasses.push_back(ClassMD); ImplementedClasses.push_back(CI); @@ -6565,7 +6479,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { // Force the definition of the EHType if necessary. if (flags & NonFragileABI_Class_Exception) - (void) GetInterfaceEHType(CI, ForDefinition); + (void)GetInterfaceEHType(CI, ForDefinition); // Make sure method definition entries are all clear for next implementation. MethodDefinitions.clear(); } @@ -6578,8 +6492,9 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { /// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1 /// which will hold address of the protocol meta-data. /// -llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, - const ObjCProtocolDecl *PD) { +llvm::Value * +CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, + const ObjCProtocolDecl *PD) { // This routine is called for @protocol only. So, we must build definition // of protocol's meta-data (not a reference to it!) @@ -6598,8 +6513,8 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::WeakAnyLinkage, Init, ProtocolName); - PTGV->setSection(GetSectionName("__objc_protorefs", - "coalesced,no_dead_strip")); + PTGV->setSection( + GetSectionName("__objc_protorefs", "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); PTGV->setAlignment(Align.getAsAlign()); if (!CGM.getTriple().isOSBinFormatMachO()) @@ -6749,9 +6664,8 @@ void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder, /// struct _objc_method method_list[method_count]; /// } /// -llvm::Constant * -CGObjCNonFragileABIMac::emitMethodList(Twine name, MethodListType kind, - ArrayRef methods) { +llvm::Constant *CGObjCNonFragileABIMac::emitMethodList( + Twine name, MethodListType kind, ArrayRef methods) { // Return null for empty list. if (methods.empty()) return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); @@ -6824,10 +6738,9 @@ CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, Name += Ivar->getName(); llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name); if (!IvarOffsetGV) { - IvarOffsetGV = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy, - false, llvm::GlobalValue::ExternalLinkage, - nullptr, Name.str()); + IvarOffsetGV = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, Name.str()); if (CGM.getTriple().isOSBinFormatCOFF()) { bool IsPrivateOrPackage = Ivar->getAccessControl() == ObjCIvarDecl::Private || @@ -6836,11 +6749,11 @@ CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface(); if (ContainingID->hasAttr()) - IvarOffsetGV - ->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + IvarOffsetGV->setDLLStorageClass( + llvm::GlobalValue::DLLImportStorageClass); else if (ContainingID->hasAttr() && !IsPrivateOrPackage) - IvarOffsetGV - ->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + IvarOffsetGV->setDLLStorageClass( + llvm::GlobalValue::DLLExportStorageClass); } } return IvarOffsetGV; @@ -6895,8 +6808,8 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, /// } /// -llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( - const ObjCImplementationDecl *ID) { +llvm::Constant * +CGObjCNonFragileABIMac::EmitIvarList(const ObjCImplementationDecl *ID) { ConstantInitBuilder builder(CGM); auto ivarList = builder.beginStruct(); @@ -6910,8 +6823,8 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( // FIXME. Consolidate this with similar code in GenerateClass. - for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); - IVD; IVD = IVD->getNextIvar()) { + for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD; + IVD = IVD->getNextIvar()) { // Ignore unnamed bit-fields. if (!IVD->getDeclName()) continue; @@ -6921,11 +6834,11 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( ComputeIvarBaseOffset(CGM, ID, IVD))); ivar.add(GetMethodVarName(IVD->getIdentifier())); ivar.add(GetMethodVarType(IVD)); - llvm::Type *FieldTy = - CGM.getTypes().ConvertTypeForMem(IVD->getType()); + llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(IVD->getType()); unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy); - unsigned Align = CGM.getContext().getPreferredTypeAlign( - IVD->getType().getTypePtr()) >> 3; + unsigned Align = + CGM.getContext().getPreferredTypeAlign(IVD->getType().getTypePtr()) >> + 3; Align = llvm::Log2_32(Align); ivar.addInt(ObjCTypes.IntTy, Align); // NOTE. Size of a bitfield does not match gcc's, because of the @@ -6954,8 +6867,8 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( return GV; } -llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( - const ObjCProtocolDecl *PD) { +llvm::Constant * +CGObjCNonFragileABIMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) { llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()]; assert(!PD->isNonRuntimeProtocol() && @@ -6965,8 +6878,8 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( // reference or not. At module finalization we add the empty // contents for protocols which were referenced but never defined. llvm::SmallString<64> Protocol; - llvm::raw_svector_ostream(Protocol) << "_OBJC_PROTOCOL_$_" - << PD->getObjCRuntimeNameAsString(); + llvm::raw_svector_ostream(Protocol) + << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, llvm::GlobalValue::ExternalLinkage, @@ -6998,8 +6911,8 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( /// @endcode /// -llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( - const ObjCProtocolDecl *PD) { +llvm::Constant * +CGObjCNonFragileABIMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()]; // Early exit if a defining object has already been generated. @@ -7019,36 +6932,34 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( // isa is NULL values.addNullPointer(ObjCTypes.ObjectPtrTy); values.add(GetClassName(PD->getObjCRuntimeNameAsString())); - values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_" - + PD->getObjCRuntimeNameAsString(), - PD->protocol_begin(), - PD->protocol_end())); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredInstanceMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::RequiredClassMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalInstanceMethods)); - values.add(methodLists.emitMethodList(this, PD, - ProtocolMethodLists::OptionalClassMethods)); - values.add(EmitPropertyList( - "_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), - nullptr, PD, ObjCTypes, false)); + values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_" + + PD->getObjCRuntimeNameAsString(), + PD->protocol_begin(), PD->protocol_end())); + values.add(methodLists.emitMethodList( + this, PD, ProtocolMethodLists::RequiredInstanceMethods)); + values.add(methodLists.emitMethodList( + this, PD, ProtocolMethodLists::RequiredClassMethods)); + values.add(methodLists.emitMethodList( + this, PD, ProtocolMethodLists::OptionalInstanceMethods)); + values.add(methodLists.emitMethodList( + this, PD, ProtocolMethodLists::OptionalClassMethods)); + values.add( + EmitPropertyList("_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), + nullptr, PD, ObjCTypes, false)); uint32_t Size = - CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); values.addInt(ObjCTypes.IntTy, Size); values.addInt(ObjCTypes.IntTy, 0); - values.add(EmitProtocolMethodTypes("_OBJC_$_PROTOCOL_METHOD_TYPES_" - + PD->getObjCRuntimeNameAsString(), - methodLists.emitExtendedTypesArray(this), - ObjCTypes)); + values.add(EmitProtocolMethodTypes( + "_OBJC_$_PROTOCOL_METHOD_TYPES_" + PD->getObjCRuntimeNameAsString(), + methodLists.emitExtendedTypesArray(this), ObjCTypes)); // const char *demangledName; values.addNullPointer(ObjCTypes.Int8PtrTy); - values.add(EmitPropertyList( - "_OBJC_$_CLASS_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), - nullptr, PD, ObjCTypes, true)); + values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + + PD->getObjCRuntimeNameAsString(), + nullptr, PD, ObjCTypes, true)); if (Entry) { // Already created, fix the linkage and update the initializer. @@ -7057,7 +6968,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( } else { llvm::SmallString<64> symbolName; llvm::raw_svector_ostream(symbolName) - << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); + << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(), /*constant*/ false, @@ -7073,19 +6984,18 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( // Use this protocol meta-data to build protocol list table in section // __DATA, __objc_protolist llvm::SmallString<64> ProtocolRef; - llvm::raw_svector_ostream(ProtocolRef) << "_OBJC_LABEL_PROTOCOL_$_" - << PD->getObjCRuntimeNameAsString(); + llvm::raw_svector_ostream(ProtocolRef) + << "_OBJC_LABEL_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString(); - llvm::GlobalVariable *PTGV = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, - false, llvm::GlobalValue::WeakAnyLinkage, Entry, - ProtocolRef); + llvm::GlobalVariable *PTGV = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, false, + llvm::GlobalValue::WeakAnyLinkage, Entry, ProtocolRef); if (!CGM.getTriple().isOSBinFormatMachO()) PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef)); PTGV->setAlignment( CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy)); - PTGV->setSection(GetSectionName("__objc_protolist", - "coalesced,no_dead_strip")); + PTGV->setSection( + GetSectionName("__objc_protolist", "coalesced,no_dead_strip")); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); CGM.addUsedGlobal(PTGV); return Entry; @@ -7099,10 +7009,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( /// } /// @endcode /// -llvm::Constant * -CGObjCNonFragileABIMac::EmitProtocolList(Twine Name, - ObjCProtocolDecl::protocol_iterator begin, - ObjCProtocolDecl::protocol_iterator end) { +llvm::Constant *CGObjCNonFragileABIMac::EmitProtocolList( + Twine Name, ObjCProtocolDecl::protocol_iterator begin, + ObjCProtocolDecl::protocol_iterator end) { // Just return null for empty protocol lists auto Protocols = GetRuntimeProtocolList(begin, end); if (Protocols.empty()) @@ -7123,7 +7032,7 @@ CGObjCNonFragileABIMac::EmitProtocolList(Twine Name, SmallString<256> TmpName; Name.toVector(TmpName); llvm::GlobalVariable *GV = - CGM.getModule().getGlobalVariable(TmpName.str(), true); + CGM.getModule().getGlobalVariable(TmpName.str(), true); if (GV) return GV; @@ -7153,11 +7062,8 @@ CGObjCNonFragileABIMac::EmitProtocolList(Twine Name, /// @encode /// LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar( - CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, - const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers) { + CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue, + const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) { ObjCInterfaceDecl *ID = ObjectTy->castAs()->getInterface(); llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar); return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers, @@ -7175,9 +7081,8 @@ CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF, ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar)); } else { llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar); - IvarOffsetValue = - CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV, - CGF.getSizeAlign(), "ivar"); + IvarOffsetValue = CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV, + CGF.getSizeAlign(), "ivar"); if (IsIvarOffsetKnownIdempotent(CGF, Ivar)) cast(IvarOffsetValue) ->setMetadata(llvm::LLVMContext::MD_invariant_load, @@ -7216,16 +7121,10 @@ static void appendSelectorForMessageRefTable(std::string &buffer, /// appropriate vtable slot, and if not, it substitues a stub function /// which tail-calls objc_msgSend. Both stubs adjust the selector /// argument to correctly point to the selector. -RValue -CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, - ReturnValueSlot returnSlot, - QualType resultType, - Selector selector, - llvm::Value *arg0, - QualType arg0Type, - bool isSuper, - const CallArgList &formalArgs, - const ObjCMethodDecl *method) { +RValue CGObjCNonFragileABIMac::EmitVTableMessageSend( + CodeGenFunction &CGF, ReturnValueSlot returnSlot, QualType resultType, + Selector selector, llvm::Value *arg0, QualType arg0Type, bool isSuper, + const CallArgList &formalArgs, const ObjCMethodDecl *method) { // Compute the actual arguments. CallArgList args; @@ -7281,18 +7180,17 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, // would have used colons. appendSelectorForMessageRefTable(messageRefName, selector); - llvm::GlobalVariable *messageRef - = CGM.getModule().getGlobalVariable(messageRefName); + llvm::GlobalVariable *messageRef = + CGM.getModule().getGlobalVariable(messageRefName); if (!messageRef) { // Build the message ref structure. ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(); values.add(cast(fn.getCallee())); values.add(GetMethodVarName(selector)); - messageRef = values.finishAndCreateGlobal(messageRefName, - CharUnits::fromQuantity(16), - /*constant*/ false, - llvm::GlobalValue::WeakAnyLinkage); + messageRef = values.finishAndCreateGlobal( + messageRefName, CharUnits::fromQuantity(16), + /*constant*/ false, llvm::GlobalValue::WeakAnyLinkage); messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility); messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced")); } @@ -7309,8 +7207,8 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, } Address mref = - Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy), - ObjCTypes.MessageRefTy, CGF.getPointerAlign()); + Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy), + ObjCTypes.MessageRefTy, CGF.getPointerAlign()); // Update the message ref argument. args[1].setRValue(RValue::get(mref, CGF)); @@ -7328,22 +7226,17 @@ CGObjCNonFragileABIMac::EmitVTableMessageSend(CodeGenFunction &CGF, } /// Generate code for a message send expression in the nonfragile abi. -CodeGen::RValue -CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList &CallArgs, - const ObjCInterfaceDecl *Class, - const ObjCMethodDecl *Method) { +CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, + Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs, + const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) { return isVTableDispatchedSelector(Sel) - ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, Method) - : EmitMessageSend(CGF, Return, ResultType, Sel, - Receiver, CGF.getContext().getObjCIdType(), - false, CallArgs, Method, Class, ObjCTypes); + ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, Receiver, + CGF.getContext().getObjCIdType(), false, + CallArgs, Method) + : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver, + CGF.getContext().getObjCIdType(), false, + CallArgs, Method, Class, ObjCTypes); } llvm::Constant * @@ -7351,13 +7244,12 @@ CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID, bool metaclass, ForDefinition_t isForDefinition) { auto prefix = - (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix()); + (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix()); return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(), - isForDefinition, - ID->isWeakImported(), - !isForDefinition - && CGM.getTriple().isOSBinFormatCOFF() - && ID->hasAttr()); + isForDefinition, ID->isWeakImported(), + !isForDefinition && + CGM.getTriple().isOSBinFormatCOFF() && + ID->hasAttr()); } llvm::Constant * @@ -7390,8 +7282,8 @@ CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name, llvm::Constant * CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) { - llvm::Constant *ClassGV = GetClassGlobal(ID, /*metaclass*/ false, - NotForDefinition); + llvm::Constant *ClassGV = + GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition); if (!ID->hasAttr()) return ClassGV; @@ -7411,18 +7303,16 @@ CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF, if (ID && ID->hasAttr()) { // Classrefs pointing at Objective-C stub classes must be loaded by calling // a special runtime function. - return CGF.EmitRuntimeCall( - ObjCTypes.getLoadClassrefFn(), Entry, "load_classref_result"); + return CGF.EmitRuntimeCall(ObjCTypes.getLoadClassrefFn(), Entry, + "load_classref_result"); } CharUnits Align = CGF.getPointerAlign(); return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align); } -llvm::Value * -CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II, - const ObjCInterfaceDecl *ID) { +llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId( + CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID) { llvm::GlobalVariable *&Entry = ClassReferences[II]; if (!Entry) { @@ -7462,8 +7352,8 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, return EmitClassRefFromId(CGF, ID->getIdentifier(), ID); } -llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( - CodeGenFunction &CGF) { +llvm::Value * +CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); return EmitClassRefFromId(CGF, II, nullptr); } @@ -7491,11 +7381,10 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, /// EmitMetaClassRef - Return a Value * of the address of _class_t /// meta-data /// -llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, - const ObjCInterfaceDecl *ID, - bool Weak) { +llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef( + CodeGenFunction &CGF, const ObjCInterfaceDecl *ID, bool Weak) { CharUnits Align = CGF.getPointerAlign(); - llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; + llvm::GlobalVariable *&Entry = MetaClassReferences[ID->getIdentifier()]; if (!Entry) { auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition); std::string SectionName = @@ -7528,17 +7417,11 @@ llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF, /// Generates a message send where the super is the receiver. This is /// a message send to self with special delivery semantics indicating /// which class's method should be called. -CodeGen::RValue -CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Receiver, - bool IsClassMessage, - const CodeGen::CallArgList &CallArgs, - const ObjCMethodDecl *Method) { +CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, + Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl, + llvm::Value *Receiver, bool IsClassMessage, + const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) { // ... // Create and init a super structure; this is a (receiver, class) // pair we will pass to objc_msgSendSuper. @@ -7546,38 +7429,38 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super"); llvm::Value *ReceiverAsObject = - CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); + CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy); CGF.Builder.CreateStore(ReceiverAsObject, CGF.Builder.CreateStructGEP(ObjCSuper, 0)); // If this is a class message the metaclass is passed as the target. llvm::Value *Target; if (IsClassMessage) - Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported()); + Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported()); else Target = EmitSuperClassRef(CGF, Class); // FIXME: We shouldn't need to do this cast, rectify the ASTContext and // ObjCTypes types. llvm::Type *ClassTy = - CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); + CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType()); Target = CGF.Builder.CreateBitCast(Target, ClassTy); CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1)); return (isVTableDispatchedSelector(Sel)) - ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, - ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, - true, CallArgs, Method) - : EmitMessageSend(CGF, Return, ResultType, Sel, - ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, - true, CallArgs, Method, Class, ObjCTypes); + ? EmitVTableMessageSend( + CGF, Return, ResultType, Sel, ObjCSuper.getPointer(), + ObjCTypes.SuperPtrCTy, true, CallArgs, Method) + : EmitMessageSend(CGF, Return, ResultType, Sel, + ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy, + true, CallArgs, Method, Class, ObjCTypes); } llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) { Address Addr = EmitSelectorAddr(Sel); - llvm::LoadInst* LI = CGF.Builder.CreateLoad(Addr); + llvm::LoadInst *LI = CGF.Builder.CreateLoad(Addr); LI->setMetadata(llvm::LLVMContext::MD_invariant_load, llvm::MDNode::get(VMContext, {})); return LI; @@ -7606,15 +7489,14 @@ ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) { /// objc_assign_ivar (id src, id *dst, ptrdiff_t) /// void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, - Address dst, + llvm::Value *src, Address dst, llvm::Value *ivarOffset) { - llvm::Type * SrcTy = src->getType(); + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); @@ -7628,22 +7510,21 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, /// objc_assign_strongCast (id src, id *dst) /// void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( - CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); + CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) { + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), - args, "weakassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args, + "weakassign"); } void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( @@ -7657,15 +7538,14 @@ void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable( /// EmitObjCWeakRead - Code gen for loading value of a __weak /// object: objc_read_weak (id *src) /// -llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( - CodeGen::CodeGenFunction &CGF, - Address AddrWeakObj) { +llvm::Value * +CGObjCNonFragileABIMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, + Address AddrWeakObj) { llvm::Type *DestTy = AddrWeakObj.getElementType(); llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast( AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); - llvm::Value *read_weak = - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcReadWeakFn(), - AddrWeakObjVal, "weakread"); + llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall( + ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread"); read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy); return read_weak; } @@ -7675,34 +7555,34 @@ llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead( /// void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) { - llvm::Type * SrcTy = src->getType(); + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), - args, "weakassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args, + "weakassign"); } /// EmitObjCGlobalAssign - Code gen for assigning to a __strong object. /// objc_assign_global (id src, id *dst) /// void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, - llvm::Value *src, Address dst, - bool threadlocal) { - llvm::Type * SrcTy = src->getType(); + llvm::Value *src, Address dst, + bool threadlocal) { + llvm::Type *SrcTy = src->getType(); if (!isa(SrcTy)) { unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) - : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); + : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy); } src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy); @@ -7710,30 +7590,27 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, ObjCTypes.PtrObjectPtrTy); llvm::Value *args[] = {src, dstVal}; if (!threadlocal) - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), - args, "globalassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args, + "globalassign"); else - CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), - args, "threadlocalassign"); + CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args, + "threadlocalassign"); } -void -CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF, - const ObjCAtSynchronizedStmt &S) { +void CGObjCNonFragileABIMac::EmitSynchronizedStmt( + CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) { EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(), ObjCTypes.getSyncExitFn()); } -llvm::Constant * -CGObjCNonFragileABIMac::GetEHType(QualType T) { +llvm::Constant *CGObjCNonFragileABIMac::GetEHType(QualType T) { // There's a particular fixed type info for 'id'. if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); if (!IDEHType) { - IDEHType = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "OBJC_EHTYPE_id"); + IDEHType = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.EHTypeTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, "OBJC_EHTYPE_id"); if (CGM.getTriple().isOSBinFormatCOFF()) IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id")); } @@ -7781,7 +7658,7 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, llvm::Constant * CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, ForDefinition_t IsForDefinition) { - llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; + llvm::GlobalVariable *&Entry = EHTypeReferences[ID->getIdentifier()]; StringRef ClassName = ID->getObjCRuntimeNameAsString(); // If we don't need a definition, return the entry if found or check @@ -7794,9 +7671,9 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, // attribute, emit an external reference. if (hasObjCExceptionAttribute(CGM.getContext(), ID)) { std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str(); - Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, - false, llvm::GlobalValue::ExternalLinkage, - nullptr, EHTypeName); + Entry = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.EHTypeTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, EHTypeName); CGM.setGVProperties(Entry, ID); return Entry; } @@ -7808,10 +7685,9 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, std::string VTableName = "objc_ehtype_vtable"; auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName); if (!VTableGV) { - VTableGV = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - VTableName); + VTableGV = new llvm::GlobalVariable( + CGM.getModule(), ObjCTypes.Int8PtrTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, VTableName); if (CGM.getTriple().isOSBinFormatCOFF()) VTableGV->setDLLStorageClass(getStorage(CGM, VTableName)); } @@ -7819,9 +7695,8 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2); ConstantInitBuilder builder(CGM); auto values = builder.beginStruct(ObjCTypes.EHTypeTy); - values.add( - llvm::ConstantExpr::getInBoundsGetElementPtr(VTableGV->getValueType(), - VTableGV, VTableIdx)); + values.add(llvm::ConstantExpr::getInBoundsGetElementPtr( + VTableGV->getValueType(), VTableGV, VTableIdx)); values.add(GetClassName(ClassName)); values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition)); @@ -7834,8 +7709,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, } else { Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName, CGM.getPointerAlign(), - /*constant*/ false, - L); + /*constant*/ false, L); if (hasObjCExceptionAttribute(CGM.getContext(), ID)) CGM.setGVProperties(Entry, ID); } @@ -7858,7 +7732,7 @@ CodeGen::CGObjCRuntime * CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) { switch (CGM.getLangOpts().ObjCRuntime.getKind()) { case ObjCRuntime::FragileMacOSX: - return new CGObjCMac(CGM); + return new CGObjCMac(CGM); case ObjCRuntime::MacOSX: case ObjCRuntime::iOS: diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 3bd981256f475..72997bf6348ae 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -23,40 +23,40 @@ #include "llvm/ADT/UniqueVector.h" namespace llvm { - class Constant; - class Function; - class Module; - class StructLayout; - class StructType; - class Type; - class Value; -} +class Constant; +class Function; +class Module; +class StructLayout; +class StructType; +class Type; +class Value; +} // namespace llvm namespace clang { namespace CodeGen { class CGFunctionInfo; class CodeGenFunction; -} - - class FieldDecl; - class ObjCAtTryStmt; - class ObjCAtThrowStmt; - class ObjCAtSynchronizedStmt; - class ObjCContainerDecl; - class ObjCCategoryImplDecl; - class ObjCImplementationDecl; - class ObjCInterfaceDecl; - class ObjCMessageExpr; - class ObjCMethodDecl; - class ObjCProtocolDecl; - class Selector; - class ObjCIvarDecl; - class ObjCStringLiteral; - class BlockDeclRefExpr; +} // namespace CodeGen + +class FieldDecl; +class ObjCAtTryStmt; +class ObjCAtThrowStmt; +class ObjCAtSynchronizedStmt; +class ObjCContainerDecl; +class ObjCCategoryImplDecl; +class ObjCImplementationDecl; +class ObjCInterfaceDecl; +class ObjCMessageExpr; +class ObjCMethodDecl; +class ObjCProtocolDecl; +class Selector; +class ObjCIvarDecl; +class ObjCStringLiteral; +class BlockDeclRefExpr; namespace CodeGen { - class CodeGenModule; - class CGBlockInfo; +class CodeGenModule; +class CGBlockInfo; // FIXME: Several methods should be pure virtual but aren't to avoid the // partially-implemented subclass breaking. @@ -88,8 +88,7 @@ class CGObjCRuntime { const ObjCInterfaceDecl *OID, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers, - llvm::Value *Offset); + unsigned CVRQualifiers, llvm::Value *Offset); /// Emits a try / catch statement. This function is intended to be called by /// subclasses, and provides a generic mechanism for generating these, which /// should be usable by all runtimes. The caller must provide the functions @@ -145,7 +144,7 @@ class CGObjCRuntime { /// error to Sema. virtual llvm::Constant *GetEHType(QualType T) = 0; - virtual CatchTypeInfo getCatchAllTypeInfo() { return { nullptr, 0 }; } + virtual CatchTypeInfo getCatchAllTypeInfo() { return {nullptr, 0}; } /// Generate a constant string object. virtual ConstantAddress GenerateConstantString(const StringLiteral *) = 0; @@ -165,11 +164,8 @@ class CGObjCRuntime { /// \param Method - The method being called, this may be null if synthesizing /// a property setter or getter. virtual CodeGen::RValue - GenerateMessageSend(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot ReturnSlot, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, + GenerateMessageSend(CodeGen::CodeGenFunction &CGF, ReturnValueSlot ReturnSlot, + QualType ResultType, Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs, const ObjCInterfaceDecl *Class = nullptr, const ObjCMethodDecl *Method = nullptr) = 0; @@ -178,16 +174,11 @@ class CGObjCRuntime { /// /// This variant allows for the call to be substituted with an optimized /// variant. - CodeGen::RValue - GeneratePossiblySpecializedMessageSend(CodeGenFunction &CGF, - ReturnValueSlot Return, - QualType ResultType, - Selector Sel, - llvm::Value *Receiver, - const CallArgList& Args, - const ObjCInterfaceDecl *OID, - const ObjCMethodDecl *Method, - bool isClassMessage); + CodeGen::RValue GeneratePossiblySpecializedMessageSend( + CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType, + Selector Sel, llvm::Value *Receiver, const CallArgList &Args, + const ObjCInterfaceDecl *OID, const ObjCMethodDecl *Method, + bool isClassMessage); /// Generate an Objective-C message send operation to the super /// class initiated in a method for Class and with the given Self @@ -195,17 +186,11 @@ class CGObjCRuntime { /// /// \param Method - The method being called, this may be null if synthesizing /// a property setter or getter. - virtual CodeGen::RValue - GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, - ReturnValueSlot ReturnSlot, - QualType ResultType, - Selector Sel, - const ObjCInterfaceDecl *Class, - bool isCategoryImpl, - llvm::Value *Self, - bool IsClassMessage, - const CallArgList &CallArgs, - const ObjCMethodDecl *Method = nullptr) = 0; + virtual CodeGen::RValue GenerateMessageSendSuper( + CodeGen::CodeGenFunction &CGF, ReturnValueSlot ReturnSlot, + QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class, + bool isCategoryImpl, llvm::Value *Self, bool IsClassMessage, + const CallArgList &CallArgs, const ObjCMethodDecl *Method = nullptr) = 0; /// Walk the list of protocol references from a class, category or /// protocol to traverse the DAG formed from it's inheritance hierarchy. Find @@ -272,7 +257,6 @@ class CGObjCRuntime { virtual llvm::Value *GetClass(CodeGenFunction &CGF, const ObjCInterfaceDecl *OID) = 0; - virtual llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { llvm_unreachable("autoreleasepool unsupported in this ABI"); } @@ -287,14 +271,14 @@ class CGObjCRuntime { const ObjCAtTryStmt &S) = 0; virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S, - bool ClearInsertionPoint=true) = 0; + bool ClearInsertionPoint = true) = 0; virtual llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF, Address AddrWeakObj) = 0; virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dest) = 0; virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dest, - bool threadlocal=false) = 0; + bool threadlocal = false) = 0; virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dest, llvm::Value *ivarOffset) = 0; @@ -302,21 +286,21 @@ class CGObjCRuntime { llvm::Value *src, Address dest) = 0; virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, - QualType ObjectTy, - llvm::Value *BaseValue, + QualType ObjectTy, llvm::Value *BaseValue, const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) = 0; virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF, const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar) = 0; virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, - Address DestPtr, - Address SrcPtr, + Address DestPtr, Address SrcPtr, llvm::Value *Size) = 0; - virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, - const CodeGen::CGBlockInfo &blockInfo) = 0; - virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, - const CodeGen::CGBlockInfo &blockInfo) = 0; + virtual llvm::Constant * + BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, + const CodeGen::CGBlockInfo &blockInfo) = 0; + virtual llvm::Constant * + BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, + const CodeGen::CGBlockInfo &blockInfo) = 0; virtual std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM, const CGBlockInfo &blockInfo) { return {}; @@ -332,15 +316,14 @@ class CGObjCRuntime { MessageSendInfo(const CGFunctionInfo &callInfo, llvm::PointerType *messengerType) - : CallInfo(callInfo), MessengerType(messengerType) {} + : CallInfo(callInfo), MessengerType(messengerType) {} }; MessageSendInfo getMessageSendInfo(const ObjCMethodDecl *method, QualType resultType, CallArgList &callArgs); bool canMessageReceiverBeNull(CodeGenFunction &CGF, - const ObjCMethodDecl *method, - bool isSuper, + const ObjCMethodDecl *method, bool isSuper, const ObjCInterfaceDecl *classReceiver, llvm::Value *receiver); static bool isWeakLinkedClass(const ObjCInterfaceDecl *cls); @@ -364,9 +347,9 @@ class CGObjCRuntime { }; /// Creates an instance of an Objective-C runtime class. -//TODO: This should include some way of selecting which runtime to target. +// TODO: This should include some way of selecting which runtime to target. CGObjCRuntime *CreateGNUObjCRuntime(CodeGenModule &CGM); CGObjCRuntime *CreateMacObjCRuntime(CodeGenModule &CGM); -} -} +} // namespace CodeGen +} // namespace clang #endif diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp index b679d63874b3b..9f7db25a15bec 100644 --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -7447,7 +7447,7 @@ class MappableExprsHandler { // Update info about the lowest and highest elements for this struct if (!PartialStruct.Base.isValid()) { PartialStruct.LowestElem = {FieldIndex, LowestElem}; - if (IsFinalArraySection) { + if (IsFinalArraySection && OASE) { Address HB = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false) .getAddress(); @@ -7460,7 +7460,7 @@ class MappableExprsHandler { } else if (FieldIndex < PartialStruct.LowestElem.first) { PartialStruct.LowestElem = {FieldIndex, LowestElem}; } else if (FieldIndex > PartialStruct.HighestElem.first) { - if (IsFinalArraySection) { + if (IsFinalArraySection && OASE) { Address HB = CGF.EmitArraySectionExpr(OASE, /*IsLowerBound=*/false) .getAddress(); diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index c96301c306d41..7368df1ebe272 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -221,6 +221,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef Attrs) { case Stmt::OMPTileDirectiveClass: EmitOMPTileDirective(cast(*S)); break; + case Stmt::OMPStripeDirectiveClass: + EmitOMPStripeDirective(cast(*S)); + break; case Stmt::OMPUnrollDirectiveClass: EmitOMPUnrollDirective(cast(*S)); break; diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index a2cc54b05259c..e4d1db264aac9 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -2459,10 +2459,86 @@ static void emitSimdlenSafelenClause(CodeGenFunction &CGF, } } +// Check for the presence of an `OMPOrderedDirective`, +// i.e., `ordered` in `#pragma omp ordered simd`. +// +// Consider the following source code: +// ``` +// __attribute__((noinline)) void omp_simd_loop(float X[ARRAY_SIZE][ARRAY_SIZE]) +// { +// for (int r = 1; r < ARRAY_SIZE; ++r) { +// for (int c = 1; c < ARRAY_SIZE; ++c) { +// #pragma omp simd +// for (int k = 2; k < ARRAY_SIZE; ++k) { +// #pragma omp ordered simd +// X[r][k] = X[r][k - 2] + sinf((float)(r / c)); +// } +// } +// } +// } +// ``` +// +// Suppose we are in `CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective +// &D)`. By examining `D.dump()` we have the following AST containing +// `OMPOrderedDirective`: +// +// ``` +// OMPSimdDirective 0x1c32950 +// `-CapturedStmt 0x1c32028 +// |-CapturedDecl 0x1c310e8 +// | |-ForStmt 0x1c31e30 +// | | |-DeclStmt 0x1c31298 +// | | | `-VarDecl 0x1c31208 used k 'int' cinit +// | | | `-IntegerLiteral 0x1c31278 'int' 2 +// | | |-<<>> +// | | |-BinaryOperator 0x1c31308 'int' '<' +// | | | |-ImplicitCastExpr 0x1c312f0 'int' +// | | | | `-DeclRefExpr 0x1c312b0 'int' lvalue Var 0x1c31208 'k' 'int' +// | | | `-IntegerLiteral 0x1c312d0 'int' 256 +// | | |-UnaryOperator 0x1c31348 'int' prefix '++' +// | | | `-DeclRefExpr 0x1c31328 'int' lvalue Var 0x1c31208 'k' 'int' +// | | `-CompoundStmt 0x1c31e18 +// | | `-OMPOrderedDirective 0x1c31dd8 +// | | |-OMPSimdClause 0x1c31380 +// | | `-CapturedStmt 0x1c31cd0 +// ``` +// +// Note the presence of `OMPOrderedDirective` above: +// It's (transitively) nested in a `CapturedStmt` representing the pragma +// annotated compound statement. Thus, we need to consider this nesting and +// include checking the `getCapturedStmt` in this case. +static bool hasOrderedDirective(const Stmt *S) { + if (isa(S)) + return true; + + if (const auto *CS = dyn_cast(S)) + return hasOrderedDirective(CS->getCapturedStmt()); + + for (const Stmt *Child : S->children()) { + if (Child && hasOrderedDirective(Child)) + return true; + } + + return false; +} + +static void applyConservativeSimdOrderedDirective(const Stmt &AssociatedStmt, + LoopInfoStack &LoopStack) { + // Check for the presence of an `OMPOrderedDirective` + // i.e., `ordered` in `#pragma omp ordered simd` + bool HasOrderedDirective = hasOrderedDirective(&AssociatedStmt); + // If present then conservatively disable loop vectorization + // analogously to how `emitSimdlenSafelenClause` does. + if (HasOrderedDirective) + LoopStack.setParallel(/*Enable=*/false); +} + void CodeGenFunction::EmitOMPSimdInit(const OMPLoopDirective &D) { // Walk clauses and process safelen/lastprivate. LoopStack.setParallel(/*Enable=*/true); LoopStack.setVectorizeEnable(); + const Stmt *AssociatedStmt = D.getAssociatedStmt(); + applyConservativeSimdOrderedDirective(*AssociatedStmt, LoopStack); emitSimdlenSafelenClause(*this, D); if (const auto *C = D.getSingleClause()) if (C->getKind() == OMPC_ORDER_concurrent) diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index f7ce46cf1bcf2..64cd8a3ac55e2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -54,7 +54,7 @@ class SwitchInst; class Twine; class Value; class CanonicalLoopInfo; -} +} // namespace llvm namespace clang { class ASTContext; @@ -102,6 +102,7 @@ class TargetCodeGenInfo; struct OMPTaskDataTy; struct CGCoroData; +// clang-format off /// The kind of evaluation to perform on values of a particular /// type. Basically, is the code in CGExprScalar, CGExprComplex, or /// CGExprAgg? @@ -112,6 +113,7 @@ enum TypeEvaluationKind { TEK_Complex, TEK_Aggregate }; +// clang-format on #define LIST_SANITIZER_CHECKS \ SANITIZER_CHECK(AddOverflow, add_overflow, 0) \ @@ -150,7 +152,7 @@ enum SanitizerHandler { /// Helper class with most of the code for saving a value for a /// conditional expression cleanup. struct DominatingLLVMValue { - typedef llvm::PointerIntPair saved_type; + typedef llvm::PointerIntPair saved_type; /// Answer whether the given value needs extra work to be saved. static bool needsSaving(llvm::Value *value) { @@ -158,7 +160,8 @@ struct DominatingLLVMValue { return false; // If it's not an instruction, we don't need to save. - if (!isa(value)) return false; + if (!isa(value)) + return false; // If it's an instruction in the entry block, we don't need to save. llvm::BasicBlock *block = cast(value)->getParent(); @@ -171,10 +174,10 @@ struct DominatingLLVMValue { /// A partial specialization of DominatingValue for llvm::Values that /// might be llvm::Instructions. -template struct DominatingPointer : DominatingLLVMValue { +template struct DominatingPointer : DominatingLLVMValue { typedef T *type; static type restore(CodeGenFunction &CGF, saved_type value) { - return static_cast(DominatingLLVMValue::restore(CGF, value)); + return static_cast(DominatingLLVMValue::restore(CGF, value)); } }; @@ -212,8 +215,13 @@ template <> struct DominatingValue
{ template <> struct DominatingValue { typedef RValue type; class saved_type { - enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral, - AggregateAddress, ComplexAddress }; + enum Kind { + ScalarLiteral, + ScalarAddress, + AggregateLiteral, + AggregateAddress, + ComplexAddress + }; union { struct { DominatingLLVMValue::saved_type first, second; @@ -241,9 +249,7 @@ template <> struct DominatingValue { // implementations in CGCleanup.cpp }; - static bool needsSaving(type value) { - return saved_type::needsSaving(value); - } + static bool needsSaving(type value) { return saved_type::needsSaving(value); } static saved_type save(CodeGenFunction &CGF, type value) { return saved_type::save(CGF, value); } @@ -259,6 +265,7 @@ class CodeGenFunction : public CodeGenTypeCache { void operator=(const CodeGenFunction &) = delete; friend class CGCXXABI; + public: /// A jump destination is an abstract label, branching to which may /// require a jump out through normal cleanups. @@ -284,7 +291,7 @@ class CodeGenFunction : public CodeGenTypeCache { unsigned Index; }; - CodeGenModule &CGM; // Per-module state. + CodeGenModule &CGM; // Per-module state. const TargetInfo &Target; // For EH/SEH outlined funclets, this field points to parent's CGF @@ -369,9 +376,7 @@ class CodeGenFunction : public CodeGenTypeCache { }; CGCoroInfo CurCoro; - bool isCoroutine() const { - return CurCoro.Data != nullptr; - } + bool isCoroutine() const { return CurCoro.Data != nullptr; } bool inSuspendBlock() const { return isCoroutine() && CurCoro.InSuspendBlock; @@ -464,10 +469,10 @@ class CodeGenFunction : public CodeGenTypeCache { : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) {} explicit CGCapturedStmtInfo(const CapturedStmt &S, CapturedRegionKind K = CR_Default) - : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) { + : Kind(K), ThisValue(nullptr), CXXThisFieldDecl(nullptr) { RecordDecl::field_iterator Field = - S.getCapturedRecordDecl()->field_begin(); + S.getCapturedRecordDecl()->field_begin(); for (CapturedStmt::const_capture_iterator I = S.capture_begin(), E = S.capture_end(); I != E; ++I, ++Field) { @@ -496,9 +501,7 @@ class CodeGenFunction : public CodeGenTypeCache { bool isCXXThisExprCaptured() const { return getThisFieldDecl() != nullptr; } virtual FieldDecl *getThisFieldDecl() const { return CXXThisFieldDecl; } - static bool classof(const CGCapturedStmtInfo *) { - return true; - } + static bool classof(const CGCapturedStmtInfo *) { return true; } /// Emit the captured statement body. virtual void EmitBody(CodeGenFunction &CGF, const Stmt *S) { @@ -535,6 +538,7 @@ class CodeGenFunction : public CodeGenTypeCache { private: CodeGenFunction &CGF; CGCapturedStmtInfo *PrevCapturedStmtInfo; + public: CGCapturedStmtRAII(CodeGenFunction &CGF, CGCapturedStmtInfo *NewCapturedStmtInfo) @@ -578,6 +582,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// RAII object to set/unset CodeGenFunction::IsSanitizerScope. class SanitizerScope { CodeGenFunction *CGF; + public: SanitizerScope(CodeGenFunction *CGF); ~SanitizerScope(); @@ -832,7 +837,7 @@ class CodeGenFunction : public CodeGenTypeCache { public: /// ObjCEHValueStack - Stack of Objective-C exception values, used for /// rethrows. - SmallVector ObjCEHValueStack; + SmallVector ObjCEHValueStack; /// A class controlling the emission of a finally block. class FinallyInfo { @@ -900,7 +905,8 @@ class CodeGenFunction : public CodeGenTypeCache { SavedTuple Saved{saveValueInCond(A)...}; typedef EHScopeStack::ConditionalCleanup CleanupType; - pushCleanupAfterFullExprWithActiveFlag(Kind, ActiveFlag, Saved); + pushCleanupAfterFullExprWithActiveFlag(Kind, ActiveFlag, + Saved); } template @@ -990,15 +996,16 @@ class CodeGenFunction : public CodeGenTypeCache { size_t LifetimeExtendedCleanupStackSize; CleanupDeactivationScope DeactivateCleanups; bool OldDidCallStackSave; + protected: bool PerformCleanup; - private: + private: RunCleanupsScope(const RunCleanupsScope &) = delete; void operator=(const RunCleanupsScope &) = delete; protected: - CodeGenFunction& CGF; + CodeGenFunction &CGF; public: /// Enter a new cleanup scope. @@ -1030,7 +1037,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// the insertion point after cleanup emission. If cleanup emission created /// a shared cleanup block, these value pointers will be rewritten. /// Otherwise, they not will be modified. - void ForceCleanup(std::initializer_list ValuesToReload = {}) { + void + ForceCleanup(std::initializer_list ValuesToReload = {}) { assert(PerformCleanup && "Already forced cleanup"); CGF.DidCallStackSave = OldDidCallStackSave; DeactivateCleanups.ForceDeactivate(); @@ -1047,7 +1055,7 @@ class CodeGenFunction : public CodeGenTypeCache { class LexicalScope : public RunCleanupsScope { SourceRange Range; - SmallVector Labels; + SmallVector Labels; LexicalScope *ParentScope; LexicalScope(const LexicalScope &) = delete; @@ -1056,7 +1064,8 @@ class CodeGenFunction : public CodeGenTypeCache { public: /// Enter a new cleanup scope. explicit LexicalScope(CodeGenFunction &CGF, SourceRange Range) - : RunCleanupsScope(CGF), Range(Range), ParentScope(CGF.CurLexicalScope) { + : RunCleanupsScope(CGF), Range(Range), + ParentScope(CGF.CurLexicalScope) { CGF.CurLexicalScope = this; if (CGDebugInfo *DI = CGF.getDebugInfo()) DI->EmitLexicalBlockStart(CGF.Builder, Range.getBegin()); @@ -1091,9 +1100,7 @@ class CodeGenFunction : public CodeGenTypeCache { rescopeLabels(); } - bool hasLabels() const { - return !Labels.empty(); - } + bool hasLabels() const { return !Labels.empty(); } void rescopeLabels(); }; @@ -1120,7 +1127,8 @@ class CodeGenFunction : public CodeGenTypeCache { Address TempAddr) { LocalVD = LocalVD->getCanonicalDecl(); // Only save it once. - if (SavedLocals.count(LocalVD)) return false; + if (SavedLocals.count(LocalVD)) + return false; // Copy the existing local entry to SavedLocals. auto it = CGF.LocalDeclMap.find(LocalVD); @@ -1259,8 +1267,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// target of a potentially scope-crossing jump; get a stable handle /// to which we can perform this jump later. JumpDest getJumpDestInCurrentScope(llvm::BasicBlock *Target) { - return JumpDest(Target, - EHStack.getInnermostNormalCleanup(), + return JumpDest(Target, EHStack.getInnermostNormalCleanup(), NextCleanupDestIndex++); } @@ -1297,7 +1304,7 @@ class CodeGenFunction : public CodeGenTypeCache { public: ConditionalEvaluation(CodeGenFunction &CGF) - : StartBB(CGF.Builder.GetInsertBlock()) {} + : StartBB(CGF.Builder.GetInsertBlock()) {} void begin(CodeGenFunction &CGF) { assert(CGF.OutermostConditional != this); @@ -1313,9 +1320,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// Returns a block which will be executed prior to each /// evaluation of the conditional code. - llvm::BasicBlock *getStartingBlock() const { - return StartBB; - } + llvm::BasicBlock *getStartingBlock() const { return StartBB; } }; /// isInConditionalBranch - Return true if we're currently emitting @@ -1343,7 +1348,7 @@ class CodeGenFunction : public CodeGenTypeCache { public: StmtExprEvaluation(CodeGenFunction &CGF) - : CGF(CGF), SavedOutermostConditional(CGF.OutermostConditional) { + : CGF(CGF), SavedOutermostConditional(CGF.OutermostConditional) { CGF.OutermostConditional = nullptr; } @@ -1375,9 +1380,9 @@ class CodeGenFunction : public CodeGenTypeCache { bool BoundLValue; CodeGenFunction::PeepholeProtection Protection; - OpaqueValueMappingData(const OpaqueValueExpr *ov, - bool boundLValue) - : OpaqueValue(ov), BoundLValue(boundLValue) {} + OpaqueValueMappingData(const OpaqueValueExpr *ov, bool boundLValue) + : OpaqueValue(ov), BoundLValue(boundLValue) {} + public: OpaqueValueMappingData() : OpaqueValue(nullptr) {} @@ -1387,30 +1392,26 @@ class CodeGenFunction : public CodeGenTypeCache { // always keeps them in memory. Expressions of function type // act exactly like l-values but are formally required to be // r-values in C. - return expr->isGLValue() || - expr->getType()->isFunctionType() || + return expr->isGLValue() || expr->getType()->isFunctionType() || hasAggregateEvaluationKind(expr->getType()); } - static OpaqueValueMappingData bind(CodeGenFunction &CGF, - const OpaqueValueExpr *ov, - const Expr *e) { + static OpaqueValueMappingData + bind(CodeGenFunction &CGF, const OpaqueValueExpr *ov, const Expr *e) { if (shouldBindAsLValue(ov)) return bind(CGF, ov, CGF.EmitLValue(e)); return bind(CGF, ov, CGF.EmitAnyExpr(e)); } - static OpaqueValueMappingData bind(CodeGenFunction &CGF, - const OpaqueValueExpr *ov, - const LValue &lv) { + static OpaqueValueMappingData + bind(CodeGenFunction &CGF, const OpaqueValueExpr *ov, const LValue &lv) { assert(shouldBindAsLValue(ov)); CGF.OpaqueLValues.insert(std::make_pair(ov, lv)); return OpaqueValueMappingData(ov, true); } - static OpaqueValueMappingData bind(CodeGenFunction &CGF, - const OpaqueValueExpr *ov, - const RValue &rv) { + static OpaqueValueMappingData + bind(CodeGenFunction &CGF, const OpaqueValueExpr *ov, const RValue &rv) { assert(!shouldBindAsLValue(ov)); CGF.OpaqueRValues.insert(std::make_pair(ov, rv)); @@ -1455,7 +1456,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// helpful. /// OpaqueValueMapping(CodeGenFunction &CGF, - const AbstractConditionalOperator *op) : CGF(CGF) { + const AbstractConditionalOperator *op) + : CGF(CGF) { if (isa(op)) // Leave Data empty. return; @@ -1476,17 +1478,15 @@ class CodeGenFunction : public CodeGenTypeCache { } } - OpaqueValueMapping(CodeGenFunction &CGF, - const OpaqueValueExpr *opaqueValue, + OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *opaqueValue, LValue lvalue) - : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, lvalue)) { - } + : CGF(CGF), + Data(OpaqueValueMappingData::bind(CGF, opaqueValue, lvalue)) {} - OpaqueValueMapping(CodeGenFunction &CGF, - const OpaqueValueExpr *opaqueValue, + OpaqueValueMapping(CodeGenFunction &CGF, const OpaqueValueExpr *opaqueValue, RValue rvalue) - : CGF(CGF), Data(OpaqueValueMappingData::bind(CGF, opaqueValue, rvalue)) { - } + : CGF(CGF), + Data(OpaqueValueMappingData::bind(CGF, opaqueValue, rvalue)) {} void pop() { Data.unbind(CGF); @@ -1494,7 +1494,8 @@ class CodeGenFunction : public CodeGenTypeCache { } ~OpaqueValueMapping() { - if (Data.isValid()) Data.unbind(CGF); + if (Data.isValid()) + Data.unbind(CGF); } }; @@ -1534,13 +1535,13 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::DenseMap EscapedLocals; /// LabelMap - This keeps track of the LLVM basic block for each C label. - llvm::DenseMap LabelMap; + llvm::DenseMap LabelMap; // BreakContinueStack - This keeps track of where break and continue // statements should jump to. struct BreakContinue { BreakContinue(JumpDest Break, JumpDest Continue) - : BreakBlock(Break), ContinueBlock(Continue) {} + : BreakBlock(Break), ContinueBlock(Continue) {} JumpDest BreakBlock; JumpDest ContinueBlock; @@ -1716,12 +1717,9 @@ class CodeGenFunction : public CodeGenTypeCache { /// Get the profiler's current count. This is generally the count for the most /// recently incremented counter. - uint64_t getCurrentProfileCount() { - return PGO.getCurrentRegionCount(); - } + uint64_t getCurrentProfileCount() { return PGO.getCurrentRegionCount(); } private: - /// SwitchInsn - This is nearest current switch instruction. It is null if /// current context is not in a switch. llvm::SwitchInst *SwitchInsn = nullptr; @@ -1746,7 +1744,7 @@ class CodeGenFunction : public CodeGenTypeCache { // multiple VLA types can share the same size expression. // FIXME: Maybe this could be a stack of maps that is pushed/popped as we // enter/leave scopes. - llvm::DenseMap VLASizeMap; + llvm::DenseMap VLASizeMap; /// A block containing a single 'unreachable' instruction. Created /// lazily by getUnreachableBlock(). @@ -1788,7 +1786,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// The scope of a CXXDefaultInitExpr. Within this scope, the value of 'this' /// is overridden to be the object under construction. - class CXXDefaultInitExprScope { + class CXXDefaultInitExprScope { public: CXXDefaultInitExprScope(CodeGenFunction &CGF, const CXXDefaultInitExpr *E) : CGF(CGF), OldCXXThisValue(CGF.CXXThisValue), @@ -1819,12 +1817,10 @@ class CodeGenFunction : public CodeGenTypeCache { class ArrayInitLoopExprScope { public: ArrayInitLoopExprScope(CodeGenFunction &CGF, llvm::Value *Index) - : CGF(CGF), OldArrayInitIndex(CGF.ArrayInitIndex) { + : CGF(CGF), OldArrayInitIndex(CGF.ArrayInitIndex) { CGF.ArrayInitIndex = Index; } - ~ArrayInitLoopExprScope() { - CGF.ArrayInitIndex = OldArrayInitIndex; - } + ~ArrayInitLoopExprScope() { CGF.ArrayInitIndex = OldArrayInitIndex; } private: CodeGenFunction &CGF; @@ -2151,7 +2147,7 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitKernelMetadata(const FunctionDecl *FD, llvm::Function *Fn); public: - CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext=false); + CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext = false); ~CodeGenFunction(); CodeGenTypes &getTypes() const { return CGM.getTypes(); } @@ -2191,7 +2187,8 @@ class CodeGenFunction : public CodeGenTypeCache { } llvm::BasicBlock *getInvokeDest() { - if (!EHStack.requiresLandingPad()) return nullptr; + if (!EHStack.requiresLandingPad()) + return nullptr; return getInvokeDestImpl(); } @@ -2220,10 +2217,10 @@ class CodeGenFunction : public CodeGenTypeCache { CharUnits elementAlignment, Destroyer *destroyer); - void pushDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type); - void pushEHDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type); + void pushDestroy(QualType::DestructionKind dtorKind, Address addr, + QualType type); + void pushEHDestroy(QualType::DestructionKind dtorKind, Address addr, + QualType type); void pushDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); void pushDestroyAndDeferDeactivation(QualType::DestructionKind dtorKind, @@ -2248,8 +2245,8 @@ class CodeGenFunction : public CodeGenTypeCache { const VarDecl *VD); void emitArrayDestroy(llvm::Value *begin, llvm::Value *end, QualType elementType, CharUnits elementAlign, - Destroyer *destroyer, - bool checkZeroLength, bool useEHCleanup); + Destroyer *destroyer, bool checkZeroLength, + bool useEHCleanup); Destroyer *getDestroyer(QualType::DestructionKind destructionKind); @@ -2311,8 +2308,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// captured variables, etc. llvm::Value *EmitBlockLiteral(const BlockExpr *); - llvm::Function *GenerateBlockFunction(GlobalDecl GD, - const CGBlockInfo &Info, + llvm::Function *GenerateBlockFunction(GlobalDecl GD, const CGBlockInfo &Info, const DeclMapTy &ldm, bool IsLambdaConversionToBlock, bool BuildGlobalBlock); @@ -2322,10 +2318,10 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo); llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo); - llvm::Constant *GenerateObjCAtomicSetterCopyHelperFunction( - const ObjCPropertyImplDecl *PID); - llvm::Constant *GenerateObjCAtomicGetterCopyHelperFunction( - const ObjCPropertyImplDecl *PID); + llvm::Constant * + GenerateObjCAtomicSetterCopyHelperFunction(const ObjCPropertyImplDecl *PID); + llvm::Constant * + GenerateObjCAtomicGetterCopyHelperFunction(const ObjCPropertyImplDecl *PID); llvm::Value *EmitBlockCopyAndAutorelease(llvm::Value *Block, QualType Ty); void BuildBlockRelease(llvm::Value *DeclPtr, BlockFieldFlags flags, @@ -2364,10 +2360,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// data in a variable which is declared as __block. Address emitBlockByrefAddress(Address baseAddr, const VarDecl *V, bool followForward = true); - Address emitBlockByrefAddress(Address baseAddr, - const BlockByrefInfo &info, - bool followForward, - const llvm::Twine &name); + Address emitBlockByrefAddress(Address baseAddr, const BlockByrefInfo &info, + bool followForward, const llvm::Twine &name); const BlockByrefInfo &getBlockByrefInfo(const VarDecl *var); @@ -2383,11 +2377,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// Emit code for the start of a function. /// \param Loc The location to be associated with the function. /// \param StartLoc The location of the function body. - void StartFunction(GlobalDecl GD, - QualType RetTy, - llvm::Function *Fn, - const CGFunctionInfo &FnInfo, - const FunctionArgList &Args, + void StartFunction(GlobalDecl GD, QualType RetTy, llvm::Function *Fn, + const CGFunctionInfo &FnInfo, const FunctionArgList &Args, SourceLocation Loc = SourceLocation(), SourceLocation StartLoc = SourceLocation()); @@ -2424,7 +2415,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// FinishFunction - Complete IR generation of the current function. It is /// legal to call this function even if there is no current insertion point. - void FinishFunction(SourceLocation EndLoc=SourceLocation()); + void FinishFunction(SourceLocation EndLoc = SourceLocation()); void StartThunk(llvm::Function *Fn, GlobalDecl GD, const CGFunctionInfo &FnInfo, bool IsUnprototyped); @@ -2567,8 +2558,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitFunctionProlog - Emit the target specific LLVM code to load the /// arguments for the given function. This is also responsible for naming the /// LLVM function arguments. - void EmitFunctionProlog(const CGFunctionInfo &FI, - llvm::Function *Fn, + void EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Function *Fn, const FunctionArgList &Args); /// EmitFunctionEpilog - Emit the target specific LLVM code to return the @@ -2647,7 +2637,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// IsFinished - If true, indicates that the caller has finished emitting /// branches to the given block and does not expect to emit code into it. This /// means the block can be ignored if it is unreachable. - void EmitBlock(llvm::BasicBlock *BB, bool IsFinished=false); + void EmitBlock(llvm::BasicBlock *BB, bool IsFinished = false); /// EmitBlockAfterUses - Emit the given block somewhere hopefully /// near its uses, and leave the insertion point in it. @@ -2665,9 +2655,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// HaveInsertPoint - True if an insertion point is defined. If not, this /// indicates that the current code being emitted is unreachable. - bool HaveInsertPoint() const { - return Builder.GetInsertBlock() != nullptr; - } + bool HaveInsertPoint() const { return Builder.GetInsertBlock() != nullptr; } /// EnsureInsertPoint - Ensure that an insertion point is defined so that /// emitted IR has a place to go. Note that by definition, if this function @@ -2768,9 +2756,9 @@ class CodeGenFunction : public CodeGenTypeCache { LValueBaseInfo *PointeeBaseInfo = nullptr, TBAAAccessInfo *PointeeTBAAInfo = nullptr); LValue EmitLoadOfReferenceLValue(LValue RefLVal); - LValue EmitLoadOfReferenceLValue(Address RefAddr, QualType RefTy, - AlignmentSource Source = - AlignmentSource::Type) { + LValue + EmitLoadOfReferenceLValue(Address RefAddr, QualType RefTy, + AlignmentSource Source = AlignmentSource::Type) { LValue RefLVal = MakeAddrLValue(RefAddr, RefTy, LValueBaseInfo(Source), CGM.getTBAAAccessInfo(RefTy)); return EmitLoadOfReferenceLValue(RefLVal); @@ -2914,7 +2902,8 @@ class CodeGenFunction : public CodeGenTypeCache { const CGBitFieldInfo &Info, SourceLocation Loc); - /// EmitIgnoredExpr - Emit an expression in a context which ignores the result. + /// EmitIgnoredExpr - Emit an expression in a context which ignores the + /// result. void EmitIgnoredExpr(const Expr *E); /// EmitAnyExpr - Emit code to compute the specified expression which can have @@ -2942,8 +2931,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitAnyExprToMem - Emits the code necessary to evaluate an /// arbitrary expression into the given memory location. - void EmitAnyExprToMem(const Expr *E, Address Location, - Qualifiers Quals, bool IsInitializer); + void EmitAnyExprToMem(const Expr *E, Address Location, Qualifiers Quals, + bool IsInitializer); void EmitAnyExprToExn(const Expr *E, Address Addr); @@ -3061,8 +3050,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// emitArrayLength - Compute the length of an array, even if it's a /// VLA, and drill down to the base element type. - llvm::Value *emitArrayLength(const ArrayType *arrayType, - QualType &baseType, + llvm::Value *emitArrayLength(const ArrayType *arrayType, QualType &baseType, Address &addr); /// EmitVLASize - Capture all the sizes for the VLA expressions in @@ -3109,24 +3097,21 @@ class CodeGenFunction : public CodeGenTypeCache { /// GetAddressOfBaseOfCompleteClass - Convert the given pointer to a /// complete class to the given direct base. - Address - GetAddressOfDirectBaseInCompleteClass(Address Value, - const CXXRecordDecl *Derived, - const CXXRecordDecl *Base, - bool BaseIsVirtual); + Address GetAddressOfDirectBaseInCompleteClass(Address Value, + const CXXRecordDecl *Derived, + const CXXRecordDecl *Base, + bool BaseIsVirtual); static bool ShouldNullCheckClassCastValue(const CastExpr *Cast); /// GetAddressOfBaseClass - This function will add the necessary delta to the /// load of 'this' and returns address of the base class. - Address GetAddressOfBaseClass(Address Value, - const CXXRecordDecl *Derived, + Address GetAddressOfBaseClass(Address Value, const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, bool NullCheckValue, SourceLocation Loc); - Address GetAddressOfDerivedClass(Address Value, - const CXXRecordDecl *Derived, + Address GetAddressOfDerivedClass(Address Value, const CXXRecordDecl *Derived, CastExpr::path_const_iterator PathBegin, CastExpr::path_const_iterator PathEnd, bool NullCheckValue); @@ -3185,20 +3170,17 @@ class CodeGenFunction : public CodeGenTypeCache { /// Emit assumption that vptr load == global vtable. void EmitVTableAssumptionLoad(const VPtr &vptr, Address This); - void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, - Address This, Address Src, - const CXXConstructExpr *E); + void EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Address This, + Address Src, const CXXConstructExpr *E); void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, - const ArrayType *ArrayTy, - Address ArrayPtr, + const ArrayType *ArrayTy, Address ArrayPtr, const CXXConstructExpr *E, bool NewPointerIsChecked, bool ZeroInitialization = false); void EmitCXXAggrConstructorCall(const CXXConstructorDecl *D, - llvm::Value *NumElements, - Address ArrayPtr, + llvm::Value *NumElements, Address ArrayPtr, const CXXConstructExpr *E, bool NewPointerIsChecked, bool ZeroInitialization = false); @@ -3342,7 +3324,6 @@ class CodeGenFunction : public CodeGenTypeCache { /// Get the record field index as represented in debug info. unsigned getDebugInfoFIndex(const RecordDecl *Rec, unsigned FieldIndex); - //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// @@ -3426,9 +3407,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// Returns the raw, allocated address, which is not necessarily /// the address of the object itself. It is casted to default /// address space for address space agnostic languages. - Address getAllocatedAddress() const { - return Addr; - } + Address getAllocatedAddress() const { return Addr; } /// Returns the address for the original alloca instruction. RawAddress getOriginalAllocatedAddress() const { return AllocaAddr; } @@ -3437,7 +3416,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// Note that this does not chase the forwarding pointer for /// __block decls. Address getObjectAddress(CodeGenFunction &CGF) const { - if (!IsEscapingByRef) return Addr; + if (!IsEscapingByRef) + return Addr; return CGF.emitBlockByrefAddress(Addr, Variable, /*forward*/ false); } @@ -3453,8 +3433,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// QualTypes and size expression's debug node, so that CGDebugInfo can /// reference this node when creating the DISubrange object to describe the /// array types. - void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI, - const VarDecl &D, + void EmitAndRegisterVariableArrayDimensions(CGDebugInfo *DI, const VarDecl &D, bool EmitDebugInfo); void EmitStaticVarDecl(const VarDecl &D, @@ -3557,10 +3536,9 @@ class CodeGenFunction : public CodeGenTypeCache { Address EmitCompoundStmt(const CompoundStmt &S, bool GetLast = false, AggValueSlot AVS = AggValueSlot::ignored()); - Address EmitCompoundStmtWithoutScope(const CompoundStmt &S, - bool GetLast = false, - AggValueSlot AVS = - AggValueSlot::ignored()); + Address + EmitCompoundStmtWithoutScope(const CompoundStmt &S, bool GetLast = false, + AggValueSlot AVS = AggValueSlot::ignored()); /// EmitLabel - Emit the block for the given label. It is legal to call this /// function even if there is no current insertion point. @@ -3614,8 +3592,7 @@ class CodeGenFunction : public CodeGenTypeCache { void VolatilizeTryBlocks(llvm::BasicBlock *BB, llvm::SmallPtrSet &V); - void pushSEHCleanup(CleanupKind kind, - llvm::Function *FinallyFunc); + void pushSEHCleanup(CleanupKind kind, llvm::Function *FinallyFunc); void startOutlinedSEHHelper(CodeGenFunction &ParentCGF, bool IsFilter, const Stmt *OutlinedStmt); @@ -3626,8 +3603,7 @@ class CodeGenFunction : public CodeGenTypeCache { const SEHFinallyStmt &Finally); void EmitSEHExceptionCodeSave(CodeGenFunction &ParentCGF, - llvm::Value *ParentFP, - llvm::Value *EntryEBP); + llvm::Value *ParentFP, llvm::Value *EntryEBP); llvm::Value *EmitSEHExceptionCode(); llvm::Value *EmitSEHExceptionInfo(); llvm::Value *EmitSEHAbnormalTermination(); @@ -3647,8 +3623,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// outlined functions. ParentFP is the frame pointer of the outermost parent /// frame. Address recoverAddrOfEscapedLocal(CodeGenFunction &ParentCGF, - Address ParentVar, - llvm::Value *ParentFP); + Address ParentVar, llvm::Value *ParentFP); void EmitCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef Attrs = {}); @@ -3701,8 +3676,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// the base array element). /// \param Copy Actual copygin expression for copying data from \a SrcVD to \a /// DestVD. - void EmitOMPCopy(QualType OriginalType, - Address DestAddr, Address SrcAddr, + void EmitOMPCopy(QualType OriginalType, Address DestAddr, Address SrcAddr, const VarDecl *DestVD, const VarDecl *SrcVD, const Expr *Copy); /// Emit atomic update code for constructs: \a X = \a X \a BO \a E or @@ -3828,10 +3802,8 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitOMPTargetTaskBasedDirective(const OMPExecutableDirective &S, const RegionCodeGenTy &BodyGen, OMPTargetDataInfo &InputInfo); - void processInReduction(const OMPExecutableDirective &S, - OMPTaskDataTy &Data, - CodeGenFunction &CGF, - const CapturedStmt *CS, + void processInReduction(const OMPExecutableDirective &S, OMPTaskDataTy &Data, + CodeGenFunction &CGF, const CapturedStmt *CS, OMPPrivateScope &Scope); void EmitOMPMetaDirective(const OMPMetaDirective &S); void EmitOMPParallelDirective(const OMPParallelDirective &S); @@ -4188,13 +4160,11 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitUnsupportedRValue - Emit a dummy r-value using the type of E /// and issue an ErrorUnsupported style diagnostic (using the /// provided Name). - RValue EmitUnsupportedRValue(const Expr *E, - const char *Name); + RValue EmitUnsupportedRValue(const Expr *E, const char *Name); /// EmitUnsupportedLValue - Emit a dummy l-value using the type of E and issue /// an ErrorUnsupported style diagnostic (using the provided Name). - LValue EmitUnsupportedLValue(const Expr *E, - const char *Name); + LValue EmitUnsupportedLValue(const Expr *E, const char *Name); /// EmitLValue - Emit code to compute a designator that specifies the location /// of the expression. @@ -4224,8 +4194,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// that the address will be used to access the object. LValue EmitCheckedLValue(const Expr *E, TypeCheckKind TCK); - RValue convertTempToRValue(Address addr, QualType type, - SourceLocation Loc); + RValue convertTempToRValue(Address addr, QualType type, SourceLocation Loc); void EmitAtomicInit(Expr *E, LValue lvalue); @@ -4303,25 +4272,26 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to /// the LLVM value representation. - void EmitStoreOfScalar(llvm::Value *Value, Address Addr, - bool Volatile, QualType Ty, + void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, + QualType Ty, AlignmentSource Source = AlignmentSource::Type, bool isInit = false, bool isNontemporal = false) { EmitStoreOfScalar(Value, Addr, Volatile, Ty, LValueBaseInfo(Source), CGM.getTBAAAccessInfo(Ty), isInit, isNontemporal); } - void EmitStoreOfScalar(llvm::Value *Value, Address Addr, - bool Volatile, QualType Ty, - LValueBaseInfo BaseInfo, TBAAAccessInfo TBAAInfo, - bool isInit = false, bool isNontemporal = false); + void EmitStoreOfScalar(llvm::Value *Value, Address Addr, bool Volatile, + QualType Ty, LValueBaseInfo BaseInfo, + TBAAAccessInfo TBAAInfo, bool isInit = false, + bool isNontemporal = false); /// EmitStoreOfScalar - Store a scalar value to an address, taking /// care to appropriately convert from the memory representation to /// the LLVM value representation. The l-value must be a simple /// l-value. The isInit flag indicates whether this is an initialization. /// If so, atomic qualifiers are ignored and the store is always non-atomic. - void EmitStoreOfScalar(llvm::Value *value, LValue lvalue, bool isInit=false); + void EmitStoreOfScalar(llvm::Value *value, LValue lvalue, + bool isInit = false); /// EmitLoadOfLValue - Given an expression that represents a value lvalue, /// this method emits the address of the lvalue, then loads the result as an @@ -4350,7 +4320,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// bit-field contents after the store, appropriate for use as the result of /// an assignment to the bit-field. void EmitStoreThroughBitfieldLValue(RValue Src, LValue Dst, - llvm::Value **Result=nullptr); + llvm::Value **Result = nullptr); /// Emit an l-value for an assignment (simple or compound) of complex type. LValue EmitComplexAssignmentLValue(const BinaryOperator *E); @@ -4403,9 +4373,10 @@ class CodeGenFunction : public CodeGenTypeCache { TBAAAccessInfo *TBAAInfo = nullptr); class ConstantEmission { - llvm::PointerIntPair ValueAndIsReference; + llvm::PointerIntPair ValueAndIsReference; ConstantEmission(llvm::Constant *C, bool isReference) - : ValueAndIsReference(C, isReference) {} + : ValueAndIsReference(C, isReference) {} + public: ConstantEmission() {} static ConstantEmission forReference(llvm::Constant *C) { @@ -4449,7 +4420,7 @@ class CodeGenFunction : public CodeGenTypeCache { const ObjCIvarDecl *Ivar); llvm::Value *EmitIvarOffsetAsPointerDiff(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); - LValue EmitLValueForField(LValue Base, const FieldDecl* Field); + LValue EmitLValueForField(LValue Base, const FieldDecl *Field); LValue EmitLValueForLambdaField(const FieldDecl *Field); LValue EmitLValueForLambdaField(const FieldDecl *Field, llvm::Value *ThisValue); @@ -4457,12 +4428,10 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that /// if the Field is a reference, this will return the address of the reference /// and not the address of the value stored in the reference. - LValue EmitLValueForFieldInitialization(LValue Base, - const FieldDecl* Field); + LValue EmitLValueForFieldInitialization(LValue Base, const FieldDecl *Field); - LValue EmitLValueForIvar(QualType ObjectTy, - llvm::Value* Base, const ObjCIvarDecl *Ivar, - unsigned CVRQualifiers); + LValue EmitLValueForIvar(QualType ObjectTy, llvm::Value *Base, + const ObjCIvarDecl *Ivar, unsigned CVRQualifiers); LValue EmitCXXConstructLValue(const CXXConstructExpr *E); LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E); @@ -4474,7 +4443,7 @@ class CodeGenFunction : public CodeGenTypeCache { LValue EmitStmtExprLValue(const StmtExpr *E); LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E); LValue EmitObjCSelectorLValue(const ObjCSelectorExpr *E); - void EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init); + void EmitDeclRefExprDbgValue(const DeclRefExpr *E, const APValue &Init); //===--------------------------------------------------------------------===// // Scalar Expression Emission @@ -4541,8 +4510,7 @@ class CodeGenFunction : public CodeGenTypeCache { ArrayRef args); CGCallee BuildAppleKextVirtualCall(const CXXMethodDecl *MD, - NestedNameSpecifier *Qual, - llvm::Type *Ty); + NestedNameSpecifier *Qual, llvm::Type *Ty); CGCallee BuildAppleKextVirtualDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, @@ -4628,11 +4596,10 @@ class CodeGenFunction : public CodeGenTypeCache { bool HasQualifier, NestedNameSpecifier *Qualifier, bool IsArrow, const Expr *Base, llvm::CallBase **CallOrInvoke); // Compute the object pointer. - Address EmitCXXMemberDataPointerAddress(const Expr *E, Address base, - llvm::Value *memberPtr, - const MemberPointerType *memberPtrType, - LValueBaseInfo *BaseInfo = nullptr, - TBAAAccessInfo *TBAAInfo = nullptr); + Address EmitCXXMemberDataPointerAddress( + const Expr *E, Address base, llvm::Value *memberPtr, + const MemberPointerType *memberPtrType, + LValueBaseInfo *BaseInfo = nullptr, TBAAAccessInfo *TBAAInfo = nullptr); RValue EmitCXXMemberPointerCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue, llvm::CallBase **CallOrInvoke); @@ -4693,22 +4660,18 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitCMSEClearRecord(llvm::Value *V, llvm::ArrayType *ATy, QualType RTy); - llvm::Value *EmitCommonNeonBuiltinExpr(unsigned BuiltinID, - unsigned LLVMIntrinsic, - unsigned AltLLVMIntrinsic, - const char *NameHint, - unsigned Modifier, - const CallExpr *E, - SmallVectorImpl &Ops, - Address PtrOp0, Address PtrOp1, - llvm::Triple::ArchType Arch); + llvm::Value * + EmitCommonNeonBuiltinExpr(unsigned BuiltinID, unsigned LLVMIntrinsic, + unsigned AltLLVMIntrinsic, const char *NameHint, + unsigned Modifier, const CallExpr *E, + SmallVectorImpl &Ops, Address PtrOp0, + Address PtrOp1, llvm::Triple::ArchType Arch); llvm::Function *LookupNeonLLVMIntrinsic(unsigned IntrinsicID, unsigned Modifier, llvm::Type *ArgTy, const CallExpr *E); llvm::Value *EmitNeonCall(llvm::Function *F, - SmallVectorImpl &O, - const char *name, + SmallVectorImpl &O, const char *name, unsigned shift = 0, bool rightshift = false); llvm::Value *EmitFP8NeonCall(unsigned IID, ArrayRef Tys, SmallVectorImpl &O, @@ -4812,7 +4775,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Triple::ArchType Arch); llvm::Value *EmitBPFBuiltinExpr(unsigned BuiltinID, const CallExpr *E); - llvm::Value *BuildVector(ArrayRef Ops); + llvm::Value *BuildVector(ArrayRef Ops); llvm::Value *EmitX86BuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitPPCBuiltinExpr(unsigned BuiltinID, const CallExpr *E); llvm::Value *EmitAMDGPUBuiltinExpr(unsigned BuiltinID, const CallExpr *E); @@ -4851,8 +4814,9 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitObjCBoxedExpr(const ObjCBoxedExpr *E); llvm::Value *EmitObjCArrayLiteral(const ObjCArrayLiteral *E); llvm::Value *EmitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E); - llvm::Value *EmitObjCCollectionLiteral(const Expr *E, - const ObjCMethodDecl *MethodWithObjects); + llvm::Value * + EmitObjCCollectionLiteral(const Expr *E, + const ObjCMethodDecl *MethodWithObjects); llvm::Value *EmitObjCSelectorExpr(const ObjCSelectorExpr *E); RValue EmitObjCMessageExpr(const ObjCMessageExpr *E, ReturnValueSlot Return = ReturnValueSlot()); @@ -4860,8 +4824,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// Retrieves the default cleanup kind for an ARC cleanup. /// Except under -fobjc-arc-eh, ARC cleanups are normal-only. CleanupKind getARCCleanupKind() { - return CGM.getCodeGenOpts().ObjCAutoRefCountExceptions - ? NormalAndEHCleanup : NormalCleanup; + return CGM.getCodeGenOpts().ObjCAutoRefCountExceptions ? NormalAndEHCleanup + : NormalCleanup; } // ARC primitives. @@ -4896,15 +4860,14 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Type *returnType); void EmitObjCRelease(llvm::Value *value, ARCPreciseLifetime_t precise); - std::pair + std::pair EmitARCStoreAutoreleasing(const BinaryOperator *e); - std::pair - EmitARCStoreStrong(const BinaryOperator *e, bool ignored); - std::pair + std::pair EmitARCStoreStrong(const BinaryOperator *e, + bool ignored); + std::pair EmitARCStoreUnsafeUnretained(const BinaryOperator *e, bool ignored); - llvm::Value *EmitObjCAlloc(llvm::Value *value, - llvm::Type *returnType); + llvm::Value *EmitObjCAlloc(llvm::Value *value, llvm::Type *returnType); llvm::Value *EmitObjCAllocWithZone(llvm::Value *value, llvm::Type *returnType); llvm::Value *EmitObjCAllocInit(llvm::Value *value, llvm::Type *resultType); @@ -4920,7 +4883,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *EmitARCRetainAutoreleaseScalarExpr(const Expr *expr); llvm::Value *EmitARCUnsafeUnretainedScalarExpr(const Expr *expr); - void EmitARCIntrinsicUse(ArrayRef values); + void EmitARCIntrinsicUse(ArrayRef values); void EmitARCNoopIntrinsicUse(ArrayRef values); @@ -4947,7 +4910,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitScalarExpr - Emit the computation of the specified expression of LLVM /// scalar type, returning the result. - llvm::Value *EmitScalarExpr(const Expr *E , bool IgnoreResultAssign = false); + llvm::Value *EmitScalarExpr(const Expr *E, bool IgnoreResultAssign = false); /// Emit a conversion from the specified type to the specified destination /// type, both of which are LLVM scalar types. @@ -4987,8 +4950,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// EmitComplexExpr - Emit the computation of the specified expression of /// complex type, returning the result. - ComplexPairTy EmitComplexExpr(const Expr *E, - bool IgnoreReal = false, + ComplexPairTy EmitComplexExpr(const Expr *E, bool IgnoreReal = false, bool IgnoreImag = false); /// EmitComplexExprIntoLValue - Emit the given expression of complex @@ -5004,7 +4966,8 @@ class CodeGenFunction : public CodeGenTypeCache { ComplexPairTy EmitPromotedComplexExpr(const Expr *E, QualType PromotionType); llvm::Value *EmitPromotedScalarExpr(const Expr *E, QualType PromotionType); ComplexPairTy EmitPromotedValue(ComplexPairTy result, QualType PromotionType); - ComplexPairTy EmitUnPromotedValue(ComplexPairTy result, QualType PromotionType); + ComplexPairTy EmitUnPromotedValue(ComplexPairTy result, + QualType PromotionType); Address emitAddrOfRealComponent(Address complex, QualType complexType); Address emitAddrOfImagComponent(Address complex, QualType complexType); @@ -5013,9 +4976,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// global variable that has already been created for it. If the initializer /// has a different type than GV does, this may free GV and return a different /// one. Otherwise it just returns GV. - llvm::GlobalVariable * - AddInitializerToStaticVarDecl(const VarDecl &D, - llvm::GlobalVariable *GV); + llvm::GlobalVariable *AddInitializerToStaticVarDecl(const VarDecl &D, + llvm::GlobalVariable *GV); // Emit an @llvm.invariant.start call for the given memory region. void EmitInvariantStart(llvm::Constant *Addr, CharUnits Size); @@ -5062,8 +5024,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// Emit a branch to select whether or not to perform guarded initialization. void EmitCXXGuardedInitBranch(llvm::Value *NeedsInit, llvm::BasicBlock *InitBlock, - llvm::BasicBlock *NoInitBlock, - GuardKind Kind, const VarDecl *D); + llvm::BasicBlock *NoInitBlock, GuardKind Kind, + const VarDecl *D); /// GenerateCXXGlobalInitFunc - Generates code for initializing global /// variables. @@ -5080,8 +5042,7 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Constant *>> DtorsOrStermFinalizers); - void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, - const VarDecl *D, + void GenerateCXXGlobalVarDeclInitFunc(llvm::Function *Fn, const VarDecl *D, llvm::GlobalVariable *Addr, bool PerformInit); @@ -5186,8 +5147,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// is a subtraction. llvm::Value *EmitCheckedInBoundsGEP(llvm::Type *ElemTy, llvm::Value *Ptr, ArrayRef IdxList, - bool SignedIndices, - bool IsSubtraction, + bool SignedIndices, bool IsSubtraction, SourceLocation Loc, const Twine &Name = ""); @@ -5370,8 +5330,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// if E is a parameter with the pass_object_size attribute. llvm::Value *emitBuiltinObjectSize(const Expr *E, unsigned Type, llvm::IntegerType *ResType, - llvm::Value *EmittedE, - bool IsDynamic); + llvm::Value *EmittedE, bool IsDynamic); llvm::Value *emitCountedByMemberSize(const Expr *E, llvm::Value *EmittedE, unsigned Type, @@ -5462,7 +5421,7 @@ class CodeGenFunction : public CodeGenTypeCache { void EmitDeclMetadata(); BlockByrefHelpers *buildByrefHelpers(llvm::StructType &byrefType, - const AutoVarEmission &emission); + const AutoVarEmission &emission); void AddObjCARCExceptionMetadata(llvm::Instruction *Inst); @@ -5482,7 +5441,8 @@ class CodeGenFunction : public CodeGenTypeCache { inline DominatingLLVMValue::saved_type DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { - if (!needsSaving(value)) return saved_type(value, false); + if (!needsSaving(value)) + return saved_type(value, false); // Otherwise, we need an alloca. auto align = CharUnits::fromQuantity( @@ -5497,7 +5457,8 @@ DominatingLLVMValue::save(CodeGenFunction &CGF, llvm::Value *value) { inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, saved_type value) { // If the value says it wasn't saved, trust that it's still dominating. - if (!value.getInt()) return value.getPointer(); + if (!value.getInt()) + return value.getPointer(); // Otherwise, it should be an alloca instruction, as set up in save(). auto alloca = cast(value.getPointer()); @@ -5505,12 +5466,12 @@ inline llvm::Value *DominatingLLVMValue::restore(CodeGenFunction &CGF, alloca->getAlign()); } -} // end namespace CodeGen +} // end namespace CodeGen // Map the LangOption for floating point exception behavior into // the corresponding enum in the IR. llvm::fp::ExceptionBehavior ToConstrainedExceptMD(LangOptions::FPExceptionModeKind Kind); -} // end namespace clang +} // end namespace clang #endif diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 0956296e2d5d8..c6f6fd5b9a7bd 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1067,7 +1067,8 @@ class CodeGenModule : public CodeGenTypeCache { bool shouldEmitRTTI(bool ForEH = false) { return (ForEH || getLangOpts().RTTI) && !getLangOpts().CUDAIsDevice && !(getLangOpts().OpenMP && getLangOpts().OpenMPIsTargetDevice && - (getTriple().isNVPTX() || getTriple().isAMDGPU())); + (getTriple().isNVPTX() || getTriple().isAMDGPU() || + getTriple().isSPIRV())); } /// Get the address of the RTTI descriptor for the given type. diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7375a511809b9..bcd171724c41d 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -1350,7 +1350,9 @@ bool ItaniumCXXABI::classifyReturnType(CGFunctionInfo &FI) const { // If C++ prohibits us from making a copy, return by address. if (!RD->canPassInRegisters()) { auto Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); - FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + FI.getReturnInfo() = ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/CGM.getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); return true; } return false; diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 4a2630e83b62d..5cb742a92a9bd 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1172,7 +1172,9 @@ bool MicrosoftCXXABI::classifyReturnType(CGFunctionInfo &FI) const { if (isIndirectReturn) { CharUnits Align = CGM.getContext().getTypeAlignInChars(FI.getReturnType()); - FI.getReturnInfo() = ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + FI.getReturnInfo() = ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/CGM.getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); // MSVC always passes `this` before the `sret` parameter. FI.getReturnInfo().setSRetAfterThis(FI.isInstanceMethod()); diff --git a/clang/lib/CodeGen/SwiftCallingConv.cpp b/clang/lib/CodeGen/SwiftCallingConv.cpp index 1ff4ece2811ec..10f9f20bca313 100644 --- a/clang/lib/CodeGen/SwiftCallingConv.cpp +++ b/clang/lib/CodeGen/SwiftCallingConv.cpp @@ -796,11 +796,14 @@ bool swiftcall::mustPassRecordIndirectly(CodeGenModule &CGM, static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering, bool forReturn, - CharUnits alignmentForIndirect) { + CharUnits alignmentForIndirect, + unsigned IndirectAS) { if (lowering.empty()) { return ABIArgInfo::getIgnore(); } else if (lowering.shouldPassIndirectly(forReturn)) { - return ABIArgInfo::getIndirect(alignmentForIndirect, /*byval*/ false); + return ABIArgInfo::getIndirect(alignmentForIndirect, + /*AddrSpace=*/IndirectAS, + /*byval=*/false); } else { auto types = lowering.getCoerceAndExpandTypes(); return ABIArgInfo::getCoerceAndExpand(types.first, types.second); @@ -809,18 +812,21 @@ static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering, static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, bool forReturn) { + unsigned IndirectAS = CGM.getDataLayout().getAllocaAddrSpace(); if (auto recordType = dyn_cast(type)) { auto record = recordType->getDecl(); auto &layout = CGM.getContext().getASTRecordLayout(record); if (mustPassRecordIndirectly(CGM, record)) - return ABIArgInfo::getIndirect(layout.getAlignment(), /*byval*/ false); + return ABIArgInfo::getIndirect(layout.getAlignment(), + /*AddrSpace=*/IndirectAS, /*byval=*/false); SwiftAggLowering lowering(CGM); lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout); lowering.finish(); - return classifyExpandedType(lowering, forReturn, layout.getAlignment()); + return classifyExpandedType(lowering, forReturn, layout.getAlignment(), + IndirectAS); } // Just assume that all of our target ABIs can support returning at least @@ -836,7 +842,7 @@ static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type, lowering.finish(); CharUnits alignment = CGM.getContext().getTypeAlignInChars(type); - return classifyExpandedType(lowering, forReturn, alignment); + return classifyExpandedType(lowering, forReturn, alignment, IndirectAS); } // Member pointer types need to be expanded, but it's a simple form of diff --git a/clang/lib/CodeGen/Targets/AArch64.cpp b/clang/lib/CodeGen/Targets/AArch64.cpp index dc3a1d4287be1..d6e0e720a0941 100644 --- a/clang/lib/CodeGen/Targets/AArch64.cpp +++ b/clang/lib/CodeGen/Targets/AArch64.cpp @@ -327,7 +327,8 @@ ABIArgInfo AArch64ABIInfo::coerceIllegalVector(QualType Ty, unsigned &NSRN, return ABIArgInfo::getDirect(ResType); } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo AArch64ABIInfo::coerceAndExpandPureScalableAggregate( @@ -335,7 +336,8 @@ ABIArgInfo AArch64ABIInfo::coerceAndExpandPureScalableAggregate( const SmallVectorImpl &UnpaddedCoerceToSeq, unsigned &NSRN, unsigned &NPRN) const { if (!IsNamedArg || NSRN + NVec > 8 || NPRN + NPred > 4) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); NSRN += NVec; NPRN += NPred; @@ -375,7 +377,8 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > 128) - return getNaturalAlignIndirect(Ty, false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + false); if (Ty->isVectorType()) NSRN = std::min(NSRN + 1, 8u); @@ -411,8 +414,9 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, // Structures with either a non-trivial destructor or a non-trivial // copy constructor are always indirect. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { - return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == - CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory); } // Empty records: @@ -489,7 +493,8 @@ ABIArgInfo AArch64ABIInfo::classifyArgumentType(QualType Ty, bool IsVariadicFn, : llvm::ArrayType::get(BaseTy, Size / Alignment)); } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, @@ -507,7 +512,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, // Large vector types should be returned via memory. if (RetTy->isVectorType() && getContext().getTypeSize(RetTy) > 128) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); if (!passAsAggregateType(RetTy)) { // Treat an enum type as its underlying type. @@ -516,7 +521,8 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > 128) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); return (isPromotableIntegerTypeForABI(RetTy) && isDarwinPCS() ? ABIArgInfo::getExtend(RetTy) @@ -575,7 +581,7 @@ ABIArgInfo AArch64ABIInfo::classifyReturnType(QualType RetTy, return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Size)); } - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); } /// isIllegalVectorType - check whether the vector type is legal for AArch64. diff --git a/clang/lib/CodeGen/Targets/AMDGPU.cpp b/clang/lib/CodeGen/Targets/AMDGPU.cpp index 788eac5f28231..dc45def4f3249 100644 --- a/clang/lib/CodeGen/Targets/AMDGPU.cpp +++ b/clang/lib/CodeGen/Targets/AMDGPU.cpp @@ -236,7 +236,8 @@ ABIArgInfo AMDGPUABIInfo::classifyArgumentType(QualType Ty, bool Variadic, // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (auto RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); // Ignore empty structs/unions. if (isEmptyRecord(getContext(), Ty, true)) diff --git a/clang/lib/CodeGen/Targets/ARC.cpp b/clang/lib/CodeGen/Targets/ARC.cpp index 1904e8fdb3888..c8db7e8f9706e 100644 --- a/clang/lib/CodeGen/Targets/ARC.cpp +++ b/clang/lib/CodeGen/Targets/ARC.cpp @@ -69,16 +69,19 @@ class ARCTargetCodeGenInfo : public TargetCodeGenInfo { ABIArgInfo ARCABIInfo::getIndirectByRef(QualType Ty, bool HasFreeRegs) const { - return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) : - getNaturalAlignIndirect(Ty, false); + return HasFreeRegs ? getNaturalAlignIndirectInReg(Ty) + : getNaturalAlignIndirect( + Ty, getDataLayout().getAllocaAddrSpace(), false); } ABIArgInfo ARCABIInfo::getIndirectByValue(QualType Ty) const { // Compute the byval alignment. const unsigned MinABIStackAlignInBytes = 4; unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, - TypeAlign > MinABIStackAlignInBytes); + return ABIArgInfo::getIndirect( + CharUnits::fromQuantity(4), + /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true, TypeAlign > MinABIStackAlignInBytes); } RValue ARCABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp index 77641ce10e3d3..a6d9a5549355c 100644 --- a/clang/lib/CodeGen/Targets/ARM.cpp +++ b/clang/lib/CodeGen/Targets/ARM.cpp @@ -299,7 +299,9 @@ ABIArgInfo ARMABIInfo::coerceIllegalVector(QualType Ty) const { llvm::Type::getInt32Ty(getVMContext()), Size / 32); return ABIArgInfo::getDirect(ResType); } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo ARMABIInfo::classifyHomogeneousAggregate(QualType Ty, @@ -381,7 +383,9 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > 64) - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty, CGT.ConvertType(Ty)) @@ -389,7 +393,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); } // Empty records are either ignored completely or passed as if they were a @@ -429,7 +434,8 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, // bigger than 128-bits, they get placed in space allocated by the caller, // and a pointer is passed. return ABIArgInfo::getIndirect( - CharUnits::fromQuantity(getContext().getTypeAlign(Ty) / 8), false); + CharUnits::fromQuantity(getContext().getTypeAlign(Ty) / 8), + getDataLayout().getAllocaAddrSpace(), false); } // Support byval for ARM. @@ -447,9 +453,10 @@ ABIArgInfo ARMABIInfo::classifyArgumentType(QualType Ty, bool isVariadic, } if (getContext().getTypeSizeInChars(Ty) > CharUnits::fromQuantity(64)) { assert(getABIKind() != ARMABIKind::AAPCS16_VFP && "unexpected byval"); - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign), - /*ByVal=*/true, - /*Realign=*/TyAlign > ABIAlign); + return ABIArgInfo::getIndirect( + CharUnits::fromQuantity(ABIAlign), + /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true, /*Realign=*/TyAlign > ABIAlign); } // Otherwise, pass by coercing to a structure of the appropriate size. @@ -566,7 +573,8 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, if (const VectorType *VT = RetTy->getAs()) { // Large vector types should be returned via memory. if (getContext().getTypeSize(RetTy) > 128) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); // TODO: FP16/BF16 vectors should be converted to integer vectors // This check is similar to isIllegalVectorType - refactor? if ((!getTarget().hasLegalHalfType() && @@ -584,7 +592,9 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > 64) - return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + return getNaturalAlignIndirect( + RetTy, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect(); @@ -615,7 +625,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, } // Otherwise return in memory. - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); } // Otherwise this is an AAPCS variant. @@ -653,7 +663,7 @@ ABIArgInfo ARMABIInfo::classifyReturnType(QualType RetTy, bool isVariadic, return ABIArgInfo::getDirect(CoerceTy); } - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); } /// isIllegalVector - check whether Ty is an illegal vector type. diff --git a/clang/lib/CodeGen/Targets/AVR.cpp b/clang/lib/CodeGen/Targets/AVR.cpp index 50547dd6dec5e..26e2a22f14d1e 100644 --- a/clang/lib/CodeGen/Targets/AVR.cpp +++ b/clang/lib/CodeGen/Targets/AVR.cpp @@ -45,7 +45,7 @@ class AVRABIInfo : public DefaultABIInfo { // stack slot, along with a pointer as the function's implicit argument. if (getContext().getTypeSize(Ty) > RetRegs * 8) { LargeRet = true; - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); } // An i8 return value should not be extended to i16, since AVR has 8-bit // registers. diff --git a/clang/lib/CodeGen/Targets/BPF.cpp b/clang/lib/CodeGen/Targets/BPF.cpp index 2849222f7a186..880a891083c3a 100644 --- a/clang/lib/CodeGen/Targets/BPF.cpp +++ b/clang/lib/CodeGen/Targets/BPF.cpp @@ -42,7 +42,8 @@ class BPFABIInfo : public DefaultABIInfo { } return ABIArgInfo::getDirect(CoerceTy); } else { - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, + getDataLayout().getAllocaAddrSpace()); } } @@ -52,7 +53,8 @@ class BPFABIInfo : public DefaultABIInfo { ASTContext &Context = getContext(); if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, + getDataLayout().getAllocaAddrSpace()); return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) : ABIArgInfo::getDirect()); @@ -63,7 +65,8 @@ class BPFABIInfo : public DefaultABIInfo { return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy)) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); // Treat an enum type as its underlying type. if (const EnumType *EnumTy = RetTy->getAs()) @@ -72,7 +75,8 @@ class BPFABIInfo : public DefaultABIInfo { ASTContext &Context = getContext(); if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > Context.getTypeSize(Context.Int128Ty)) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); // Caller will do necessary sign/zero extension. return ABIArgInfo::getDirect(); diff --git a/clang/lib/CodeGen/Targets/CSKY.cpp b/clang/lib/CodeGen/Targets/CSKY.cpp index d8720afd1a713..ef26d483a180a 100644 --- a/clang/lib/CodeGen/Targets/CSKY.cpp +++ b/clang/lib/CodeGen/Targets/CSKY.cpp @@ -82,8 +82,9 @@ ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { if (ArgGPRsLeft) ArgGPRsLeft -= 1; - return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == - CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory); } // Ignore empty structs/unions. @@ -144,7 +145,8 @@ ABIArgInfo CSKYABIInfo::classifyArgumentType(QualType Ty, int &ArgGPRsLeft, llvm::IntegerType::get(getVMContext(), XLen), (Size + 31) / XLen)); } } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo CSKYABIInfo::classifyReturnType(QualType RetTy) const { diff --git a/clang/lib/CodeGen/Targets/Hexagon.cpp b/clang/lib/CodeGen/Targets/Hexagon.cpp index aada8d0d61303..2976657360650 100644 --- a/clang/lib/CodeGen/Targets/Hexagon.cpp +++ b/clang/lib/CodeGen/Targets/Hexagon.cpp @@ -105,14 +105,16 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty, HexagonAdjustRegsLeft(Size, RegsLeft); if (Size > 64 && Ty->isBitIntType()) - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); return isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) : ABIArgInfo::getDirect(); } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); // Ignore empty records. if (isEmptyRecord(getContext(), Ty, true)) @@ -122,7 +124,8 @@ ABIArgInfo HexagonABIInfo::classifyArgumentType(QualType Ty, unsigned Align = getContext().getTypeAlign(Ty); if (Size > 64) - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); if (HexagonAdjustRegsLeft(Size, RegsLeft)) Align = Size <= 32 ? 32 : 64; @@ -151,7 +154,8 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { } // Large vector types should be returned via memory. if (Size > 64) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); } if (!isAggregateTypeForABI(RetTy)) { @@ -160,7 +164,8 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { RetTy = EnumTy->getDecl()->getIntegerType(); if (Size > 64 && RetTy->isBitIntType()) - return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + return getNaturalAlignIndirect( + RetTy, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); return isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect(); @@ -176,7 +181,8 @@ ABIArgInfo HexagonABIInfo::classifyReturnType(QualType RetTy) const { Size = llvm::bit_ceil(Size); return ABIArgInfo::getDirect(llvm::Type::getIntNTy(getVMContext(), Size)); } - return getNaturalAlignIndirect(RetTy, /*ByVal=*/true); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); } Address HexagonABIInfo::EmitVAArgFromMemory(CodeGenFunction &CGF, diff --git a/clang/lib/CodeGen/Targets/Lanai.cpp b/clang/lib/CodeGen/Targets/Lanai.cpp index 2578fc0291e76..6f75bd54a8ef2 100644 --- a/clang/lib/CodeGen/Targets/Lanai.cpp +++ b/clang/lib/CodeGen/Targets/Lanai.cpp @@ -72,15 +72,17 @@ ABIArgInfo LanaiABIInfo::getIndirectResult(QualType Ty, bool ByVal, --State.FreeRegs; // Non-byval indirects just use one pointer. return getNaturalAlignIndirectInReg(Ty); } - return getNaturalAlignIndirect(Ty, false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + false); } // Compute the byval alignment. const unsigned MinABIStackAlignInBytes = 4; unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true, - /*Realign=*/TypeAlign > - MinABIStackAlignInBytes); + return ABIArgInfo::getIndirect( + CharUnits::fromQuantity(4), + /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), /*ByVal=*/true, + /*Realign=*/TypeAlign > MinABIStackAlignInBytes); } ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, @@ -92,7 +94,9 @@ ABIArgInfo LanaiABIInfo::classifyArgumentType(QualType Ty, if (RAA == CGCXXABI::RAA_Indirect) { return getIndirectResult(Ty, /*ByVal=*/false, State); } else if (RAA == CGCXXABI::RAA_DirectInMemory) { - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); } } diff --git a/clang/lib/CodeGen/Targets/LoongArch.cpp b/clang/lib/CodeGen/Targets/LoongArch.cpp index 6c90e48a5ea41..0f689371a60db 100644 --- a/clang/lib/CodeGen/Targets/LoongArch.cpp +++ b/clang/lib/CodeGen/Targets/LoongArch.cpp @@ -305,8 +305,9 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { if (GARsLeft) GARsLeft -= 1; - return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == - CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory); } uint64_t Size = getContext().getTypeSize(Ty); @@ -381,7 +382,9 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, if (EIT->getNumBits() > 128 || (!getContext().getTargetInfo().hasInt128Type() && EIT->getNumBits() > 64)) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } return ABIArgInfo::getDirect(); @@ -404,7 +407,9 @@ ABIArgInfo LoongArchABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, return ABIArgInfo::getDirect( llvm::ArrayType::get(llvm::IntegerType::get(getVMContext(), GRLen), 2)); } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo LoongArchABIInfo::classifyReturnType(QualType RetTy) const { diff --git a/clang/lib/CodeGen/Targets/Mips.cpp b/clang/lib/CodeGen/Targets/Mips.cpp index 771a85c84b357..c025f7312959c 100644 --- a/clang/lib/CodeGen/Targets/Mips.cpp +++ b/clang/lib/CodeGen/Targets/Mips.cpp @@ -226,7 +226,8 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { Offset = OrigOffset + MinABIStackAlignInBytes; - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); } // If we have reached here, aggregates are passed directly by coercing to @@ -248,7 +249,7 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { if (EIT->getNumBits() > 128 || (EIT->getNumBits() > 64 && !getContext().getTargetInfo().hasInt128Type())) - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); // All integral types are promoted to the GPR width. if (Ty->isIntegralOrEnumerationType()) @@ -327,7 +328,7 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { } } - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); } // Treat an enum type as its underlying type. @@ -339,7 +340,8 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { if (EIT->getNumBits() > 128 || (EIT->getNumBits() > 64 && !getContext().getTargetInfo().hasInt128Type())) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); if (isPromotableIntegerTypeForABI(RetTy)) return ABIArgInfo::getExtend(RetTy); diff --git a/clang/lib/CodeGen/Targets/NVPTX.cpp b/clang/lib/CodeGen/Targets/NVPTX.cpp index b82e4ddb9f3f2..98a90613a2d3e 100644 --- a/clang/lib/CodeGen/Targets/NVPTX.cpp +++ b/clang/lib/CodeGen/Targets/NVPTX.cpp @@ -192,14 +192,18 @@ ABIArgInfo NVPTXABIInfo::classifyArgumentType(QualType Ty) const { return ABIArgInfo::getDirect( CGInfo.getCUDADeviceBuiltinTextureDeviceType()); } - return getNaturalAlignIndirect(Ty, /* byval */ true); + return getNaturalAlignIndirect( + Ty, /* AddrSpace */ getDataLayout().getAllocaAddrSpace(), + /* byval */ true); } if (const auto *EIT = Ty->getAs()) { if ((EIT->getNumBits() > 128) || (!getContext().getTargetInfo().hasInt128Type() && EIT->getNumBits() > 64)) - return getNaturalAlignIndirect(Ty, /* byval */ true); + return getNaturalAlignIndirect( + Ty, /* AddrSpace */ getDataLayout().getAllocaAddrSpace(), + /* byval */ true); } return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) @@ -375,11 +379,8 @@ void CodeGenModule::handleCUDALaunchBoundsAttr(llvm::Function *F, if (MinBlocks > 0) { if (MinBlocksVal) *MinBlocksVal = MinBlocks.getExtValue(); - if (F) { - // Create !{, metadata !"minctasm", i32 } node - NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "minctasm", - MinBlocks.getExtValue()); - } + if (F) + F->addFnAttr("nvvm.minctasm", llvm::utostr(MinBlocks.getExtValue())); } } if (Attr->getMaxBlocks()) { @@ -388,11 +389,9 @@ void CodeGenModule::handleCUDALaunchBoundsAttr(llvm::Function *F, if (MaxBlocks > 0) { if (MaxClusterRankVal) *MaxClusterRankVal = MaxBlocks.getExtValue(); - if (F) { - // Create !{, metadata !"maxclusterrank", i32 } node - NVPTXTargetCodeGenInfo::addNVVMMetadata(F, "maxclusterrank", - MaxBlocks.getExtValue()); - } + if (F) + F->addFnAttr("nvvm.maxclusterrank", + llvm::utostr(MaxBlocks.getExtValue())); } } } diff --git a/clang/lib/CodeGen/Targets/PNaCl.cpp b/clang/lib/CodeGen/Targets/PNaCl.cpp index 9b7d757df3a39..358010785850e 100644 --- a/clang/lib/CodeGen/Targets/PNaCl.cpp +++ b/clang/lib/CodeGen/Targets/PNaCl.cpp @@ -63,8 +63,9 @@ RValue PNaClABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const { if (isAggregateTypeForABI(Ty)) { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); } else if (const EnumType *EnumTy = Ty->getAs()) { // Treat an enum type as its underlying type. Ty = EnumTy->getDecl()->getIntegerType(); @@ -75,7 +76,7 @@ ABIArgInfo PNaClABIInfo::classifyArgumentType(QualType Ty) const { // Treat bit-precise integers as integers if <= 64, otherwise pass // indirectly. if (EIT->getNumBits() > 64) - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); return ABIArgInfo::getDirect(); } @@ -89,12 +90,13 @@ ABIArgInfo PNaClABIInfo::classifyReturnType(QualType RetTy) const { // In the PNaCl ABI we always return records/structures on the stack. if (isAggregateTypeForABI(RetTy)) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); // Treat bit-precise integers as integers if <= 64, otherwise pass indirectly. if (const auto *EIT = RetTy->getAs()) { if (EIT->getNumBits() > 64) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); return ABIArgInfo::getDirect(); } diff --git a/clang/lib/CodeGen/Targets/PPC.cpp b/clang/lib/CodeGen/Targets/PPC.cpp index 989e46f4b66a7..4df4c9f3c3475 100644 --- a/clang/lib/CodeGen/Targets/PPC.cpp +++ b/clang/lib/CodeGen/Targets/PPC.cpp @@ -189,7 +189,7 @@ ABIArgInfo AIXABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy)) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); return (isPromotableTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect()); @@ -208,13 +208,16 @@ ABIArgInfo AIXABIInfo::classifyArgumentType(QualType Ty) const { // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); CharUnits CCAlign = getParamTypeAlignment(Ty); CharUnits TyAlign = getContext().getTypeAlignInChars(Ty); - return ABIArgInfo::getIndirect(CCAlign, /*ByVal*/ true, - /*Realign*/ TyAlign > CCAlign); + return ABIArgInfo::getIndirect( + CCAlign, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true, + /*Realign=*/TyAlign > CCAlign); } return (isPromotableTypeForABI(Ty) @@ -833,7 +836,8 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { if (Ty->isVectorType()) { uint64_t Size = getContext().getTypeSize(Ty); if (Size > 128) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); else if (Size < 128) { llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size); return ABIArgInfo::getDirect(CoerceTy); @@ -842,11 +846,13 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { if (const auto *EIT = Ty->getAs()) if (EIT->getNumBits() > 128) - return getNaturalAlignIndirect(Ty, /*ByVal=*/true); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); if (isAggregateTypeForABI(Ty)) { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); uint64_t ABIAlign = getParamTypeAlignment(Ty).getQuantity(); uint64_t TyAlign = getContext().getTypeAlignInChars(Ty).getQuantity(); @@ -887,9 +893,10 @@ PPC64_SVR4_ABIInfo::classifyArgumentType(QualType Ty) const { } // All other aggregates are passed ByVal. - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(ABIAlign), - /*ByVal=*/true, - /*Realign=*/TyAlign > ABIAlign); + return ABIArgInfo::getIndirect( + CharUnits::fromQuantity(ABIAlign), + /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true, /*Realign=*/TyAlign > ABIAlign); } return (isPromotableTypeForABI(Ty) @@ -910,7 +917,8 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { if (RetTy->isVectorType()) { uint64_t Size = getContext().getTypeSize(RetTy); if (Size > 128) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, + getDataLayout().getAllocaAddrSpace()); else if (Size < 128) { llvm::Type *CoerceTy = llvm::IntegerType::get(getVMContext(), Size); return ABIArgInfo::getDirect(CoerceTy); @@ -919,7 +927,8 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { if (const auto *EIT = RetTy->getAs()) if (EIT->getNumBits() > 128) - return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + return getNaturalAlignIndirect( + RetTy, getDataLayout().getAllocaAddrSpace(), /*ByVal=*/false); if (isAggregateTypeForABI(RetTy)) { // ELFv2 homogeneous aggregates are returned as array types. @@ -949,7 +958,7 @@ PPC64_SVR4_ABIInfo::classifyReturnType(QualType RetTy) const { } // All other aggregates are returned indirectly. - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); } return (isPromotableTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) diff --git a/clang/lib/CodeGen/Targets/RISCV.cpp b/clang/lib/CodeGen/Targets/RISCV.cpp index 2c48ba37fd206..aa5fb6329c1c1 100644 --- a/clang/lib/CodeGen/Targets/RISCV.cpp +++ b/clang/lib/CodeGen/Targets/RISCV.cpp @@ -410,8 +410,9 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) { if (ArgGPRsLeft) ArgGPRsLeft -= 1; - return getNaturalAlignIndirect(Ty, /*ByVal=*/RAA == - CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/RAA == CGCXXABI::RAA_DirectInMemory); } uint64_t Size = getContext().getTypeSize(Ty); @@ -492,7 +493,9 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, if (EIT->getNumBits() > 128 || (!getContext().getTargetInfo().hasInt128Type() && EIT->getNumBits() > 64)) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } return ABIArgInfo::getDirect(); @@ -524,7 +527,9 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, llvm::IntegerType::get(getVMContext(), XLen), 2)); } } - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const { diff --git a/clang/lib/CodeGen/Targets/SPIR.cpp b/clang/lib/CodeGen/Targets/SPIR.cpp index 5c75e985e953d..b81ed29a5159b 100644 --- a/clang/lib/CodeGen/Targets/SPIR.cpp +++ b/clang/lib/CodeGen/Targets/SPIR.cpp @@ -156,8 +156,10 @@ ABIArgInfo SPIRVABIInfo::classifyKernelArgumentType(QualType Ty) const { // copied to be valid on the device. // This behavior follows the CUDA spec // https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#global-function-argument-processing, - // and matches the NVPTX implementation. - return getNaturalAlignIndirect(Ty, /* byval */ true); + // and matches the NVPTX implementation. TODO: hardcoding to 0 should be + // revisited if HIPSPV / byval starts making use of the AS of an indirect + // arg. + return getNaturalAlignIndirect(Ty, /*AddrSpace=*/0, /*byval=*/true); } } return classifyArgumentType(Ty); @@ -172,7 +174,8 @@ ABIArgInfo SPIRVABIInfo::classifyArgumentType(QualType Ty) const { // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (auto RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); if (const RecordType *RT = Ty->getAs()) { const RecordDecl *RD = RT->getDecl(); diff --git a/clang/lib/CodeGen/Targets/Sparc.cpp b/clang/lib/CodeGen/Targets/Sparc.cpp index da8c7219be263..9642196b78c63 100644 --- a/clang/lib/CodeGen/Targets/Sparc.cpp +++ b/clang/lib/CodeGen/Targets/Sparc.cpp @@ -232,7 +232,9 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { // Anything too big to fit in registers is passed with an explicit indirect // pointer / sret pointer. if (Size > SizeLimit) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect( + Ty, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) @@ -253,7 +255,8 @@ SparcV9ABIInfo::classifyType(QualType Ty, unsigned SizeLimit) const { // If a C++ object has either a non-trivial copy constructor or a non-trivial // destructor, it is passed with an explicit indirect pointer / sret pointer. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); // This is a small aggregate type that should be passed in registers. // Build a coercion type from the LLVM struct type. diff --git a/clang/lib/CodeGen/Targets/SystemZ.cpp b/clang/lib/CodeGen/Targets/SystemZ.cpp index 9bb8ddbc548d2..8a9fddace76d9 100644 --- a/clang/lib/CodeGen/Targets/SystemZ.cpp +++ b/clang/lib/CodeGen/Targets/SystemZ.cpp @@ -406,7 +406,7 @@ ABIArgInfo SystemZABIInfo::classifyReturnType(QualType RetTy) const { if (isVectorArgumentType(RetTy)) return ABIArgInfo::getDirect(); if (isCompoundType(RetTy) || getContext().getTypeSize(RetTy) > 64) - return getNaturalAlignIndirect(RetTy); + return getNaturalAlignIndirect(RetTy, getDataLayout().getAllocaAddrSpace()); return (isPromotableIntegerTypeForABI(RetTy) ? ABIArgInfo::getExtend(RetTy) : ABIArgInfo::getDirect()); } @@ -417,7 +417,8 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { // Handle the generic C++ ABI. if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); // Integers and enums are extended to full register width. if (isPromotableIntegerTypeForABI(Ty)) @@ -434,7 +435,8 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { // Values that are not 1, 2, 4 or 8 bytes in size are passed indirectly. if (Size != 8 && Size != 16 && Size != 32 && Size != 64) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); // Handle small structures. if (const RecordType *RT = Ty->getAs()) { @@ -442,7 +444,8 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { // fail the size test above. const RecordDecl *RD = RT->getDecl(); if (RD->hasFlexibleArrayMember()) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); // The structure is passed as an unextended integer, a float, or a double. if (isFPArgumentType(SingleElementTy)) { @@ -459,7 +462,8 @@ ABIArgInfo SystemZABIInfo::classifyArgumentType(QualType Ty) const { // Non-structure compounds are passed indirectly. if (isCompoundType(Ty)) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); return ABIArgInfo::getDirect(nullptr); } diff --git a/clang/lib/CodeGen/Targets/WebAssembly.cpp b/clang/lib/CodeGen/Targets/WebAssembly.cpp index 70a968fe93ca7..9217c78a540a3 100644 --- a/clang/lib/CodeGen/Targets/WebAssembly.cpp +++ b/clang/lib/CodeGen/Targets/WebAssembly.cpp @@ -103,7 +103,8 @@ ABIArgInfo WebAssemblyABIInfo::classifyArgumentType(QualType Ty) const { // Records with non-trivial destructors/copy-constructors should not be // passed by value. if (auto RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); // Ignore empty structs/unions. if (isEmptyRecord(getContext(), Ty, true)) return ABIArgInfo::getIgnore(); diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp index 7e470abe078f5..b7a1374d5b399 100644 --- a/clang/lib/CodeGen/Targets/X86.cpp +++ b/clang/lib/CodeGen/Targets/X86.cpp @@ -462,7 +462,9 @@ ABIArgInfo X86_32ABIInfo::getIndirectReturnResult(QualType RetTy, CCState &State if (!IsMCUABI) return getNaturalAlignIndirectInReg(RetTy); } - return getNaturalAlignIndirect(RetTy, /*ByVal=*/false); + return getNaturalAlignIndirect( + RetTy, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy, @@ -599,20 +601,26 @@ ABIArgInfo X86_32ABIInfo::getIndirectResult(QualType Ty, bool ByVal, if (!IsMCUABI) return getNaturalAlignIndirectInReg(Ty); } - return getNaturalAlignIndirect(Ty, false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + false); } // Compute the byval alignment. unsigned TypeAlign = getContext().getTypeAlign(Ty) / 8; unsigned StackAlign = getTypeStackAlignInBytes(Ty, TypeAlign); if (StackAlign == 0) - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(4), /*ByVal=*/true); + return ABIArgInfo::getIndirect( + CharUnits::fromQuantity(4), + /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/true); // If the stack alignment is less than the type alignment, realign the // argument. bool Realign = TypeAlign > StackAlign; - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(StackAlign), - /*ByVal=*/true, Realign); + return ABIArgInfo::getIndirect( + CharUnits::fromQuantity(StackAlign), + /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), /*ByVal=*/true, + Realign); } X86_32ABIInfo::Class X86_32ABIInfo::classify(QualType Ty) const { @@ -2180,13 +2188,13 @@ ABIArgInfo X86_64ABIInfo::getIndirectReturnResult(QualType Ty) const { Ty = EnumTy->getDecl()->getIntegerType(); if (Ty->isBitIntType()) - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); return (isPromotableIntegerTypeForABI(Ty) ? ABIArgInfo::getExtend(Ty) : ABIArgInfo::getDirect()); } - return getNaturalAlignIndirect(Ty); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace()); } bool X86_64ABIInfo::IsIllegalVectorType(QualType Ty) const { @@ -2226,7 +2234,8 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, } if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); // Compute the byval alignment. We specify the alignment of the byval in all // cases so that the mid-level optimizer knows the alignment of the byval. @@ -2263,7 +2272,8 @@ ABIArgInfo X86_64ABIInfo::getIndirectResult(QualType Ty, Size)); } - return ABIArgInfo::getIndirect(CharUnits::fromQuantity(Align)); + return ABIArgInfo::getIndirect(CharUnits::fromQuantity(Align), + getDataLayout().getAllocaAddrSpace()); } /// The ABI specifies that a value should be passed in a full vector XMM/YMM @@ -3299,12 +3309,13 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, if (RT) { if (!IsReturnType) { if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(RT, getCXXABI())) - return getNaturalAlignIndirect(Ty, RAA == CGCXXABI::RAA_DirectInMemory); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + RAA == CGCXXABI::RAA_DirectInMemory); } if (RT->getDecl()->hasFlexibleArrayMember()) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); - + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } const Type *Base = nullptr; @@ -3320,7 +3331,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, return ABIArgInfo::getDirect(); return ABIArgInfo::getExpand(); } - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + return ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } else if (IsVectorCall) { if (FreeSSERegs >= NumElts && (IsReturnType || Ty->isBuiltinType() || Ty->isVectorType())) { @@ -3330,7 +3343,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, return ABIArgInfo::getExpand(); } else if (!Ty->isBuiltinType() && !Ty->isVectorType()) { // HVAs are delayed and reclassified in the 2nd step. - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + return ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } } } @@ -3347,7 +3362,8 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is // not 1, 2, 4, or 8 bytes, must be passed by reference." if (Width > 64 || !llvm::isPowerOf2_64(Width)) - return getNaturalAlignIndirect(Ty, /*ByVal=*/false); + return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); // Otherwise, coerce it to a small integer. return ABIArgInfo::getDirect(llvm::IntegerType::get(getVMContext(), Width)); @@ -3366,7 +3382,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, if (IsMingw64) { const llvm::fltSemantics *LDF = &getTarget().getLongDoubleFormat(); if (LDF == &llvm::APFloat::x87DoubleExtended()) - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + return ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } break; @@ -3376,7 +3394,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, // than 8 bytes are passed indirectly. GCC follows it. We follow it too, // even though it isn't particularly efficient. if (!IsReturnType) - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + return ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); // Mingw64 GCC returns i128 in XMM0. Coerce to v2i64 to handle that. // Clang matches them for compatibility. @@ -3396,7 +3416,9 @@ ABIArgInfo WinX86_64ABIInfo::classify(QualType Ty, unsigned &FreeSSERegs, // the power of 2. if (Width <= 64) return ABIArgInfo::getDirect(); - return ABIArgInfo::getIndirect(Align, /*ByVal=*/false); + return ABIArgInfo::getIndirect( + Align, /*AddrSpace=*/getDataLayout().getAllocaAddrSpace(), + /*ByVal=*/false); } return ABIArgInfo::getDirect(); diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp index e66e5a32e58ac..6a35a2feabc9b 100644 --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -936,7 +936,8 @@ void ROCMToolChain::addClangTargetOptions( DriverArgs.hasArg(options::OPT_nostdlib)) return; - if (DriverArgs.hasArg(options::OPT_nogpulib)) + if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true)) return; // Get the device name and canonicalize it @@ -950,13 +951,7 @@ void ROCMToolChain::addClangTargetOptions( ABIVer)) return; - std::tuple GPUSan( - DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, true), - getSanitizerArgs(DriverArgs)); - bool Wave64 = isWave64(DriverArgs, Kind); - // TODO: There are way too many flags that change this. Do we need to check // them all? bool DAZ = DriverArgs.hasArg(options::OPT_cl_denorms_are_zero) || @@ -969,6 +964,12 @@ void ROCMToolChain::addClangTargetOptions( bool CorrectSqrt = DriverArgs.hasArg(options::OPT_cl_fp32_correctly_rounded_divide_sqrt); + // GPU Sanitizer currently only supports ASan and is enabled through host + // ASan. + bool GPUSan = DriverArgs.hasFlag(options::OPT_fgpu_sanitize, + options::OPT_fno_gpu_sanitize, true) && + getSanitizerArgs(DriverArgs).needsAsanRt(); + // Add the OpenCL specific bitcode library. llvm::SmallVector BCLibs; BCLibs.emplace_back(RocmInstallation->getOpenCLPath().str()); @@ -1009,30 +1010,25 @@ llvm::SmallVector RocmInstallationDetector::getCommonBitcodeLibs( const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64, bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath, - bool CorrectSqrt, DeviceLibABIVersion ABIVer, - const std::tuple &GPUSan, - bool isOpenMP = false) const { + bool CorrectSqrt, DeviceLibABIVersion ABIVer, bool GPUSan, + bool isOpenMP) const { llvm::SmallVector BCLibs; - auto GPUSanEnabled = [GPUSan]() { return std::get(GPUSan); }; auto AddBCLib = [&](ToolChain::BitCodeLibraryInfo BCLib, bool Internalize = true) { BCLib.ShouldInternalize = Internalize; BCLibs.emplace_back(BCLib); }; auto AddSanBCLibs = [&]() { - if (GPUSanEnabled()) { - auto SanArgs = std::get(GPUSan); - if (SanArgs.needsAsanRt()) - AddBCLib(getAsanRTLPath(), false); - } + if (GPUSan) + AddBCLib(getAsanRTLPath(), false); }; AddSanBCLibs(); AddBCLib(getOCMLPath()); if (!isOpenMP) AddBCLib(getOCKLPath()); - else if (GPUSanEnabled() && isOpenMP) + else if (GPUSan && isOpenMP) AddBCLib(getOCKLPath(), false); AddBCLib(getDenormalsAreZeroPath(DAZ)); AddBCLib(getUnsafeMathPath(UnsafeMathOpt || FastRelaxedMath)); @@ -1064,10 +1060,6 @@ ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, // If --hip-device-lib is not set, add the default bitcode libraries. // TODO: There are way too many flags that change this. Do we need to check // them all? - std::tuple GPUSan( - DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, false), - getSanitizerArgs(DriverArgs)); bool DAZ = DriverArgs.hasFlag(options::OPT_fgpu_flush_denormals_to_zero, options::OPT_fno_gpu_flush_denormals_to_zero, getDefaultDenormsAreZeroForTarget(Kind)); @@ -1083,6 +1075,12 @@ ROCMToolChain::getCommonDeviceLibNames(const llvm::opt::ArgList &DriverArgs, options::OPT_fno_hip_fp32_correctly_rounded_divide_sqrt, true); bool Wave64 = isWave64(DriverArgs, Kind); + // GPU Sanitizer currently only supports ASan and is enabled through host + // ASan. + bool GPUSan = DriverArgs.hasFlag(options::OPT_fgpu_sanitize, + options::OPT_fno_gpu_sanitize, true) && + getSanitizerArgs(DriverArgs).needsAsanRt(); + return RocmInstallation->getCommonBitcodeLibs( DriverArgs, LibDeviceFile, Wave64, DAZ, FiniteOnly, UnsafeMathOpt, FastRelaxedMath, CorrectSqrt, ABIVer, GPUSan, isOpenMP); @@ -1095,11 +1093,12 @@ bool AMDGPUToolChain::shouldSkipSanitizeOption( if (TargetID.empty()) return false; Option O = A->getOption(); + if (!O.matches(options::OPT_fsanitize_EQ)) return false; if (!DriverArgs.hasFlag(options::OPT_fgpu_sanitize, - options::OPT_fno_gpu_sanitize, false)) + options::OPT_fno_gpu_sanitize, true)) return true; auto &Diags = TC.getDriver().getDiags(); diff --git a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp index 00bf9c7338edd..fe8bfb361e5a6 100644 --- a/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPUOpenMP.cpp @@ -49,7 +49,8 @@ void AMDGPUOpenMPToolChain::addClangTargetOptions( assert(DeviceOffloadingKind == Action::OFK_OpenMP && "Only OpenMP offloading kinds are supported."); - if (DriverArgs.hasArg(options::OPT_nogpulib)) + if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true)) return; for (auto BCFile : getDeviceLibs(DriverArgs)) { @@ -68,11 +69,18 @@ llvm::opt::DerivedArgList *AMDGPUOpenMPToolChain::TranslateArgs( Action::OffloadKind DeviceOffloadKind) const { DerivedArgList *DAL = HostTC.TranslateArgs(Args, BoundArch, DeviceOffloadKind); + if (!DAL) DAL = new DerivedArgList(Args.getBaseArgs()); const OptTable &Opts = getDriver().getOpts(); + // Skip sanitize options passed from the HostTC. Claim them early. + // The decision to sanitize device code is computed only by + // 'shouldSkipSanitizeOption'. + if (DAL->hasArg(options::OPT_fsanitize_EQ)) + DAL->claimAllArgs(options::OPT_fsanitize_EQ); + for (Arg *A : Args) if (!shouldSkipSanitizeOption(*this, Args, BoundArch, A) && !llvm::is_contained(*DAL, A)) @@ -134,7 +142,7 @@ AMDGPUOpenMPToolChain::computeMSVCVersion(const Driver *D, llvm::SmallVector AMDGPUOpenMPToolChain::getDeviceLibs(const llvm::opt::ArgList &Args) const { - if (Args.hasArg(options::OPT_nogpulib)) + if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true)) return {}; StringRef GpuArch = getProcessorFromTargetID( diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5deafa2ad0f4a..96af466e067a8 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -2633,6 +2633,7 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, bool UseNoExecStack = false; bool Msa = false; const char *MipsTargetFeature = nullptr; + llvm::SmallVector SparcTargetFeatures; StringRef ImplicitIt; for (const Arg *A : Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler, @@ -2778,6 +2779,31 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, if (MipsTargetFeature) continue; break; + + case llvm::Triple::sparc: + case llvm::Triple::sparcel: + case llvm::Triple::sparcv9: + if (Value == "--undeclared-regs") { + // LLVM already allows undeclared use of G registers, so this option + // becomes a no-op. This solely exists for GNU compatibility. + // TODO implement --no-undeclared-regs + continue; + } + SparcTargetFeatures = + llvm::StringSwitch>(Value) + .Case("-Av8", {"-v8plus"}) + .Case("-Av8plus", {"+v8plus", "+v9"}) + .Case("-Av8plusa", {"+v8plus", "+v9", "+vis"}) + .Case("-Av8plusb", {"+v8plus", "+v9", "+vis", "+vis2"}) + .Case("-Av8plusd", {"+v8plus", "+v9", "+vis", "+vis2", "+vis3"}) + .Case("-Av9", {"+v9"}) + .Case("-Av9a", {"+v9", "+vis"}) + .Case("-Av9b", {"+v9", "+vis", "+vis2"}) + .Case("-Av9d", {"+v9", "+vis", "+vis2", "+vis3"}) + .Default({}); + if (!SparcTargetFeatures.empty()) + continue; + break; } if (Value == "-force_cpusubtype_ALL") { @@ -2882,6 +2908,10 @@ static void CollectArgsForIntegratedAssembler(Compilation &C, CmdArgs.push_back("-target-feature"); CmdArgs.push_back(MipsTargetFeature); } + for (const char *Feature : SparcTargetFeatures) { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back(Feature); + } // forward -fembed-bitcode to assmebler if (C.getDriver().embedBitcodeEnabled() || @@ -7087,9 +7117,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // Forward -nogpulib to -cc1. - if (Args.hasArg(options::OPT_nogpulib)) - CmdArgs.push_back("-nogpulib"); + // Forward --no-offloadlib to -cc1. + if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true)) + CmdArgs.push_back("--no-offloadlib"); if (Arg *A = Args.getLastArg(options::OPT_fcf_protection_EQ)) { CmdArgs.push_back( @@ -9252,6 +9282,14 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, for (StringRef Arg : LinkerArgs) CmdArgs.push_back(Args.MakeArgString( "--device-linker=" + TC->getTripleString() + "=" + Arg)); + + // Forward the LTO mode relying on the Driver's parsing. + if (C.getDriver().getOffloadLTOMode() == LTOK_Full) + CmdArgs.push_back(Args.MakeArgString( + "--device-compiler=" + TC->getTripleString() + "=-flto=full")); + else if (C.getDriver().getOffloadLTOMode() == LTOK_Thin) + CmdArgs.push_back(Args.MakeArgString( + "--device-compiler=" + TC->getTripleString() + "=-flto=thin")); } } @@ -9259,6 +9297,9 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString("--host-triple=" + getToolChain().getTripleString())); if (Args.hasArg(options::OPT_v)) CmdArgs.push_back("--wrapper-verbose"); + if (Arg *A = Args.getLastArg(options::OPT_cuda_path_EQ)) + CmdArgs.push_back( + Args.MakeArgString(Twine("--cuda-path=") + A->getValue())); // Construct the link job so we can wrap around it. Linker->ConstructJob(C, JA, Output, Inputs, Args, LinkingOutput); @@ -9289,7 +9330,8 @@ void LinkerWrapper::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--save-temps"); // Pass in the C library for GPUs if present and not disabled. - if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r, options::OPT_nogpulib, + if (Args.hasFlag(options::OPT_offloadlib, OPT_no_offloadlib, true) && + !Args.hasArg(options::OPT_nostdlib, options::OPT_r, options::OPT_nodefaultlibs, options::OPT_nolibc, options::OPT_nogpulibc)) { forAllAssociatedToolChains(C, JA, getToolChain(), [&](const ToolChain &TC) { diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 9a4d3f55c911c..2d01943ca1ac4 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -1289,7 +1289,8 @@ bool tools::addOpenMPRuntime(const Compilation &C, ArgStringList &CmdArgs, if (IsOffloadingHost) CmdArgs.push_back("-lomptarget"); - if (IsOffloadingHost && !Args.hasArg(options::OPT_nogpulib)) + if (IsOffloadingHost && + Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true)) CmdArgs.push_back("-lomptarget.devicertl"); addArchSpecificRPath(TC, Args, CmdArgs); diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp index d6487d4bc274d..06b0b0913d24e 100644 --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -196,7 +196,8 @@ CudaInstallationDetector::CudaInstallationDetector( Candidates.emplace_back(D.SysRoot + "/usr/lib/cuda"); } - bool NoCudaLib = Args.hasArg(options::OPT_nogpulib); + bool NoCudaLib = + !Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, true); for (const auto &Candidate : Candidates) { InstallPath = Candidate.Path; @@ -865,7 +866,8 @@ void CudaToolChain::addClangTargetOptions( options::OPT_fno_cuda_short_ptr, false)) CC1Args.append({"-mllvm", "--nvptx-short-ptr"}); - if (DriverArgs.hasArg(options::OPT_nogpulib)) + if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true)) return; if (DeviceOffloadingKind == Action::OFK_OpenMP && diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp index 591003f56e8bb..9ad795edd724d 100644 --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -261,11 +261,18 @@ void Flang::AddPPCTargetArgs(const ArgList &Args, void Flang::AddRISCVTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); const llvm::Triple &Triple = getToolChain().getTriple(); + + StringRef ABIName = riscv::getRISCVABI(Args, Triple); + if (ABIName == "lp64" || ABIName == "lp64f" || ABIName == "lp64d") + CmdArgs.push_back(Args.MakeArgString("-mabi=" + ABIName)); + else + D.Diag(diag::err_drv_unsupported_option_argument) << "-mabi=" << ABIName; + // Handle -mrvv-vector-bits= if (Arg *A = Args.getLastArg(options::OPT_mrvv_vector_bits_EQ)) { StringRef Val = A->getValue(); - const Driver &D = getToolChain().getDriver(); // Get minimum VLen from march. unsigned MinVLen = 0; @@ -557,7 +564,8 @@ void Flang::addOffloadOptions(Compilation &C, const InputInfoList &Inputs, CmdArgs.push_back("-fopenmp-assume-no-thread-state"); if (Args.hasArg(options::OPT_fopenmp_assume_no_nested_parallelism)) CmdArgs.push_back("-fopenmp-assume-no-nested-parallelism"); - if (Args.hasArg(options::OPT_nogpulib)) + if (!Args.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true)) CmdArgs.push_back("-nogpulib"); } diff --git a/clang/lib/Driver/ToolChains/HIPAMD.cpp b/clang/lib/Driver/ToolChains/HIPAMD.cpp index 0e50eddd6b3d2..271626ed54aed 100644 --- a/clang/lib/Driver/ToolChains/HIPAMD.cpp +++ b/clang/lib/Driver/ToolChains/HIPAMD.cpp @@ -352,7 +352,8 @@ VersionTuple HIPAMDToolChain::computeMSVCVersion(const Driver *D, llvm::SmallVector HIPAMDToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const { llvm::SmallVector BCLibs; - if (DriverArgs.hasArg(options::OPT_nogpulib) || + if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true) || getGPUArch(DriverArgs) == "amdgcnspirv") return {}; ArgStringList LibraryPaths; diff --git a/clang/lib/Driver/ToolChains/HIPSPV.cpp b/clang/lib/Driver/ToolChains/HIPSPV.cpp index bdbcf9109129d..bbde5c047c3f9 100644 --- a/clang/lib/Driver/ToolChains/HIPSPV.cpp +++ b/clang/lib/Driver/ToolChains/HIPSPV.cpp @@ -204,7 +204,8 @@ void HIPSPVToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, llvm::SmallVector HIPSPVToolChain::getDeviceLibs(const llvm::opt::ArgList &DriverArgs) const { llvm::SmallVector BCLibs; - if (DriverArgs.hasArg(options::OPT_nogpulib)) + if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true)) return {}; ArgStringList LibraryPaths; diff --git a/clang/lib/Driver/ToolChains/ROCm.h b/clang/lib/Driver/ToolChains/ROCm.h index 681c242b0678e..a6cc41db383b6 100644 --- a/clang/lib/Driver/ToolChains/ROCm.h +++ b/clang/lib/Driver/ToolChains/ROCm.h @@ -178,7 +178,7 @@ class RocmInstallationDetector { const llvm::opt::ArgList &DriverArgs, StringRef LibDeviceFile, bool Wave64, bool DAZ, bool FiniteOnly, bool UnsafeMathOpt, bool FastRelaxedMath, bool CorrectSqrt, DeviceLibABIVersion ABIVer, - const std::tuple &GPUSan, bool isOpenMP) const; + bool GPUSan, bool isOpenMP) const; /// Check file paths of default bitcode libraries common to AMDGPU based /// toolchains. \returns false if there are invalid or missing files. bool checkCommonBitcodeLibs(StringRef GPUArch, StringRef LibDeviceFile, diff --git a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp index 1f27245e2839c..a688fd8d9fb50 100644 --- a/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp +++ b/clang/lib/Driver/ToolChains/SPIRVOpenMP.cpp @@ -27,7 +27,8 @@ void SPIRVOpenMPToolChain::addClangTargetOptions( if (DeviceOffloadingKind != Action::OFK_OpenMP) return; - if (DriverArgs.hasArg(options::OPT_nogpulib)) + if (!DriverArgs.hasFlag(options::OPT_offloadlib, options::OPT_no_offloadlib, + true)) return; addOpenMPDeviceRTL(getDriver(), DriverArgs, CC1Args, "", getTriple(), HostTC); } diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 32f5ebb55155e..627a1d6fb3dd5 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1086,6 +1086,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_HLSLVectorTruncation: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: llvm_unreachable("HLSL-specific cast in Objective-C?"); break; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 46545aa1f4c07..14e984529d640 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -366,8 +366,7 @@ class LineJoiner { // instead of TheLine->First. if (Style.AllowShortNamespacesOnASingleLine && - TheLine->First->is(tok::kw_namespace) && - TheLine->Last->is(tok::l_brace)) { + TheLine->First->is(tok::kw_namespace)) { const auto result = tryMergeNamespace(I, E, Limit); if (result > 0) return result; @@ -633,24 +632,37 @@ class LineJoiner { if (Limit == 0) return 0; - assert(I[1]); - const auto &L1 = *I[1]; + // The merging code is relative to the opening namespace brace, which could + // be either on the first or second line due to the brace wrapping rules. + const bool OpenBraceWrapped = Style.BraceWrapping.AfterNamespace; + const auto *BraceOpenLine = I + OpenBraceWrapped; + + assert(*BraceOpenLine); + if (BraceOpenLine[0]->Last->isNot(TT_NamespaceLBrace)) + return 0; + + if (std::distance(BraceOpenLine, E) <= 2) + return 0; + + if (BraceOpenLine[0]->Last->is(tok::comment)) + return 0; + + assert(BraceOpenLine[1]); + const auto &L1 = *BraceOpenLine[1]; if (L1.InPPDirective != (*I)->InPPDirective || (L1.InPPDirective && L1.First->HasUnescapedNewline)) { return 0; } - if (std::distance(I, E) <= 2) - return 0; - - assert(I[2]); - const auto &L2 = *I[2]; + assert(BraceOpenLine[2]); + const auto &L2 = *BraceOpenLine[2]; if (L2.Type == LT_Invalid) return 0; Limit = limitConsideringMacros(I + 1, E, Limit); - if (!nextTwoLinesFitInto(I, Limit)) + const auto LinesToBeMerged = OpenBraceWrapped + 2; + if (!nextNLinesFitInto(I, I + LinesToBeMerged, Limit)) return 0; // Check if it's a namespace inside a namespace, and call recursively if so. @@ -661,17 +673,19 @@ class LineJoiner { assert(Limit >= L1.Last->TotalLength + 3); const auto InnerLimit = Limit - L1.Last->TotalLength - 3; - const auto MergedLines = tryMergeNamespace(I + 1, E, InnerLimit); + const auto MergedLines = + tryMergeNamespace(BraceOpenLine + 1, E, InnerLimit); if (MergedLines == 0) return 0; - const auto N = MergedLines + 2; + const auto N = MergedLines + LinesToBeMerged; // Check if there is even a line after the inner result. if (std::distance(I, E) <= N) return 0; // Check that the line after the inner result starts with a closing brace // which we are permitted to merge into one line. - if (I[N]->First->is(tok::r_brace) && !I[N]->First->MustBreakBefore && - I[MergedLines + 1]->Last->isNot(tok::comment) && + if (I[N]->First->is(TT_NamespaceRBrace) && + !I[N]->First->MustBreakBefore && + BraceOpenLine[MergedLines + 1]->Last->isNot(tok::comment) && nextNLinesFitInto(I, I + N + 1, Limit)) { return N; } @@ -686,11 +700,11 @@ class LineJoiner { return 0; // Last, check that the third line starts with a closing brace. - if (L2.First->isNot(tok::r_brace) || L2.First->MustBreakBefore) + if (L2.First->isNot(TT_NamespaceRBrace) || L2.First->MustBreakBefore) return 0; - // If so, merge all three lines. - return 2; + // If so, merge all lines. + return LinesToBeMerged; } unsigned diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp index 1005825441b3e..2ae355fb33885 100644 --- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp @@ -974,11 +974,10 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok, // Loop over the contents and print them as a comma-delimited list of // values. bool PrintComma = false; - for (auto Iter = Data->BinaryData.begin(), End = Data->BinaryData.end(); - Iter != End; ++Iter) { + for (unsigned char Byte : Data->BinaryData.bytes()) { if (PrintComma) *Callbacks->OS << ", "; - *Callbacks->OS << static_cast(*Iter); + *Callbacks->OS << static_cast(Byte); PrintComma = true; } } else if (Tok.isAnnotation()) { diff --git a/clang/lib/Lex/CMakeLists.txt b/clang/lib/Lex/CMakeLists.txt index 766336b89a238..b3c3ca704e860 100644 --- a/clang/lib/Lex/CMakeLists.txt +++ b/clang/lib/Lex/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_library(clangLex HeaderSearch.cpp InitHeaderSearch.cpp Lexer.cpp + LexHLSLRootSignature.cpp LiteralSupport.cpp MacroArgs.cpp MacroInfo.cpp diff --git a/clang/lib/Lex/LexHLSLRootSignature.cpp b/clang/lib/Lex/LexHLSLRootSignature.cpp new file mode 100644 index 0000000000000..8344aad15a9bc --- /dev/null +++ b/clang/lib/Lex/LexHLSLRootSignature.cpp @@ -0,0 +1,120 @@ +#include "clang/Lex/LexHLSLRootSignature.h" + +namespace clang { +namespace hlsl { + +// Lexer Definitions + +static bool IsNumberChar(char C) { + // TODO(#126565): extend for float support exponents + return isdigit(C); // integer support +} + +RootSignatureToken RootSignatureLexer::LexToken() { + // Discard any leading whitespace + AdvanceBuffer(Buffer.take_while(isspace).size()); + + if (EndOfBuffer()) + return RootSignatureToken(TokenKind::end_of_stream, SourceLoc); + + // Record where this token is in the text for usage in parser diagnostics + RootSignatureToken Result(SourceLoc); + + char C = Buffer.front(); + + // Punctuators + switch (C) { +#define PUNCTUATOR(X, Y) \ + case Y: { \ + Result.Kind = TokenKind::pu_##X; \ + AdvanceBuffer(); \ + return Result; \ + } +#include "clang/Lex/HLSLRootSignatureTokenKinds.def" + default: + break; + } + + // Integer literal + if (isdigit(C)) { + Result.Kind = TokenKind::int_literal; + Result.NumSpelling = Buffer.take_while(IsNumberChar); + AdvanceBuffer(Result.NumSpelling.size()); + return Result; + } + + // All following tokens require at least one additional character + if (Buffer.size() <= 1) { + Result = RootSignatureToken(TokenKind::invalid, SourceLoc); + return Result; + } + + // Peek at the next character to deteremine token type + char NextC = Buffer[1]; + + // Registers: [tsub][0-9+] + if ((C == 't' || C == 's' || C == 'u' || C == 'b') && isdigit(NextC)) { + // Convert character to the register type. + switch (C) { + case 'b': + Result.Kind = TokenKind::bReg; + break; + case 't': + Result.Kind = TokenKind::tReg; + break; + case 'u': + Result.Kind = TokenKind::uReg; + break; + case 's': + Result.Kind = TokenKind::sReg; + break; + default: + llvm_unreachable("Switch for an expected token was not provided"); + } + + AdvanceBuffer(); + + // Lex the integer literal + Result.NumSpelling = Buffer.take_while(IsNumberChar); + AdvanceBuffer(Result.NumSpelling.size()); + + return Result; + } + + // Keywords and Enums: + StringRef TokSpelling = + Buffer.take_while([](char C) { return isalnum(C) || C == '_'; }); + + // Define a large string switch statement for all the keywords and enums + auto Switch = llvm::StringSwitch(TokSpelling); +#define KEYWORD(NAME) Switch.Case(#NAME, TokenKind::kw_##NAME); +#define ENUM(NAME, LIT) Switch.CaseLower(LIT, TokenKind::en_##NAME); +#include "clang/Lex/HLSLRootSignatureTokenKinds.def" + + // Then attempt to retreive a string from it + Result.Kind = Switch.Default(TokenKind::invalid); + AdvanceBuffer(TokSpelling.size()); + return Result; +} + +RootSignatureToken RootSignatureLexer::ConsumeToken() { + // If we previously peeked then just return the previous value over + if (NextToken && NextToken->Kind != TokenKind::end_of_stream) { + RootSignatureToken Result = *NextToken; + NextToken = std::nullopt; + return Result; + } + return LexToken(); +} + +RootSignatureToken RootSignatureLexer::PeekNextToken() { + // Already peeked from the current token + if (NextToken) + return *NextToken; + + NextToken = LexToken(); + return *NextToken; +} + +} // namespace hlsl +} // namespace clang diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 75b5e11f8327c..7ae136af47391 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6024,7 +6024,7 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() { TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope()); StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); if (!R.isUsable()) - return nullptr; + R = Actions.ActOnNullStmt(Tok.getLocation()); Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get()); diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index da5f2ccf3a0c6..0c28972d6ed8f 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -2236,6 +2236,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (PP.isCodeCompletionReached() && !CalledSignatureHelp) RunSignatureHelp(); LHS = ExprError(); + } else if (!HasError && HasTrailingComma) { + Diag(Tok, diag::err_expected_expression); } else if (LHS.isInvalid()) { for (auto &E : ArgExprs) Actions.CorrectDelayedTyposInExpr(E); diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp index c9806a77d5ef6..3af4d001d6c1a 100644 --- a/clang/lib/Sema/HeuristicResolver.cpp +++ b/clang/lib/Sema/HeuristicResolver.cpp @@ -210,37 +210,46 @@ QualType HeuristicResolverImpl::getPointeeType(QualType T) { QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E, bool UnwrapPointer) { bool DidUnwrapPointer = false; - auto SimplifyOneStep = [&](QualType T) { + // A type, together with an optional expression whose type it represents + // which may have additional information about the expression's type + // not stored in the QualType itself. + struct TypeExprPair { + QualType Type; + const Expr *E = nullptr; + }; + TypeExprPair Current{Type, E}; + auto SimplifyOneStep = [UnwrapPointer, &DidUnwrapPointer, + this](TypeExprPair T) -> TypeExprPair { if (UnwrapPointer) { - if (QualType Pointee = getPointeeType(T); !Pointee.isNull()) { + if (QualType Pointee = getPointeeType(T.Type); !Pointee.isNull()) { DidUnwrapPointer = true; - return Pointee; + return {Pointee}; } } - if (const auto *RT = T->getAs()) { + if (const auto *RT = T.Type->getAs()) { // Does not count as "unwrap pointer". - return RT->getPointeeType(); + return {RT->getPointeeType()}; } - if (const auto *BT = T->getAs()) { + if (const auto *BT = T.Type->getAs()) { // If BaseType is the type of a dependent expression, it's just // represented as BuiltinType::Dependent which gives us no information. We // can get further by analyzing the dependent expression. - if (E && BT->getKind() == BuiltinType::Dependent) { - return resolveExprToType(E); + if (T.E && BT->getKind() == BuiltinType::Dependent) { + return {resolveExprToType(T.E), T.E}; } } - if (const auto *AT = T->getContainedAutoType()) { + if (const auto *AT = T.Type->getContainedAutoType()) { // If T contains a dependent `auto` type, deduction will not have // been performed on it yet. In simple cases (e.g. `auto` variable with // initializer), get the approximate type that would result from // deduction. // FIXME: A more accurate implementation would propagate things like the // `const` in `const auto`. - if (E && AT->isUndeducedAutoType()) { - if (const auto *DRE = dyn_cast(E)) { + if (T.E && AT->isUndeducedAutoType()) { + if (const auto *DRE = dyn_cast(T.E)) { if (const auto *VD = dyn_cast(DRE->getDecl())) { - if (VD->hasInit()) - return resolveExprToType(VD->getInit()); + if (auto *Init = VD->getInit()) + return {resolveExprToType(Init), Init}; } } } @@ -251,15 +260,15 @@ QualType HeuristicResolverImpl::simplifyType(QualType Type, const Expr *E, // simplification steps. size_t StepCount = 0; const size_t MaxSteps = 64; - while (!Type.isNull() && StepCount++ < MaxSteps) { - QualType New = SimplifyOneStep(Type); - if (New == Type) + while (!Current.Type.isNull() && StepCount++ < MaxSteps) { + TypeExprPair New = SimplifyOneStep(Current); + if (New.Type == Current.Type) break; - Type = New; + Current = New; } if (UnwrapPointer && !DidUnwrapPointer) return QualType(); - return Type; + return Current.Type; } std::vector HeuristicResolverImpl::resolveMemberExpr( diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 15c18f9a4525b..afd1d7a4e36c1 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -709,6 +709,7 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, case CK_ToVoid: case CK_NonAtomicToAtomic: case CK_HLSLArrayRValue: + case CK_HLSLAggregateSplatCast: break; } } diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 23be71ad8e2ae..8972957ded9f5 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2776,9 +2776,9 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, CheckedConversionKind CCK = FunctionalStyle ? CheckedConversionKind::FunctionalCast : CheckedConversionKind::CStyleCast; - // This case should not trigger on regular vector splat - // vector cast, vector truncation, or special hlsl splat cases + QualType SrcTy = SrcExpr.get()->getType(); + // This case should not trigger on regular vector cast, vector truncation if (Self.getLangOpts().HLSL && Self.HLSL().CanPerformElementwiseCast(SrcExpr.get(), DestType)) { if (SrcTy->isConstantArrayType()) @@ -2789,6 +2789,28 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle, return; } + // This case should not trigger on regular vector splat + // If the relative order of this and the HLSLElementWise cast checks + // are changed, it might change which cast handles what in a few cases + if (Self.getLangOpts().HLSL && + Self.HLSL().CanPerformAggregateSplatCast(SrcExpr.get(), DestType)) { + const VectorType *VT = SrcTy->getAs(); + // change splat from vec1 case to splat from scalar + if (VT && VT->getNumElements() == 1) + SrcExpr = Self.ImpCastExprToType( + SrcExpr.get(), VT->getElementType(), CK_HLSLVectorTruncation, + SrcExpr.get()->getValueKind(), nullptr, CCK); + // Inserting a scalar cast here allows for a simplified codegen in + // the case the destTy is a vector + if (const VectorType *DVT = DestType->getAs()) + SrcExpr = Self.ImpCastExprToType( + SrcExpr.get(), DVT->getElementType(), + Self.PrepareScalarCast(SrcExpr, DVT->getElementType()), + SrcExpr.get()->getValueKind(), nullptr, CCK); + Kind = CK_HLSLAggregateSplatCast; + return; + } + if (ValueKind == VK_PRValue && !DestType->isRecordType() && !isPlaceholder(BuiltinType::Overload)) { SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.get()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6eedc77ed20a0..98c245cdea78f 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13399,8 +13399,11 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated( // about the properties of the function containing it. const ValueDecl *Target = Dcl; // VarDecls and FunctionDecls have different functions for checking - // inline-ness, so we have to do it manually. + // inline-ness, and whether they were originally templated, so we have to + // call the appropriate functions manually. bool TargetIsInline = Dcl->isInline(); + bool TargetWasTemplated = + Dcl->getTemplateSpecializationKind() != TSK_Undeclared; // Update the Target and TargetIsInline property if necessary if (Dcl->isStaticLocal()) { @@ -13416,12 +13419,13 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated( Target = FunDcl; // IsInlined() checks for the C++ inline property TargetIsInline = FunDcl->isInlined(); + TargetWasTemplated = + FunDcl->getTemplateSpecializationKind() != TSK_Undeclared; } - // Non-inline variables can only legally appear in one TU - // FIXME: This also applies to templated variables, but that can rarely lead - // to false positives so templates are disabled for now. - if (!TargetIsInline) + // Non-inline functions/variables can only legally appear in one TU, + // unless they were part of a template. + if (!TargetIsInline && !TargetWasTemplated) return false; // If the object isn't hidden, the dynamic linker will prevent duplication. @@ -13436,6 +13440,55 @@ bool Sema::GloballyUniqueObjectMightBeAccidentallyDuplicated( return true; } +void Sema::DiagnoseUniqueObjectDuplication(const VarDecl *VD) { + // If this object has external linkage and hidden visibility, it might be + // duplicated when built into a shared library, which causes problems if it's + // mutable (since the copies won't be in sync) or its initialization has side + // effects (since it will run once per copy instead of once globally). + // FIXME: Windows uses dllexport/dllimport instead of visibility, and we don't + // handle that yet. Disable the warning on Windows for now. + + // Don't diagnose if we're inside a template; + // we'll diagnose during instantiation instead. + if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() && + !VD->isTemplated() && + GloballyUniqueObjectMightBeAccidentallyDuplicated(VD)) { + + // Check mutability. For pointers, ensure that both the pointer and the + // pointee are (recursively) const. + QualType Type = VD->getType().getNonReferenceType(); + if (!Type.isConstant(VD->getASTContext())) { + Diag(VD->getLocation(), diag::warn_possible_object_duplication_mutable) + << VD; + } else { + while (Type->isPointerType()) { + Type = Type->getPointeeType(); + if (Type->isFunctionType()) + break; + if (!Type.isConstant(VD->getASTContext())) { + Diag(VD->getLocation(), + diag::warn_possible_object_duplication_mutable) + << VD; + break; + } + } + } + + // To keep false positives low, only warn if we're certain that the + // initializer has side effects. Don't warn on operator new, since a mutable + // pointer will trigger the previous warning, and an immutable pointer + // getting duplicated just results in a little extra memory usage. + const Expr *Init = VD->getAnyInitializer(); + if (Init && + Init->HasSideEffects(VD->getASTContext(), + /*IncludePossibleEffects=*/false) && + !isa(Init->IgnoreParenImpCasts())) { + Diag(Init->getExprLoc(), diag::warn_possible_object_duplication_init) + << VD; + } + } +} + void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // If there is no declaration, there was an error parsing it. Just ignore // the initializer. @@ -14655,6 +14708,8 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { return; } + DiagnoseUniqueObjectDuplication(var); + // Require the destructor. if (!type->isDependentType()) if (const RecordType *recordType = baseType->getAs()) @@ -14842,51 +14897,6 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { if (DC->getRedeclContext()->isFileContext() && VD->isExternallyVisible()) AddPushedVisibilityAttribute(VD); - // If this object has external linkage and hidden visibility, it might be - // duplicated when built into a shared library, which causes problems if it's - // mutable (since the copies won't be in sync) or its initialization has side - // effects (since it will run once per copy instead of once globally) - // FIXME: Windows uses dllexport/dllimport instead of visibility, and we don't - // handle that yet. Disable the warning on Windows for now. - // FIXME: Checking templates can cause false positives if the template in - // question is never instantiated (e.g. only specialized templates are used). - if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() && - !VD->isTemplated() && - GloballyUniqueObjectMightBeAccidentallyDuplicated(VD)) { - // Check mutability. For pointers, ensure that both the pointer and the - // pointee are (recursively) const. - QualType Type = VD->getType().getNonReferenceType(); - if (!Type.isConstant(VD->getASTContext())) { - Diag(VD->getLocation(), diag::warn_possible_object_duplication_mutable) - << VD; - } else { - while (Type->isPointerType()) { - Type = Type->getPointeeType(); - if (Type->isFunctionType()) - break; - if (!Type.isConstant(VD->getASTContext())) { - Diag(VD->getLocation(), - diag::warn_possible_object_duplication_mutable) - << VD; - break; - } - } - } - - // To keep false positives low, only warn if we're certain that the - // initializer has side effects. Don't warn on operator new, since a mutable - // pointer will trigger the previous warning, and an immutable pointer - // getting duplicated just results in a little extra memory usage. - const Expr *Init = VD->getAnyInitializer(); - if (Init && - Init->HasSideEffects(VD->getASTContext(), - /*IncludePossibleEffects=*/false) && - !isa(Init->IgnoreParenImpCasts())) { - Diag(Init->getExprLoc(), diag::warn_possible_object_duplication_init) - << VD; - } - } - // FIXME: Warn on unused var template partial specializations. if (VD->isFileVarDecl() && !isa(VD)) MarkUnusedFileScopedDecl(VD); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 527db176cf8dd..620290af9509f 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -64,6 +64,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/Support/Error.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include "llvm/TargetParser/Triple.h" @@ -2949,15 +2950,49 @@ static void handleSectionAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } +static bool isValidCodeModelAttr(llvm::Triple &Triple, StringRef Str) { + if (Triple.isLoongArch()) { + return Str == "normal" || Str == "medium" || Str == "extreme"; + } else { + assert(Triple.getArch() == llvm::Triple::x86_64 && + "only loongarch/x86-64 supported"); + return Str == "small" || Str == "large"; + } +} + static void handleCodeModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { StringRef Str; SourceLocation LiteralLoc; + auto IsTripleSupported = [](llvm::Triple &Triple) { + return Triple.getArch() == llvm::Triple::ArchType::x86_64 || + Triple.isLoongArch(); + }; + // Check that it is a string. if (!S.checkStringLiteralArgumentAttr(AL, 0, Str, &LiteralLoc)) return; + SmallVector Triples = { + S.Context.getTargetInfo().getTriple()}; + if (auto *aux = S.Context.getAuxTargetInfo()) { + Triples.push_back(aux->getTriple()); + } else if (S.Context.getTargetInfo().getTriple().isNVPTX() || + S.Context.getTargetInfo().getTriple().isAMDGPU() || + S.Context.getTargetInfo().getTriple().isSPIRV()) { + // Ignore the attribute for pure GPU device compiles since it only applies + // to host globals. + return; + } + + auto SupportedTripleIt = llvm::find_if(Triples, IsTripleSupported); + if (SupportedTripleIt == Triples.end()) { + S.Diag(LiteralLoc, diag::warn_unknown_attribute_ignored) << AL; + return; + } + llvm::CodeModel::Model CM; - if (!CodeModelAttr::ConvertStrToModel(Str, CM)) { + if (!CodeModelAttr::ConvertStrToModel(Str, CM) || + !isValidCodeModelAttr(*SupportedTripleIt, Str)) { S.Diag(LiteralLoc, diag::err_attr_codemodel_arg) << Str; return; } diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 4abd870ad6aaa..9a60054a6169e 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -2717,6 +2717,9 @@ bool SemaHLSL::CheckCompatibleParameterABI(FunctionDecl *New, // clarity of what types are supported bool SemaHLSL::CanPerformScalarCast(QualType SrcTy, QualType DestTy) { + if (!SrcTy->isScalarType() || !DestTy->isScalarType()) + return false; + if (SemaRef.getASTContext().hasSameUnqualifiedType(SrcTy, DestTy)) return true; @@ -2778,7 +2781,7 @@ bool SemaHLSL::CanPerformScalarCast(QualType SrcTy, QualType DestTy) { } // Detect if a type contains a bitfield. Will be removed when -// bitfield support is added to HLSLElementwiseCast +// bitfield support is added to HLSLElementwiseCast and HLSLAggregateSplatCast bool SemaHLSL::ContainsBitField(QualType BaseTy) { llvm::SmallVector WorkList; WorkList.push_back(BaseTy); @@ -2811,6 +2814,42 @@ bool SemaHLSL::ContainsBitField(QualType BaseTy) { return false; } +// Can perform an HLSL Aggregate splat cast if the Dest is an aggregate and the +// Src is a scalar or a vector of length 1 +// Or if Dest is a vector and Src is a vector of length 1 +bool SemaHLSL::CanPerformAggregateSplatCast(Expr *Src, QualType DestTy) { + + QualType SrcTy = Src->getType(); + // Not a valid HLSL Aggregate Splat cast if Dest is a scalar or if this is + // going to be a vector splat from a scalar. + if ((SrcTy->isScalarType() && DestTy->isVectorType()) || + DestTy->isScalarType()) + return false; + + const VectorType *SrcVecTy = SrcTy->getAs(); + + // Src isn't a scalar or a vector of length 1 + if (!SrcTy->isScalarType() && !(SrcVecTy && SrcVecTy->getNumElements() == 1)) + return false; + + if (SrcVecTy) + SrcTy = SrcVecTy->getElementType(); + + if (ContainsBitField(DestTy)) + return false; + + llvm::SmallVector DestTypes; + BuildFlattenedTypeList(DestTy, DestTypes); + + for (unsigned I = 0, Size = DestTypes.size(); I < Size; ++I) { + if (DestTypes[I]->isUnionType()) + return false; + if (!CanPerformScalarCast(SrcTy, DestTypes[I])) + return false; + } + return true; +} + // Can we perform an HLSL Elementwise cast? // TODO: update this code when matrices are added; see issue #88060 bool SemaHLSL::CanPerformElementwiseCast(Expr *Src, QualType DestTy) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 9e68972b33f0a..38fa3ff3ab5b4 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4905,7 +4905,7 @@ bool Sema::CheckTemplateTypeArgument( [[fallthrough]]; } default: { - // We allow instantiateing a template with template argument packs when + // We allow instantiating a template with template argument packs when // building deduction guides. if (Arg.getKind() == TemplateArgument::Pack && CodeSynthesisContexts.back().Kind == diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index e5931f4684a57..b789824d97020 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -998,8 +998,6 @@ getRHSTemplateDeclAndArgs(Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate) { Template = CTSD->getSpecializedTemplate(); AliasRhsTemplateArgs = CTSD->getTemplateArgs().asArray(); } - } else { - assert(false && "unhandled RHS type of the alias"); } return {Template, AliasRhsTemplateArgs}; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index d9a47ca3daa20..d1a45af6ca58f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1466,6 +1466,18 @@ namespace { } } + static TemplateArgument + getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) { + if (TA.getKind() != TemplateArgument::Pack) + return TA; + assert(TA.pack_size() == 1 && + "unexpected pack arguments in template rewrite"); + TemplateArgument Arg = *TA.pack_begin(); + if (Arg.isPackExpansion()) + Arg = Arg.getPackExpansionPattern(); + return Arg; + } + /// Transform the given declaration by instantiating a reference to /// this declaration. Decl *TransformDecl(SourceLocation Loc, Decl *D); @@ -1627,7 +1639,7 @@ namespace { TemplateArgumentLoc Input = SemaRef.getTrivialTemplateArgumentLoc( pack, QualType(), SourceLocation{}); TemplateArgumentLoc Output; - if (SemaRef.SubstTemplateArgument(Input, TemplateArgs, Output)) + if (TransformTemplateArgument(Input, Output, Uneval)) return true; // fails TArgs.push_back(Output.getArgument()); } @@ -2040,11 +2052,7 @@ TemplateName TemplateInstantiator::TransformTemplateName( if (TemplateArgs.isRewrite()) { // We're rewriting the template parameter as a reference to another // template parameter. - if (Arg.getKind() == TemplateArgument::Pack) { - assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() && - "unexpected pack arguments in template rewrite"); - Arg = Arg.pack_begin()->getPackExpansionPattern(); - } + Arg = getTemplateArgumentPackPatternForRewrite(Arg); assert(Arg.getKind() == TemplateArgument::Template && "unexpected nontype template argument kind in template rewrite"); return Arg.getAsTemplate(); @@ -2125,11 +2133,7 @@ TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E, if (TemplateArgs.isRewrite()) { // We're rewriting the template parameter as a reference to another // template parameter. - if (Arg.getKind() == TemplateArgument::Pack) { - assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() && - "unexpected pack arguments in template rewrite"); - Arg = Arg.pack_begin()->getPackExpansionPattern(); - } + Arg = getTemplateArgumentPackPatternForRewrite(Arg); assert(Arg.getKind() == TemplateArgument::Expression && "unexpected nontype template argument kind in template rewrite"); // FIXME: This can lead to the same subexpression appearing multiple times @@ -2591,11 +2595,7 @@ TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, if (TemplateArgs.isRewrite()) { // We're rewriting the template parameter as a reference to another // template parameter. - if (Arg.getKind() == TemplateArgument::Pack) { - assert(Arg.pack_size() == 1 && Arg.pack_begin()->isPackExpansion() && - "unexpected pack arguments in template rewrite"); - Arg = Arg.pack_begin()->getPackExpansionPattern(); - } + Arg = getTemplateArgumentPackPatternForRewrite(Arg); assert(Arg.getKind() == TemplateArgument::Type && "unexpected nontype template argument kind in template rewrite"); QualType NewT = Arg.getAsType(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 6f30a36621601..db0177f9750e0 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1593,35 +1593,38 @@ QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc, // object or incomplete types shall not be restrict-qualified." if (Qs.hasRestrict()) { unsigned DiagID = 0; - QualType ProblemTy; - - if (T->isAnyPointerType() || T->isReferenceType() || - T->isMemberPointerType()) { - QualType EltTy; - if (T->isObjCObjectPointerType()) - EltTy = T; - else if (const MemberPointerType *PTy = T->getAs()) + QualType EltTy = Context.getBaseElementType(T); + + if (EltTy->isAnyPointerType() || EltTy->isReferenceType() || + EltTy->isMemberPointerType()) { + + if (const auto *PTy = EltTy->getAs()) EltTy = PTy->getPointeeType(); else - EltTy = T->getPointeeType(); + EltTy = EltTy->getPointeeType(); // If we have a pointer or reference, the pointee must have an object // incomplete type. - if (!EltTy->isIncompleteOrObjectType()) { + if (!EltTy->isIncompleteOrObjectType()) DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee; - ProblemTy = EltTy; - } + } else if (!isDependentOrGNUAutoType(T)) { // For an __auto_type variable, we may not have seen the initializer yet // and so have no idea whether the underlying type is a pointer type or // not. DiagID = diag::err_typecheck_invalid_restrict_not_pointer; - ProblemTy = T; + EltTy = T; } + Loc = DS ? DS->getRestrictSpecLoc() : Loc; if (DiagID) { - Diag(DS ? DS->getRestrictSpecLoc() : Loc, DiagID) << ProblemTy; + Diag(Loc, DiagID) << EltTy; Qs.removeRestrict(); + } else { + if (T->isArrayType()) + Diag(Loc, getLangOpts().C23 + ? diag::warn_c23_compat_restrict_on_array_of_pointers + : diag::ext_restrict_on_array_of_pointers_c23); } } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 3c64b67503195..4a40df6399f64 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10188,12 +10188,12 @@ void ASTReader::visitTopLevelModuleMaps( } void ASTReader::finishPendingActions() { - while (!PendingIdentifierInfos.empty() || - !PendingDeducedFunctionTypes.empty() || - !PendingDeducedVarTypes.empty() || !PendingDeclChains.empty() || - !PendingMacroIDs.empty() || !PendingDeclContextInfos.empty() || - !PendingUpdateRecords.empty() || - !PendingObjCExtensionIvarRedeclarations.empty()) { + while ( + !PendingIdentifierInfos.empty() || !PendingDeducedFunctionTypes.empty() || + !PendingDeducedVarTypes.empty() || !PendingIncompleteDeclChains.empty() || + !PendingDeclChains.empty() || !PendingMacroIDs.empty() || + !PendingDeclContextInfos.empty() || !PendingUpdateRecords.empty() || + !PendingObjCExtensionIvarRedeclarations.empty()) { // If any identifiers with corresponding top-level declarations have // been loaded, load those declarations now. using TopLevelDeclsMap = @@ -10241,6 +10241,13 @@ void ASTReader::finishPendingActions() { } PendingDeducedVarTypes.clear(); + // For each decl chain that we wanted to complete while deserializing, mark + // it as "still needs to be completed". + for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { + markIncompleteDeclChain(PendingIncompleteDeclChains[I]); + } + PendingIncompleteDeclChains.clear(); + // Load pending declaration chains. for (unsigned I = 0; I != PendingDeclChains.size(); ++I) loadPendingDeclChain(PendingDeclChains[I].first, @@ -10478,12 +10485,6 @@ void ASTReader::finishPendingActions() { for (auto *ND : PendingMergedDefinitionsToDeduplicate) getContext().deduplicateMergedDefinitonsFor(ND); PendingMergedDefinitionsToDeduplicate.clear(); - - // For each decl chain that we wanted to complete while deserializing, mark - // it as "still needs to be completed". - for (Decl *D : PendingIncompleteDeclChains) - markIncompleteDeclChain(D); - PendingIncompleteDeclChains.clear(); } void ASTReader::diagnoseOdrViolations() { diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index 12bf12a0b2322..8955cb209c399 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -314,6 +314,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE, RegionArgIsBad = true; } + assert(ArgSM); // Is the argument to the call being tracked? const AllocationState *AS = State->get(ArgSM); if (!AS) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp index 5d28982c41fc4..a12853d01819f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp @@ -154,10 +154,10 @@ bool isConstOwnerPtrMemberExpr(const clang::Expr *E) { if (auto *MCE = dyn_cast(E)) { if (auto *Callee = MCE->getDirectCallee()) { auto Name = safeGetName(Callee); - if (Name == "get" || Name == "ptr") { - auto *ThisArg = MCE->getImplicitObjectArgument(); - E = ThisArg; - } + if (Name == "get" || Name == "ptr") + E = MCE->getImplicitObjectArgument(); + if (isa(Callee)) + E = MCE->getImplicitObjectArgument(); } } else if (auto *OCE = dyn_cast(E)) { if (OCE->getOperator() == OO_Star && OCE->getNumArgs() == 1) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp index d40b4b4dbb560..8340de9e5a7a9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp @@ -392,6 +392,11 @@ class TrivialFunctionAnalysisVisitor return false; } + bool VisitAttributedStmt(const AttributedStmt *AS) { + // Ignore attributes. + return Visit(AS->getSubStmt()); + } + bool VisitCompoundStmt(const CompoundStmt *CS) { // A compound statement is allowed as long each individual sub-statement // is trivial. @@ -503,6 +508,11 @@ class TrivialFunctionAnalysisVisitor return true; } + bool VisitOffsetOfExpr(const OffsetOfExpr *OE) { + // offsetof(T, D) is considered trivial. + return true; + } + bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE) { if (!checkArguments(MCE)) return false; @@ -589,6 +599,19 @@ class TrivialFunctionAnalysisVisitor return Visit(BTE->getSubExpr()); } + bool VisitArrayInitLoopExpr(const ArrayInitLoopExpr *AILE) { + return Visit(AILE->getCommonExpr()) && Visit(AILE->getSubExpr()); + } + + bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *AIIE) { + return true; // The current array index in VisitArrayInitLoopExpr is always + // trivial. + } + + bool VisitOpaqueValueExpr(const OpaqueValueExpr *OVE) { + return Visit(OVE->getSourceExpr()); + } + bool VisitExprWithCleanups(const ExprWithCleanups *EWC) { return Visit(EWC->getSubExpr()); } diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp index a56f48c83c660..4ffdac5ca4873 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedLambdaCapturesChecker.cpp @@ -41,6 +41,9 @@ class UncountedLambdaCapturesChecker const UncountedLambdaCapturesChecker *Checker; llvm::DenseSet DeclRefExprsToIgnore; llvm::DenseSet LambdasToIgnore; + llvm::DenseSet ProtectedThisDecls; + llvm::DenseSet ConstructToIgnore; + QualType ClsType; explicit LocalVisitor(const UncountedLambdaCapturesChecker *Checker) @@ -65,7 +68,7 @@ class UncountedLambdaCapturesChecker bool VisitLambdaExpr(LambdaExpr *L) override { if (LambdasToIgnore.contains(L)) return true; - Checker->visitLambdaExpr(L, shouldCheckThis()); + Checker->visitLambdaExpr(L, shouldCheckThis() && !hasProtectedThis(L)); return true; } @@ -93,7 +96,7 @@ class UncountedLambdaCapturesChecker if (!L) return true; LambdasToIgnore.insert(L); - Checker->visitLambdaExpr(L, shouldCheckThis()); + Checker->visitLambdaExpr(L, shouldCheckThis() && !hasProtectedThis(L)); return true; } @@ -106,6 +109,27 @@ class UncountedLambdaCapturesChecker return safeGetName(NsDecl) == "WTF" && safeGetName(Decl) == "switchOn"; } + bool VisitCXXConstructExpr(CXXConstructExpr *CE) override { + if (ConstructToIgnore.contains(CE)) + return true; + if (auto *Callee = CE->getConstructor()) { + unsigned ArgIndex = 0; + for (auto *Param : Callee->parameters()) { + if (ArgIndex >= CE->getNumArgs()) + return true; + auto *Arg = CE->getArg(ArgIndex)->IgnoreParenCasts(); + if (auto *L = findLambdaInArg(Arg)) { + LambdasToIgnore.insert(L); + if (!Param->hasAttr()) + Checker->visitLambdaExpr(L, shouldCheckThis() && + !hasProtectedThis(L)); + } + ++ArgIndex; + } + } + return true; + } + bool VisitCallExpr(CallExpr *CE) override { checkCalleeLambda(CE); if (auto *Callee = CE->getDirectCallee()) { @@ -118,7 +142,8 @@ class UncountedLambdaCapturesChecker if (auto *L = findLambdaInArg(Arg)) { LambdasToIgnore.insert(L); if (!Param->hasAttr() && !TreatAllArgsAsNoEscape) - Checker->visitLambdaExpr(L, shouldCheckThis()); + Checker->visitLambdaExpr(L, shouldCheckThis() && + !hasProtectedThis(L)); } ++ArgIndex; } @@ -143,8 +168,17 @@ class UncountedLambdaCapturesChecker auto *CtorArg = CE->getArg(0)->IgnoreParenCasts(); if (!CtorArg) return nullptr; - if (auto *Lambda = dyn_cast(CtorArg)) + if (auto *Lambda = dyn_cast(CtorArg)) { + ConstructToIgnore.insert(CE); return Lambda; + } + if (auto *TempExpr = dyn_cast(CtorArg)) { + E = TempExpr->getSubExpr()->IgnoreParenCasts(); + if (auto *Lambda = dyn_cast(E)) { + ConstructToIgnore.insert(CE); + return Lambda; + } + } auto *DRE = dyn_cast(CtorArg); if (!DRE) return nullptr; @@ -157,6 +191,7 @@ class UncountedLambdaCapturesChecker TempExpr = dyn_cast(Init->IgnoreParenCasts()); if (!TempExpr) return nullptr; + ConstructToIgnore.insert(CE); return dyn_cast_or_null(TempExpr->getSubExpr()); } @@ -189,9 +224,68 @@ class UncountedLambdaCapturesChecker return; DeclRefExprsToIgnore.insert(ArgRef); LambdasToIgnore.insert(L); - Checker->visitLambdaExpr(L, shouldCheckThis(), + Checker->visitLambdaExpr(L, shouldCheckThis() && !hasProtectedThis(L), /* ignoreParamVarDecl */ true); } + + bool hasProtectedThis(LambdaExpr *L) { + for (const LambdaCapture &OtherCapture : L->captures()) { + if (!OtherCapture.capturesVariable()) + continue; + if (auto *ValueDecl = OtherCapture.getCapturedVar()) { + if (declProtectsThis(ValueDecl)) { + ProtectedThisDecls.insert(ValueDecl); + return true; + } + } + } + return false; + } + + bool declProtectsThis(const ValueDecl *ValueDecl) const { + auto *VD = dyn_cast(ValueDecl); + if (!VD) + return false; + auto *Init = VD->getInit()->IgnoreParenCasts(); + if (!Init) + return false; + const Expr *Arg = Init; + do { + if (auto *BTE = dyn_cast(Arg)) + Arg = BTE->getSubExpr()->IgnoreParenCasts(); + if (auto *CE = dyn_cast_or_null(Arg)) { + auto *Ctor = CE->getConstructor(); + if (!Ctor) + return false; + auto clsName = safeGetName(Ctor->getParent()); + if (!isRefType(clsName) || !CE->getNumArgs()) + return false; + Arg = CE->getArg(0)->IgnoreParenCasts(); + continue; + } + if (auto *OpCE = dyn_cast(Arg)) { + auto OpCode = OpCE->getOperator(); + if (OpCode == OO_Star || OpCode == OO_Amp) { + auto *Callee = OpCE->getDirectCallee(); + auto clsName = safeGetName(Callee->getParent()); + if (!isRefType(clsName) || !OpCE->getNumArgs()) + return false; + Arg = OpCE->getArg(0)->IgnoreParenCasts(); + continue; + } + } + if (auto *UO = dyn_cast(Arg)) { + auto OpCode = UO->getOpcode(); + if (OpCode == UO_Deref || OpCode == UO_AddrOf) + Arg = UO->getSubExpr()->IgnoreParenCasts(); + continue; + } + break; + } while (Arg); + if (auto *DRE = dyn_cast(Arg)) + return ProtectedThisDecls.contains(DRE->getDecl()); + return isa(Arg); + } }; LocalVisitor visitor(this); @@ -214,53 +308,11 @@ class UncountedLambdaCapturesChecker } else if (C.capturesThis() && shouldCheckThis) { if (ignoreParamVarDecl) // this is always a parameter to this function. continue; - bool hasProtectThis = false; - for (const LambdaCapture &OtherCapture : L->captures()) { - if (!OtherCapture.capturesVariable()) - continue; - if (auto *ValueDecl = OtherCapture.getCapturedVar()) { - if (protectThis(ValueDecl)) { - hasProtectThis = true; - break; - } - } - } - if (!hasProtectThis) - reportBugOnThisPtr(C); + reportBugOnThisPtr(C); } } } - bool protectThis(const ValueDecl *ValueDecl) const { - auto *VD = dyn_cast(ValueDecl); - if (!VD) - return false; - auto *Init = VD->getInit()->IgnoreParenCasts(); - if (!Init) - return false; - auto *BTE = dyn_cast(Init); - if (!BTE) - return false; - auto *CE = dyn_cast_or_null(BTE->getSubExpr()); - if (!CE) - return false; - auto *Ctor = CE->getConstructor(); - if (!Ctor) - return false; - auto clsName = safeGetName(Ctor->getParent()); - if (!isRefType(clsName) || !CE->getNumArgs()) - return false; - auto *Arg = CE->getArg(0)->IgnoreParenCasts(); - while (auto *UO = dyn_cast(Arg)) { - auto OpCode = UO->getOpcode(); - if (OpCode == UO_Deref || OpCode == UO_AddrOf) - Arg = UO->getSubExpr(); - else - break; - } - return isa(Arg); - } - void reportBug(const LambdaCapture &Capture, ValueDecl *CapturedVar, const QualType T) const { assert(CapturedVar); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 0ff50bb835d1c..69cf2dd6fc14e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1814,8 +1814,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: case Stmt::OMPReverseDirectiveClass: - case Stmt::OMPTileDirectiveClass: case Stmt::OMPStripeDirectiveClass: + case Stmt::OMPTileDirectiveClass: case Stmt::OMPInterchangeDirectiveClass: case Stmt::OMPInteropDirectiveClass: case Stmt::OMPDispatchDirectiveClass: @@ -2814,13 +2814,24 @@ void ExprEngine::processBranch( if (StTrue && StFalse) assert(!isa(Condition)); + // We want to ensure consistent behavior between `eagerly-assume=false`, + // when the state split is always performed by the `assumeCondition()` + // call within this function and `eagerly-assume=true` (the default), when + // some conditions (comparison operators, unary negation) can trigger a + // state split before this callback. There are some contrived corner cases + // that behave differently with and without `eagerly-assume`, but I don't + // know about an example that could plausibly appear in "real" code. + bool BothFeasible = + (StTrue && StFalse) || + didEagerlyAssumeBifurcateAt(PrevState, dyn_cast(Condition)); + if (StTrue) { - // If we are processing a loop condition where two iterations have - // already been completed and the false branch is also feasible, then - // don't assume a third iteration because it is a redundant execution - // path (unlikely to be different from earlier loop exits) and can cause - // false positives if e.g. the loop iterates over a two-element structure - // with an opaque condition. + // In a loop, if both branches are feasible (i.e. the analyzer doesn't + // understand the loop condition) and two iterations have already been + // completed, then don't assume a third iteration because it is a + // redundant execution path (unlikely to be different from earlier loop + // exits) and can cause false positives if e.g. the loop iterates over a + // two-element structure with an opaque condition. // // The iteration count "2" is hardcoded because it's the natural limit: // * the fact that the programmer wrote a loop (and not just an `if`) @@ -2831,10 +2842,7 @@ void ExprEngine::processBranch( // two iterations". (This pattern is common in FFMPEG and appears in // many other projects as well.) bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2; - bool FalseAlsoFeasible = - StFalse || - didEagerlyAssumeBifurcateAt(PrevState, dyn_cast(Condition)); - bool SkipTrueBranch = CompletedTwoIterations && FalseAlsoFeasible; + bool SkipTrueBranch = BothFeasible && CompletedTwoIterations; // FIXME: This "don't assume third iteration" heuristic partially // conflicts with the widen-loop analysis option (which is off by @@ -2844,8 +2852,25 @@ void ExprEngine::processBranch( Builder.generateNode(StTrue, true, PredN); } - if (StFalse) - Builder.generateNode(StFalse, false, PredN); + if (StFalse) { + // In a loop, if both branches are feasible (i.e. the analyzer doesn't + // understand the loop condition), we are before the first iteration and + // the analyzer option `assume-at-least-one-iteration` is set to `true`, + // then avoid creating the execution path where the loop is skipped. + // + // In some situations this "loop is skipped" execution path is an + // important corner case that may evade the notice of the developer and + // hide significant bugs -- however, there are also many situations where + // it's guaranteed that at least one iteration will happen (e.g. some + // data structure is always nonempty), but the analyzer cannot realize + // this and will produce false positives when it assumes that the loop is + // skipped. + bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0}; + bool SkipFalseBranch = BothFeasible && BeforeFirstIteration && + AMgr.options.ShouldAssumeAtLeastOneIteration; + if (!SkipFalseBranch) + Builder.generateNode(StFalse, false, PredN); + } } currBldrCtx = nullptr; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 3a983421358c7..1061dafbb2473 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -523,6 +523,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_MatrixCast: case CK_VectorSplat: case CK_HLSLElementwiseCast: + case CK_HLSLAggregateSplatCast: case CK_HLSLVectorTruncation: { QualType resultType = CastE->getType(); if (CastE->isGLValue()) diff --git a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp index d15b74a28ab24..ff076a1db0d59 100644 --- a/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp +++ b/clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp @@ -324,15 +324,12 @@ class DependencyScanningAction : public tooling::ToolAction { // Create the compiler's actual diagnostics engine. sanitizeDiagOpts(ScanInstance.getDiagnosticOpts()); + assert(!DiagConsumerFinished && "attempt to reuse finished consumer"); ScanInstance.createDiagnostics(DriverFileMgr->getVirtualFileSystem(), DiagConsumer, /*ShouldOwnClient=*/false); if (!ScanInstance.hasDiagnostics()) return false; - // Some DiagnosticConsumers require that finish() is called. - auto DiagConsumerFinisher = - llvm::make_scope_exit([DiagConsumer]() { DiagConsumer->finish(); }); - ScanInstance.getPreprocessorOpts().AllowPCHWithDifferentModulesCachePath = true; @@ -446,10 +443,11 @@ class DependencyScanningAction : public tooling::ToolAction { if (ScanInstance.getDiagnostics().hasErrorOccurred()) return false; - // Each action is responsible for calling finish. - DiagConsumerFinisher.release(); const bool Result = ScanInstance.ExecuteAction(*Action); + // ExecuteAction is responsible for calling finish. + DiagConsumerFinished = true; + if (Result) setLastCC1Arguments(std::move(OriginalInvocation)); @@ -460,6 +458,7 @@ class DependencyScanningAction : public tooling::ToolAction { } bool hasScanned() const { return Scanned; } + bool hasDiagConsumerFinished() const { return DiagConsumerFinished; } /// Take the cc1 arguments corresponding to the most recent invocation used /// with this action. Any modifications implied by the discovered dependencies @@ -491,6 +490,7 @@ class DependencyScanningAction : public tooling::ToolAction { std::shared_ptr MDC; std::vector LastCC1Arguments; bool Scanned = false; + bool DiagConsumerFinished = false; }; } // end anonymous namespace @@ -693,6 +693,11 @@ bool DependencyScanningWorker::scanDependencies( if (Success && !Action.hasScanned()) Diags->Report(diag::err_fe_expected_compiler_job) << llvm::join(CommandLine, " "); + + // Ensure finish() is called even if we never reached ExecuteAction(). + if (!Action.hasDiagConsumerFinished()) + DC.finish(); + return Success && Action.hasScanned(); } diff --git a/clang/test/AST/ByteCode/new-delete.cpp b/clang/test/AST/ByteCode/new-delete.cpp index e60ff894c9715..31f066b37858d 100644 --- a/clang/test/AST/ByteCode/new-delete.cpp +++ b/clang/test/AST/ByteCode/new-delete.cpp @@ -840,10 +840,17 @@ template struct SS { constexpr SS(unsigned long long N) : data(nullptr){ - data = alloc.allocate(N); // #call + data = alloc.allocate(N); for(std::size_t i = 0; i < N; i ++) - std::construct_at(data + i, i); // #construct_call + std::construct_at(data + i, i); } + + constexpr SS() + : data(nullptr){ + data = alloc.allocate(1); + std::construct_at(data); + } + constexpr T operator[](std::size_t i) const { return data[i]; } @@ -855,6 +862,7 @@ struct SS { T* data; }; constexpr unsigned short ssmall = SS(100)[42]; +constexpr auto Ss = SS()[0]; diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index b1631f7822ce0..f39a4cee518ce 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -156,3 +156,49 @@ ATemplatedClass2 test2(list); // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible } // namespace GH90209 + +namespace GH124715 { + +template +concept invocable = true; + +template struct Struct { + template + requires invocable + Struct(U, Args...) {} +}; + +template struct Packs {}; + +template +Struct(Lambda lambda, Args... args) -> Struct; + +template using Alias = Struct>; + +void foo() { + Alias([](int) {}, Packs()); +} + +// CHECK: |-FunctionTemplateDecl {{.*}} implicit +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 1 ... Ts +// CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 2 U +// CHECK-NEXT: | |-BinaryOperator {{.*}} 'bool' '&&' +// CHECK-NEXT: | | |-ConceptSpecializationExpr {{.*}} 'bool' Concept {{.*}} 'invocable' +// CHECK-NEXT: | | | |-ImplicitConceptSpecializationDecl {{.*}} +// CHECK-NEXT: | | | | |-TemplateArgument type 'type-parameter-0-2' +// CHECK-NEXT: | | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2 +// CHECK-NEXT: | | | | `-TemplateArgument pack '>' +// CHECK-NEXT: | | | | `-TemplateArgument type 'Packs' +// CHECK-NEXT: | | | | `-TemplateSpecializationType {{.*}} 'Packs' dependent +// CHECK-NEXT: | | | | |-name: 'GH124715::Packs' +// CHECK-NEXT: | | | | | `-ClassTemplateDecl {{.*}} Packs +// CHECK-NEXT: | | | | `-TemplateArgument pack '' +// CHECK-NEXT: | | | | `-TemplateArgument type 'type-parameter-0-1...' +// CHECK-NEXT: | | | | `-PackExpansionType {{.*}} 'type-parameter-0-1...' dependent +// CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack +// CHECK-NEXT: | | | |-TemplateArgument {{.*}} type 'U':'type-parameter-0-2' +// CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'U' dependent depth 0 index 2 +// CHECK-NEXT: | | | | `-TemplateTypeParm {{.*}} 'U' + +} // namespace GH124715 diff --git a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp index 854d12b4cdba6..abe9d6a5b5bc6 100644 --- a/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp +++ b/clang/test/AST/ast-dump-cxx2b-deducing-this.cpp @@ -13,3 +13,16 @@ void main() { // CHECK-NEXT: | `-DeclRefExpr 0x{{[^ ]*}} 'int (S &)' lvalue CXXMethod 0x{{[^ ]*}} 'f' 'int (S &)' } } + +namespace GH1269720 { +template +struct S { + void f(this S&); + void g(S s) { + s.f(); + } + // CHECK: CallExpr 0x{{[^ ]*}} '' + // CHECK-NEXT: `-MemberExpr 0x{{[^ ]*}} '' .f + // CHECK-NEXT: `-DeclRefExpr 0x{{[^ ]*}} 'S' lvalue ParmVar 0x{{[^ ]*}} 's' 'S' +}; +} diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp index 86af8c50f3174..2728dc151c3c5 100644 --- a/clang/test/AST/ast-dump-templates.cpp +++ b/clang/test/AST/ast-dump-templates.cpp @@ -1,12 +1,12 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump=json %s | FileCheck --check-prefix=JSON %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-print %s > %t +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++20 -ast-dump=json %s | FileCheck --check-prefix=JSON %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++20 -ast-print %s > %t // RUN: FileCheck < %t %s -check-prefix=CHECK1 // RUN: FileCheck < %t %s -check-prefix=CHECK2 -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -ast-dump %s | FileCheck --check-prefix=DUMP %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++20 -ast-dump %s | FileCheck --check-prefix=DUMP %s // Test with serialization: -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++17 -emit-pch -o %t %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -x c++ -std=c++17 -include-pch %t \ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++20 -emit-pch -o %t %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -x c++ -std=c++20 -include-pch %t \ // RUN: -ast-dump-all /dev/null \ // RUN: | sed -e "s/ //" -e "s/ imported//" \ // RUN: | FileCheck --strict-whitespace --check-prefix=DUMP %s @@ -135,6 +135,17 @@ namespace test7 { // DUMP: ClassTemplateSpecializationDecl {{.*}} struct A definition explicit_instantiation_definition strict-pack-match{{$}} } // namespce test7 +namespace test8 { +template<_Complex int x> +struct pr126341; +template<> +struct pr126341<{1, 2}>; +// DUMP-LABEL: NamespaceDecl {{.*}} test8{{$}} +// DUMP-NEXT: |-ClassTemplateDecl {{.*}} pr126341 +// DUMP: `-ClassTemplateSpecializationDecl {{.*}} pr126341 +// DUMP: `-TemplateArgument structural value '1+2i' +} // namespace test8 + // NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py @@ -486,6 +497,7 @@ namespace test7 { // JSON-NEXT: "trivial": true // JSON-NEXT: }, // JSON-NEXT: "defaultCtor": { +// JSON-NEXT: "defaultedIsConstexpr": true, // JSON-NEXT: "exists": true, // JSON-NEXT: "nonTrivial": true, // JSON-NEXT: "userProvided": true @@ -819,6 +831,7 @@ namespace test7 { // JSON-NEXT: "trivial": true // JSON-NEXT: }, // JSON-NEXT: "defaultCtor": { +// JSON-NEXT: "defaultedIsConstexpr": true, // JSON-NEXT: "exists": true, // JSON-NEXT: "nonTrivial": true, // JSON-NEXT: "userProvided": true @@ -1408,6 +1421,7 @@ namespace test7 { // JSON-NEXT: "qualType": "void () noexcept" // JSON-NEXT: }, // JSON-NEXT: "inline": true, +// JSON-NEXT: "constexpr": true, // JSON-NEXT: "explicitlyDefaulted": "default" // JSON-NEXT: } // JSON-NEXT: ] @@ -1454,6 +1468,7 @@ namespace test7 { // JSON-NEXT: "trivial": true // JSON-NEXT: }, // JSON-NEXT: "defaultCtor": { +// JSON-NEXT: "defaultedIsConstexpr": true, // JSON-NEXT: "exists": true, // JSON-NEXT: "nonTrivial": true, // JSON-NEXT: "userProvided": true @@ -2067,6 +2082,7 @@ namespace test7 { // JSON-NEXT: "qualType": "void () noexcept" // JSON-NEXT: }, // JSON-NEXT: "inline": true, +// JSON-NEXT: "constexpr": true, // JSON-NEXT: "explicitlyDefaulted": "default" // JSON-NEXT: } // JSON-NEXT: ] @@ -6158,6 +6174,148 @@ namespace test7 { // JSON-NEXT: ] // JSON-NEXT: } // JSON-NEXT: ] +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "NamespaceDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 4339, +// JSON-NEXT: "line": 138, +// JSON-NEXT: "col": 11, +// JSON-NEXT: "tokLen": 5 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 4329, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 9 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 4648, +// JSON-NEXT: "line": 147, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "test8", +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "ClassTemplateDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 4379, +// JSON-NEXT: "line": 140, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 4347, +// JSON-NEXT: "line": 139, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 4379, +// JSON-NEXT: "line": 140, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "pr126341", +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "NonTypeTemplateParmDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 4369, +// JSON-NEXT: "line": 139, +// JSON-NEXT: "col": 23, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 4356, +// JSON-NEXT: "col": 10, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 4369, +// JSON-NEXT: "col": 23, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "x", +// JSON-NEXT: "type": { +// JSON-NEXT: "qualType": "_Complex int" +// JSON-NEXT: }, +// JSON-NEXT: "depth": 0, +// JSON-NEXT: "index": 0 +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "CXXRecordDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 4379, +// JSON-NEXT: "line": 140, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 4372, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 6 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 4379, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "pr126341", +// JSON-NEXT: "tagUsed": "struct" +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "ClassTemplateSpecializationDecl", +// JSON-NEXT: "name": "pr126341" +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: }, +// JSON-NEXT: { +// JSON-NEXT: "id": "0x{{.*}}", +// JSON-NEXT: "kind": "ClassTemplateSpecializationDecl", +// JSON-NEXT: "loc": { +// JSON-NEXT: "offset": 4407, +// JSON-NEXT: "line": 142, +// JSON-NEXT: "col": 8, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "range": { +// JSON-NEXT: "begin": { +// JSON-NEXT: "offset": 4389, +// JSON-NEXT: "line": 141, +// JSON-NEXT: "col": 1, +// JSON-NEXT: "tokLen": 8 +// JSON-NEXT: }, +// JSON-NEXT: "end": { +// JSON-NEXT: "offset": 4422, +// JSON-NEXT: "line": 142, +// JSON-NEXT: "col": 23, +// JSON-NEXT: "tokLen": 1 +// JSON-NEXT: } +// JSON-NEXT: }, +// JSON-NEXT: "name": "pr126341", +// JSON-NEXT: "tagUsed": "struct", +// JSON-NEXT: "inner": [ +// JSON-NEXT: { +// JSON-NEXT: "kind": "TemplateArgument", +// JSON-NEXT: "value": "1+2i" +// JSON-NEXT: } +// JSON-NEXT: ] +// JSON-NEXT: } +// JSON-NEXT: ] // JSON-NEXT: } // JSON-NEXT: ] // JSON-NEXT: } diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp index 215238a7fcf07..8da415a818a82 100644 --- a/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp +++ b/clang/test/Analysis/Checkers/WebKit/call-args-counted-const-member.cpp @@ -31,6 +31,7 @@ class Foo { public: Foo(); void bar(); + RefCountable& obj1() const { return m_obj1; } private: const Ref m_obj1; @@ -41,6 +42,7 @@ void Foo::bar() { m_obj1->method(); m_obj2->method(); // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + obj1().method(); } } // namespace call_args_const_ref_member @@ -100,6 +102,7 @@ class Foo { public: Foo(); void bar(); + RefCountable& obj1() { return m_obj1; } private: const UniqueRef m_obj1; @@ -110,6 +113,7 @@ void Foo::bar() { m_obj1->method(); m_obj2->method(); // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} + obj1().method(); } } // namespace call_args_const_unique_ref diff --git a/clang/test/Analysis/Checkers/WebKit/call-args-loop-init-opaque-value.cpp b/clang/test/Analysis/Checkers/WebKit/call-args-loop-init-opaque-value.cpp new file mode 100644 index 0000000000000..8fa10306c20f3 --- /dev/null +++ b/clang/test/Analysis/Checkers/WebKit/call-args-loop-init-opaque-value.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s + +typedef unsigned long size_t; +template +struct Obj { + constexpr static size_t Size = N; + + constexpr T& operator[](size_t i) { return components[i]; } + constexpr const T& operator[](size_t i) const { return components[i]; } + + constexpr size_t size() const { return Size; } + + T components[N]; +}; + +template +constexpr bool operator==(const Obj& a, const Obj& b) +{ + for (size_t i = 0; i < N; ++i) { + if (a[i] == b[i]) + continue; + return false; + } + + return true; +} + +struct NonTrivial { + NonTrivial(); + NonTrivial(const NonTrivial&); + bool operator==(const NonTrivial& other) const { return value == other.value; } + float value; +}; + +class Component { +public: + void ref() const; + void deref() const; + + Obj unresolvedComponents() const { return m_components; } + Obj unresolvedNonTrivialComponents() const { return m_nonTrivialComponents; } + + bool isEqual(const Component& other) const { + return unresolvedComponents() == other.unresolvedComponents(); + } + + bool isNonTrivialEqual(const Component& other) const { + return unresolvedNonTrivialComponents() == other.unresolvedNonTrivialComponents(); + } + +private: + Obj m_components; + Obj m_nonTrivialComponents; +}; + +Component* provide(); +bool someFunction(Component* other) { + return provide()->isEqual(*other); +} + +bool otherFunction(Component* other) { + return provide()->isNonTrivialEqual(*other); + // expected-warning@-1{{Call argument for 'this' parameter is uncounted and unsafe}} +} diff --git a/clang/test/Analysis/Checkers/WebKit/mock-types.h b/clang/test/Analysis/Checkers/WebKit/mock-types.h index 85397c2d25951..a1f0cc8b046b9 100644 --- a/clang/test/Analysis/Checkers/WebKit/mock-types.h +++ b/clang/test/Analysis/Checkers/WebKit/mock-types.h @@ -289,6 +289,7 @@ class UniqueRef { u.t = nullptr; } T &get() const { return *t; } + operator T&() const { return *t; } T *operator->() const { return t; } UniqueRef &operator=(T &) { return *this; } }; diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp index 4f4a960282253..82058bf13d137 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-lambda-captures.cpp @@ -89,6 +89,7 @@ template void call(Callback callback) { someFunction(); callback(); } +void callAsync(const WTF::Function&); void raw_ptr() { RefCountable* ref_countable = make_obj(); @@ -298,6 +299,41 @@ struct RefCountableWithLambdaCapturingThis { callLambda([&]() -> RefPtr { return obj->next(); }); + WTF::HashMap> anotherMap([&] { + return obj->next(); + }); + } + + void callAsyncNoescape([[clang::noescape]] WTF::Function&&); + void method_temp_lambda(RefCountable* obj) { + callAsyncNoescape([this, otherObj = RefPtr { obj }](auto& obj) { + return otherObj == &obj; + }); + } + + void method_nested_lambda() { + callAsync([this, protectedThis = Ref { *this }] { + callAsync([this, protectedThis = static_cast&&>(protectedThis)] { + nonTrivial(); + }); + }); + } + + void method_nested_lambda2() { + callAsync([this, protectedThis = RefPtr { this }] { + callAsync([this, protectedThis = static_cast&&>(*protectedThis)] { + nonTrivial(); + }); + }); + } + + void method_nested_lambda3() { + callAsync([this, protectedThis = RefPtr { this }] { + callAsync([this] { + // expected-warning@-1{{Captured raw-pointer 'this' to ref-counted type or CheckedPtr-capable type is unsafe [webkit.UncountedLambdaCapturesChecker]}} + nonTrivial(); + }); + }); } }; diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp index ffeecbf87c451..fe7ce158eb8ba 100644 --- a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp +++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.cpp @@ -77,6 +77,8 @@ T&& forward(T& arg); template T&& move( T&& t ); +#define offsetof(t, d) __builtin_offsetof(t, d) + } // namespace std bool isMainThread(); @@ -373,6 +375,8 @@ class RefCounted { double y; }; void trivial68() { point pt = { 1.0 }; } + unsigned trivial69() { return offsetof(RefCounted, children); } + DerivedNumber* trivial70() { [[clang::suppress]] return static_cast(number); } static RefCounted& singleton() { static RefCounted s_RefCounted; @@ -560,6 +564,8 @@ class UnrelatedClass { getFieldTrivial().trivial66()->trivial6(); // no-warning getFieldTrivial().trivial67()->trivial6(); // no-warning getFieldTrivial().trivial68(); // no-warning + getFieldTrivial().trivial69(); // no-warning + getFieldTrivial().trivial70(); // no-warning RefCounted::singleton().trivial18(); // no-warning RefCounted::singleton().someFunction(); // no-warning diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c index d5eb790b82f23..f6a49680917ac 100644 --- a/clang/test/Analysis/analyzer-config.c +++ b/clang/test/Analysis/analyzer-config.c @@ -10,6 +10,7 @@ // CHECK-NEXT: alpha.cplusplus.STLAlgorithmModeling:AggressiveStdFindModeling = false // CHECK-NEXT: alpha.osx.cocoa.DirectIvarAssignment:AnnotatedFunctions = false // CHECK-NEXT: apply-fixits = false +// CHECK-NEXT: assume-at-least-one-iteration = false // CHECK-NEXT: assume-controlled-environment = false // CHECK-NEXT: avoid-suppressing-null-argument-paths = false // CHECK-NEXT: c++-allocator-inlining = true diff --git a/clang/test/Analysis/live-stmts.cpp b/clang/test/Analysis/live-stmts.cpp index 33b8d59305d3d..9cac815e65de1 100644 --- a/clang/test/Analysis/live-stmts.cpp +++ b/clang/test/Analysis/live-stmts.cpp @@ -1,5 +1,5 @@ -// Flaky on aarch64: http://llvm.org/PR126619 -// UNSUPPORTED: target=aarch64{{.*}} +// Disabling this flaky test, see https://github.com/llvm/llvm-project/pull/126913#issuecomment-2655850766 +// UNSUPPORTED: true // RUN: %clang_analyze_cc1 -w -analyzer-checker=debug.DumpLiveExprs %s 2>&1\ // RUN: | FileCheck %s @@ -29,34 +29,36 @@ int testThatDumperWorks(int x, int y, int z) { // CHECK-EMPTY: // CHECK: [ B2 (live expressions at block exit) ] // CHECK-EMPTY: -// CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' -// CHECK-EMPTY: -// CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int' -// CHECK-EMPTY: // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: `-ImplicitCastExpr {{.*}} // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' // CHECK-EMPTY: -// CHECK-EMPTY: -// CHECK: [ B3 (live expressions at block exit) ] -// CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int' // CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK: [ B3 (live expressions at block exit) ] +// CHECK-EMPTY: // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: `-ImplicitCastExpr {{.*}} // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' -// CHECK: [ B4 (live expressions at block exit) ] // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' // CHECK-EMPTY: // CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int' // CHECK-EMPTY: +// CHECK-EMPTY: +// CHECK: [ B4 (live expressions at block exit) ] +// CHECK-EMPTY: // CHECK-NEXT: ImplicitCastExpr {{.*}} // CHECK-NEXT: `-ImplicitCastExpr {{.*}} // CHECK-NEXT: `-DeclRefExpr {{.*}} 'x' 'int' // CHECK-EMPTY: +// CHECK-NEXT: DeclRefExpr {{.*}} 'y' 'int' +// CHECK-EMPTY: +// CHECK-NEXT: DeclRefExpr {{.*}} 'z' 'int' +// CHECK-EMPTY: // CHECK-EMPTY: // CHECK: [ B5 (live expressions at block exit) ] // CHECK-EMPTY: @@ -226,15 +228,15 @@ int logicalOpInTernary(bool b) { // CHECK: ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: -// CHECK: ImplicitCastExpr {{.*}} '_Bool' -// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' -// CHECK-EMPTY: // CHECK: BinaryOperator {{.*}} '_Bool' '||' // CHECK: |-ImplicitCastExpr {{.*}} '_Bool' // CHECK: | `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK: `-ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: +// CHECK: ImplicitCastExpr {{.*}} '_Bool' +// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' +// CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 0 // CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 1 @@ -245,15 +247,15 @@ int logicalOpInTernary(bool b) { // CHECK: ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: -// CHECK: ImplicitCastExpr {{.*}} '_Bool' -// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' -// CHECK-EMPTY: // CHECK: BinaryOperator {{.*}} '_Bool' '||' // CHECK: |-ImplicitCastExpr {{.*}} '_Bool' // CHECK: | `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK: `-ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: +// CHECK: ImplicitCastExpr {{.*}} '_Bool' +// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' +// CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 0 // CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 1 @@ -264,15 +266,15 @@ int logicalOpInTernary(bool b) { // CHECK: ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: -// CHECK: ImplicitCastExpr {{.*}} '_Bool' -// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' -// CHECK-EMPTY: // CHECK: BinaryOperator {{.*}} '_Bool' '||' // CHECK: |-ImplicitCastExpr {{.*}} '_Bool' // CHECK: | `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK: `-ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: +// CHECK: ImplicitCastExpr {{.*}} '_Bool' +// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' +// CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 0 // CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 1 @@ -283,15 +285,15 @@ int logicalOpInTernary(bool b) { // CHECK: ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: -// CHECK: ImplicitCastExpr {{.*}} '_Bool' -// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' -// CHECK-EMPTY: // CHECK: BinaryOperator {{.*}} '_Bool' '||' // CHECK: |-ImplicitCastExpr {{.*}} '_Bool' // CHECK: | `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK: `-ImplicitCastExpr {{.*}} '_Bool' // CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' // CHECK-EMPTY: +// CHECK: ImplicitCastExpr {{.*}} '_Bool' +// CHECK: `-DeclRefExpr {{.*}} '_Bool' lvalue ParmVar {{.*}} 'b' '_Bool' +// CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 0 // CHECK-EMPTY: // CHECK: IntegerLiteral {{.*}} 'int' 1 diff --git a/clang/test/Analysis/loop-assumptions.c b/clang/test/Analysis/loop-assumptions.c index eb0ffdce722e0..b61ed8815e3f6 100644 --- a/clang/test/Analysis/loop-assumptions.c +++ b/clang/test/Analysis/loop-assumptions.c @@ -1,25 +1,48 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection \ -// RUN: -verify=expected,eagerlyassume %s +// RUN: -verify=expected,noassumeone,eagerlyassume,combo %s // RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection \ // RUN: -analyzer-config eagerly-assume=false \ +// RUN: -verify=expected,noassumeone,noeagerlyassume,combo %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config assume-at-least-one-iteration=true \ +// RUN: -verify=expected,eagerlyassume,combo %s +// RUN: %clang_analyze_cc1 -analyzer-checker=debug.ExprInspection \ +// RUN: -analyzer-config assume-at-least-one-iteration=true,eagerly-assume=false \ // RUN: -verify=expected,noeagerlyassume %s +// The verify tag "combo" is used for one unique warning which is produced in three +// of the four RUN combinations. + // These tests validate the logic within `ExprEngine::processBranch` which // ensures that in loops with opaque conditions we don't assume execution paths // if the code does not imply that they are possible. +// In particular, if two (or more) iterations are already completed in a loop, +// we don't assume that there can be another iteration. Moreover, if the +// analyzer option `assume-at-least-one-iteration` is enabled, then we don't +// assume that a loop can be skipped completely. void clang_analyzer_numTimesReached(void); -void clang_analyzer_warnIfReached(void); void clang_analyzer_dump(int); -void clearCondition(void) { - // If the analyzer can definitely determine the value of the loop condition, +void clearTrueCondition(void) { + // If the analyzer can definitely determine that the loop condition is true, // then this corrective logic doesn't activate and the engine executes // `-analyzer-max-loop` iterations (by default, 4). - for (int i = 0; i < 10; i++) + int i; + for (i = 0; i < 10; i++) clang_analyzer_numTimesReached(); // expected-warning {{4}} - clang_analyzer_warnIfReached(); // unreachable + clang_analyzer_dump(i); // Unreachable, no reports. +} + +void clearFalseCondition(void) { + // If the analyzer can definitely determine that the loop condition is false, + // then the loop is skipped, even in `assume-at-least-one-iteration` mode. + int i; + for (i = 0; i > 10; i++) + clang_analyzer_numTimesReached(); // Unreachable, no report. + + clang_analyzer_dump(i); // expected-warning {{0}} } void opaqueCondition(int arg) { @@ -28,10 +51,13 @@ void opaqueCondition(int arg) { // that more than two iterations are possible. (It _does_ imply that two // iterations may be possible at least in some cases, because otherwise an // `if` would've been enough.) - for (int i = 0; i < arg; i++) + // Moreover, if `assume-at-least-one-iteration` is enabled, then assume at + // least one iteration. + int i; + for (i = 0; i < arg; i++) clang_analyzer_numTimesReached(); // expected-warning {{2}} - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + clang_analyzer_dump(i); // noassumeone-warning {{0}} expected-warning {{1}} expected-warning {{2}} } int check(void); @@ -42,22 +68,26 @@ void opaqueConditionCall(int arg) { // insert an assertion to guide the analyzer and rule out more than two // iterations (so the analyzer needs to proactively avoid those unjustified // branches). - while (check()) + int i = 0; // Helper to distinguish the the branches after the loop. + while (check()) { clang_analyzer_numTimesReached(); // expected-warning {{2}} + i++; + } - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + clang_analyzer_dump(i); // noassumeone-warning {{0}} expected-warning {{1}} expected-warning {{2}} } void opaqueConditionDoWhile(int arg) { // Same situation as `opaqueCondition()` but with a `do {} while ()` loop. // This is tested separately because this loop type is a special case in the // iteration count calculation. + // Obviously, this loop guarantees that at least one iteration will happen. int i = 0; do { clang_analyzer_numTimesReached(); // expected-warning {{2}} } while (i++ < arg); - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + clang_analyzer_dump(i); // expected-warning {{1}} expected-warning {{2}} } void dontRememberOldBifurcation(int arg) { @@ -69,7 +99,7 @@ void dontRememberOldBifurcation(int arg) { // by default), because the code remembered that there was a bifurcation on // the first iteration of the loop and didn't realize that this is obsolete. - // NOTE: The variable `i` is introduced to ensure that the iterations of the + // NOTE: The variable `i` is significant to ensure that the iterations of the // loop change the state -- otherwise the analyzer stops iterating because it // returns to the same `ExplodedNode`. int i = 0; @@ -78,10 +108,12 @@ void dontRememberOldBifurcation(int arg) { i++; } - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + clang_analyzer_dump(i); // noassumeone-warning {{0}} } void dontAssumeFourthIterartion(int arg) { + int i; + if (arg == 2) return; @@ -89,10 +121,10 @@ void dontAssumeFourthIterartion(int arg) { // iterations (because it knows that `arg != 2` at that point), so it // performs a third iteration, but it does not assume that a fourth iteration // is also possible. - for (int i = 0; i < arg; i++) + for (i = 0; i < arg; i++) clang_analyzer_numTimesReached(); // expected-warning {{3}} - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + clang_analyzer_dump(i); // noassumeone-warning {{0}} expected-warning {{1}} expected-warning {{3}} } #define TRUE 1 @@ -108,42 +140,53 @@ void shortCircuitInLoopCondition(int arg) { // false positive on the ffmpeg codebase. Eventually we should properly // recognize the full syntactical loop condition expression as "the loop // condition", but this will be complicated to implement. - for (int i = 0; i < arg && TRUE; i++) { + int i; + for (i = 0; i < arg && TRUE; i++) { clang_analyzer_numTimesReached(); // expected-warning {{4}} } - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + + clang_analyzer_dump(i); // expected-warning {{0}} expected-warning {{1}} expected-warning {{2}} expected-warning {{3}} } void shortCircuitInLoopConditionRHS(int arg) { // Unlike `shortCircuitInLoopCondition()`, this case is handled properly // because the analyzer thinks that the right hand side of the `&&` is the // loop condition. - for (int i = 0; TRUE && i < arg; i++) { + int i; + for (i = 0; TRUE && i < arg; i++) { clang_analyzer_numTimesReached(); // expected-warning {{2}} } - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + + clang_analyzer_dump(i); // noassumeone-warning {{0}} expected-warning {{1}} expected-warning {{2}} } void eagerlyAssumeInSubexpression(int arg) { // The `EagerlyAssume` logic is another complication that can "split the // state" within the loop condition, but before the `processBranch()` call - // which is (in theory) responsible for evaluating the loop condition. - // The current implementation partially compensates this by noticing the + // which would be "naturally" responsible for evaluating the loop condition. + // The current implementation tries to handle this by noticing the // cases where the loop condition is targeted by `EagerlyAssume`, but does // not handle the (fortunately rare) case when `EagerlyAssume` hits a // sub-expression of the loop condition (as in this contrived test case). - // FIXME: I don't know a real-world example for this inconsistency, but it - // would be good to eliminate it eventually. - for (int i = 0; (i >= arg) - 1; i++) { + // FIXME: It would be good to eventually eliminate this inconsistency, but + // I don't know a realistic example that could appear in real-world code, so + // this seems to be a low-priority goal. + int i; + for (i = 0; (i >= arg) - 1; i++) { clang_analyzer_numTimesReached(); // eagerlyassume-warning {{4}} noeagerlyassume-warning {{2}} } - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + + // The 'combo' note intentionally appears if `assume-at-least-one-iteration` + // is disabled, but also appears as a bug when `eagerly-assume` and + // `assume-at-least-one-iteration` are both enabled. + clang_analyzer_dump(i); // combo-warning {{0}} expected-warning {{1}} expected-warning {{2}} eagerlyassume-warning {{3}} } void calledTwice(int arg, int isFirstCall) { // This function is called twice (with two different unknown 'arg' values) to // check the iteration count handling in this situation. - for (int i = 0; i < arg; i++) { + int i; + for (i = 0; i < arg; i++) { if (isFirstCall) { clang_analyzer_numTimesReached(); // expected-warning {{2}} } else { @@ -215,5 +258,5 @@ void onlyLoopConditions(int arg) { break; } - clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}} + clang_analyzer_dump(i); // expected-warning {{1}} expected-warning {{2}} expected-warning {{3}} expected-warning {{4}} } diff --git a/clang/test/Analysis/out-of-bounds-constraint-check.c b/clang/test/Analysis/out-of-bounds-constraint-check.c index df48c8c170713..f20159da02997 100644 --- a/clang/test/Analysis/out-of-bounds-constraint-check.c +++ b/clang/test/Analysis/out-of-bounds-constraint-check.c @@ -1,112 +1,163 @@ // RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,security.ArrayBound,debug.ExprInspection \ // RUN: -analyzer-config eagerly-assume=false -verify %s -void clang_analyzer_eval(int); -void clang_analyzer_printState(void); - -typedef typeof(sizeof(int)) size_t; -const char a[] = "abcd"; // extent: 5 bytes - -void symbolic_size_t_and_int0(size_t len) { - (void)a[len + 1]; // no-warning - // We infered that the 'len' must be in a specific range to make the previous indexing valid. - // len: [0,3] - clang_analyzer_eval(len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} -} - -void symbolic_size_t_and_int1(size_t len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} - -void symbolic_size_t_and_int2(size_t len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} -} - -void symbolic_uint_and_int0(unsigned len) { - (void)a[len + 1]; // no-warning - // len: [0,3] - clang_analyzer_eval(0 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} -} - -void symbolic_uint_and_int1(unsigned len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(0 <= len && len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} -void symbolic_uint_and_int2(unsigned len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} -} - -void symbolic_int_and_int0(int len) { - (void)a[len + 1]; // no-warning - // len: [-1,3] - clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} -} -void symbolic_int_and_int1(int len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(0 <= len && len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} -void symbolic_int_and_int2(int len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} -} - -void symbolic_longlong_and_int0(long long len) { - (void)a[len + 1]; // no-warning - // len: [-1,3] - clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} +// When the checker security.ArrayBound encounters an array subscript operation +// that _may be_ in bounds, it assumes that indexing _is_ in bound. This test +// file validates these assumptions. + +void clang_analyzer_value(int); + +// Simple case: memory area with a static extent. + +extern int FiveInts[5]; + +void int_plus_one(int len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} +} + +void int_neutral(int len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void int_minus_one(int len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} +} + +void unsigned_plus_one(unsigned len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} +} + +void unsigned_neutral(unsigned len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void unsigned_minus_one(unsigned len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} +} + +void ll_plus_one(long long len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} +} + +void ll_neutral(long long len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void ll_minus_one(long long len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} +} + +void ull_plus_one(unsigned long long len) { + (void)FiveInts[len + 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} +} + +void ull_neutral(unsigned long long len) { + (void)FiveInts[len]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} +} + +void ull_minus_one(unsigned long long len) { + (void)FiveInts[len - 1]; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} } +// Also try the same with a dynamically allocated memory block, because in the +// past there were issues with the type/signedness of dynamic extent symbols. + +typedef __typeof(sizeof(int)) size_t; void *malloc(size_t); void free(void *); -void symbolic_longlong_and_int0_dynamic_extent(long long len) { - char *b = malloc(5); - (void)b[len + 1]; // no-warning - // len: [-1,3] - clang_analyzer_eval(-1 <= len && len <= 3); // expected-warning {{TRUE}} - clang_analyzer_eval(0 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 2); // expected-warning {{UNKNOWN}} - free(b); -} - -void symbolic_longlong_and_int1(long long len) { - (void)a[len]; // no-warning - // len: [0,4] - clang_analyzer_eval(0 <= len && len <= 4); // expected-warning {{TRUE}} - clang_analyzer_eval(1 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 3); // expected-warning {{UNKNOWN}} -} - -void symbolic_longlong_and_int2(long long len) { - (void)a[len - 1]; // no-warning - // len: [1,5] - clang_analyzer_eval(1 <= len && len <= 5); // expected-warning {{TRUE}} - clang_analyzer_eval(2 <= len); // expected-warning {{UNKNOWN}} - clang_analyzer_eval(len <= 4); // expected-warning {{UNKNOWN}} + +void dyn_int_plus_one(int len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} + free(p); +} + +void dyn_int_neutral(int len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_int_minus_one(int len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); +} + +void dyn_unsigned_plus_one(unsigned len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} + free(p); +} + +void dyn_unsigned_neutral(unsigned len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_unsigned_minus_one(unsigned len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); +} + +void dyn_ll_plus_one(long long len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [-1, 3] }}} + free(p); +} + +void dyn_ll_neutral(long long len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_ll_minus_one(long long len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); +} + +void dyn_ull_plus_one(unsigned long long len) { + char *p = malloc(5); + p[len + 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 3] }}} + free(p); +} + +void dyn_ull_neutral(unsigned long long len) { + char *p = malloc(5); + p[len] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [0, 4] }}} + free(p); +} + +void dyn_ull_minus_one(unsigned long long len) { + char *p = malloc(5); + p[len - 1] = 1; // no-warning + clang_analyzer_value(len); // expected-warning {{{ [1, 5] }}} + free(p); } diff --git a/clang/test/Analysis/out-of-bounds.c b/clang/test/Analysis/out-of-bounds.c index 923797200d0b4..7a094b8fdc840 100644 --- a/clang/test/Analysis/out-of-bounds.c +++ b/clang/test/Analysis/out-of-bounds.c @@ -1,6 +1,6 @@ // RUN: %clang_analyze_cc1 -Wno-array-bounds -analyzer-checker=core,security.ArrayBound,debug.ExprInspection -verify %s -void clang_analyzer_eval(int); +void clang_analyzer_value(int); // Tests doing an out-of-bounds access after the end of an array using: // - constant integer index @@ -142,12 +142,6 @@ void test4(int x) { buf[x] = 1; // expected-warning{{Out of bound access to memory}} } -void test_assume_after_access(unsigned long x) { - int buf[100]; - buf[x] = 1; - clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} -} - // Don't warn when indexing below the start of a symbolic region's whose // base extent we don't know. int *get_symbolic(void); @@ -180,12 +174,6 @@ void test_extern_void(void) { p[1] = 42; // no-warning } -void test_assume_after_access2(unsigned long x) { - char buf[100]; - buf[x] = 1; - clang_analyzer_eval(x <= 99); // expected-warning{{TRUE}} -} - struct incomplete; char test_comparison_with_extent_symbol(struct incomplete *p) { // Previously this was reported as a (false positive) overflow error because @@ -194,3 +182,36 @@ char test_comparison_with_extent_symbol(struct incomplete *p) { return ((char *)p)[-1]; // no-warning } +int table[256], small_table[128]; +int test_cast_to_unsigned(signed char x) { + unsigned char y = x; + if (x >= 0) + return x; + // FIXME: Here the analyzer ignores the signed -> unsigned cast, and manages to + // load a negative value from an unsigned variable. This causes an underflow + // report, which is an ugly false positive. + // The underlying issue is tracked by Github ticket #39492. + clang_analyzer_value(y); // expected-warning {{8s:{ [-128, -1] } }} + return table[y]; // expected-warning {{Out of bound access to memory preceding}} +} + +int test_cast_to_unsigned_overflow(signed char x) { + unsigned char y = x; + if (x >= 0) + return x; + // A variant of 'test_cast_to_unsigned' where the correct behavior would be + // an overflow report (because the negative values are cast to `unsigned + // char` values that are too large). + // FIXME: See comment in 'test_cast_to_unsigned'. + clang_analyzer_value(y); // expected-warning {{8s:{ [-128, -1] } }} + return small_table[y]; // expected-warning {{Out of bound access to memory preceding}} +} + +int test_negative_offset_with_unsigned_idx(void) { + // An example where the subscript operator uses an unsigned index, but the + // underflow report is still justified. (We should try to keep this if we + // silence false positives like the one in 'test_cast_to_unsigned'.) + int *p = table - 10; + unsigned idx = 2u; + return p[idx]; // expected-warning {{Out of bound access to memory preceding}} +} diff --git a/clang/test/CMakeLists.txt b/clang/test/CMakeLists.txt index e9eb54a67204c..b796a51ef600e 100644 --- a/clang/test/CMakeLists.txt +++ b/clang/test/CMakeLists.txt @@ -103,6 +103,15 @@ if(CLANG_BUILD_EXAMPLES AND CLANG_PLUGIN_SUPPORT) ) endif () +if(LLVM_INCLUDE_SPIRV_TOOLS_TESTS) + list(APPEND CLANG_TEST_DEPS + spirv-dis + spirv-val + spirv-as + spirv-link + ) +endif() + set(CLANG_TEST_PARAMS USE_Z3_SOLVER=0 ) diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-vector-constrained.c b/clang/test/CodeGen/SystemZ/builtins-systemz-vector-constrained.c index 6d2845504a39f..ff24ef9a091b7 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-vector-constrained.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-vector-constrained.c @@ -44,12 +44,14 @@ void test_float(void) { // CHECK: call <2 x double> @llvm.experimental.constrained.nearbyint.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 1); // CHECK: call <2 x double> @llvm.experimental.constrained.round.v2f64(<2 x double> %{{.*}}) + vd = __builtin_s390_vfidb(vd, 4, 4); + // CHECK: call <2 x double> @llvm.experimental.constrained.roundeven.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 5); // CHECK: call <2 x double> @llvm.experimental.constrained.trunc.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 6); // CHECK: call <2 x double> @llvm.experimental.constrained.ceil.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 7); // CHECK: call <2 x double> @llvm.experimental.constrained.floor.v2f64(<2 x double> %{{.*}}) - vd = __builtin_s390_vfidb(vd, 4, 4); - // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4) + vd = __builtin_s390_vfidb(vd, 4, 3); + // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 3) } diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-vector.c b/clang/test/CodeGen/SystemZ/builtins-systemz-vector.c index 58e452ae05c40..ae3b08a1b67eb 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-vector.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-vector.c @@ -593,12 +593,14 @@ void test_float(void) { // CHECK: call <2 x double> @llvm.nearbyint.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 1); // CHECK: call <2 x double> @llvm.round.v2f64(<2 x double> %{{.*}}) + vd = __builtin_s390_vfidb(vd, 4, 4); + // CHECK: call <2 x double> @llvm.roundeven.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 5); // CHECK: call <2 x double> @llvm.trunc.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 6); // CHECK: call <2 x double> @llvm.ceil.v2f64(<2 x double> %{{.*}}) vd = __builtin_s390_vfidb(vd, 4, 7); // CHECK: call <2 x double> @llvm.floor.v2f64(<2 x double> %{{.*}}) - vd = __builtin_s390_vfidb(vd, 4, 4); - // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4) + vd = __builtin_s390_vfidb(vd, 4, 3); + // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 3) } diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-vector2-constrained.c b/clang/test/CodeGen/SystemZ/builtins-systemz-vector2-constrained.c index 735b6a0249ab6..12c675041af76 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-vector2-constrained.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-vector2-constrained.c @@ -59,11 +59,15 @@ void test_float(void) { // CHECK: call <4 x float> @llvm.experimental.constrained.nearbyint.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 1); // CHECK: call <4 x float> @llvm.experimental.constrained.round.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) + vf = __builtin_s390_vfisb(vf, 4, 4); + // CHECK: call <4 x float> @llvm.experimental.constrained.roundeven.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 5); // CHECK: call <4 x float> @llvm.experimental.constrained.trunc.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 6); // CHECK: call <4 x float> @llvm.experimental.constrained.ceil.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 7); // CHECK: call <4 x float> @llvm.experimental.constrained.floor.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) + vf = __builtin_s390_vfisb(vf, 4, 3); + // CHECK: call <4 x float> @llvm.s390.vfisb(<4 x float> %{{.*}}, i32 4, i32 3) } diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c b/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c index 3761f252d724b..8f9e164ebef8c 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-vector2.c @@ -125,13 +125,15 @@ void test_float(void) { // CHECK: call <4 x float> @llvm.nearbyint.v4f32(<4 x float> %{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 1); // CHECK: call <4 x float> @llvm.round.v4f32(<4 x float> %{{.*}}) + vf = __builtin_s390_vfisb(vf, 4, 4); + // CHECK: call <4 x float> @llvm.roundeven.v4f32(<4 x float> %{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 5); // CHECK: call <4 x float> @llvm.trunc.v4f32(<4 x float> %{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 6); // CHECK: call <4 x float> @llvm.ceil.v4f32(<4 x float> %{{.*}}) vf = __builtin_s390_vfisb(vf, 4, 7); // CHECK: call <4 x float> @llvm.floor.v4f32(<4 x float> %{{.*}}) - vf = __builtin_s390_vfisb(vf, 4, 4); - // CHECK: call <4 x float> @llvm.s390.vfisb(<4 x float> %{{.*}}, i32 4, i32 4) + vf = __builtin_s390_vfisb(vf, 4, 3); + // CHECK: call <4 x float> @llvm.s390.vfisb(<4 x float> %{{.*}}, i32 4, i32 3) } diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector-constrained.c b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector-constrained.c index 6a1f8f0e923f6..4993df20df143 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector-constrained.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector-constrained.c @@ -315,4 +315,6 @@ void test_float(void) { // CHECK: call <2 x double> @llvm.experimental.constrained.rint.v2f64(<2 x double> %{{.*}}, metadata !{{.*}}) // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 0, 0 vd = vec_round(vd); + // CHECK: call <2 x double> @llvm.experimental.constrained.roundeven.v2f64(<2 x double> %{{.*}}, metadata !{{.*}}) + // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 4 } diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c index 775733ad3b948..d5d15b4dea966 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c @@ -4889,7 +4889,7 @@ void test_float(void) { // CHECK: call <2 x double> @llvm.rint.v2f64(<2 x double> %{{.*}}) // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 0, 0 vd = vec_round(vd); - // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4) + // CHECK: call <2 x double> @llvm.roundeven.v2f64(<2 x double> %{{.*}}) // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 4 vbl = vec_fp_test_data_class(vd, 0, &cc); diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2-constrained.c b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2-constrained.c index 750f5011a2679..25b3e0b68cd02 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2-constrained.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2-constrained.c @@ -522,10 +522,10 @@ void test_float(void) { // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 0, 0 vf = vec_round(vf); - // CHECK: call <4 x float> @llvm.s390.vfisb(<4 x float> %{{.*}}, i32 4, i32 4) + // CHECK: call <4 x float> @llvm.experimental.constrained.roundeven.v4f32(<4 x float> %{{.*}}, metadata !{{.*}}) // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 4 vd = vec_round(vd); - // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4) + // CHECK: call <2 x double> @llvm.experimental.constrained.roundeven.v2f64(<2 x double> %{{.*}}, metadata !{{.*}}) // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 4 vbi = vec_fp_test_data_class(vf, 0, &cc); diff --git a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2.c b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2.c index 60df95817a329..c1ef178fcfaa9 100644 --- a/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2.c +++ b/clang/test/CodeGen/SystemZ/builtins-systemz-zvector2.c @@ -908,10 +908,10 @@ void test_float(void) { // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 0, 0 vf = vec_round(vf); - // CHECK: call <4 x float> @llvm.s390.vfisb(<4 x float> %{{.*}}, i32 4, i32 4) + // CHECK: call <4 x float> @llvm.roundeven.v4f32(<4 x float> %{{.*}}) // CHECK-ASM: vfisb %{{.*}}, %{{.*}}, 4, 4 vd = vec_round(vd); - // CHECK: call <2 x double> @llvm.s390.vfidb(<2 x double> %{{.*}}, i32 4, i32 4) + // CHECK: call <2 x double> @llvm.roundeven.v2f64(<2 x double> %{{.*}}) // CHECK-ASM: vfidb %{{.*}}, %{{.*}}, 4, 4 vbi = vec_fp_test_data_class(vf, 0, &cc); diff --git a/clang/test/CodeGen/X86/codemodel.cpp b/clang/test/CodeGen/X86/codemodel.cpp new file mode 100644 index 0000000000000..60a840665b49c --- /dev/null +++ b/clang/test/CodeGen/X86/codemodel.cpp @@ -0,0 +1,27 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-unknown-unknown %s -o - | FileCheck %s + +// CHECK: @_ZL2v1 ={{.*}} global i32 0, code_model "small" +static int v1 __attribute__((model("small"))); + +void use1() { + v1 = 1; +} + +// CHECK: @v2 ={{.*}} global float 0.000000e+00, code_model "large" +float v2 __attribute__((model("large"))); + +// CHECK: @_ZL2v3IiE ={{.*}} global i32 0, code_model "small" +template +static T v3 __attribute__((model("small"))); + +void use2() { + v3 = 1; +} +struct S { + double d; +}; + +typedef void (*F)(); + +// CHECK: @v4 ={{.*}} global ptr null, code_model "large" +F v4 __attribute__((model("large"))); diff --git a/clang/test/CodeGen/allow-ubsan-check.c b/clang/test/CodeGen/allow-ubsan-check.c index 0cd81a77f5cc5..c116604288546 100644 --- a/clang/test/CodeGen/allow-ubsan-check.c +++ b/clang/test/CodeGen/allow-ubsan-check.c @@ -86,7 +86,7 @@ int div(int x, int y) { } // CHECK-LABEL: define dso_local i32 @null( -// CHECK-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] // CHECK-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]] // @@ -102,7 +102,7 @@ int div(int x, int y) { // CHECK-NEXT: ret i32 [[TMP2]] // // TR-LABEL: define dso_local i32 @null( -// TR-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// TR-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { // TR-NEXT: [[ENTRY:.*:]] // TR-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]] // TR-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]] @@ -116,7 +116,7 @@ int div(int x, int y) { // TR-NEXT: ret i32 [[TMP2]] // // REC-LABEL: define dso_local i32 @null( -// REC-SAME: ptr noundef readonly [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { +// REC-SAME: ptr noundef readonly captures(address_is_null) [[X:%.*]]) local_unnamed_addr #[[ATTR0]] { // REC-NEXT: [[ENTRY:.*:]] // REC-NEXT: [[TMP0:%.*]] = icmp eq ptr [[X]], null, !nosanitize [[META2]] // REC-NEXT: [[TMP1:%.*]] = tail call i1 @llvm.allow.ubsan.check(i8 29), !nosanitize [[META2]] diff --git a/clang/test/CodeGen/builtin-assume-dereferenceable.c b/clang/test/CodeGen/builtin-assume-dereferenceable.c new file mode 100644 index 0000000000000..cadffd4a84c26 --- /dev/null +++ b/clang/test/CodeGen/builtin-assume-dereferenceable.c @@ -0,0 +1,34 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s + +// CHECK-LABEL: @test1( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 10) ] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int test1(int *a) { + __builtin_assume_dereferenceable(a, 10); + return a[0]; +} + +// CHECK-LABEL: @test2( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store ptr [[A:%.*]], ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[TMP0]], i64 32) ] +// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[A_ADDR]], align 8 +// CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[TMP1]], i64 0 +// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX]], align 4 +// CHECK-NEXT: ret i32 [[TMP2]] +// +int test2(int *a) { + __builtin_assume_dereferenceable(a, 32ull); + return a[0]; +} diff --git a/clang/test/CodeGen/fat-lto-objects-cfi.cpp b/clang/test/CodeGen/fat-lto-objects-cfi.cpp index 4055c5bee9b8a..6eee88884229f 100644 --- a/clang/test/CodeGen/fat-lto-objects-cfi.cpp +++ b/clang/test/CodeGen/fat-lto-objects-cfi.cpp @@ -1,21 +1,24 @@ // REQUIRES: x86-registered-target +// RUN: rm -rf %t && split-file %s %t // RUN: %clang_cc1 -triple x86_64-unknown-fuchsia -O2 -flto -ffat-lto-objects \ -// RUN: -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -fvisibility=hidden -emit-llvm -o - %s \ +// RUN: -fsanitize=cfi-icall -fsanitize-trap=cfi-icall -fvisibility=hidden \ +// RUN: -emit-llvm -o - %t/a.cpp \ // RUN: | FileCheck %s --check-prefix=TYPE_TEST +//--- a.cpp // TYPE_TEST: llvm.embedded.object // TYPE_TEST-SAME: section ".llvm.lto" +// COM: The FatLTO pipeline should remove all llvm.type.test instructions. // TYPE_TEST-LABEL: define hidden void @foo -// TYPE_TEST: entry: -// TYPE_TEST-NEXT: %cmp14.not = icmp eq i64 %len, 0 -// TYPE_TEST-NEXT: br i1 %cmp14.not, label %for.end7, label %for.cond1.preheader.preheader -// TYPE_TEST: for.cond1.preheader.preheader: ; preds = %entry -// TYPE_TEST-NEXT: %arrayidx.1 = getelementptr inbounds nuw i8, ptr %ptr, i64 4 -// TYPE_TEST-NEXT: br label %for.cond1.preheader - -// TYPE_TEST-NOT: @llvm.type.test +// TYPE_TEST-NOT: @llvm.type.test +// TYPE_TEST-NEXT: entry: +// TYPE_TEST-NEXT: %cmp14.not = icmp eq i64 %len, 0 +// TYPE_TEST-NEXT: br i1 %cmp14.not, label %for.end7, label %for.cond1.preheader.preheader +// TYPE_TEST-LABEL: for.cond1.preheader.preheader: ; preds = %entry +// TYPE_TEST-NEXT: %arrayidx.1 = getelementptr inbounds nuw i8, ptr %ptr, i64 4 +// TYPE_TEST-NEXT: br label %for.cond1.preheader // The code below is a reduced case from https://github.com/llvm/llvm-project/issues/112053 #define __PRINTFLIKE(__fmt, __varargs) __attribute__((__format__(__printf__, __fmt, __varargs))) @@ -44,3 +47,44 @@ void foo(const void* ptr, size_t len, long disp_addr, } } +//--- b.cpp +// COM: Prior to the introduction of the FatLTO cleanup pass, this used to cause +// COM: the backend to crash, either due to an assertion failure, or because +// COM: the CFI instructions couldn't be correctly generated. So, check to make +// COM: sure that the FatLTO pipeline used by clang does not regress. + +// COM: Check the generated IR doesn't contain llvm.type.checked.load in the final IR. +// RUN: %clang_cc1 -triple=x86_64-unknown-fuchsia -O1 -emit-llvm -o - \ +// RUN: -ffat-lto-objects -fvisibility=hidden \ +// RUN: -fno-rtti -fsanitize=cfi-icall,cfi-mfcall,cfi-nvcall,cfi-vcall \ +// RUN: -fsanitize-trap=cfi-icall,cfi-mfcall,cfi-nvcall,cfi-vcall \ +// RUN: -fwhole-program-vtables %t/b.cpp 2>&1 | FileCheck %s --check-prefix=NO_CHECKED_LOAD + +// RUN: %clang_cc1 -triple=x86_64-unknown-fuchsia -O1 -emit-llvm -o - \ +// RUN: -ffat-lto-objects -fvisibility=hidden -fexperimental-relative-c++-abi-vtables \ +// RUN: -fno-rtti -fsanitize=cfi-icall,cfi-mfcall,cfi-nvcall,cfi-vcall \ +// RUN: -fsanitize-trap=cfi-icall,cfi-mfcall,cfi-nvcall,cfi-vcall \ +// RUN: -fwhole-program-vtables %t/b.cpp 2>&1 | FileCheck %s --check-prefix=NO_CHECKED_LOAD + +// COM: Note that the embedded bitcode section will contain references to +// COM: llvm.type.checked.load, so we need to match the function body first. +// NO_CHECKED_LOAD-LABEL: entry: +// NO_CHECKED_LOAD-NEXT: %vtable = load ptr, ptr %p1 +// NO_CHECKED_LOAD-NOT: llvm.type.checked.load +// NO_CHECKED_LOAD-NEXT: %vfunc = load ptr, ptr %vtable +// NO_CHECKED_LOAD-NEXT: %call = tail call {{.*}} %vfunc(ptr {{.*}} %p1) +// NO_CHECKED_LOAD-NEXT: ret void + +// COM: Ensure that we don't crash in the backend anymore when clang uses +// COM: CFI checks with -ffat-lto-objects. +// RUN: %clang_cc1 -triple=x86_64-unknown-fuchsia -O1 -emit-codegen-only \ +// RUN: -ffat-lto-objects -fvisibility=hidden \ +// RUN: -fno-rtti -fsanitize=cfi-icall,cfi-mfcall,cfi-nvcall,cfi-vcall \ +// RUN: -fsanitize-trap=cfi-icall,cfi-mfcall,cfi-nvcall,cfi-vcall \ +// RUN: -fwhole-program-vtables %t/b.cpp + +class a { +public: + virtual long b(); +}; +void c(a &p1) { p1.b(); } diff --git a/clang/test/CodeGen/partial-reinitialization2.c b/clang/test/CodeGen/partial-reinitialization2.c index e709c1d4ad1ee..7949a69555031 100644 --- a/clang/test/CodeGen/partial-reinitialization2.c +++ b/clang/test/CodeGen/partial-reinitialization2.c @@ -91,8 +91,8 @@ void test5(void) // CHECK-LABEL: test6 void test6(void) { - // CHECK: [[LP:%[a-z0-9]+]] = getelementptr{{.*}}%struct.LLP2P2, ptr{{.*}}, i32 0, i32 0 - // CHECK: call {{.*}}get456789(ptr {{.*}}[[LP]]) + // CHECK: [[VAR:%[a-z0-9]+]] = alloca + // CHECK: call {{.*}}get456789(ptr {{.*}}sret{{.*}} [[VAR]]) // CHECK: [[CALL:%[a-z0-9]+]] = call {{.*}}@get235() // CHECK: store{{.*}}[[CALL]], {{.*}}[[TMP0:%[a-z0-9.]+]] diff --git a/clang/test/CodeGen/sret.c b/clang/test/CodeGen/sret.c index 83dce80aa279b..883049041b708 100644 --- a/clang/test/CodeGen/sret.c +++ b/clang/test/CodeGen/sret.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -Wno-strict-prototypes -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -Wno-strict-prototypes -triple amdgcn-amd-amdhsa -emit-llvm -o - | FileCheck --check-prefix=NONZEROALLOCAAS %s struct abc { long a; @@ -6,18 +7,28 @@ struct abc { long c; long d; long e; + long f; + long g; + long h; + long i; + long j; }; struct abc foo1(void); // CHECK-DAG: declare {{.*}} @foo1(ptr dead_on_unwind writable sret(%struct.abc) +// NONZEROALLOCAAS-DAG: declare {{.*}} @foo1(ptr addrspace(5) dead_on_unwind writable sret(%struct.abc) struct abc foo2(); // CHECK-DAG: declare {{.*}} @foo2(ptr dead_on_unwind writable sret(%struct.abc) +// NONZEROALLOCAAS-DAG: declare {{.*}} @foo2(ptr addrspace(5) dead_on_unwind writable sret(%struct.abc) struct abc foo3(void) { return (struct abc){0}; } // CHECK-DAG: define {{.*}} @foo3(ptr dead_on_unwind noalias writable sret(%struct.abc) +// NONZEROALLOCAAS-DAG: define {{.*}} @foo3(ptr addrspace(5) dead_on_unwind noalias writable sret(%struct.abc) void bar(void) { struct abc dummy1 = foo1(); // CHECK-DAG: call {{.*}} @foo1(ptr dead_on_unwind writable sret(%struct.abc) + // NONZEROALLOCAAS-DAG: call {{.*}} @foo1(ptr addrspace(5) dead_on_unwind writable sret(%struct.abc) struct abc dummy2 = foo2(); // CHECK-DAG: call {{.*}} @foo2(ptr dead_on_unwind writable sret(%struct.abc) + // NONZEROALLOCAAS-DAG: call {{.*}} @foo2(ptr addrspace(5) dead_on_unwind writable sret(%struct.abc) } diff --git a/clang/test/CodeGenCUDA/launch-bounds.cu b/clang/test/CodeGenCUDA/launch-bounds.cu index 31ca9216b413e..72f7857264f8c 100644 --- a/clang/test/CodeGenCUDA/launch-bounds.cu +++ b/clang/test/CodeGenCUDA/launch-bounds.cu @@ -9,6 +9,25 @@ #define MAX_BLOCKS_PER_MP 4 #endif +// CHECK: @Kernel1() #[[ATTR0:[0-9]+]] +// CHECK: @{{.*}}Kernel4{{.*}}() #[[ATTR0]] +// CHECK: @{{.*}}Kernel5{{.*}}() #[[ATTR1:[0-9]+]] +// CHECK: @{{.*}}Kernel6{{.*}}() #[[ATTR0]] +// CHECK: @{{.*}}Kernel8{{.*}}() #[[ATTR3:[0-9]+]] + +// CHECK: attributes #[[ATTR0]] = {{{.*}} "nvvm.minctasm"="2" {{.*}}} +// CHECK: attributes #[[ATTR1]] = {{{.*}} "nvvm.minctasm"="258" {{.*}}} +// CHECK: attributes #[[ATTR3]] = {{{.*}} "nvvm.minctasm"="12" {{.*}}} + +// CHECK_MAX_BLOCKS: @Kernel1_sm_90() #[[ATTR4:[0-9]+]] +// CHECK_MAX_BLOCKS: @{{.*}}Kernel4_sm_90{{.*}} #[[ATTR4]] +// CHECK_MAX_BLOCKS: @{{.*}}Kernel5_sm_90{{.*}} #[[ATTR5:[0-9]+]] +// CHECK_MAX_BLOCKS: @{{.*}}Kernel8_sm_90{{.*}} #[[ATTR6:[0-9]+]] + +// CHECK_MAX_BLOCKS: attributes #[[ATTR4]] = {{{.*}} "nvvm.maxclusterrank"="4" "nvvm.minctasm"="2" {{.*}}} +// CHECK_MAX_BLOCKS: attributes #[[ATTR5]] = {{{.*}} "nvvm.maxclusterrank"="260" "nvvm.minctasm"="258" {{.*}}} +// CHECK_MAX_BLOCKS: attributes #[[ATTR6]] = {{{.*}} "nvvm.maxclusterrank"="14" "nvvm.minctasm"="12" {{.*}}} + // Test both max threads per block and Min cta per sm. extern "C" { __global__ void @@ -19,7 +38,6 @@ Kernel1() } // CHECK: !{{[0-9]+}} = !{ptr @Kernel1, !"maxntidx", i32 256} -// CHECK: !{{[0-9]+}} = !{ptr @Kernel1, !"minctasm", i32 2} #ifdef USE_MAX_BLOCKS // Test max threads per block and min/max cta per sm. @@ -32,8 +50,6 @@ Kernel1_sm_90() } // CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @Kernel1_sm_90, !"maxntidx", i32 256} -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @Kernel1_sm_90, !"minctasm", i32 2} -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @Kernel1_sm_90, !"maxclusterrank", i32 4} #endif // USE_MAX_BLOCKS // Test only max threads per block. Min cta per sm defaults to 0, and @@ -67,7 +83,6 @@ Kernel4() template __global__ void Kernel4(); // CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4{{.*}}, !"maxntidx", i32 256} -// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4{{.*}}, !"minctasm", i32 2} #ifdef USE_MAX_BLOCKS template @@ -79,8 +94,6 @@ Kernel4_sm_90() template __global__ void Kernel4_sm_90(); // CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4_sm_90{{.*}}, !"maxntidx", i32 256} -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4_sm_90{{.*}}, !"minctasm", i32 2} -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel4_sm_90{{.*}}, !"maxclusterrank", i32 4} #endif //USE_MAX_BLOCKS const int constint = 100; @@ -94,7 +107,6 @@ Kernel5() template __global__ void Kernel5(); // CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5{{.*}}, !"maxntidx", i32 356} -// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5{{.*}}, !"minctasm", i32 258} #ifdef USE_MAX_BLOCKS @@ -109,8 +121,6 @@ Kernel5_sm_90() template __global__ void Kernel5_sm_90(); // CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5_sm_90{{.*}}, !"maxntidx", i32 356} -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5_sm_90{{.*}}, !"minctasm", i32 258} -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel5_sm_90{{.*}}, !"maxclusterrank", i32 260} #endif //USE_MAX_BLOCKS // Make sure we don't emit negative launch bounds values. @@ -120,7 +130,6 @@ Kernel6() { } // CHECK-NOT: !{{[0-9]+}} = !{ptr @{{.*}}Kernel6{{.*}}, !"maxntidx", -// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel6{{.*}}, !"minctasm", __global__ void __launch_bounds__( MAX_THREADS_PER_BLOCK, -MIN_BLOCKS_PER_MP ) @@ -144,12 +153,9 @@ Kernel7_sm_90() const char constchar = 12; __global__ void __launch_bounds__(constint, constchar) Kernel8() {} // CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8{{.*}}, !"maxntidx", i32 100 -// CHECK: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8{{.*}}, !"minctasm", i32 12 #ifdef USE_MAX_BLOCKS const char constchar_2 = 14; __global__ void __launch_bounds__(constint, constchar, constchar_2) Kernel8_sm_90() {} // CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8_sm_90{{.*}}, !"maxntidx", i32 100 -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8_sm_90{{.*}}, !"minctasm", i32 12 -// CHECK_MAX_BLOCKS: !{{[0-9]+}} = !{ptr @{{.*}}Kernel8_sm_90{{.*}}, !"maxclusterrank", i32 14 #endif // USE_MAX_BLOCKS diff --git a/clang/test/CodeGenCUDA/redux-f32-builtins.cu b/clang/test/CodeGenCUDA/redux-f32-builtins.cu new file mode 100644 index 0000000000000..7359fb0006991 --- /dev/null +++ b/clang/test/CodeGenCUDA/redux-f32-builtins.cu @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 "-triple" "nvptx-nvidia-cuda" "-target-feature" "+ptx86" "-target-cpu" "sm_100a" -emit-llvm -fcuda-is-device -o - %s | FileCheck %s +// RUN: %clang_cc1 "-triple" "nvptx64-nvidia-cuda" "-target-feature" "+ptx86" "-target-cpu" "sm_100a" -emit-llvm -fcuda-is-device -o - %s | FileCheck %s + +// CHECK: define{{.*}} void @_Z6kernelPf(ptr noundef %out_f) +__attribute__((global)) void kernel(float* out_f) { + float a = 3.0; + int i = 0; + + out_f[i++] = __nvvm_redux_sync_fmin(a, 0xFF); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmin + + out_f[i++] = __nvvm_redux_sync_fmin_abs(a, 0xFF); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmin.abs + + out_f[i++] = __nvvm_redux_sync_fmin_NaN(a, 0xF0); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmin.NaN + + out_f[i++] = __nvvm_redux_sync_fmin_abs_NaN(a, 0x0F); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmin.abs.NaN + + out_f[i++] = __nvvm_redux_sync_fmax(a, 0xFF); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmax + + out_f[i++] = __nvvm_redux_sync_fmax_abs(a, 0x01); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmax.abs + + out_f[i++] = __nvvm_redux_sync_fmax_NaN(a, 0xF1); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmax.NaN + + out_f[i++] = __nvvm_redux_sync_fmax_abs_NaN(a, 0x10); + // CHECK: call contract float @llvm.nvvm.redux.sync.fmax.abs.NaN + + // CHECK: ret void +} diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/dynamic-cast.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/dynamic-cast.cpp index 83daf57be22ff..3662a270713b6 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/dynamic-cast.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/dynamic-cast.cpp @@ -3,7 +3,7 @@ // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O3 -o - -emit-llvm | FileCheck %s -// CHECK: define{{.*}} ptr @_Z6upcastP1B(ptr noundef readnone returned %b) local_unnamed_addr +// CHECK: define{{.*}} ptr @_Z6upcastP1B(ptr noundef readnone returned captures(ret: address, provenance) %b) local_unnamed_addr // CHECK-NEXT: entry: // CHECK-NEXT: ret ptr %b // CHECK-NEXT: } @@ -22,12 +22,12 @@ // CHECK: declare ptr @__dynamic_cast(ptr, ptr, ptr, i64) local_unnamed_addr -// CHECK: define{{.*}} ptr @_Z8selfcastP1B(ptr noundef readnone returned %b) local_unnamed_addr +// CHECK: define{{.*}} ptr @_Z8selfcastP1B(ptr noundef readnone returned captures(ret: address, provenance) %b) local_unnamed_addr // CHECK-NEXT: entry // CHECK-NEXT: ret ptr %b // CHECK-NEXT: } -// CHECK: define{{.*}} ptr @_Z9void_castP1B(ptr noundef readonly %b) local_unnamed_addr +// CHECK: define{{.*}} ptr @_Z9void_castP1B(ptr noundef readonly captures(address_is_null, ret: address, provenance) %b) local_unnamed_addr // CHECK-NEXT: entry: // CHECK-NEXT: [[isnull:%[0-9]+]] = icmp eq ptr %b, null // CHECK-NEXT: br i1 [[isnull]], label %[[dynamic_cast_end:[a-z0-9._]+]], label %[[dynamic_cast_notnull:[a-z0-9._]+]] diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp index c471e5dbd7b33..2a838708ca231 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/type-info.cpp @@ -24,7 +24,7 @@ // CHECK-NEXT: ret ptr @_ZTS1A // CHECK-NEXT: } -// CHECK: define{{.*}} i1 @_Z5equalP1A(ptr noundef readonly %a) local_unnamed_addr +// CHECK: define{{.*}} i1 @_Z5equalP1A(ptr noundef readonly captures(address_is_null) %a) local_unnamed_addr // CHECK-NEXT: entry: // CHECK-NEXT: [[isnull:%[0-9]+]] = icmp eq ptr %a, null // CHECK-NEXT: br i1 [[isnull]], label %[[bad_typeid:[a-z0-9._]+]], label %[[end:[a-z0-9.+]+]] diff --git a/clang/test/CodeGenCXX/debug-info-template-parameter.cpp b/clang/test/CodeGenCXX/debug-info-template-parameter.cpp index 360cc1fb30784..b2ca54a02f1c9 100644 --- a/clang/test/CodeGenCXX/debug-info-template-parameter.cpp +++ b/clang/test/CodeGenCXX/debug-info-template-parameter.cpp @@ -4,6 +4,7 @@ // RUN: %clang_cc1 -emit-llvm %std_cxx11-14 -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,PRE17 // RUN: %clang_cc1 -emit-llvm %std_cxx17- -dwarf-version=5 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,CXX17 // RUN: %clang_cc1 -emit-llvm %std_cxx17- -dwarf-version=4 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefixes=CHECK,CXX17 +// RUN: %clang_cc1 -emit-llvm %std_cxx20- -dwarf-version=5 -DCXX20=1 -triple x86_64 %s -O0 -disable-llvm-passes -debug-info-kind=standalone -o - | FileCheck %s --check-prefix=CHECK-CXX20 // CHECK: DILocalVariable(name: "f1", {{.*}}, type: ![[TEMPLATE_TYPE:[0-9]+]] // CHECK: [[TEMPLATE_TYPE]] = {{.*}}!DICompositeType({{.*}}, templateParams: ![[F1_TYPE:[0-9]+]] @@ -50,6 +51,29 @@ template