From 7cb1aa9d9368274300cf472bc5532aa5a099da51 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 17 Apr 2020 17:06:17 -0400 Subject: [PATCH 01/56] Revert "[libc++] Use proper shell escaping in the executors" This reverts f8452ddfcc, which broke some bots. I'll figure out what's wrong and commit it again. --- libcxx/utils/run.py | 6 ++---- libcxx/utils/ssh.py | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/libcxx/utils/run.py b/libcxx/utils/run.py index e9f9859807b38..7cdf65264ec0b 100644 --- a/libcxx/utils/run.py +++ b/libcxx/utils/run.py @@ -14,7 +14,6 @@ import argparse import os -import pipes import shutil import subprocess import sys @@ -58,9 +57,8 @@ def main(): else: shutil.copy2(dep, args.execdir) - # Run the command line with the given environment in the execution directory. - commandLine = (pipes.quote(x) for x in remaining) - return subprocess.call(' '.join(commandLine), cwd=args.execdir, env=env, shell=True) + # Run the executable with the given environment in the execution directory. + return subprocess.call(' '.join(remaining), cwd=args.execdir, env=env, shell=True) finally: shutil.rmtree(args.execdir) diff --git a/libcxx/utils/ssh.py b/libcxx/utils/ssh.py index f9bcabe3c3215..c7d8c97a14078 100644 --- a/libcxx/utils/ssh.py +++ b/libcxx/utils/ssh.py @@ -15,7 +15,6 @@ import argparse import os -import pipes import posixpath import subprocess import sys @@ -98,11 +97,10 @@ def main(): # host by transforming the path of test-executables to their path in the # temporary directory, where we know they have been copied when we handled # test dependencies above. - commandLine = (pathOnRemote(x) if isTestExe(x) else x for x in commandLine) remoteCommands += [ 'cd {}'.format(tmp), 'export {}'.format(' '.join(args.env)), - ' '.join(pipes.quote(x) for x in commandLine) + ' '.join(pathOnRemote(x) if isTestExe(x) else x for x in commandLine) ] # Finally, SSH to the remote host and execute all the commands. From ef49b1d97e1ac75bff8ff7dec3097b43bcd07e73 Mon Sep 17 00:00:00 2001 From: Anna Thomas Date: Fri, 17 Apr 2020 17:11:21 -0400 Subject: [PATCH 02/56] Revert "[InlineFunction] Update metadata on loads that are return values" This reverts commit 1d0f757904919d19f1cf5dcd307874bceb1e9efb because of https://bugs.llvm.org/show_bug.cgi?id=45590. Needs investigation. --- llvm/lib/Transforms/Utils/InlineFunction.cpp | 52 ++------- .../Transforms/Inline/ret_load_metadata.ll | 103 ------------------ 2 files changed, 9 insertions(+), 146 deletions(-) delete mode 100644 llvm/test/Transforms/Inline/ret_load_metadata.ll diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 9ad9f7b8e11de..92ab8f9b7718c 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -88,10 +88,6 @@ static cl::opt UpdateReturnAttributes( "update-return-attrs", cl::init(true), cl::Hidden, cl::desc("Update return attributes on calls within inlined body")); -static cl::opt UpdateLoadMetadataDuringInlining( - "update-load-metadata-during-inlining", cl::init(true), cl::Hidden, - cl::desc("Update metadata on loads within inlined body")); - static cl::opt InlinerAttributeWindow( "max-inst-checked-for-throw-during-inlining", cl::Hidden, cl::desc("the maximum number of instructions analyzed for may throw during " @@ -1173,8 +1169,8 @@ static AttrBuilder IdentifyValidAttributes(CallBase &CB) { return Valid; } -static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) { - if (!UpdateReturnAttributes && !UpdateLoadMetadataDuringInlining) +static void AddReturnAttributes(CallSite CS, ValueToValueMapTy &VMap) { + if (!UpdateReturnAttributes) return; AttrBuilder Valid = IdentifyValidAttributes(CB); @@ -1183,32 +1179,18 @@ static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) { auto *CalledFunction = CB.getCalledFunction(); auto &Context = CalledFunction->getContext(); - auto getExpectedRV = [&](Value *V) -> Instruction * { - if (UpdateReturnAttributes && isa(V)) - return dyn_cast_or_null(VMap.lookup(V)); - if (UpdateLoadMetadataDuringInlining && isa(V)) - return dyn_cast_or_null(VMap.lookup(V)); - return nullptr; - }; - - MDBuilder MDB(Context); - auto CreateMDNode = [&](uint64_t Num) -> MDNode * { - auto *Int = ConstantInt::get(Type::getInt64Ty(Context), Num); - return MDNode::get(Context, MDB.createConstant(Int)); - }; - for (auto &BB : *CalledFunction) { auto *RI = dyn_cast(BB.getTerminator()); - if (!RI) + if (!RI || !isa(RI->getOperand(0))) continue; + auto *RetVal = cast(RI->getOperand(0)); // Sanity check that the cloned RetVal exists and is a call, otherwise we // cannot add the attributes on the cloned RetVal. // Simplification during inlining could have transformed the cloned // instruction. - auto *NewRetVal = getExpectedRV(RI->getOperand(0)); + auto *NewRetVal = dyn_cast_or_null(VMap.lookup(RetVal)); if (!NewRetVal) continue; - auto *RetVal = cast(RI->getOperand(0)); // Backward propagation of attributes to the returned value may be incorrect // if it is control flow dependent. // Consider: @@ -1236,26 +1218,10 @@ static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) { // with a differing value, the AttributeList's merge API honours the already // existing attribute value (i.e. attributes such as dereferenceable, // dereferenceable_or_null etc). See AttrBuilder::merge for more details. - if (auto *NewRetValCB = dyn_cast(NewRetVal)) { - AttributeList AL = NewRetValCB->getAttributes(); - AttributeList NewAL = - AL.addAttributes(Context, AttributeList::ReturnIndex, Valid); - NewRetValCB->setAttributes(NewAL); - } else { - auto *NewLI = cast(NewRetVal); - if (CB.isReturnNonNull()) - NewLI->setMetadata(LLVMContext::MD_nonnull, CreateMDNode(1)); - // If the load already has a dereferenceable/dereferenceable_or_null - // metadata, we should honour it. - if (uint64_t DerefBytes = Valid.getDereferenceableBytes()) - if(!NewLI->getMetadata(LLVMContext::MD_dereferenceable)) - NewLI->setMetadata(LLVMContext::MD_dereferenceable, - CreateMDNode(DerefBytes)); - if (uint64_t DerefOrNullBytes = Valid.getDereferenceableOrNullBytes()) - if (!NewLI->getMetadata(LLVMContext::MD_dereferenceable_or_null)) - NewLI->setMetadata(LLVMContext::MD_dereferenceable_or_null, - CreateMDNode(DerefOrNullBytes)); - } + AttributeList AL = NewRetVal->getAttributes(); + AttributeList NewAL = + AL.addAttributes(Context, AttributeList::ReturnIndex, Valid); + NewRetVal->setAttributes(NewAL); } } diff --git a/llvm/test/Transforms/Inline/ret_load_metadata.ll b/llvm/test/Transforms/Inline/ret_load_metadata.ll deleted file mode 100644 index 13dabb0740172..0000000000000 --- a/llvm/test/Transforms/Inline/ret_load_metadata.ll +++ /dev/null @@ -1,103 +0,0 @@ -; RUN: opt < %s -inline-threshold=0 -update-load-metadata-during-inlining=true -always-inline -S | FileCheck %s -; RUN: opt < %s -passes=always-inline -update-load-metadata-during-inlining=true -S | FileCheck %s - - -define i8* @callee(i8** %p) alwaysinline { -; CHECK: @callee( -; CHECK-NOT: nonnull - %r = load i8*, i8** %p, align 8 - ret i8* %r -} - -define i8* @test(i8** %ptr, i64 %x) { -; CHECK-LABEL: @test -; CHECK: load i8*, i8** %gep, align 8, !nonnull !0 - %gep = getelementptr inbounds i8*, i8** %ptr, i64 %x - %p = call nonnull i8* @callee(i8** %gep) - ret i8* %p -} - -declare void @does_not_return(i8*) nounwind -define internal i8* @callee_negative(i8** %p) alwaysinline { -; CHECK-NOT: @callee_negative( - %r = load i8*, i8** %p, align 8 - call void @does_not_return(i8* %r) - ret i8* %r -} - -define i8* @negative_test(i8** %ptr, i64 %x) { -; CHECK-LABEL: @negative_test -; CHECK: load i8*, i8** %gep, align 8 -; CHECK-NOT: nonnull - %gep = getelementptr inbounds i8*, i8** %ptr, i64 %x - %p = call nonnull i8* @callee_negative(i8** %gep) - ret i8* %p -} - - -define internal i8* @callee2(i8** %p) alwaysinline { -; CHECK-NOT: @callee2( - %r = load i8*, i8** %p, align 8 - ret i8* %r -} - -; dereferenceable attribute in default addrspace implies nonnull -define i8* @test2(i8** %ptr, i64 %x) { -; CHECK-LABEL: @test2 -; CHECK: load i8*, i8** %gep, align 8, !nonnull !0, !dereferenceable !1 - %gep = getelementptr inbounds i8*, i8** %ptr, i64 %x - %p = call dereferenceable(12) i8* @callee(i8** %gep) - ret i8* %p -} - -declare void @bar(i8 addrspace(1)*) argmemonly nounwind - -define internal i8 addrspace(1)* @callee3(i8 addrspace(1)* addrspace(1)* %p) alwaysinline { - %r = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %p, align 8 - call void @bar(i8 addrspace(1)* %r) - ret i8 addrspace(1)* %r -} - -; This load in callee already has a dereferenceable_or_null metadata. We should -; honour it. -define internal i8 addrspace(1)* @callee5(i8 addrspace(1)* addrspace(1)* %p) alwaysinline { - %r = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %p, align 8, !dereferenceable_or_null !3 - call void @bar(i8 addrspace(1)* %r) - ret i8 addrspace(1)* %r -} - -define i8 addrspace(1)* @test3(i8 addrspace(1)* addrspace(1)* %ptr, i64 %x) { -; CHECK-LABEL: @test3 -; CHECK: load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %gep, align 8, !dereferenceable_or_null !2 -; CHECK: load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %ptr, align 8, !dereferenceable_or_null !3 - %gep = getelementptr inbounds i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %ptr, i64 %x - %p = call dereferenceable_or_null(16) i8 addrspace(1)* @callee3(i8 addrspace(1)* addrspace(1)* %gep) - %q = call dereferenceable_or_null(20) i8 addrspace(1)* @callee5(i8 addrspace(1)* addrspace(1)* %ptr) - ret i8 addrspace(1)* %p -} - -; attribute is part of the callee itself -define nonnull i8* @callee4(i8** %p) alwaysinline { - %r = load i8*, i8** %p, align 8 - ret i8* %r -} - -; TODO : We should infer the attribute on the callee -; and add the nonnull on the load -define i8* @test4(i8** %ptr, i64 %x) { -; CHECK-LABEL: @test4 -; CHECK: load i8*, i8** %gep, align 8 -; CHECK-NOT: nonnull - %gep = getelementptr inbounds i8*, i8** %ptr, i64 %x - %p = call i8* @callee(i8** %gep) - ret i8* %p -} - -!0 = !{i64 1} -!1 = !{i64 12} -!2 = !{i64 16} -!3 = !{i64 24} -; CHECK: !0 = !{i64 1} -; CHECK: !1 = !{i64 12} -; CHECK: !2 = !{i64 16} -; CHECK: !3 = !{i64 24} From 14ad8dc0761a1e440304a03a1f4828280cf112e2 Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Fri, 17 Apr 2020 10:24:35 -0700 Subject: [PATCH 03/56] Don't accidentally create MachineFunctions in mir-debugify/mir-strip-debugify We should only modify existing ones. Previously, we were creating MachineFunctions for externally-available functions. AFAICT this was benign in tree but ultimately led to asan bugs in our out of tree target. --- llvm/lib/CodeGen/MachineDebugify.cpp | 5 ++++- llvm/lib/CodeGen/MachineStripDebug.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/llvm/lib/CodeGen/MachineDebugify.cpp b/llvm/lib/CodeGen/MachineDebugify.cpp index bee9b63467571..bc607cabcc684 100644 --- a/llvm/lib/CodeGen/MachineDebugify.cpp +++ b/llvm/lib/CodeGen/MachineDebugify.cpp @@ -27,7 +27,10 @@ using namespace llvm; namespace { bool applyDebugifyMetadataToMachineFunction(MachineModuleInfo &MMI, DIBuilder &DIB, Function &F) { - MachineFunction &MF = MMI.getOrCreateMachineFunction(F); + MachineFunction *MaybeMF = MMI.getMachineFunction(F); + if (!MaybeMF) + return false; + MachineFunction &MF = *MaybeMF; DISubprogram *SP = F.getSubprogram(); assert(SP && "IR Debugify just created it?"); diff --git a/llvm/lib/CodeGen/MachineStripDebug.cpp b/llvm/lib/CodeGen/MachineStripDebug.cpp index 48b50ceb092a5..a1cb12f91275b 100644 --- a/llvm/lib/CodeGen/MachineStripDebug.cpp +++ b/llvm/lib/CodeGen/MachineStripDebug.cpp @@ -45,7 +45,10 @@ struct StripDebugMachineModule : public ModulePass { bool Changed = false; for (Function &F : M.functions()) { - MachineFunction &MF = MMI.getOrCreateMachineFunction(F); + MachineFunction *MaybeMF = MMI.getMachineFunction(F); + if (!MaybeMF) + continue; + MachineFunction &MF = *MaybeMF; for (MachineBasicBlock &MBB : MF) { for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); I != E;) { From 7ce4e652312f776c2cdd1650370c8909f7cf992f Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Sat, 18 Apr 2020 00:29:07 +0300 Subject: [PATCH 04/56] [cmake] Temporarily disable building std::filesystem in CrossWinToARMLinux.cmake --- clang/cmake/caches/CrossWinToARMLinux.cmake | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/cmake/caches/CrossWinToARMLinux.cmake b/clang/cmake/caches/CrossWinToARMLinux.cmake index 3d1e961ada8d0..c01c31ae5a722 100644 --- a/clang/cmake/caches/CrossWinToARMLinux.cmake +++ b/clang/cmake/caches/CrossWinToARMLinux.cmake @@ -89,6 +89,9 @@ set(LIBCXXABI_LINK_TESTS_WITH_SHARED_LIBCXX OFF CACHE BOOL "") set(LIBCXX_LINK_TESTS_WITH_SHARED_LIBCXXABI OFF CACHE BOOL "") set(LIBCXX_LINK_TESTS_WITH_SHARED_LIBCXX OFF CACHE BOOL "") +# FIXME: Remove this when https://reviews.llvm.org/D78200 is merged. +set(LIBCXX_ENABLE_FILESYSTEM OFF CACHE BOOL "") + set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "") set(LIBCXX_TARGET_TRIPLE "${CMAKE_C_COMPILER_TARGET}" CACHE STRING "") set(LIBCXX_SYSROOT "${DEFAULT_SYSROOT}" CACHE STRING "") From fd5e069d23bfffd7e11995bba43fa53d5106ed2a Mon Sep 17 00:00:00 2001 From: Anna Thomas Date: Fri, 17 Apr 2020 17:38:20 -0400 Subject: [PATCH 05/56] Fix buildbot failure due to obsolete CallSite usage Fix buildbot failures due to ef49b1d97e1ac75bff8ff7dec3097b43bcd07e73 (which was a revert of a previous change). --- llvm/lib/Transforms/Utils/InlineFunction.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 92ab8f9b7718c..1f53bb9252a28 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -1169,7 +1169,7 @@ static AttrBuilder IdentifyValidAttributes(CallBase &CB) { return Valid; } -static void AddReturnAttributes(CallSite CS, ValueToValueMapTy &VMap) { +static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap) { if (!UpdateReturnAttributes) return; From 861b69faee5df8d4e13ef316c7474a10e4069e81 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Tue, 14 Apr 2020 22:27:49 -0700 Subject: [PATCH 06/56] [Darwin] Fix symbolization for recent simulator runtimes. Summary: Due to sandbox restrictions in the recent versions of the simulator runtime the atos program is no longer able to access the task port of a parent process without additional help. This patch fixes this by registering a task port for the parent process before spawning atos and also tells atos to look for this by setting a special environment variable. This patch is based on an Apple internal fix (rdar://problem/43693565) that unfortunately contained a bug (rdar://problem/58789439) because it used setenv() to set the special environment variable. This is not safe because in certain circumstances this can trigger a call to realloc() which can fail during symbolization leading to deadlock. A test case is included that captures this problem. The approach used to set the necessary environment variable is as follows: 1. Calling `putenv()` early during process init (but late enough that malloc/realloc works) to set a dummy value for the environment variable. 2. Just before `atos` is spawned the storage for the environment variable is modified to contain the correct PID. A flaw with this approach is that if the application messes with the atos environment variable (i.e. unsets it or changes it) between the time its set and the time we need it then symbolization will fail. We will ignore this issue for now but a `DCHECK()` is included in the patch that documents this assumption but doesn't check it at runtime to avoid calling `getenv()`. The issue reported in rdar://problem/58789439 manifested as a deadlock during symbolization in the following situation: 1. Before TSan detects an issue something outside of the runtime calls setenv() that sets a new environment variable that wasn't previously set. This triggers a call to malloc() to allocate a new environment array. This uses TSan's normal user-facing allocator. LibC stores this pointer for future use later. 2. TSan detects an issue and tries to launch the symbolizer. When we are in the symbolizer we switch to a different (internal allocator) and then we call setenv() to set a new environment variable. When this happen setenv() sees that it needs to make the environment array larger and calls realloc() on the existing enviroment array because it remembers that it previously allocated memory for it. Calling realloc() fails here because it is being called on a pointer its never seen before. The included test case closely reproduces the originally reported problem but it doesn't replicate the `((kBlockMagic)) == ((((u64*)addr)[0])` assertion failure exactly. This is due to the way TSan's normal allocator allocates the environment array the first time it is allocated. In the test program addr[0] accesses an inaccessible page and raises SIGBUS. If TSan's SIGBUS signal handler is active, the signal is caught and symbolication is attempted again which results in deadlock. In the originally reported problem the pointer is successfully derefenced but then the assert fails due to the provided pointer not coming from the active allocator. When the assert fails TSan tries to symbolicate the stacktrace while already being in the middle of symbolication which results in deadlock. rdar://problem/58789439 Reviewers: kubamracek, yln Subscribers: jfb, #sanitizers, llvm-commits Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D78179 --- .../sanitizer_symbolizer_mac.cpp | 46 +++++++++++++++++++ .../sanitizer_symbolizer_mac.h | 1 + .../Darwin/no_call_setenv_in_symbolize.cpp | 43 +++++++++++++++++ 3 files changed, 90 insertions(+) create mode 100644 compiler-rt/test/tsan/Darwin/no_call_setenv_in_symbolize.cpp diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp index 1379ed82d03d1..4623c3f76b120 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -50,6 +51,8 @@ bool DlAddrSymbolizer::SymbolizeData(uptr addr, DataInfo *datainfo) { return true; } +#define K_ATOS_ENV_VAR "__check_mach_ports_lookup" + class AtosSymbolizerProcess : public SymbolizerProcess { public: explicit AtosSymbolizerProcess(const char *path) @@ -57,6 +60,20 @@ class AtosSymbolizerProcess : public SymbolizerProcess { pid_str_[0] = '\0'; } + void LateInitialize() { + if (SANITIZER_IOSSIM) { + // `putenv()` may call malloc/realloc so it is only safe to do this + // during LateInitialize() or later (i.e. we can't do this in the + // constructor). We also can't do this in `StartSymbolizerSubprocess()` + // because in TSan we switch allocators when we're symbolizing. + // We use `putenv()` rather than `setenv()` so that we can later directly + // write into the storage without LibC getting involved to change what the + // variable is set to + int result = putenv(mach_port_env_var_entry_); + CHECK_EQ(result, 0); + } + } + private: bool StartSymbolizerSubprocess() override { // Configure sandbox before starting atos process. @@ -65,6 +82,28 @@ class AtosSymbolizerProcess : public SymbolizerProcess { // the call to GetArgV. internal_snprintf(pid_str_, sizeof(pid_str_), "%d", internal_getpid()); + if (SANITIZER_IOSSIM) { + // `atos` in the simulator is restricted in its ability to retrieve the + // task port for the target process (us) so we need to do extra work + // to pass our task port to it. + mach_port_t ports[]{mach_task_self()}; + kern_return_t ret = + mach_ports_register(mach_task_self(), ports, /*count=*/1); + CHECK_EQ(ret, KERN_SUCCESS); + + // Set environment variable that signals to `atos` that it should look + // for our task port. We can't call `setenv()` here because it might call + // malloc/realloc. To avoid that we instead update the + // `mach_port_env_var_entry_` variable with our current PID. + uptr count = internal_snprintf(mach_port_env_var_entry_, + sizeof(mach_port_env_var_entry_), + K_ATOS_ENV_VAR "=%s", pid_str_); + CHECK_GE(count, sizeof(K_ATOS_ENV_VAR) + internal_strlen(pid_str_)); + // Document our assumption but without calling `getenv()` in normal + // builds. + DCHECK_EQ(internal_strcmp(getenv(K_ATOS_ENV_VAR), pid_str_), 0); + } + return SymbolizerProcess::StartSymbolizerSubprocess(); } @@ -88,8 +127,13 @@ class AtosSymbolizerProcess : public SymbolizerProcess { } char pid_str_[16]; + // Space for `\0` in `kAtosEnvVar_` is reused for `=`. + char mach_port_env_var_entry_[sizeof(K_ATOS_ENV_VAR) + sizeof(pid_str_)] = + K_ATOS_ENV_VAR "=0"; }; +#undef K_ATOS_ENV_VAR + static bool ParseCommandOutput(const char *str, uptr addr, char **out_name, char **out_module, char **out_file, uptr *line, uptr *start_address) { @@ -191,6 +235,8 @@ bool AtosSymbolizer::SymbolizeData(uptr addr, DataInfo *info) { return true; } +void AtosSymbolizer::LateInitialize() { process_->LateInitialize(); } + } // namespace __sanitizer #endif // SANITIZER_MAC diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h index 68521375e64c4..8996131fc1385 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_mac.h @@ -35,6 +35,7 @@ class AtosSymbolizer : public SymbolizerTool { bool SymbolizePC(uptr addr, SymbolizedStack *stack) override; bool SymbolizeData(uptr addr, DataInfo *info) override; + void LateInitialize() override; private: AtosSymbolizerProcess *process_; diff --git a/compiler-rt/test/tsan/Darwin/no_call_setenv_in_symbolize.cpp b/compiler-rt/test/tsan/Darwin/no_call_setenv_in_symbolize.cpp new file mode 100644 index 0000000000000..1e31693cc74d5 --- /dev/null +++ b/compiler-rt/test/tsan/Darwin/no_call_setenv_in_symbolize.cpp @@ -0,0 +1,43 @@ +// RUN: %clangxx_tsan -O1 %s -o %t +// `handle_sigbus=0` is required because when the rdar://problem/58789439 bug was +// present TSan's runtime could derefence bad memory leading to SIGBUS being raised. +// If the signal was caught TSan would deadlock because it would try to run the +// symbolizer again. +// RUN: %env_tsan_opts=handle_sigbus=0,symbolize=1 %run %t 2>&1 | FileCheck %s +// RUN: %env_tsan_opts=handle_sigbus=0,symbolize=1 __check_mach_ports_lookup=some_value %run %t 2>&1 | FileCheck %s +#include +#include +#include + +const char *kEnvName = "__UNLIKELY_ENV_VAR_NAME__"; + +int main() { + if (getenv(kEnvName)) { + fprintf(stderr, "Env var %s should not be set\n", kEnvName); + abort(); + } + + // This will set an environment variable that isn't already in + // the environment array. This will cause Darwin's Libc to + // malloc() a new array. + if (setenv(kEnvName, "some_value", /*overwrite=*/1)) { + fprintf(stderr, "Failed to set %s \n", kEnvName); + abort(); + } + + // rdar://problem/58789439 + // Now trigger symbolization. If symbolization tries to call + // to `setenv` that adds a new environment variable, then Darwin + // Libc will call `realloc()` and TSan's runtime will hit + // an assertion failure because TSan's runtime uses a different + // allocator during symbolization which leads to `realloc()` being + // called on a pointer that the allocator didn't allocate. + // + // CHECK: #{{[0-9]}} main {{.*}}no_call_setenv_in_symbolize.cpp:[[@LINE+1]] + __sanitizer_print_stack_trace(); + + // CHECK: DONE + fprintf(stderr, "DONE\n"); + + return 0; +} From 66037b84cf5e2d432801fd0a3a0f2921c0860af3 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Fri, 17 Apr 2020 15:16:59 -0700 Subject: [PATCH 07/56] MachineFunctionInfo for AArch64 in MIR Starting with hasRedZone adding MachineFunctionInfo to be put in the YAML for MIR files. Split out of: D78062 Based on implementation for MachineFunctionInfo for WebAssembly Differential Revision: https://reviews.llvm.org/D78173 Patch by Andrew Litteken! (AndrewLitteken) --- .../AArch64/AArch64MachineFunctionInfo.cpp | 32 ++++++++++ .../AArch64/AArch64MachineFunctionInfo.h | 25 ++++++++ .../Target/AArch64/AArch64TargetMachine.cpp | 23 ++++++++ .../lib/Target/AArch64/AArch64TargetMachine.h | 8 +++ llvm/lib/Target/AArch64/CMakeLists.txt | 1 + .../function-info-noredzone-present.ll | 21 +++++++ .../function-info-noredzone-present.mir | 59 +++++++++++++++++++ 7 files changed, 169 insertions(+) create mode 100644 llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp create mode 100644 llvm/test/CodeGen/AArch64/function-info-noredzone-present.ll create mode 100644 llvm/test/CodeGen/MIR/AArch64/function-info-noredzone-present.mir diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp new file mode 100644 index 0000000000000..a37e380725544 --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.cpp @@ -0,0 +1,32 @@ +//=- AArch64MachineFunctionInfo.cpp - AArch64 Machine Function Info ---------=// + +// +// 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 +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// This file implements AArch64-specific per-machine-function +/// information. +/// +//===----------------------------------------------------------------------===// + +#include "AArch64MachineFunctionInfo.h" + +using namespace llvm; + +yaml::AArch64FunctionInfo::AArch64FunctionInfo( + const llvm::AArch64FunctionInfo &MFI) + : HasRedZone(MFI.hasRedZone()) {} + +void yaml::AArch64FunctionInfo::mappingImpl(yaml::IO &YamlIO) { + MappingTraits::mapping(YamlIO, *this); +} + +void AArch64FunctionInfo::initializeBaseYamlFields( + const yaml::AArch64FunctionInfo &YamlMFI) { + if (YamlMFI.HasRedZone.hasValue()) + HasRedZone = YamlMFI.HasRedZone; +} diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h index 6ddb3fdb00463..3df289ae892aa 100644 --- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h +++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MIRYamlMapping.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/TargetFrameLowering.h" #include "llvm/IR/Function.h" @@ -26,6 +27,10 @@ namespace llvm { +namespace yaml { +struct AArch64FunctionInfo; +} // end namespace yaml + class MachineInstr; /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and @@ -137,6 +142,7 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) HasRedZone = false; } + void initializeBaseYamlFields(const yaml::AArch64FunctionInfo &YamlMFI); unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } @@ -333,6 +339,25 @@ class AArch64FunctionInfo final : public MachineFunctionInfo { DenseMap> JumpTableEntryInfo; }; +namespace yaml { +struct AArch64FunctionInfo final : public yaml::MachineFunctionInfo { + Optional HasRedZone; + + AArch64FunctionInfo() = default; + AArch64FunctionInfo(const llvm::AArch64FunctionInfo &MFI); + + void mappingImpl(yaml::IO &YamlIO) override; + ~AArch64FunctionInfo() = default; +}; + +template <> struct MappingTraits { + static void mapping(IO &YamlIO, AArch64FunctionInfo &MFI) { + YamlIO.mapOptional("hasRedZone", MFI.HasRedZone); + } +}; + +} // end namespace yaml + } // end namespace llvm #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index 93d5c762ac0c7..a9718876b07c7 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -11,6 +11,7 @@ #include "AArch64TargetMachine.h" #include "AArch64.h" +#include "AArch64MachineFunctionInfo.h" #include "AArch64MacroFusion.h" #include "AArch64Subtarget.h" #include "AArch64TargetObjectFile.h" @@ -26,6 +27,7 @@ #include "llvm/CodeGen/GlobalISel/Legalizer.h" #include "llvm/CodeGen/GlobalISel/Localizer.h" #include "llvm/CodeGen/GlobalISel/RegBankSelect.h" +#include "llvm/CodeGen/MIRParser/MIParser.h" #include "llvm/CodeGen/MachineScheduler.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetPassConfig.h" @@ -661,3 +663,24 @@ void AArch64PassConfig::addPreEmitPass() { // SVE bundles move prefixes with destructive operations. addPass(createUnpackMachineBundles(nullptr)); } + +yaml::MachineFunctionInfo * +AArch64TargetMachine::createDefaultFuncInfoYAML() const { + return new yaml::AArch64FunctionInfo(); +} + +yaml::MachineFunctionInfo * +AArch64TargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const { + const auto *MFI = MF.getInfo(); + return new yaml::AArch64FunctionInfo(*MFI); +} + +bool AArch64TargetMachine::parseMachineFunctionInfo( + const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, SMRange &SourceRange) const { + const auto &YamlMFI = + reinterpret_cast(MFI); + MachineFunction &MF = PFS.MF; + MF.getInfo()->initializeBaseYamlFields(YamlMFI); + return false; +} diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.h b/llvm/lib/Target/AArch64/AArch64TargetMachine.h index 5264efb89b9c5..7738a42293919 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.h +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.h @@ -49,6 +49,14 @@ class AArch64TargetMachine : public LLVMTargetMachine { return TLOF.get(); } + yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const override; + yaml::MachineFunctionInfo * + convertFuncInfoToYAML(const MachineFunction &MF) const override; + bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &, + PerFunctionMIParsingState &PFS, + SMDiagnostic &Error, + SMRange &SourceRange) const override; + private: bool isLittle; }; diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index e17a2d7f0b6e9..a2934934d91a8 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -48,6 +48,7 @@ add_llvm_target(AArch64CodeGen AArch64InstructionSelector.cpp AArch64LegalizerInfo.cpp AArch64LoadStoreOptimizer.cpp + AArch64MachineFunctionInfo.cpp AArch64MacroFusion.cpp AArch64MCInstLower.cpp AArch64PreLegalizerCombiner.cpp diff --git a/llvm/test/CodeGen/AArch64/function-info-noredzone-present.ll b/llvm/test/CodeGen/AArch64/function-info-noredzone-present.ll new file mode 100644 index 0000000000000..737a79de09787 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/function-info-noredzone-present.ll @@ -0,0 +1,21 @@ +; RUN: llc -mtriple=aarch64--- --verify-machineinstrs -stop-before=finalize-isel -simplify-mir -o - < %s | FileCheck %s + +; Here we check thatt the noredzone attribute is carried through the machine +; IR generation and is put in MachineFunctionInfo + +define void @baz() { + entry: + ; CHECK-LABEL: name: baz + ; CHECK: machineFunctionInfo: {} + ret void +} + +define void @bar() #0 { + entry: + ; CHECK-LABEL: name: bar + ; CHECK: machineFunctionInfo: + ; CHECK-NEXT: hasRedZone: false + ret void +} + +attributes #0 = { noredzone } diff --git a/llvm/test/CodeGen/MIR/AArch64/function-info-noredzone-present.mir b/llvm/test/CodeGen/MIR/AArch64/function-info-noredzone-present.mir new file mode 100644 index 0000000000000..739538689f46d --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/function-info-noredzone-present.mir @@ -0,0 +1,59 @@ +# RUN: llc -mtriple=aarch64--- --verify-machineinstrs -simplify-mir -run-pass none %s -o - | FileCheck %s + +# This test checks for persistence of the hasRedZone attribute through a +# llc transformation that shouldn't do anything + +# CHECK-NAME: name: foo +# CHECK-LABEL: machineFunctionInfo: {} + +--- +name: foo +alignment: 4 +tracksRegLiveness: true +frameInfo: + maxAlignment: 1 + maxCallFrameSize: 0 +machineFunctionInfo: {} +body: | + bb.0.entry: + RET_ReallyLR + +... + +# CHECK-LABEL: name: bar +# CHECK: machineFunctionInfo: +# CHECK-NEXT: hasRedZone: false + +--- +name: bar +alignment: 4 +tracksRegLiveness: true +frameInfo: + maxAlignment: 1 + maxCallFrameSize: 0 +machineFunctionInfo: + hasRedZone: false +body: | + bb.0: + RET_ReallyLR + +... + +# CHECK-LABEL: name: baz +# CHECK: machineFunctionInfo: +# CHECK-NEXT: hasRedZone: true + +--- +name: baz +alignment: 4 +tracksRegLiveness: true +frameInfo: + maxAlignment: 1 + maxCallFrameSize: 0 +machineFunctionInfo: + hasRedZone: true +body: | + bb.0.entry: + RET_ReallyLR + +... From 7b72a17ee7f0889ad6756d338e8963ccafb8dd33 Mon Sep 17 00:00:00 2001 From: LLVM GN Syncbot Date: Fri, 17 Apr 2020 22:33:56 +0000 Subject: [PATCH 08/56] [gn build] Port 66037b84cf5 --- llvm/utils/gn/secondary/llvm/lib/Target/AArch64/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/llvm/lib/Target/AArch64/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/AArch64/BUILD.gn index 11d84ff45a377..376d18bd58b38 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Target/AArch64/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Target/AArch64/BUILD.gn @@ -101,6 +101,7 @@ static_library("LLVMAArch64CodeGen") { "AArch64LegalizerInfo.cpp", "AArch64LoadStoreOptimizer.cpp", "AArch64MCInstLower.cpp", + "AArch64MachineFunctionInfo.cpp", "AArch64MacroFusion.cpp", "AArch64PBQPRegAlloc.cpp", "AArch64PreLegalizerCombiner.cpp", From 73b7dd1fb3c17a4ac4b1f1e603f26fa708009649 Mon Sep 17 00:00:00 2001 From: Andrew Litteken Date: Fri, 17 Apr 2020 15:50:01 -0700 Subject: [PATCH 09/56] Test commit for AndrewLitteken (empty) From b8d08e961df1d229872c785ebdbc8367432e9752 Mon Sep 17 00:00:00 2001 From: Andrew Browne Date: Fri, 17 Apr 2020 16:11:13 -0700 Subject: [PATCH 10/56] ADT: SmallVector size/capacity use word-size integers when elements are small SmallVector currently uses 32bit integers for size and capacity to reduce sizeof(SmallVector). This limits the number of elements to UINT32_MAX. For a SmallVector, this limits the SmallVector size to only 4GB. Buffering bitcode output uses SmallVector, but needs >4GB output. This changes SmallVector size and capacity to conditionally use word-size integers if the element type is small (<4 bytes). For larger elements types, the vector size can reach ~16GB with 32bit size. Making this conditional on the element type provides both the smaller sizeof(SmallVector) for larger types which are unlikely to grow so large, and supports larger capacities for smaller element types. This change also includes a fix for the bug where a SmallVector with 32bit size has reached UINT32_MAX elements, and cannot provide guaranteed growth. Context: // Double the size of the allocated memory, guaranteeing space for at // least one more element or MinSize if specified. void grow(size_t MinSize = 0) { this->grow_pod(MinSize, sizeof(T)); } void push_back(const T &Elt) { if (LLVM_UNLIKELY(this->size() >= this->capacity())) this->grow(); memcpy(reinterpret_cast(this->end()), &Elt, sizeof(T)); this->set_size(this->size() + 1); } When grow is called in push_back() without a MinSize specified, this is relying on the guarantee of space for at least one more element. There is an edge case bug where the SmallVector is already at its maximum size and push_back() calls grow() with default MinSize of zero. Grow is unable to provide space for one more element, but push_back() assumes the additional element it will be available. This can result in silent memory corruption, as this->end() will be an invalid pointer and the program may continue executing. An alternative to this fix would be to remove the default argument from grow(), which would mean several changing grow() to grow(this->size()+1) in several places. No test case added because it would require allocating a large ammount. Differential Revision: https://reviews.llvm.org/D77621 --- llvm/include/llvm/ADT/SmallVector.h | 98 ++++++++++++++++++++++++----- llvm/lib/Support/SmallVector.cpp | 30 +-------- 2 files changed, 85 insertions(+), 43 deletions(-) diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index 28b514d530dc9..0e5a56f085f0b 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -16,10 +16,10 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemAlloc.h" #include "llvm/Support/type_traits.h" -#include "llvm/Support/ErrorHandling.h" #include #include #include @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -34,11 +35,23 @@ namespace llvm { -/// This is all the non-templated stuff common to all SmallVectors. -class SmallVectorBase { +/// This is all the stuff common to all SmallVectors. +/// +/// The template parameter specifies the type which should be used to hold the +/// Size and Capacity of the SmallVector, so it can be adjusted. +/// Using 32 bit size is desirable to shink the size of the SmallVector. +/// Using 64 bit size is desirable for cases like SmallVector, where a +/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for +/// buffering bitcode output - which can exceed 4GB. +template class SmallVectorBase { protected: void *BeginX; - unsigned Size = 0, Capacity; + Size_T Size = 0, Capacity; + + /// The maximum value of the Size_T used. + static constexpr size_t SizeTypeMax() { + return std::numeric_limits::max(); + } SmallVectorBase() = delete; SmallVectorBase(void *FirstEl, size_t TotalCapacity) @@ -46,7 +59,39 @@ class SmallVectorBase { /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. - void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); + /// This function will report a fatal error if it cannot increase capacity. + void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize) { + // Ensure we can fit the new capacity. + // This is only going to be applicable if the when the capacity is 32 bit. + if (MinCapacity > SizeTypeMax()) + report_bad_alloc_error("SmallVector capacity overflow during allocation"); + + // Ensure we can meet the guarantee of space for at least one more element. + // The above check alone will not catch the case where grow is called with a + // default MinCapacity of 0, but the current capacity cannot be increased. + // This is only going to be applicable if the when the capacity is 32 bit. + if (capacity() == SizeTypeMax()) + report_bad_alloc_error("SmallVector capacity unable to grow"); + + // In theory 2*capacity can overflow if the capacity is 64 bit, but the + // original capacity would never be large enough for this to be a problem. + size_t NewCapacity = 2 * capacity() + 1; // Always grow. + NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); + + void *NewElts; + if (BeginX == FirstEl) { + NewElts = safe_malloc(NewCapacity * TSize); + + // Copy the elements over. No need to run dtors on PODs. + memcpy(NewElts, this->BeginX, size() * TSize); + } else { + // If this wasn't grown from the inline copy, grow the allocated space. + NewElts = safe_realloc(this->BeginX, NewCapacity * TSize); + } + + this->BeginX = NewElts; + this->Capacity = NewCapacity; + } public: size_t size() const { return Size; } @@ -69,9 +114,13 @@ class SmallVectorBase { } }; +template +using SmallVectorSizeType = + typename std::conditional::type; + /// Figure out the offset of the first element. template struct SmallVectorAlignmentAndSize { - AlignedCharArrayUnion Base; + AlignedCharArrayUnion>> Base; AlignedCharArrayUnion FirstEl; }; @@ -79,7 +128,10 @@ template struct SmallVectorAlignmentAndSize { /// the type T is a POD. The extra dummy template argument is used by ArrayRef /// to avoid unnecessarily requiring T to be complete. template -class SmallVectorTemplateCommon : public SmallVectorBase { +class SmallVectorTemplateCommon + : public SmallVectorBase> { + using Base = SmallVectorBase>; + /// Find the address of the first element. For this pointer math to be valid /// with small-size of 0 for T with lots of alignment, it's important that /// SmallVectorStorage is properly-aligned even for small-size of 0. @@ -91,21 +143,20 @@ class SmallVectorTemplateCommon : public SmallVectorBase { // Space after 'FirstEl' is clobbered, do not add any instance vars after it. protected: - SmallVectorTemplateCommon(size_t Size) - : SmallVectorBase(getFirstEl(), Size) {} + SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {} void grow_pod(size_t MinCapacity, size_t TSize) { - SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize); + Base::grow_pod(getFirstEl(), MinCapacity, TSize); } /// Return true if this is a smallvector which has not had dynamic /// memory allocated for it. - bool isSmall() const { return BeginX == getFirstEl(); } + bool isSmall() const { return this->BeginX == getFirstEl(); } /// Put this vector in a state of being small. void resetToSmall() { - BeginX = getFirstEl(); - Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. + this->BeginX = getFirstEl(); + this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. } public: @@ -123,6 +174,10 @@ class SmallVectorTemplateCommon : public SmallVectorBase { using pointer = T *; using const_pointer = const T *; + using Base::capacity; + using Base::empty; + using Base::size; + // forward iterator creation methods. iterator begin() { return (iterator)this->BeginX; } const_iterator begin() const { return (const_iterator)this->BeginX; } @@ -136,7 +191,9 @@ class SmallVectorTemplateCommon : public SmallVectorBase { const_reverse_iterator rend() const { return const_reverse_iterator(begin());} size_type size_in_bytes() const { return size() * sizeof(T); } - size_type max_size() const { return size_type(-1) / sizeof(T); } + size_type max_size() const { + return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T)); + } size_t capacity_in_bytes() const { return capacity() * sizeof(T); } @@ -231,12 +288,21 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon { // Define this out-of-line to dissuade the C++ compiler from inlining it. template void SmallVectorTemplateBase::grow(size_t MinSize) { - if (MinSize > UINT32_MAX) + // Ensure we can fit the new capacity. + // This is only going to be applicable if the when the capacity is 32 bit. + if (MinSize > this->SizeTypeMax()) report_bad_alloc_error("SmallVector capacity overflow during allocation"); + // Ensure we can meet the guarantee of space for at least one more element. + // The above check alone will not catch the case where grow is called with a + // default MinCapacity of 0, but the current capacity cannot be increased. + // This is only going to be applicable if the when the capacity is 32 bit. + if (this->capacity() == this->SizeTypeMax()) + report_bad_alloc_error("SmallVector capacity unable to grow"); + // Always grow, even from zero. size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2)); - NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX)); + NewCapacity = std::min(std::max(NewCapacity, MinSize), this->SizeTypeMax()); T *NewElts = static_cast(llvm::safe_malloc(NewCapacity*sizeof(T))); // Move the elements over. diff --git a/llvm/lib/Support/SmallVector.cpp b/llvm/lib/Support/SmallVector.cpp index 36f0a81f6b00d..0d1765ab3e5ca 100644 --- a/llvm/lib/Support/SmallVector.cpp +++ b/llvm/lib/Support/SmallVector.cpp @@ -36,30 +36,6 @@ static_assert(sizeof(SmallVector) >= alignof(Struct32B), static_assert(sizeof(SmallVector) == sizeof(unsigned) * 2 + sizeof(void *) * 2, "wasted space in SmallVector size 1"); - -/// grow_pod - This is an implementation of the grow() method which only works -/// on POD-like datatypes and is out of line to reduce code duplication. -void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, - size_t TSize) { - // Ensure we can fit the new capacity in 32 bits. - if (MinCapacity > UINT32_MAX) - report_bad_alloc_error("SmallVector capacity overflow during allocation"); - - size_t NewCapacity = 2 * capacity() + 1; // Always grow. - NewCapacity = - std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX)); - - void *NewElts; - if (BeginX == FirstEl) { - NewElts = safe_malloc(NewCapacity * TSize); - - // Copy the elements over. No need to run dtors on PODs. - memcpy(NewElts, this->BeginX, size() * TSize); - } else { - // If this wasn't grown from the inline copy, grow the allocated space. - NewElts = safe_realloc(this->BeginX, NewCapacity * TSize); - } - - this->BeginX = NewElts; - this->Capacity = NewCapacity; -} +static_assert(sizeof(SmallVector) == + sizeof(void *) * 2 + sizeof(void *), + "1 byte elements have word-sized type for size and capacity"); From 50511a406df4475984e5c51feadada2c92aaf97a Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Fri, 17 Apr 2020 16:31:58 -0700 Subject: [PATCH 11/56] Add SemaTemplateDeduction.cpp to /bigobj According to Nathaniel McVicar on the review for D73967, SematTemplateDeduction hit the 16 bit COFF limit. This adds it to the /bigobj list. --- clang/lib/Sema/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 89ea6904de858..98f121f4b6f0a 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -8,6 +8,7 @@ if (MSVC) set_source_files_properties(SemaExpr.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaExprCXX.cpp PROPERTIES COMPILE_FLAGS /bigobj) set_source_files_properties(SemaTemplate.cpp PROPERTIES COMPILE_FLAGS /bigobj) + set_source_files_properties(SemaTemplateDeduction.cpp PROPERTIES COMPILE_FLAGS /bigobj) endif() clang_tablegen(OpenCLBuiltins.inc -gen-clang-opencl-builtins From f4637925065d31c67433977656525c059e697678 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Fri, 6 Sep 2019 18:27:40 -0400 Subject: [PATCH 12/56] AMDGPU: Remove custom node for RSQ_LEGACY Directly select from the intrinsic. This wasn't getting much value from the custom node. --- llvm/include/llvm/IR/IntrinsicsAMDGPU.td | 1 + llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp | 23 +++++++++++++++++-- llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h | 1 - llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.td | 5 ---- llvm/lib/Target/AMDGPU/SIISelLowering.cpp | 11 +++++---- llvm/lib/Target/AMDGPU/VOP1Instructions.td | 2 +- 6 files changed, 30 insertions(+), 13 deletions(-) diff --git a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td index b5f9685f5b7bc..221d723c3e4aa 100644 --- a/llvm/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/llvm/include/llvm/IR/IntrinsicsAMDGPU.td @@ -275,6 +275,7 @@ def int_amdgcn_rsq_legacy : GCCBuiltin<"__builtin_amdgcn_rsq_legacy">, [llvm_float_ty], [llvm_float_ty], [IntrNoMem, IntrSpeculatable] >; +// out = 1.0 / sqrt(a) result clamped to +/- max_float. def int_amdgcn_rsq_clamp : Intrinsic< [llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem, IntrSpeculatable]>; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp index 51f4132b10962..014bb5a1b4eeb 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.cpp @@ -3000,6 +3000,16 @@ SDValue AMDGPUTargetLowering::performIntrinsicWOChainCombine( case Intrinsic::amdgcn_mul_i24: case Intrinsic::amdgcn_mul_u24: return simplifyI24(N, DCI); + case Intrinsic::amdgcn_fract: + case Intrinsic::amdgcn_rsq: + case Intrinsic::amdgcn_rcp_legacy: + case Intrinsic::amdgcn_rsq_legacy: + case Intrinsic::amdgcn_rsq_clamp: + case Intrinsic::amdgcn_ldexp: { + // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted + SDValue Src = N->getOperand(1); + return Src.isUndef() ? Src : SDValue(); + } default: return SDValue(); } @@ -4258,7 +4268,6 @@ const char* AMDGPUTargetLowering::getTargetNodeName(unsigned Opcode) const { NODE_NAME_CASE(RCP) NODE_NAME_CASE(RSQ) NODE_NAME_CASE(RCP_LEGACY) - NODE_NAME_CASE(RSQ_LEGACY) NODE_NAME_CASE(RCP_IFLAG) NODE_NAME_CASE(FMUL_LEGACY) NODE_NAME_CASE(RSQ_CLAMP) @@ -4653,7 +4662,6 @@ bool AMDGPUTargetLowering::isKnownNeverNaNForTargetNode(SDValue Op, case AMDGPUISD::RCP: case AMDGPUISD::RSQ: case AMDGPUISD::RCP_LEGACY: - case AMDGPUISD::RSQ_LEGACY: case AMDGPUISD::RSQ_CLAMP: { if (SNaN) return true; @@ -4697,6 +4705,17 @@ bool AMDGPUTargetLowering::isKnownNeverNaNForTargetNode(SDValue Op, return DAG.isKnownNeverNaN(Op.getOperand(1), SNaN, Depth + 1) && DAG.isKnownNeverNaN(Op.getOperand(2), SNaN, Depth + 1); } + case Intrinsic::amdgcn_rcp: + case Intrinsic::amdgcn_rsq: + case Intrinsic::amdgcn_rcp_legacy: + case Intrinsic::amdgcn_rsq_legacy: + case Intrinsic::amdgcn_rsq_clamp: { + if (SNaN) + return true; + + // TODO: Need is known positive check. + return false; + } case Intrinsic::amdgcn_fdot2: // TODO: Refine on operand return SNaN; diff --git a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h index 7d0b17f7e8164..d81b447d1a195 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h +++ b/llvm/lib/Target/AMDGPU/AMDGPUISelLowering.h @@ -416,7 +416,6 @@ enum NodeType : unsigned { RCP, RSQ, RCP_LEGACY, - RSQ_LEGACY, RCP_IFLAG, FMUL_LEGACY, RSQ_CLAMP, diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.td b/llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.td index eae00f0867d38..b9ded3b196bb9 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.td +++ b/llvm/lib/Target/AMDGPU/AMDGPUInstrInfo.td @@ -121,8 +121,6 @@ def AMDGPUrcp_impl : SDNode<"AMDGPUISD::RCP", SDTFPUnaryOp>; // out = 1.0 / sqrt(a) def AMDGPUrsq_impl : SDNode<"AMDGPUISD::RSQ", SDTFPUnaryOp>; -// out = 1.0 / sqrt(a) -def AMDGPUrsq_legacy_impl : SDNode<"AMDGPUISD::RSQ_LEGACY", SDTFPUnaryOp>; def AMDGPUrcp_legacy_impl : SDNode<"AMDGPUISD::RCP_LEGACY", SDTFPUnaryOp>; def AMDGPUrcp_iflag : SDNode<"AMDGPUISD::RCP_IFLAG", SDTFPUnaryOp>; @@ -385,9 +383,6 @@ def AMDGPUrcp : PatFrags<(ops node:$src), [(int_amdgcn_rcp node:$src), def AMDGPUrcp_legacy : PatFrags<(ops node:$src), [(int_amdgcn_rcp_legacy node:$src), (AMDGPUrcp_legacy_impl node:$src)]>; -def AMDGPUrsq_legacy : PatFrags<(ops node:$src), [(int_amdgcn_rsq_legacy node:$src), - (AMDGPUrsq_legacy_impl node:$src)]>; - def AMDGPUrsq : PatFrags<(ops node:$src), [(int_amdgcn_rsq node:$src), (AMDGPUrsq_impl node:$src)]>; diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp index a0260f5d57e78..1bdd2ed8111c0 100644 --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -5842,8 +5842,7 @@ SDValue SITargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::amdgcn_rsq_legacy: if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) return emitRemovedIntrinsicError(DAG, DL, VT); - - return DAG.getNode(AMDGPUISD::RSQ_LEGACY, DL, VT, Op.getOperand(1)); + return SDValue(); case Intrinsic::amdgcn_rcp_legacy: if (Subtarget->getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) return emitRemovedIntrinsicError(DAG, DL, VT); @@ -8777,7 +8776,6 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case AMDGPUISD::RSQ: case AMDGPUISD::RSQ_CLAMP: case AMDGPUISD::RCP_LEGACY: - case AMDGPUISD::RSQ_LEGACY: case AMDGPUISD::RCP_IFLAG: case AMDGPUISD::TRIG_PREOP: case AMDGPUISD::DIV_SCALE: @@ -8882,6 +8880,11 @@ bool SITargetLowering::isCanonicalized(SelectionDAG &DAG, SDValue Op, case Intrinsic::amdgcn_cubeid: case Intrinsic::amdgcn_frexp_mant: case Intrinsic::amdgcn_fdot2: + case Intrinsic::amdgcn_rcp: + case Intrinsic::amdgcn_rsq: + case Intrinsic::amdgcn_rsq_clamp: + case Intrinsic::amdgcn_rcp_legacy: + case Intrinsic::amdgcn_rsq_legacy: return true; default: break; @@ -10068,10 +10071,10 @@ SDValue SITargetLowering::PerformDAGCombine(SDNode *N, case AMDGPUISD::FRACT: case AMDGPUISD::RSQ: case AMDGPUISD::RCP_LEGACY: - case AMDGPUISD::RSQ_LEGACY: case AMDGPUISD::RCP_IFLAG: case AMDGPUISD::RSQ_CLAMP: case AMDGPUISD::LDEXP: { + // FIXME: This is probably wrong. If src is an sNaN, it won't be quieted SDValue Src = N->getOperand(0); if (Src.isUndef()) return Src; diff --git a/llvm/lib/Target/AMDGPU/VOP1Instructions.td b/llvm/lib/Target/AMDGPU/VOP1Instructions.td index 95f0c0e02aecc..d8578578dc358 100644 --- a/llvm/lib/Target/AMDGPU/VOP1Instructions.td +++ b/llvm/lib/Target/AMDGPU/VOP1Instructions.td @@ -325,7 +325,7 @@ let SubtargetPredicate = isGFX6GFX7 in { defm V_RSQ_CLAMP_F32 : VOP1Inst<"v_rsq_clamp_f32", VOP_F32_F32, AMDGPUrsq_clamp>; defm V_RSQ_LEGACY_F32 : - VOP1Inst<"v_rsq_legacy_f32", VOP_F32_F32, AMDGPUrsq_legacy>; + VOP1Inst<"v_rsq_legacy_f32", VOP_F32_F32, int_amdgcn_rsq_legacy>; } // End SchedRW = [WriteQuarterRate32] let SchedRW = [WriteDouble] in { From cd28a4736ab299f81a6bc74e8f22fb6d2b9375ed Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 17 Apr 2020 17:07:19 -0700 Subject: [PATCH 13/56] [AbstractCallSite] Fix some doxygen comments I failed to update when ImmutableCallSite was replaced with CallBase. Also fix an 80 column violation. --- llvm/include/llvm/IR/CallSite.h | 7 ++++--- llvm/lib/IR/AbstractCallSite.cpp | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/IR/CallSite.h b/llvm/include/llvm/IR/CallSite.h index d3d644e448343..ea224e59a4a71 100644 --- a/llvm/include/llvm/IR/CallSite.h +++ b/llvm/include/llvm/IR/CallSite.h @@ -798,10 +798,11 @@ class AbstractCallSite { /// as well as the callee of the abstract call site. AbstractCallSite(const Use *U); - /// Add operand uses of \p ICS that represent callback uses into \p CBUses. + /// Add operand uses of \p CB that represent callback uses into + /// \p CallbackUses. /// - /// All uses added to \p CBUses can be used to create abstract call sites for - /// which AbstractCallSite::isCallbackCall() will return true. + /// All uses added to \p CallbackUses can be used to create abstract call + /// sites for which AbstractCallSite::isCallbackCall() will return true. static void getCallbackUses(const CallBase &CB, SmallVectorImpl &CallbackUses); diff --git a/llvm/lib/IR/AbstractCallSite.cpp b/llvm/lib/IR/AbstractCallSite.cpp index 0354e7d5305cd..ab5551a8ea39c 100644 --- a/llvm/lib/IR/AbstractCallSite.cpp +++ b/llvm/lib/IR/AbstractCallSite.cpp @@ -33,8 +33,8 @@ STATISTIC(NumInvalidAbstractCallSitesUnknownCallee, STATISTIC(NumInvalidAbstractCallSitesNoCallback, "Number of invalid abstract call sites created (no callback)"); -void AbstractCallSite::getCallbackUses(const CallBase &CB, - SmallVectorImpl &CallbackUses) { +void AbstractCallSite::getCallbackUses( + const CallBase &CB, SmallVectorImpl &CallbackUses) { const Function *Callee = CB.getCalledFunction(); if (!Callee) return; From 91a6bfed61631b23deabad9986ac29b74d7491ea Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Wed, 15 Apr 2020 09:54:22 -0700 Subject: [PATCH 14/56] [COFF] Assign unique identifiers to ObjFiles from LTO Use the unique filenames that are used when /lldsavetemps is passed. After this change, module names for LTO blobs in PDBs will be unique. Visual Studio and probably other debuggers expect module names to be unique. Revert some changes from 1e0b158db (2017) that are no longer necessary after removing MSVC LTO support. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D78221 --- lld/COFF/LTO.cpp | 38 +++++++++++++++++++------------ lld/COFF/LTO.h | 2 +- lld/COFF/SymbolTable.cpp | 14 ++++-------- lld/COFF/SymbolTable.h | 1 - lld/test/COFF/lto-parallel.ll | 22 ++++++++++++++---- lld/test/COFF/pdb-thinlto.ll | 38 +++++++++++++++++++++++++++++++ lld/test/COFF/thinlto.ll | 8 +++---- lld/test/COFF/weak-external.test | 4 ++-- lld/test/COFF/weak-external3.test | 4 ++-- 9 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 lld/test/COFF/pdb-thinlto.ll diff --git a/lld/COFF/LTO.cpp b/lld/COFF/LTO.cpp index 94906e5005932..c88ce0ee95a93 100644 --- a/lld/COFF/LTO.cpp +++ b/lld/COFF/LTO.cpp @@ -144,7 +144,7 @@ void BitcodeCompiler::add(BitcodeFile &f) { // Merge all the bitcode files we have seen, codegen the result // and return the resulting objects. -std::vector BitcodeCompiler::compile() { +std::vector BitcodeCompiler::compile() { unsigned maxTasks = ltoObj->getMaxTasks(); buf.resize(maxTasks); files.resize(maxTasks); @@ -188,22 +188,32 @@ std::vector BitcodeCompiler::compile() { if (!config->ltoCache.empty()) pruneCache(config->ltoCache, config->ltoCachePolicy); - std::vector ret; + std::vector ret; for (unsigned i = 0; i != maxTasks; ++i) { - if (buf[i].empty()) + // Assign unique names to LTO objects. This ensures they have unique names + // in the PDB if one is produced. The names should look like: + // - foo.exe.lto.obj + // - foo.exe.lto.1.obj + // - ... + StringRef ltoObjName = + saver.save(Twine(config->outputFile) + ".lto" + + (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ".obj"); + + // Get the native object contents either from the cache or from memory. Do + // not use the cached MemoryBuffer directly, or the PDB will not be + // deterministic. + StringRef objBuf; + if (files[i]) + objBuf = files[i]->getBuffer(); + else + objBuf = buf[i]; + if (objBuf.empty()) continue; - if (config->saveTemps) { - if (i == 0) - saveBuffer(buf[i], config->outputFile + ".lto.obj"); - else - saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.obj"); - } - ret.emplace_back(buf[i].data(), buf[i].size()); - } - for (std::unique_ptr &file : files) - if (file) - ret.push_back(file->getBuffer()); + if (config->saveTemps) + saveBuffer(buf[i], ltoObjName); + ret.push_back(make(MemoryBufferRef(objBuf, ltoObjName))); + } return ret; } diff --git a/lld/COFF/LTO.h b/lld/COFF/LTO.h index 2a0cfa061c951..a2b321df7901b 100644 --- a/lld/COFF/LTO.h +++ b/lld/COFF/LTO.h @@ -45,7 +45,7 @@ class BitcodeCompiler { ~BitcodeCompiler(); void add(BitcodeFile &f); - std::vector compile(); + std::vector compile(); private: std::unique_ptr ltoObj; diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 8c5556a451b97..f846af83e9008 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -789,20 +789,16 @@ Symbol *SymbolTable::addUndefined(StringRef name) { return addUndefined(name, nullptr, false); } -std::vector SymbolTable::compileBitcodeFiles() { - lto.reset(new BitcodeCompiler); - for (BitcodeFile *f : BitcodeFile::instances) - lto->add(*f); - return lto->compile(); -} - void SymbolTable::addCombinedLTOObjects() { if (BitcodeFile::instances.empty()) return; ScopedTimer t(ltoTimer); - for (StringRef object : compileBitcodeFiles()) { - auto *obj = make(MemoryBufferRef(object, "lto.tmp")); + lto.reset(new BitcodeCompiler); + for (BitcodeFile *f : BitcodeFile::instances) + lto->add(*f); + for (InputFile *newObj : lto->compile()) { + ObjFile *obj = cast(newObj); obj->parse(); ObjFile::instances.push_back(obj); } diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index cd8a53dcecdcd..870a7151fa8ea 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -77,7 +77,6 @@ class SymbolTable { // BitcodeFiles and add them to the symbol table. Called after all files are // added and before the writer writes results to a file. void addCombinedLTOObjects(); - std::vector compileBitcodeFiles(); // Creates an Undefined symbol for a given name. Symbol *addUndefined(StringRef name); diff --git a/lld/test/COFF/lto-parallel.ll b/lld/test/COFF/lto-parallel.ll index 8e1f44a8ebb01..3ba1126a72229 100644 --- a/lld/test/COFF/lto-parallel.ll +++ b/lld/test/COFF/lto-parallel.ll @@ -1,23 +1,35 @@ ; REQUIRES: x86 ; RUN: llvm-as -o %t.obj %s -; RUN: lld-link -opt:noicf /out:%t.exe /entry:foo /include:bar /opt:lldltopartitions=2 /subsystem:console /lldmap:%t.map %t.obj +; RUN: lld-link -opt:noicf /out:%t.exe /entry:foo /include:bar /opt:lldltopartitions=2 /subsystem:console /lldmap:%t.map %t.obj /debug /pdb:%t.pdb ; RUN: FileCheck %s < %t.map +; RUN: llvm-pdbutil dump %t.pdb --modules | FileCheck %s --check-prefix=PDB target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" -; CHECK: lto.tmp -; CHECK: lto.tmp +; CHECK: lto-parallel.ll.tmp.exe.lto.obj: +; CHECK: lto-parallel.ll.tmp.exe.lto.obj: ; CHECK-NEXT: foo define void @foo() { call void @bar() ret void } -; CHECK: lto.tmp -; CHECK: lto.tmp +; CHECK: lto-parallel.ll.tmp.exe.lto.1.obj: +; CHECK: lto-parallel.ll.tmp.exe.lto.1.obj: ; CHECK: bar define void @bar() { call void @foo() ret void } + + +; Objects in the PDB should receive distinct names. + +; PDB: Modules +; PDB: Mod 0000 | `{{.*}}lto-parallel.ll.tmp.exe.lto.obj`: +; PDB: Obj: `{{.*}}lto-parallel.ll.tmp.exe.lto.obj`: +; PDB: Mod 0001 | `{{.*}}lto-parallel.ll.tmp.exe.lto.1.obj`: +; PDB: Obj: `{{.*}}lto-parallel.ll.tmp.exe.lto.1.obj`: +; PDB: Mod 0002 | `* Linker *`: +; PDB: Obj: ``: diff --git a/lld/test/COFF/pdb-thinlto.ll b/lld/test/COFF/pdb-thinlto.ll new file mode 100644 index 0000000000000..de0eef2b67da4 --- /dev/null +++ b/lld/test/COFF/pdb-thinlto.ll @@ -0,0 +1,38 @@ +; REQUIRES: x86 +; RUN: rm -rf %t && mkdir -p %t && cd %t +; RUN: opt -thinlto-bc -o main.bc %s +; RUN: opt -thinlto-bc -o foo.bc %S/Inputs/lto-dep.ll + +; Even if the native object is cached, the PDB must be the same. +; RUN: rm -rf thinltocachedir && mkdir thinltocachedir + +; RUN: lld-link /lldltocache:thinltocachedir /out:main.exe /entry:main /subsystem:console main.bc foo.bc /debug /pdb:main.pdb + +; RUN: llvm-pdbutil dump --modules main.pdb | FileCheck %s + +; Run again with the cache. Make sure we get the same object names. + +; RUN: lld-link /lldltocache:thinltocachedir /out:main.exe /entry:main /subsystem:console main.bc foo.bc /debug /pdb:main.pdb + +; RUN: llvm-pdbutil dump --modules main.pdb | FileCheck %s + + +target datalayout = "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define i32 @main() { + call void @foo() + ret i32 0 +} + +declare void @foo() + +; CHECK: Modules +; CHECK: ============================================================ +; CHECK: Mod 0000 | `{{.*}}main.exe.lto.obj`: +; CHECK: Obj: `{{.*}}main.exe.lto.obj`: +; CHECK: Mod 0001 | `{{.*}}main.exe.lto.1.obj`: +; CHECK: Obj: `{{.*}}main.exe.lto.1.obj`: +; CHECK: Mod 0002 | `{{.*}}main.exe.lto.2.obj`: +; CHECK: Obj: `{{.*}}main.exe.lto.2.obj`: +; CHECK: Mod 0003 | `* Linker *`: diff --git a/lld/test/COFF/thinlto.ll b/lld/test/COFF/thinlto.ll index 8727ac0070a5f..1a3ba23a24607 100644 --- a/lld/test/COFF/thinlto.ll +++ b/lld/test/COFF/thinlto.ll @@ -4,15 +4,15 @@ ; RUN: opt -thinlto-bc -o %T/thinlto/main.obj %s ; RUN: opt -thinlto-bc -o %T/thinlto/foo.obj %S/Inputs/lto-dep.ll ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj -; RUN: llvm-nm %T/thinlto/main.exe1.lto.obj | FileCheck %s +; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s ; Test various possible options for /opt:lldltojobs ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=1 -; RUN: llvm-nm %T/thinlto/main.exe1.lto.obj | FileCheck %s +; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=all -; RUN: llvm-nm %T/thinlto/main.exe1.lto.obj | FileCheck %s +; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s ; RUN: lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=100 -; RUN: llvm-nm %T/thinlto/main.exe1.lto.obj | FileCheck %s +; RUN: llvm-nm %T/thinlto/main.exe.lto.1.obj | FileCheck %s ; RUN: not lld-link /lldsavetemps /out:%T/thinlto/main.exe /entry:main /subsystem:console %T/thinlto/main.obj %T/thinlto/foo.obj /opt:lldltojobs=foo 2>&1 | FileCheck %s --check-prefix=BAD-JOBS ; BAD-JOBS: error: /opt:lldltojobs: invalid job count: foo diff --git a/lld/test/COFF/weak-external.test b/lld/test/COFF/weak-external.test index 352b14f083810..2d650112ab620 100644 --- a/lld/test/COFF/weak-external.test +++ b/lld/test/COFF/weak-external.test @@ -5,8 +5,8 @@ # RUN: lld-link /out:%t2.exe /entry:g /subsystem:console /lldmap:%t2.map %t.obj %t.lto.obj # RUN: FileCheck %s < %t2.map -# CHECK: lto.tmp -# CHECK-NEXT: lto.tmp +# CHECK: .lto.obj: +# CHECK-NEXT: .lto.obj: # CHECK-NEXT: 0 g --- !COFF diff --git a/lld/test/COFF/weak-external3.test b/lld/test/COFF/weak-external3.test index 480b09b2eb0f4..8a4afdbb1b31d 100644 --- a/lld/test/COFF/weak-external3.test +++ b/lld/test/COFF/weak-external3.test @@ -6,8 +6,8 @@ # RUN: lld-link /out:%t2.exe /entry:f /subsystem:console /lldmap:%t2.map %t.obj %t.lto.obj # RUN: FileCheck --check-prefix=CHECK2 %s < %t2.map -# CHECK1: lto.tmp -# CHECK1: lto.tmp +# CHECK1: .lto.obj: +# CHECK1-NEXT: .lto.obj: # CHECK1-NEXT: 0 g # CHECK2: weak-external3.test.tmp.obj From 21d50019ca83765a655b3d67331dfb83cf3d260d Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 27 Jan 2020 18:43:46 -0800 Subject: [PATCH 15/56] scudo: Add support for diagnosing memory errors when memory tagging is enabled. Introduce a function __scudo_get_error_info() that may be called to interpret a crash resulting from a memory error, potentially in another process, given information extracted from the crashing process. The crash may be interpreted as a use-after-free, buffer overflow or buffer underflow. Also introduce a feature to optionally record a stack trace for each allocation and deallocation. If this feature is enabled, a stack trace for the allocation and (if applicable) the deallocation will also be available via __scudo_get_error_info(). Differential Revision: https://reviews.llvm.org/D77283 --- compiler-rt/lib/CMakeLists.txt | 6 + compiler-rt/lib/scudo/standalone/combined.h | 222 +++++++++++++++++- compiler-rt/lib/scudo/standalone/common.h | 9 + compiler-rt/lib/scudo/standalone/fuchsia.cpp | 2 + .../lib/scudo/standalone/fuzz/CMakeLists.txt | 12 + .../standalone/fuzz/get_error_info_fuzzer.cpp | 48 ++++ .../standalone/include/scudo/interface.h | 83 +++++++ compiler-rt/lib/scudo/standalone/linux.cpp | 8 + compiler-rt/lib/scudo/standalone/memtag.h | 61 +++-- compiler-rt/lib/scudo/standalone/primary32.h | 9 + compiler-rt/lib/scudo/standalone/primary64.h | 60 ++++- .../lib/scudo/standalone/stack_depot.h | 144 ++++++++++++ .../lib/scudo/standalone/wrappers_c.inc | 9 + .../scudo/standalone/wrappers_c_bionic.cpp | 24 ++ 14 files changed, 674 insertions(+), 23 deletions(-) create mode 100644 compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt create mode 100644 compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp create mode 100644 compiler-rt/lib/scudo/standalone/stack_depot.h diff --git a/compiler-rt/lib/CMakeLists.txt b/compiler-rt/lib/CMakeLists.txt index 39082aa06d42e..2020ee32d4f71 100644 --- a/compiler-rt/lib/CMakeLists.txt +++ b/compiler-rt/lib/CMakeLists.txt @@ -59,3 +59,9 @@ endif() if(COMPILER_RT_BUILD_LIBFUZZER) compiler_rt_build_runtime(fuzzer) endif() + +# It doesn't normally make sense to build runtimes when a sanitizer is enabled, +# so we don't add_subdirectory the runtimes in that case. However, the opposite +# is true for fuzzers that exercise parts of the runtime. So we add the fuzzer +# directories explicitly here. +add_subdirectory(scudo/standalone/fuzz) diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h index 1fffea4dc5c21..51e0c5d1966c1 100644 --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -18,6 +18,7 @@ #include "quarantine.h" #include "report.h" #include "secondary.h" +#include "stack_depot.h" #include "string_utils.h" #include "tsd.h" @@ -31,6 +32,14 @@ extern "C" inline void EmptyCallback() {} +#if SCUDO_ANDROID && __ANDROID_API__ == 10000 +// This function is not part of the NDK so it does not appear in any public +// header files. We only declare/use it when targeting the platform (i.e. API +// level 10000). +extern "C" size_t android_unsafe_frame_pointer_chase(scudo::uptr *buf, + size_t num_entries); +#endif + namespace scudo { enum class Option { ReleaseInterval }; @@ -142,6 +151,7 @@ class Allocator { Options.ZeroContents = getFlags()->zero_contents; Options.DeallocTypeMismatch = getFlags()->dealloc_type_mismatch; Options.DeleteSizeMismatch = getFlags()->delete_size_mismatch; + Options.TrackAllocationStacks = false; Options.QuarantineMaxChunkSize = static_cast(getFlags()->quarantine_max_chunk_size); @@ -221,6 +231,20 @@ class Allocator { return Ptr; } + NOINLINE u32 collectStackTrace() { +#if SCUDO_ANDROID && __ANDROID_API__ == 10000 + // Discard collectStackTrace() frame and allocator function frame. + constexpr uptr DiscardFrames = 2; + uptr Stack[MaxTraceSize + DiscardFrames]; + uptr Size = + android_unsafe_frame_pointer_chase(Stack, MaxTraceSize + DiscardFrames); + Size = Min(Size, MaxTraceSize + DiscardFrames); + return Depot.insert(Stack + Min(DiscardFrames, Size), Stack + Size); +#else + return 0; +#endif + } + NOINLINE void *allocate(uptr Size, Chunk::Origin Origin, uptr Alignment = MinAlignment, bool ZeroContents = false) { @@ -359,9 +383,15 @@ class Allocator { PrevEnd = NextPage; TaggedPtr = reinterpret_cast(TaggedUserPtr); resizeTaggedChunk(PrevEnd, TaggedUserPtr + Size, BlockEnd); + if (Size) { + // Clear any stack metadata that may have previously been stored in + // the chunk data. + memset(TaggedPtr, 0, archMemoryTagGranuleSize()); + } } else { TaggedPtr = prepareTaggedChunk(Ptr, Size, BlockEnd); } + storeAllocationStackMaybe(Ptr); } else if (UNLIKELY(ZeroContents)) { // This condition is not necessarily unlikely, but since memset is // costly, we might as well mark it as such. @@ -515,10 +545,12 @@ class Allocator { : BlockEnd - (reinterpret_cast(OldPtr) + NewSize)) & Chunk::SizeOrUnusedBytesMask; Chunk::compareExchangeHeader(Cookie, OldPtr, &NewHeader, &OldHeader); - if (UNLIKELY(ClassId && useMemoryTagging())) + if (UNLIKELY(ClassId && useMemoryTagging())) { resizeTaggedChunk(reinterpret_cast(OldTaggedPtr) + OldSize, reinterpret_cast(OldTaggedPtr) + NewSize, BlockEnd); + storeAllocationStackMaybe(OldPtr); + } return OldTaggedPtr; } } @@ -689,6 +721,135 @@ class Allocator { void disableMemoryTagging() { Primary.disableMemoryTagging(); } + void setTrackAllocationStacks(bool Track) { + Options.TrackAllocationStacks = Track; + } + + const char *getStackDepotAddress() const { + return reinterpret_cast(&Depot); + } + + const char *getRegionInfoArrayAddress() const { + return Primary.getRegionInfoArrayAddress(); + } + + static uptr getRegionInfoArraySize() { + return PrimaryT::getRegionInfoArraySize(); + } + + static void getErrorInfo(struct scudo_error_info *ErrorInfo, + uintptr_t FaultAddr, const char *DepotPtr, + const char *RegionInfoPtr, const char *Memory, + const char *MemoryTags, uintptr_t MemoryAddr, + size_t MemorySize) { + *ErrorInfo = {}; + if (!PrimaryT::SupportsMemoryTagging || + MemoryAddr + MemorySize < MemoryAddr) + return; + + uptr UntaggedFaultAddr = untagPointer(FaultAddr); + u8 FaultAddrTag = extractTag(FaultAddr); + BlockInfo Info = + PrimaryT::findNearestBlock(RegionInfoPtr, UntaggedFaultAddr); + + auto GetGranule = [&](uptr Addr, const char **Data, uint8_t *Tag) -> bool { + if (Addr < MemoryAddr || + Addr + archMemoryTagGranuleSize() < Addr || + Addr + archMemoryTagGranuleSize() > MemoryAddr + MemorySize) + return false; + *Data = &Memory[Addr - MemoryAddr]; + *Tag = static_cast( + MemoryTags[(Addr - MemoryAddr) / archMemoryTagGranuleSize()]); + return true; + }; + + auto ReadBlock = [&](uptr Addr, uptr *ChunkAddr, + Chunk::UnpackedHeader *Header, const u32 **Data, + u8 *Tag) { + const char *BlockBegin; + u8 BlockBeginTag; + if (!GetGranule(Addr, &BlockBegin, &BlockBeginTag)) + return false; + uptr ChunkOffset = getChunkOffsetFromBlock(BlockBegin); + *ChunkAddr = Addr + ChunkOffset; + + const char *ChunkBegin; + if (!GetGranule(*ChunkAddr, &ChunkBegin, Tag)) + return false; + *Header = *reinterpret_cast( + ChunkBegin - Chunk::getHeaderSize()); + *Data = reinterpret_cast(ChunkBegin); + return true; + }; + + auto *Depot = reinterpret_cast(DepotPtr); + + auto MaybeCollectTrace = [&](uintptr_t(&Trace)[MaxTraceSize], u32 Hash) { + uptr RingPos, Size; + if (!Depot->find(Hash, &RingPos, &Size)) + return; + for (unsigned I = 0; I != Size && I != MaxTraceSize; ++I) + Trace[I] = (*Depot)[RingPos + I]; + }; + + size_t NextErrorReport = 0; + + // First, check for UAF. + { + uptr ChunkAddr; + Chunk::UnpackedHeader Header; + const u32 *Data; + uint8_t Tag; + if (ReadBlock(Info.BlockBegin, &ChunkAddr, &Header, &Data, &Tag) && + Header.State != Chunk::State::Allocated && + Data[MemTagPrevTagIndex] == FaultAddrTag) { + auto *R = &ErrorInfo->reports[NextErrorReport++]; + R->error_type = USE_AFTER_FREE; + R->allocation_address = ChunkAddr; + R->allocation_size = Header.SizeOrUnusedBytes; + MaybeCollectTrace(R->allocation_trace, + Data[MemTagAllocationTraceIndex]); + R->allocation_tid = Data[MemTagAllocationTidIndex]; + MaybeCollectTrace(R->deallocation_trace, + Data[MemTagDeallocationTraceIndex]); + R->deallocation_tid = Data[MemTagDeallocationTidIndex]; + } + } + + auto CheckOOB = [&](uptr BlockAddr) { + if (BlockAddr < Info.RegionBegin || BlockAddr >= Info.RegionEnd) + return false; + + uptr ChunkAddr; + Chunk::UnpackedHeader Header; + const u32 *Data; + uint8_t Tag; + if (!ReadBlock(BlockAddr, &ChunkAddr, &Header, &Data, &Tag) || + Header.State != Chunk::State::Allocated || Tag != FaultAddrTag) + return false; + + auto *R = &ErrorInfo->reports[NextErrorReport++]; + R->error_type = + UntaggedFaultAddr < ChunkAddr ? BUFFER_UNDERFLOW : BUFFER_OVERFLOW; + R->allocation_address = ChunkAddr; + R->allocation_size = Header.SizeOrUnusedBytes; + MaybeCollectTrace(R->allocation_trace, Data[MemTagAllocationTraceIndex]); + R->allocation_tid = Data[MemTagAllocationTidIndex]; + return NextErrorReport == + sizeof(ErrorInfo->reports) / sizeof(ErrorInfo->reports[0]); + }; + + if (CheckOOB(Info.BlockBegin)) + return; + + // Check for OOB in the 30 surrounding blocks. Beyond that we are likely to + // hit false positives. + for (int I = 1; I != 16; ++I) + if (CheckOOB(Info.BlockBegin + I * Info.BlockSize) || + CheckOOB(Info.BlockBegin - I * Info.BlockSize)) + return; + } + private: using SecondaryT = typename Params::Secondary; typedef typename PrimaryT::SizeClassMap SizeClassMap; @@ -708,6 +869,26 @@ class Allocator { static const u32 BlockMarker = 0x44554353U; + // These are indexes into an "array" of 32-bit values that store information + // inline with a chunk that is relevant to diagnosing memory tag faults, where + // 0 corresponds to the address of the user memory. This means that negative + // indexes may be used to store information about allocations, while positive + // indexes may only be used to store information about deallocations, because + // the user memory is in use until it has been deallocated. The smallest index + // that may be used is -2, which corresponds to 8 bytes before the user + // memory, because the chunk header size is 8 bytes and in allocators that + // support memory tagging the minimum alignment is at least the tag granule + // size (16 on aarch64), and the largest index that may be used is 3 because + // we are only guaranteed to have at least a granule's worth of space in the + // user memory. + static const sptr MemTagAllocationTraceIndex = -2; + static const sptr MemTagAllocationTidIndex = -1; + static const sptr MemTagDeallocationTraceIndex = 0; + static const sptr MemTagDeallocationTidIndex = 1; + static const sptr MemTagPrevTagIndex = 2; + + static const uptr MaxTraceSize = 64; + GlobalStats Stats; TSDRegistryT TSDRegistry; PrimaryT Primary; @@ -721,6 +902,7 @@ class Allocator { u8 ZeroContents : 1; // zero_contents u8 DeallocTypeMismatch : 1; // dealloc_type_mismatch u8 DeleteSizeMismatch : 1; // delete_size_mismatch + u8 TrackAllocationStacks : 1; u32 QuarantineMaxChunkSize; // quarantine_max_chunk_size } Options; @@ -728,6 +910,8 @@ class Allocator { gwp_asan::GuardedPoolAllocator GuardedAlloc; #endif // GWP_ASAN_HOOKS + StackDepot Depot; + // The following might get optimized out by the compiler. NOINLINE void performSanityChecks() { // Verify that the header offset field can hold the maximum offset. In the @@ -787,8 +971,10 @@ class Allocator { uptr Size) { Chunk::UnpackedHeader NewHeader = *Header; if (UNLIKELY(NewHeader.ClassId && useMemoryTagging())) { + u8 PrevTag = extractTag(loadTag(reinterpret_cast(Ptr))); uptr TaggedBegin, TaggedEnd; setRandomTag(Ptr, Size, &TaggedBegin, &TaggedEnd); + storeDeallocationStackMaybe(Ptr, PrevTag); } // If the quarantine is disabled, the actual size of a chunk is 0 or larger // than the maximum allowed, we return a chunk directly to the backend. @@ -824,13 +1010,39 @@ class Allocator { bool getChunkFromBlock(uptr Block, uptr *Chunk, Chunk::UnpackedHeader *Header) { - u32 Offset = 0; - if (reinterpret_cast(Block)[0] == BlockMarker) - Offset = reinterpret_cast(Block)[1]; - *Chunk = Block + Offset + Chunk::getHeaderSize(); + *Chunk = + Block + getChunkOffsetFromBlock(reinterpret_cast(Block)); return Chunk::isValid(Cookie, reinterpret_cast(*Chunk), Header); } + static uptr getChunkOffsetFromBlock(const char *Block) { + u32 Offset = 0; + if (reinterpret_cast(Block)[0] == BlockMarker) + Offset = reinterpret_cast(Block)[1]; + return Offset + Chunk::getHeaderSize(); + } + + void storeAllocationStackMaybe(void *Ptr) { + if (!UNLIKELY(Options.TrackAllocationStacks)) + return; + auto *Ptr32 = reinterpret_cast(Ptr); + Ptr32[MemTagAllocationTraceIndex] = collectStackTrace(); + Ptr32[MemTagAllocationTidIndex] = getThreadID(); + } + + void storeDeallocationStackMaybe(void *Ptr, uint8_t PrevTag) { + if (!UNLIKELY(Options.TrackAllocationStacks)) + return; + + // Disable tag checks here so that we don't need to worry about zero sized + // allocations. + ScopedDisableMemoryTagChecks x; + auto *Ptr32 = reinterpret_cast(Ptr); + Ptr32[MemTagDeallocationTraceIndex] = collectStackTrace(); + Ptr32[MemTagDeallocationTidIndex] = getThreadID(); + Ptr32[MemTagPrevTagIndex] = PrevTag; + } + uptr getStats(ScopedString *Str) { Primary.getStats(Str); Secondary.getStats(Str); diff --git a/compiler-rt/lib/scudo/standalone/common.h b/compiler-rt/lib/scudo/standalone/common.h index e026e34c0045c..350d8d9fcd91e 100644 --- a/compiler-rt/lib/scudo/standalone/common.h +++ b/compiler-rt/lib/scudo/standalone/common.h @@ -133,6 +133,8 @@ const char *getEnv(const char *Name); u64 getMonotonicTime(); +u32 getThreadID(); + // Our randomness gathering function is limited to 256 bytes to ensure we get // as many bytes as requested, and avoid interruptions (on Linux). constexpr uptr MaxRandomLength = 256U; @@ -173,6 +175,13 @@ void NORETURN dieOnMapUnmapError(bool OutOfMemory = false); void setAbortMessage(const char *Message); +struct BlockInfo { + uptr BlockBegin; + uptr BlockSize; + uptr RegionBegin; + uptr RegionEnd; +}; + } // namespace scudo #endif // SCUDO_COMMON_H_ diff --git a/compiler-rt/lib/scudo/standalone/fuchsia.cpp b/compiler-rt/lib/scudo/standalone/fuchsia.cpp index b3d72de158cf9..d4ea332779415 100644 --- a/compiler-rt/lib/scudo/standalone/fuchsia.cpp +++ b/compiler-rt/lib/scudo/standalone/fuchsia.cpp @@ -170,6 +170,8 @@ u64 getMonotonicTime() { return _zx_clock_get_monotonic(); } u32 getNumberOfCPUs() { return _zx_system_get_num_cpus(); } +u32 getThreadID() { return 0; } + bool getRandom(void *Buffer, uptr Length, UNUSED bool Blocking) { static_assert(MaxRandomLength <= ZX_CPRNG_DRAW_MAX_LEN, ""); if (UNLIKELY(!Buffer || !Length || Length > MaxRandomLength)) diff --git a/compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt b/compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt new file mode 100644 index 0000000000000..d29c2f2fe7493 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/fuzz/CMakeLists.txt @@ -0,0 +1,12 @@ +if (LLVM_USE_SANITIZE_COVERAGE) + add_executable(get_error_info_fuzzer + get_error_info_fuzzer.cpp) + set_target_properties( + get_error_info_fuzzer PROPERTIES FOLDER "Fuzzers") + target_compile_options( + get_error_info_fuzzer PRIVATE -fsanitize=fuzzer) + set_target_properties( + get_error_info_fuzzer PROPERTIES LINK_FLAGS -fsanitize=fuzzer) + target_include_directories( + get_error_info_fuzzer PRIVATE .. ../include) +endif() diff --git a/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp b/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp new file mode 100644 index 0000000000000..d29f515215e67 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/fuzz/get_error_info_fuzzer.cpp @@ -0,0 +1,48 @@ +//===-- get_error_info_fuzzer.cpp -----------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#define SCUDO_FUZZ +#include "allocator_config.h" +#include "combined.h" + +#include + +#include +#include + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *Data, size_t Size) { + using AllocatorT = scudo::Allocator; + FuzzedDataProvider FDP(Data, Size); + + uintptr_t FaultAddr = FDP.ConsumeIntegral(); + uintptr_t MemoryAddr = FDP.ConsumeIntegral(); + + std::string MemoryAndTags = FDP.ConsumeRandomLengthString(FDP.remaining_bytes()); + const char *Memory = MemoryAndTags.c_str(); + // Assume 16-byte alignment. + size_t MemorySize = (MemoryAndTags.length() / 17) * 16; + const char *MemoryTags = Memory + MemorySize; + + std::string StackDepotBytes = FDP.ConsumeRandomLengthString(FDP.remaining_bytes()); + std::vector StackDepot(sizeof(scudo::StackDepot), 0); + for (size_t i = 0; i < StackDepotBytes.length() && i < StackDepot.size(); ++i) { + StackDepot[i] = StackDepotBytes[i]; + } + + std::string RegionInfoBytes = FDP.ConsumeRemainingBytesAsString(); + std::vector RegionInfo(AllocatorT::getRegionInfoArraySize(), 0); + for (size_t i = 0; i < RegionInfoBytes.length() && i < RegionInfo.size(); ++i) { + RegionInfo[i] = RegionInfoBytes[i]; + } + + scudo_error_info ErrorInfo; + AllocatorT::getErrorInfo(&ErrorInfo, FaultAddr, StackDepot.data(), + RegionInfo.data(), Memory, MemoryTags, MemoryAddr, + MemorySize); + return 0; +} diff --git a/compiler-rt/lib/scudo/standalone/include/scudo/interface.h b/compiler-rt/lib/scudo/standalone/include/scudo/interface.h index e527d0a5d3043..d30fb6514a14a 100644 --- a/compiler-rt/lib/scudo/standalone/include/scudo/interface.h +++ b/compiler-rt/lib/scudo/standalone/include/scudo/interface.h @@ -9,6 +9,8 @@ #ifndef SCUDO_INTERFACE_H_ #define SCUDO_INTERFACE_H_ +#include + extern "C" { __attribute__((weak)) const char *__scudo_default_options(); @@ -22,6 +24,87 @@ void __scudo_print_stats(void); typedef void (*iterate_callback)(uintptr_t base, size_t size, void *arg); +// Determine the likely cause of a tag check fault or other memory protection +// error on a system with memory tagging support. The results are returned via +// the error_info data structure. Up to three possible causes are returned in +// the reports array, in decreasing order of probability. The remaining elements +// of reports are zero-initialized. +// +// This function may be called from a different process from the one that +// crashed. In this case, various data structures must be copied from the +// crashing process to the process that analyzes the crash. +// +// This interface is not guaranteed to be stable and may change at any time. +// Furthermore, the version of scudo in the crashing process must be the same as +// the version in the process that analyzes the crash. +// +// fault_addr is the fault address. On aarch64 this is available in the system +// register FAR_ELx, or far_context.far in an upcoming release of the Linux +// kernel. This address must include the pointer tag; note that the kernel +// strips the tag from the fields siginfo.si_addr and sigcontext.fault_address, +// so these addresses are not suitable to be passed as fault_addr. +// +// stack_depot is a pointer to the stack depot data structure, which may be +// obtained by calling the function __scudo_get_stack_depot_addr() in the +// crashing process. The size of the stack depot is available by calling the +// function __scudo_get_stack_depot_size(). +// +// region_info is a pointer to the region info data structure, which may be +// obtained by calling the function __scudo_get_region_info_addr() in the +// crashing process. The size of the region info is available by calling the +// function __scudo_get_region_info_size(). +// +// memory is a pointer to a region of memory surrounding the fault address. +// The more memory available via this pointer, the more likely it is that the +// function will be able to analyze a crash correctly. It is recommended to +// provide an amount of memory equal to 16 * the primary allocator's largest +// size class either side of the fault address. +// +// memory_tags is a pointer to an array of memory tags for the memory accessed +// via memory. Each byte of this array corresponds to a region of memory of size +// equal to the architecturally defined memory tag granule size (16 on aarch64). +// +// memory_addr is the start address of memory in the crashing process's address +// space. +// +// memory_size is the size of the memory region referred to by the memory +// pointer. +void __scudo_get_error_info(struct scudo_error_info *error_info, + uintptr_t fault_addr, const char *stack_depot, + const char *region_info, const char *memory, + const char *memory_tags, uintptr_t memory_addr, + size_t memory_size); + +enum scudo_error_type { + UNKNOWN, + USE_AFTER_FREE, + BUFFER_OVERFLOW, + BUFFER_UNDERFLOW, +}; + +struct scudo_error_report { + enum scudo_error_type error_type; + + uintptr_t allocation_address; + uintptr_t allocation_size; + + uint32_t allocation_tid; + uintptr_t allocation_trace[64]; + + uint32_t deallocation_tid; + uintptr_t deallocation_trace[64]; +}; + +struct scudo_error_info { + struct scudo_error_report reports[3]; +}; + +const char *__scudo_get_stack_depot_addr(); +size_t __scudo_get_stack_depot_size(); + +const char *__scudo_get_region_info_addr(); +size_t __scudo_get_region_info_size(); + } // extern "C" #endif // SCUDO_INTERFACE_H_ diff --git a/compiler-rt/lib/scudo/standalone/linux.cpp b/compiler-rt/lib/scudo/standalone/linux.cpp index 0ab96836fc44a..69ffdd9a165ba 100644 --- a/compiler-rt/lib/scudo/standalone/linux.cpp +++ b/compiler-rt/lib/scudo/standalone/linux.cpp @@ -139,6 +139,14 @@ u32 getNumberOfCPUs() { return static_cast(CPU_COUNT(&CPUs)); } +u32 getThreadID() { +#if SCUDO_ANDROID + return static_cast(gettid()); +#else + return static_cast(syscall(SYS_gettid)); +#endif +} + // Blocking is possibly unused if the getrandom block is not compiled in. bool getRandom(void *Buffer, uptr Length, UNUSED bool Blocking) { if (!Buffer || !Length || Length > MaxRandomLength) diff --git a/compiler-rt/lib/scudo/standalone/memtag.h b/compiler-rt/lib/scudo/standalone/memtag.h index 762713337541c..18dae2b8ca41d 100644 --- a/compiler-rt/lib/scudo/standalone/memtag.h +++ b/compiler-rt/lib/scudo/standalone/memtag.h @@ -21,11 +21,39 @@ namespace scudo { -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(SCUDO_FUZZ) inline constexpr bool archSupportsMemoryTagging() { return true; } inline constexpr uptr archMemoryTagGranuleSize() { return 16; } +inline uptr untagPointer(uptr Ptr) { return Ptr & ((1ULL << 56) - 1); } + +inline uint8_t extractTag(uptr Ptr) { + return (Ptr >> 56) & 0xf; +} + +#else + +inline constexpr bool archSupportsMemoryTagging() { return false; } + +inline uptr archMemoryTagGranuleSize() { + UNREACHABLE("memory tagging not supported"); +} + +inline uptr untagPointer(uptr Ptr) { + (void)Ptr; + UNREACHABLE("memory tagging not supported"); +} + +inline uint8_t extractTag(uptr Ptr) { + (void)Ptr; + UNREACHABLE("memory tagging not supported"); +} + +#endif + +#if defined(__aarch64__) + inline bool systemSupportsMemoryTagging() { #if defined(ANDROID_EXPERIMENTAL_MTE) return getauxval(AT_HWCAP2) & HWCAP2_MTE; @@ -51,7 +79,19 @@ inline void enableMemoryTagChecksTestOnly() { __asm__ __volatile__(".arch_extension mte; msr tco, #0"); } -inline uptr untagPointer(uptr Ptr) { return Ptr & ((1ULL << 56) - 1); } +class ScopedDisableMemoryTagChecks { + size_t PrevTCO; + + public: + ScopedDisableMemoryTagChecks() { + __asm__ __volatile__(".arch_extension mte; mrs %0, tco; msr tco, #1" + : "=r"(PrevTCO)); + } + + ~ScopedDisableMemoryTagChecks() { + __asm__ __volatile__(".arch_extension mte; msr tco, %0" : : "r"(PrevTCO)); + } +}; inline void setRandomTag(void *Ptr, uptr Size, uptr *TaggedBegin, uptr *TaggedEnd) { @@ -154,10 +194,6 @@ inline void resizeTaggedChunk(uptr OldPtr, uptr NewPtr, uptr BlockEnd) { : "memory"); } -inline uptr tagPointer(uptr UntaggedPtr, uptr Tag) { - return UntaggedPtr | (Tag & (0xfUL << 56)); -} - inline uptr loadTag(uptr Ptr) { uptr TaggedPtr = Ptr; __asm__ __volatile__(".arch_extension mte; ldg %0, [%0]" @@ -169,8 +205,6 @@ inline uptr loadTag(uptr Ptr) { #else -inline constexpr bool archSupportsMemoryTagging() { return false; } - inline bool systemSupportsMemoryTagging() { UNREACHABLE("memory tagging not supported"); } @@ -179,10 +213,6 @@ inline bool systemDetectsMemoryTagFaultsTestOnly() { UNREACHABLE("memory tagging not supported"); } -inline uptr archMemoryTagGranuleSize() { - UNREACHABLE("memory tagging not supported"); -} - inline void disableMemoryTagChecksTestOnly() { UNREACHABLE("memory tagging not supported"); } @@ -191,10 +221,9 @@ inline void enableMemoryTagChecksTestOnly() { UNREACHABLE("memory tagging not supported"); } -inline uptr untagPointer(uptr Ptr) { - (void)Ptr; - UNREACHABLE("memory tagging not supported"); -} +struct ScopedDisableMemoryTagChecks { + ScopedDisableMemoryTagChecks() {} +}; inline void setRandomTag(void *Ptr, uptr Size, uptr *TaggedBegin, uptr *TaggedEnd) { diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h index 293b5610311aa..29a2680981852 100644 --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -206,6 +206,15 @@ class SizeClassAllocator32 { bool useMemoryTagging() { return false; } void disableMemoryTagging() {} + const char *getRegionInfoArrayAddress() const { return nullptr; } + static uptr getRegionInfoArraySize() { return 0; } + + static BlockInfo findNearestBlock(const char *RegionInfoData, uptr Ptr) { + (void)RegionInfoData; + (void)Ptr; + return {}; + } + private: static const uptr NumClasses = SizeClassMap::NumClasses; static const uptr RegionSize = 1UL << RegionSizeLog; diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h index b92ca2d96169e..d4767882ba2c7 100644 --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -209,6 +209,58 @@ class SizeClassAllocator64 { } void disableMemoryTagging() { UseMemoryTagging = false; } + const char *getRegionInfoArrayAddress() const { + return reinterpret_cast(RegionInfoArray); + } + + static uptr getRegionInfoArraySize() { + return sizeof(RegionInfoArray); + } + + static BlockInfo findNearestBlock(const char *RegionInfoData, uptr Ptr) { + const RegionInfo *RegionInfoArray = + reinterpret_cast(RegionInfoData); + uptr ClassId; + uptr MinDistance = -1UL; + for (uptr I = 0; I != NumClasses; ++I) { + if (I == SizeClassMap::BatchClassId) + continue; + uptr Begin = RegionInfoArray[I].RegionBeg; + uptr End = Begin + RegionInfoArray[I].AllocatedUser; + if (Begin > End || End - Begin < SizeClassMap::getSizeByClassId(I)) + continue; + uptr RegionDistance; + if (Begin <= Ptr) { + if (Ptr < End) + RegionDistance = 0; + else + RegionDistance = Ptr - End; + } else { + RegionDistance = Begin - Ptr; + } + + if (RegionDistance < MinDistance) { + MinDistance = RegionDistance; + ClassId = I; + } + } + + BlockInfo B = {}; + if (MinDistance <= 8192) { + B.RegionBegin = RegionInfoArray[ClassId].RegionBeg; + B.RegionEnd = B.RegionBegin + RegionInfoArray[ClassId].AllocatedUser; + B.BlockSize = SizeClassMap::getSizeByClassId(ClassId); + B.BlockBegin = + B.RegionBegin + uptr(sptr(Ptr - B.RegionBegin) / sptr(B.BlockSize) * + sptr(B.BlockSize)); + while (B.BlockBegin < B.RegionBegin) + B.BlockBegin += B.BlockSize; + while (B.RegionEnd < B.BlockBegin + B.BlockSize) + B.BlockBegin -= B.BlockSize; + } + return B; + } + private: static const uptr RegionSize = 1UL << RegionSizeLog; static const uptr NumClasses = SizeClassMap::NumClasses; @@ -231,7 +283,7 @@ class SizeClassAllocator64 { u64 LastReleaseAtNs; }; - struct alignas(SCUDO_CACHE_LINE_SIZE) RegionInfo { + struct UnpaddedRegionInfo { HybridMutex Mutex; SinglyLinkedList FreeList; RegionStats Stats; @@ -244,13 +296,17 @@ class SizeClassAllocator64 { MapPlatformData Data; ReleaseToOsInfo ReleaseInfo; }; + struct RegionInfo : UnpaddedRegionInfo { + char Padding[SCUDO_CACHE_LINE_SIZE - + (sizeof(UnpaddedRegionInfo) % SCUDO_CACHE_LINE_SIZE)]; + }; static_assert(sizeof(RegionInfo) % SCUDO_CACHE_LINE_SIZE == 0, ""); uptr PrimaryBase; MapPlatformData Data; atomic_s32 ReleaseToOsIntervalMs; bool UseMemoryTagging; - RegionInfo RegionInfoArray[NumClasses]; + alignas(SCUDO_CACHE_LINE_SIZE) RegionInfo RegionInfoArray[NumClasses]; RegionInfo *getRegionInfo(uptr ClassId) { DCHECK_LT(ClassId, NumClasses); diff --git a/compiler-rt/lib/scudo/standalone/stack_depot.h b/compiler-rt/lib/scudo/standalone/stack_depot.h new file mode 100644 index 0000000000000..c4d9b277a1c58 --- /dev/null +++ b/compiler-rt/lib/scudo/standalone/stack_depot.h @@ -0,0 +1,144 @@ +//===-- stack_depot.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 +// +//===----------------------------------------------------------------------===// + +#ifndef SCUDO_STACK_DEPOT_H_ +#define SCUDO_STACK_DEPOT_H_ + +#include "atomic_helpers.h" +#include "mutex.h" + +namespace scudo { + +class MurMur2HashBuilder { + static const u32 M = 0x5bd1e995; + static const u32 Seed = 0x9747b28c; + static const u32 R = 24; + u32 H; + + public: + explicit MurMur2HashBuilder(u32 Init = 0) { H = Seed ^ Init; } + void add(u32 K) { + K *= M; + K ^= K >> R; + K *= M; + H *= M; + H ^= K; + } + u32 get() { + u32 X = H; + X ^= X >> 13; + X *= M; + X ^= X >> 15; + return X; + } +}; + +class StackDepot { + HybridMutex RingEndMu; + u32 RingEnd; + + // This data structure stores a stack trace for each allocation and + // deallocation when stack trace recording is enabled, that may be looked up + // using a hash of the stack trace. The lower bits of the hash are an index + // into the Tab array, which stores an index into the Ring array where the + // stack traces are stored. As the name implies, Ring is a ring buffer, so a + // stack trace may wrap around to the start of the array. + // + // Each stack trace in Ring is prefixed by a stack trace marker consisting of + // a fixed 1 bit in bit 0 (this allows disambiguation between stack frames + // and stack trace markers in the case where instruction pointers are 4-byte + // aligned, as they are on arm64), the stack trace hash in bits 1-32, and the + // size of the stack trace in bits 33-63. + // + // The insert() function is potentially racy in its accesses to the Tab and + // Ring arrays, but find() is resilient to races in the sense that, barring + // hash collisions, it will either return the correct stack trace or no stack + // trace at all, even if two instances of insert() raced with one another. + // This is achieved by re-checking the hash of the stack trace before + // returning the trace. + +#ifdef SCUDO_FUZZ + // Use smaller table sizes for fuzzing in order to reduce input size. + static const uptr TabBits = 4; +#else + static const uptr TabBits = 16; +#endif + static const uptr TabSize = 1 << TabBits; + static const uptr TabMask = TabSize - 1; + atomic_u32 Tab[TabSize]; + +#ifdef SCUDO_FUZZ + static const uptr RingBits = 4; +#else + static const uptr RingBits = 19; +#endif + static const uptr RingSize = 1 << RingBits; + static const uptr RingMask = RingSize - 1; + atomic_u64 Ring[RingSize]; + +public: + // Insert hash of the stack trace [Begin, End) into the stack depot, and + // return the hash. + u32 insert(uptr *Begin, uptr *End) { + MurMur2HashBuilder B; + for (uptr *I = Begin; I != End; ++I) + B.add(u32(*I) >> 2); + u32 Hash = B.get(); + + u32 Pos = Hash & TabMask; + u32 RingPos = atomic_load_relaxed(&Tab[Pos]); + u64 Entry = atomic_load_relaxed(&Ring[RingPos]); + u64 Id = (u64(End - Begin) << 33) | (u64(Hash) << 1) | 1; + if (Entry == Id) + return Hash; + + ScopedLock Lock(RingEndMu); + RingPos = RingEnd; + atomic_store_relaxed(&Tab[Pos], RingPos); + atomic_store_relaxed(&Ring[RingPos], Id); + for (uptr *I = Begin; I != End; ++I) { + RingPos = (RingPos + 1) & RingMask; + atomic_store_relaxed(&Ring[RingPos], *I); + } + RingEnd = (RingPos + 1) & RingMask; + return Hash; + } + + // Look up a stack trace by hash. Returns true if successful. The trace may be + // accessed via operator[] passing indexes between *RingPosPtr and + // *RingPosPtr + *SizePtr. + bool find(u32 Hash, uptr *RingPosPtr, uptr *SizePtr) const { + u32 Pos = Hash & TabMask; + u32 RingPos = atomic_load_relaxed(&Tab[Pos]); + if (RingPos >= RingSize) + return false; + u64 Entry = atomic_load_relaxed(&Ring[RingPos]); + u64 HashWithTagBit = (u64(Hash) << 1) | 1; + if ((Entry & 0x1ffffffff) != HashWithTagBit) + return false; + u32 Size = Entry >> 33; + if (Size >= RingSize) + return false; + *RingPosPtr = (RingPos + 1) & RingMask; + *SizePtr = Size; + MurMur2HashBuilder B; + for (uptr I = 0; I != Size; ++I) { + RingPos = (RingPos + 1) & RingMask; + B.add(u32(atomic_load_relaxed(&Ring[RingPos])) >> 2); + } + return B.get() == Hash; + } + + u64 operator[](uptr RingPos) const { + return atomic_load_relaxed(&Ring[RingPos & RingMask]); + } +}; + +} // namespace scudo + +#endif // SCUDO_STACK_DEPOT_H_ diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.inc b/compiler-rt/lib/scudo/standalone/wrappers_c.inc index 5a6c1a8d4087f..765d7daa349d1 100644 --- a/compiler-rt/lib/scudo/standalone/wrappers_c.inc +++ b/compiler-rt/lib/scudo/standalone/wrappers_c.inc @@ -219,4 +219,13 @@ INTERFACE WEAK void SCUDO_PREFIX(malloc_disable_memory_tagging)() { SCUDO_ALLOCATOR.disableMemoryTagging(); } +// Sets whether scudo records stack traces and other metadata for allocations +// and deallocations. This function only has an effect if the allocator and +// hardware support memory tagging. The program must be single threaded at the +// point when the function is called. +INTERFACE WEAK void +SCUDO_PREFIX(malloc_set_track_allocation_stacks)(int track) { + SCUDO_ALLOCATOR.setTrackAllocationStacks(track); +} + } // extern "C" diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp index 7a012a23bcf1b..4298e69b57749 100644 --- a/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp +++ b/compiler-rt/lib/scudo/standalone/wrappers_c_bionic.cpp @@ -48,4 +48,28 @@ static scudo::Allocator Date: Fri, 17 Apr 2020 22:06:01 -0400 Subject: [PATCH 16/56] add temporary logging to help diagnose a bot-only failure --- lld/test/ELF/reproduce-linkerscript.s | 1 + 1 file changed, 1 insertion(+) diff --git a/lld/test/ELF/reproduce-linkerscript.s b/lld/test/ELF/reproduce-linkerscript.s index 7cc070c3737f3..32440d9b0d331 100644 --- a/lld/test/ELF/reproduce-linkerscript.s +++ b/lld/test/ELF/reproduce-linkerscript.s @@ -8,6 +8,7 @@ # RUN: echo "/* empty */" > %t.dir/build/bar.script # RUN: cd %t.dir # RUN: ld.lld build/foo.script -o /dev/null --reproduce repro.tar +# RUN: tar tf repro.tar # RUN: tar tf repro.tar | FileCheck -DPATH='%:t.dir' %s # CHECK: [[PATH]]/build/foo.script From 41ad8b7388c13cdbe456478d8a0b4433b21a451f Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Fri, 17 Apr 2020 10:55:45 -0700 Subject: [PATCH 17/56] [llvm][NFC][CallSite] Remove CallSite from Evaluator. Reviewers: craig.topper, dblaikie Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78395 --- .../include/llvm/Transforms/Utils/Evaluator.h | 20 +++++------ llvm/lib/Transforms/Utils/Evaluator.cpp | 36 +++++++++---------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/llvm/include/llvm/Transforms/Utils/Evaluator.h b/llvm/include/llvm/Transforms/Utils/Evaluator.h index bffd65f71b2ef..31034d950c817 100644 --- a/llvm/include/llvm/Transforms/Utils/Evaluator.h +++ b/llvm/include/llvm/Transforms/Utils/Evaluator.h @@ -17,8 +17,8 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" #include @@ -73,15 +73,6 @@ class Evaluator { ValueStack.back()[V] = C; } - /// Given call site return callee and list of its formal arguments - Function *getCalleeWithFormalArgs(CallSite &CS, - SmallVector &Formals); - - /// Given call site and callee returns list of callee formal argument - /// values converting them when necessary - bool getFormalParams(CallSite &CS, Function *F, - SmallVector &Formals); - /// Casts call result to a type of bitcast call expression Constant *castCallResultIfNeeded(Value *CallExpr, Constant *RV); @@ -94,6 +85,15 @@ class Evaluator { } private: + /// Given call site return callee and list of its formal arguments + Function *getCalleeWithFormalArgs(CallBase &CB, + SmallVectorImpl &Formals); + + /// Given call site and callee returns list of callee formal argument + /// values converting them when necessary + bool getFormalParams(CallBase &CB, Function *F, + SmallVectorImpl &Formals); + Constant *ComputeLoadResult(Constant *P); /// As we compute SSA register values, we store their contents here. The back diff --git a/llvm/lib/Transforms/Utils/Evaluator.cpp b/llvm/lib/Transforms/Utils/Evaluator.cpp index 90eca28db1f15..451a68e7e3ce2 100644 --- a/llvm/lib/Transforms/Utils/Evaluator.cpp +++ b/llvm/lib/Transforms/Utils/Evaluator.cpp @@ -17,7 +17,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Constant.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -265,33 +264,33 @@ static Function *getFunction(Constant *C) { } Function * -Evaluator::getCalleeWithFormalArgs(CallSite &CS, - SmallVector &Formals) { - auto *V = CS.getCalledValue(); +Evaluator::getCalleeWithFormalArgs(CallBase &CB, + SmallVectorImpl &Formals) { + auto *V = CB.getCalledValue(); if (auto *Fn = getFunction(getVal(V))) - return getFormalParams(CS, Fn, Formals) ? Fn : nullptr; + return getFormalParams(CB, Fn, Formals) ? Fn : nullptr; auto *CE = dyn_cast(V); if (!CE || CE->getOpcode() != Instruction::BitCast || - !getFormalParams(CS, getFunction(CE->getOperand(0)), Formals)) + !getFormalParams(CB, getFunction(CE->getOperand(0)), Formals)) return nullptr; return dyn_cast( ConstantFoldLoadThroughBitcast(CE, CE->getOperand(0)->getType(), DL)); } -bool Evaluator::getFormalParams(CallSite &CS, Function *F, - SmallVector &Formals) { +bool Evaluator::getFormalParams(CallBase &CB, Function *F, + SmallVectorImpl &Formals) { if (!F) return false; auto *FTy = F->getFunctionType(); - if (FTy->getNumParams() > CS.getNumArgOperands()) { + if (FTy->getNumParams() > CB.getNumArgOperands()) { LLVM_DEBUG(dbgs() << "Too few arguments for function.\n"); return false; } - auto ArgI = CS.arg_begin(); + auto ArgI = CB.arg_begin(); for (auto ParI = FTy->param_begin(), ParE = FTy->param_end(); ParI != ParE; ++ParI) { auto *ArgC = ConstantFoldLoadThroughBitcast(getVal(*ArgI), *ParI, DL); @@ -477,22 +476,22 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, InstResult = AllocaTmps.back().get(); LLVM_DEBUG(dbgs() << "Found an alloca. Result: " << *InstResult << "\n"); } else if (isa(CurInst) || isa(CurInst)) { - CallSite CS(&*CurInst); + CallBase &CB = *cast(&*CurInst); // Debug info can safely be ignored here. - if (isa(CS.getInstruction())) { + if (isa(CB)) { LLVM_DEBUG(dbgs() << "Ignoring debug info.\n"); ++CurInst; continue; } // Cannot handle inline asm. - if (isa(CS.getCalledValue())) { + if (isa(CB.getCalledValue())) { LLVM_DEBUG(dbgs() << "Found inline asm, can not evaluate.\n"); return false; } - if (IntrinsicInst *II = dyn_cast(CS.getInstruction())) { + if (IntrinsicInst *II = dyn_cast(&CB)) { if (MemSetInst *MSI = dyn_cast(II)) { if (MSI->isVolatile()) { LLVM_DEBUG(dbgs() << "Can not optimize a volatile memset " @@ -560,7 +559,7 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, // Resolve function pointers. SmallVector Formals; - Function *Callee = getCalleeWithFormalArgs(CS, Formals); + Function *Callee = getCalleeWithFormalArgs(CB, Formals); if (!Callee || Callee->isInterposable()) { LLVM_DEBUG(dbgs() << "Can not resolve function pointer.\n"); return false; // Cannot resolve. @@ -568,9 +567,8 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, if (Callee->isDeclaration()) { // If this is a function we can constant fold, do it. - if (Constant *C = ConstantFoldCall(cast(CS.getInstruction()), - Callee, Formals, TLI)) { - InstResult = castCallResultIfNeeded(CS.getCalledValue(), C); + if (Constant *C = ConstantFoldCall(&CB, Callee, Formals, TLI)) { + InstResult = castCallResultIfNeeded(CB.getCalledValue(), C); if (!InstResult) return false; LLVM_DEBUG(dbgs() << "Constant folded function call. Result: " @@ -593,7 +591,7 @@ bool Evaluator::EvaluateBlock(BasicBlock::iterator CurInst, return false; } ValueStack.pop_back(); - InstResult = castCallResultIfNeeded(CS.getCalledValue(), RetVal); + InstResult = castCallResultIfNeeded(CB.getCalledValue(), RetVal); if (RetVal && !InstResult) return false; From 495cf27291884347dc8e1ee76a3c65fc66517f92 Mon Sep 17 00:00:00 2001 From: Lucy Fox Date: Wed, 25 Mar 2020 15:10:31 -0700 Subject: [PATCH 18/56] [MLIR] Update tutorial to add missing tests and bring directory paths and code snippets up to date. Summary: The tests referred to in Chapter 3 of the tutorial were missing from the tutorial test directory; this adds those missing tests. This also cleans up some stale directory paths and code snippets used throughout the tutorial. Subscribers: mehdi_amini, rriddle, jpienaar, burmako, shauheen, antiagainst, nicolasvasilache, arpith-jacob, mgester, aartbik, liufengdb, Joonsoo, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D76809 --- mlir/docs/Tutorials/Toy/Ch-1.md | 64 +++++----- mlir/docs/Tutorials/Toy/Ch-2.md | 116 ++++++------------ mlir/docs/Tutorials/Toy/Ch-3.md | 10 +- mlir/docs/Tutorials/Toy/Ch-5.md | 6 +- mlir/docs/Tutorials/Toy/Ch-6.md | 7 +- .../Examples/Toy/Ch3/transpose_transpose.toy | 25 ++++ .../test/Examples/Toy/Ch3/trivial_reshape.toy | 16 +++ .../Examples/Toy/Ch4/transpose_transpose.toy | 25 ++++ .../test/Examples/Toy/Ch4/trivial_reshape.toy | 16 +++ .../Examples/Toy/Ch5/transpose_transpose.toy | 25 ++++ .../test/Examples/Toy/Ch5/trivial_reshape.toy | 16 +++ .../Examples/Toy/Ch6/transpose_transpose.toy | 25 ++++ .../test/Examples/Toy/Ch6/trivial_reshape.toy | 16 +++ .../Examples/Toy/Ch7/transpose_transpose.toy | 25 ++++ .../test/Examples/Toy/Ch7/trivial_reshape.toy | 16 +++ 15 files changed, 287 insertions(+), 121 deletions(-) create mode 100644 mlir/test/Examples/Toy/Ch3/transpose_transpose.toy create mode 100644 mlir/test/Examples/Toy/Ch3/trivial_reshape.toy create mode 100644 mlir/test/Examples/Toy/Ch4/transpose_transpose.toy create mode 100644 mlir/test/Examples/Toy/Ch4/trivial_reshape.toy create mode 100644 mlir/test/Examples/Toy/Ch5/transpose_transpose.toy create mode 100644 mlir/test/Examples/Toy/Ch5/trivial_reshape.toy create mode 100644 mlir/test/Examples/Toy/Ch6/transpose_transpose.toy create mode 100644 mlir/test/Examples/Toy/Ch6/trivial_reshape.toy create mode 100644 mlir/test/Examples/Toy/Ch7/transpose_transpose.toy create mode 100644 mlir/test/Examples/Toy/Ch7/trivial_reshape.toy diff --git a/mlir/docs/Tutorials/Toy/Ch-1.md b/mlir/docs/Tutorials/Toy/Ch-1.md index 347eb3b03b04d..7c2f49918049a 100644 --- a/mlir/docs/Tutorials/Toy/Ch-1.md +++ b/mlir/docs/Tutorials/Toy/Ch-1.md @@ -109,48 +109,48 @@ The AST from the above code is fairly straightforward; here is a dump of it: ``` Module: - Function - Proto 'multiply_transpose' @test/ast.toy:5:1' - Args: [a, b] + Function + Proto 'multiply_transpose' @test/Examples/Toy/Ch1/ast.toy:4:1' + Params: [a, b] Block { Return - BinOp: * @test/ast.toy:6:25 - Call 'transpose' [ @test/ast.toy:6:10 - var: a @test/ast.toy:6:20 + BinOp: * @test/Examples/Toy/Ch1/ast.toy:5:25 + Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:10 + var: a @test/Examples/Toy/Ch1/ast.toy:5:20 ] - Call 'transpose' [ @test/ast.toy:6:25 - var: b @test/ast.toy:6:35 + Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:25 + var: b @test/Examples/Toy/Ch1/ast.toy:5:35 ] } // Block - Function - Proto 'main' @test/ast.toy:9:1' - Args: [] + Function + Proto 'main' @test/Examples/Toy/Ch1/ast.toy:8:1' + Params: [] Block { - VarDecl a<> @test/ast.toy:11:3 - Literal: <2, 3>[<3>[1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[4.000000e+00, 5.000000e+00, 6.000000e+00]] @test/ast.toy:11:17 - VarDecl b<2, 3> @test/ast.toy:12:3 - Literal: <6>[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @test/ast.toy:12:17 - VarDecl c<> @test/ast.toy:15:3 - Call 'multiply_transpose' [ @test/ast.toy:15:11 - var: a @test/ast.toy:15:30 - var: b @test/ast.toy:15:33 + VarDecl a<> @test/Examples/Toy/Ch1/ast.toy:11:3 + Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @test/Examples/Toy/Ch1/ast.toy:11:11 + VarDecl b<2, 3> @test/Examples/Toy/Ch1/ast.toy:15:3 + Literal: <6>[ 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @test/Examples/Toy/Ch1/ast.toy:15:17 + VarDecl c<> @test/Examples/Toy/Ch1/ast.toy:19:3 + Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:19:11 + var: a @test/Examples/Toy/Ch1/ast.toy:19:30 + var: b @test/Examples/Toy/Ch1/ast.toy:19:33 ] - VarDecl d<> @test/ast.toy:18:3 - Call 'multiply_transpose' [ @test/ast.toy:18:11 - var: b @test/ast.toy:18:30 - var: a @test/ast.toy:18:33 + VarDecl d<> @test/Examples/Toy/Ch1/ast.toy:22:3 + Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:22:11 + var: b @test/Examples/Toy/Ch1/ast.toy:22:30 + var: a @test/Examples/Toy/Ch1/ast.toy:22:33 ] - VarDecl e<> @test/ast.toy:21:3 - Call 'multiply_transpose' [ @test/ast.toy:21:11 - var: b @test/ast.toy:21:30 - var: c @test/ast.toy:21:33 + VarDecl e<> @test/Examples/Toy/Ch1/ast.toy:25:3 + Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:25:11 + var: b @test/Examples/Toy/Ch1/ast.toy:25:30 + var: c @test/Examples/Toy/Ch1/ast.toy:25:33 ] - VarDecl f<> @test/ast.toy:24:3 - Call 'multiply_transpose' [ @test/ast.toy:24:11 - Call 'transpose' [ @test/ast.toy:24:30 - var: a @test/ast.toy:24:40 + VarDecl f<> @test/Examples/Toy/Ch1/ast.toy:28:3 + Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:11 + Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:30 + var: a @test/Examples/Toy/Ch1/ast.toy:28:40 ] - var: c @test/ast.toy:24:44 + var: c @test/Examples/Toy/Ch1/ast.toy:28:44 ] } // Block ``` diff --git a/mlir/docs/Tutorials/Toy/Ch-2.md b/mlir/docs/Tutorials/Toy/Ch-2.md index c8be4819a2771..e57bd7da4b227 100755 --- a/mlir/docs/Tutorials/Toy/Ch-2.md +++ b/mlir/docs/Tutorials/Toy/Ch-2.md @@ -491,8 +491,7 @@ def ConstantOp : Toy_Op<"constant"> { #### Specifying a Custom Assembly Format -At this point we can generate our "Toy IR". A simplified version of the previous -example: +At this point we can generate our "Toy IR". For example, the following: ```toy # User defined generic function that operates on unknown shaped arguments. @@ -514,22 +513,22 @@ Results in the following IR: ```mlir module { func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> { - %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64> loc("test/codegen.toy":5:10) - %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64> loc("test/codegen.toy":5:25) - %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64> loc("test/codegen.toy":5:25) - "toy.return"(%2) : (tensor<*xf64>) -> () loc("test/codegen.toy":5:3) - } loc("test/codegen.toy":4:1) + %0 = "toy.transpose"(%arg0) : (tensor<*xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:10) + %1 = "toy.transpose"(%arg1) : (tensor<*xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25) + %2 = "toy.mul"(%0, %1) : (tensor<*xf64>, tensor<*xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25) + "toy.return"(%2) : (tensor<*xf64>) -> () loc("test/Examples/Toy/Ch2/codegen.toy":5:3) + } loc("test/Examples/Toy/Ch2/codegen.toy":4:1) func @main() { - %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64> loc("test/codegen.toy":9:17) - %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64> loc("test/codegen.toy":9:3) - %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64> loc("test/codegen.toy":10:17) - %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64> loc("test/codegen.toy":10:3) - %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":11:11) - %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":12:11) - "toy.print"(%5) : (tensor<*xf64>) -> () loc("test/codegen.toy":13:3) - "toy.return"() : () -> () loc("test/codegen.toy":8:1) - } loc("test/codegen.toy":8:1) -} loc("test/codegen.toy":0:0) + %0 = "toy.constant"() {value = dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64>} : () -> tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":9:17) + %1 = "toy.reshape"(%0) : (tensor<2x3xf64>) -> tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":9:3) + %2 = "toy.constant"() {value = dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64>} : () -> tensor<6xf64> loc("test/Examples/Toy/Ch2/codegen.toy":10:17) + %3 = "toy.reshape"(%2) : (tensor<6xf64>) -> tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":10:3) + %4 = "toy.generic_call"(%1, %3) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":11:11) + %5 = "toy.generic_call"(%3, %1) {callee = @multiply_transpose} : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":12:11) + "toy.print"(%5) : (tensor<*xf64>) -> () loc("test/Examples/Toy/Ch2/codegen.toy":13:3) + "toy.return"() : () -> () loc("test/Examples/Toy/Ch2/codegen.toy":8:1) + } loc("test/Examples/Toy/Ch2/codegen.toy":8:1) +} loc(unknown) ``` One thing to notice here is that all of our Toy operations are printed using the @@ -645,22 +644,22 @@ now get a much more readable: ```mlir module { func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> { - %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:10) - %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:25) - %2 = toy.mul %0, %1 : tensor<*xf64> loc("test/codegen.toy":5:25) - toy.return %2 : tensor<*xf64> loc("test/codegen.toy":5:3) - } loc("test/codegen.toy":4:1) + %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:10) + %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25) + %2 = toy.mul %0, %1 : tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:25) + toy.return %2 : tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":5:3) + } loc("test/Examples/Toy/Ch2/codegen.toy":4:1) func @main() { - %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> loc("test/codegen.toy":9:17) - %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("test/codegen.toy":9:3) - %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64> loc("test/codegen.toy":10:17) - %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("test/codegen.toy":10:3) - %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":11:11) - %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":12:11) - toy.print %5 : tensor<*xf64> loc("test/codegen.toy":13:3) - toy.return loc("test/codegen.toy":8:1) - } loc("test/codegen.toy":8:1) -} loc("test/codegen.toy":0:0) + %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":9:17) + %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":9:3) + %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64> loc("test/Examples/Toy/Ch2/codegen.toy":10:17) + %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("test/Examples/Toy/Ch2/codegen.toy":10:3) + %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":11:11) + %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":12:11) + toy.print %5 : tensor<*xf64> loc("test/Examples/Toy/Ch2/codegen.toy":13:3) + toy.return loc("test/Examples/Toy/Ch2/codegen.toy":8:1) + } loc("test/Examples/Toy/Ch2/codegen.toy":8:1) +} loc(unknown) ``` Above we introduce several of the concepts for defining operations in the ODS @@ -670,53 +669,12 @@ variadic operands, etc. Check out the ## Complete Toy Example -At this point we can generate our "Toy IR". A simplified version of the previous -example: - -```toy -# User defined generic function that operates on unknown shaped arguments. -def multiply_transpose(a, b) { - return transpose(a) * transpose(b); -} - -def main() { - var a<2, 3> = [[1, 2, 3], [4, 5, 6]]; - var b<2, 3> = [1, 2, 3, 4, 5, 6]; - var c = multiply_transpose(a, b); - var d = multiply_transpose(b, a); - print(d); -} -``` - -Results in the following IR: - -```mlir -module { - func @multiply_transpose(%arg0: tensor<*xf64>, %arg1: tensor<*xf64>) -> tensor<*xf64> { - %0 = toy.transpose(%arg0 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:10) - %1 = toy.transpose(%arg1 : tensor<*xf64>) to tensor<*xf64> loc("test/codegen.toy":5:25) - %2 = toy.mul %0, %1 : tensor<*xf64> loc("test/codegen.toy":5:25) - toy.return %2 : tensor<*xf64> loc("test/codegen.toy":5:3) - } loc("test/codegen.toy":4:1) - func @main() { - %0 = toy.constant dense<[[1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> loc("test/codegen.toy":9:17) - %1 = toy.reshape(%0 : tensor<2x3xf64>) to tensor<2x3xf64> loc("test/codegen.toy":9:3) - %2 = toy.constant dense<[1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00]> : tensor<6xf64> loc("test/codegen.toy":10:17) - %3 = toy.reshape(%2 : tensor<6xf64>) to tensor<2x3xf64> loc("test/codegen.toy":10:3) - %4 = toy.generic_call @multiply_transpose(%1, %3) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":11:11) - %5 = toy.generic_call @multiply_transpose(%3, %1) : (tensor<2x3xf64>, tensor<2x3xf64>) -> tensor<*xf64> loc("test/codegen.toy":12:11) - toy.print %5 : tensor<*xf64> loc("test/codegen.toy":13:3) - toy.return loc("test/codegen.toy":8:1) - } loc("test/codegen.toy":8:1) -} loc("test/codegen.toy":0:0) -``` - -You can build `toyc-ch2` and try yourself: `toyc-ch2 -test/Examples/Toy/Ch2/codegen.toy -emit=mlir -mlir-print-debuginfo`. We can also -check our RoundTrip: `toyc-ch2 test/Examples/Toy/Ch2/codegen.toy -emit=mlir --mlir-print-debuginfo 2> codegen.mlir` followed by `toyc-ch2 codegen.mlir --emit=mlir`. You should also use `mlir-tblgen` on the final definition file and -study the generated C++ code. +We can now generate our "Toy IR". You can build `toyc-ch2` and try yourself on +the above example: `toyc-ch2 test/Examples/Toy/Ch2/codegen.toy -emit=mlir +-mlir-print-debuginfo`. We can also check our RoundTrip: `toyc-ch2 +test/Examples/Toy/Ch2/codegen.toy -emit=mlir -mlir-print-debuginfo 2> +codegen.mlir` followed by `toyc-ch2 codegen.mlir -emit=mlir`. You should also +use `mlir-tblgen` on the final definition file and study the generated C++ code. At this point, MLIR knows about our Toy dialect and operations. In the [next chapter](Ch-3.md), we will leverage our new dialect to implement some diff --git a/mlir/docs/Tutorials/Toy/Ch-3.md b/mlir/docs/Tutorials/Toy/Ch-3.md index 0f741e7a54109..cc31454fe5331 100644 --- a/mlir/docs/Tutorials/Toy/Ch-3.md +++ b/mlir/docs/Tutorials/Toy/Ch-3.md @@ -129,8 +129,8 @@ similar way to LLVM: pm.addNestedPass(mlir::createCanonicalizerPass()); ``` -Finally, we can run `toyc-ch3 test/transpose_transpose.toy -emit=mlir -opt` and -observe our pattern in action: +Finally, we can run `toyc-ch3 test/Examples/Toy/Ch3/transpose_transpose.toy +-emit=mlir -opt` and observe our pattern in action: ```mlir func @transpose_transpose(%arg0: tensor<*xf64>) -> tensor<*xf64> { @@ -216,7 +216,7 @@ def FoldConstantReshapeOptPattern : Pat< ``` We demonstrate these reshape optimizations using the following -trivialReshape.toy program: +trivial_reshape.toy program: ```c++ def main() { @@ -240,8 +240,8 @@ module { } ``` -We can try to run `toyc-ch3 test/trivialReshape.toy -emit=mlir -opt` and observe -our pattern in action: +We can try to run `toyc-ch3 test/Examples/Toy/Ch3/trivial_reshape.toy -emit=mlir +-opt` and observe our pattern in action: ```mlir module { diff --git a/mlir/docs/Tutorials/Toy/Ch-5.md b/mlir/docs/Tutorials/Toy/Ch-5.md index fd0341a26ea52..28e799d7d6bba 100644 --- a/mlir/docs/Tutorials/Toy/Ch-5.md +++ b/mlir/docs/Tutorials/Toy/Ch-5.md @@ -222,7 +222,7 @@ def PrintOp : Toy_Op<"print"> { ## Complete Toy Example -Looking back at our current working example: +Let's take a concrete example: ```mlir func @main() { @@ -336,8 +336,8 @@ func @main() { Here, we can see that a redundant allocation was removed, the two loop nests were fused, and some unnecessary `load`s were removed. You can build `toyc-ch5` -and try yourself: `toyc-ch5 test/lowering.toy -emit=mlir-affine`. We can also -check our optimizations by adding `-opt`. +and try yourself: `toyc-ch5 test/Examples/Toy/Ch5/affine-lowering.mlir +-emit=mlir-affine`. We can also check our optimizations by adding `-opt`. In this chapter we explored some aspects of partial lowering, with the intent to optimize. In the [next chapter](Ch-6.md) we will continue the discussion about diff --git a/mlir/docs/Tutorials/Toy/Ch-6.md b/mlir/docs/Tutorials/Toy/Ch-6.md index feaf42c39ba4e..2808961f378f5 100644 --- a/mlir/docs/Tutorials/Toy/Ch-6.md +++ b/mlir/docs/Tutorials/Toy/Ch-6.md @@ -239,8 +239,8 @@ define void @main() } ``` -The full code listing for dumping LLVM IR can be found in `Ch6/toy.cpp` in the -`dumpLLVMIR()` function: +The full code listing for dumping LLVM IR can be found in +`examples/toy/Ch6/toy.cpp` in the `dumpLLVMIR()` function: ```c++ @@ -318,5 +318,8 @@ You can also play with `-emit=mlir`, `-emit=mlir-affine`, `-emit=mlir-llvm`, and [`--print-ir-after-all`](../../WritingAPass.md#ir-printing) to track the evolution of the IR throughout the pipeline. +The example code used throughout this section can be found in +test/Examples/Toy/Ch6/llvm-lowering.mlir. + So far, we have worked with primitive data types. In the [next chapter](Ch-7.md), we will add a composite `struct` type. diff --git a/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy new file mode 100644 index 0000000000000..9945e7cf8397b --- /dev/null +++ b/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy @@ -0,0 +1,25 @@ +# RUN: toyc-ch3 %s -emit=mlir 2>&1 | FileCheck %s + +# User defined generic function that operates on unknown shaped arguments +def transpose_transpose(x) { + return transpose(transpose(x)); +} + +def main() { + var a<2, 3> = [[1, 2, 3], [4, 5, 6]]; + var b = transpose_transpose(a); + print(b); +} + +# CHECK-LABEL: func @transpose_transpose( +# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> +# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> +# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> +# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy new file mode 100644 index 0000000000000..aa2c38714cf86 --- /dev/null +++ b/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy @@ -0,0 +1,16 @@ +# RUN: toyc-ch3 %s -emit=mlir 2>&1 | FileCheck %s + +def main() { + var a<2,1> = [1, 2]; + var b<2,1> = a; + var c<2,1> = b; + print(c); +} + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy new file mode 100644 index 0000000000000..77bacec0ae80c --- /dev/null +++ b/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy @@ -0,0 +1,25 @@ +# RUN: toyc-ch4 %s -emit=mlir 2>&1 | FileCheck %s + +# User defined generic function that operates on unknown shaped arguments +def transpose_transpose(x) { + return transpose(transpose(x)); +} + +def main() { + var a<2, 3> = [[1, 2, 3], [4, 5, 6]]; + var b = transpose_transpose(a); + print(b); +} + +# CHECK-LABEL: func @transpose_transpose( +# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> +# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> +# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> +# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy new file mode 100644 index 0000000000000..318bd07b36d3f --- /dev/null +++ b/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy @@ -0,0 +1,16 @@ +# RUN: toyc-ch4 %s -emit=mlir 2>&1 | FileCheck %s + +def main() { + var a<2,1> = [1, 2]; + var b<2,1> = a; + var c<2,1> = b; + print(c); +} + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy new file mode 100644 index 0000000000000..b038352a3dc00 --- /dev/null +++ b/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy @@ -0,0 +1,25 @@ +# RUN: toyc-ch5 %s -emit=mlir 2>&1 | FileCheck %s + +# User defined generic function that operates on unknown shaped arguments +def transpose_transpose(x) { + return transpose(transpose(x)); +} + +def main() { + var a<2, 3> = [[1, 2, 3], [4, 5, 6]]; + var b = transpose_transpose(a); + print(b); +} + +# CHECK-LABEL: func @transpose_transpose( +# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> +# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> +# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> +# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy new file mode 100644 index 0000000000000..48828c4c10f73 --- /dev/null +++ b/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy @@ -0,0 +1,16 @@ +# RUN: toyc-ch5 %s -emit=mlir 2>&1 | FileCheck %s + +def main() { + var a<2,1> = [1, 2]; + var b<2,1> = a; + var c<2,1> = b; + print(c); +} + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy new file mode 100644 index 0000000000000..5ddfbc23a851a --- /dev/null +++ b/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy @@ -0,0 +1,25 @@ +# RUN: toyc-ch6 %s -emit=mlir 2>&1 | FileCheck %s + +# User defined generic function that operates on unknown shaped arguments +def transpose_transpose(x) { + return transpose(transpose(x)); +} + +def main() { + var a<2, 3> = [[1, 2, 3], [4, 5, 6]]; + var b = transpose_transpose(a); + print(b); +} + +# CHECK-LABEL: func @transpose_transpose( +# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> +# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> +# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> +# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy new file mode 100644 index 0000000000000..6fa9f68b68ca5 --- /dev/null +++ b/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy @@ -0,0 +1,16 @@ +# RUN: toyc-ch6 %s -emit=mlir 2>&1 | FileCheck %s + +def main() { + var a<2,1> = [1, 2]; + var b<2,1> = a; + var c<2,1> = b; + print(c); +} + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy new file mode 100644 index 0000000000000..804cdb879884a --- /dev/null +++ b/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy @@ -0,0 +1,25 @@ +# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s + +# User defined generic function that operates on unknown shaped arguments +def transpose_transpose(x) { + return transpose(transpose(x)); +} + +def main() { + var a<2, 3> = [[1, 2, 3], [4, 5, 6]]; + var b = transpose_transpose(a); + print(b); +} + +# CHECK-LABEL: func @transpose_transpose( +# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> +# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> +# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> +# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> +# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy new file mode 100644 index 0000000000000..73209d8f5ffec --- /dev/null +++ b/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy @@ -0,0 +1,16 @@ +# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s + +def main() { + var a<2,1> = [1, 2]; + var b<2,1> = a; + var c<2,1> = b; + print(c); +} + +# CHECK-LABEL: func @main() +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: toy.return \ No newline at end of file From a6b427167e0560202529563cf94a210694038185 Mon Sep 17 00:00:00 2001 From: Lucy Fox Date: Fri, 17 Apr 2020 17:12:25 -0700 Subject: [PATCH 19/56] [MLIR] Update tutorial to add missing tests and bring directory paths and code snippets up to date. Summary: The tests referred to in Chapter 3 of the tutorial were missing from the tutorial test directory; this adds those missing tests. This also cleans up some stale directory paths and code snippets used throughout the tutorial. Differential Revision: https://reviews.llvm.org/D76809 --- mlir/test/Examples/Toy/Ch3/transpose_transpose.toy | 13 +++++-------- mlir/test/Examples/Toy/Ch3/trivial_reshape.toy | 12 ++++++------ mlir/test/Examples/Toy/Ch4/transpose_transpose.toy | 14 +++----------- mlir/test/Examples/Toy/Ch4/trivial_reshape.toy | 12 ++++++------ mlir/test/Examples/Toy/Ch5/transpose_transpose.toy | 14 +++----------- mlir/test/Examples/Toy/Ch5/trivial_reshape.toy | 12 ++++++------ mlir/test/Examples/Toy/Ch6/transpose_transpose.toy | 14 +++----------- mlir/test/Examples/Toy/Ch6/trivial_reshape.toy | 12 ++++++------ mlir/test/Examples/Toy/Ch7/transpose_transpose.toy | 14 +++----------- mlir/test/Examples/Toy/Ch7/trivial_reshape.toy | 12 ++++++------ 10 files changed, 47 insertions(+), 82 deletions(-) diff --git a/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy index 9945e7cf8397b..c686f6ab1c313 100644 --- a/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy +++ b/mlir/test/Examples/Toy/Ch3/transpose_transpose.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch3 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch3 %s -emit=mlir -opt 2>&1 | FileCheck %s # User defined generic function that operates on unknown shaped arguments def transpose_transpose(x) { @@ -13,13 +13,10 @@ def main() { # CHECK-LABEL: func @transpose_transpose( # CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> -# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> +# CHECK-NEXT: toy.return [[VAL_0]] : tensor<*xf64> # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> -# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> -# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> -# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: [[VAL_2:%.*]] = toy.generic_call @transpose_transpose([[VAL_1]]) : (tensor<2x3xf64>) -> tensor<*xf64> +# CHECK-NEXT: toy.print [[VAL_2]] : tensor<*xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy index aa2c38714cf86..0f0b1af1f50eb 100644 --- a/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch3/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch3 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch3 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -8,9 +8,9 @@ def main() { } # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> -# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant +# CHECK-SAME: dense<[ +# CHECK-SAME: [1.000000e+00], [2.000000e+00] +# CHECK-SAME: ]> : tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy index 77bacec0ae80c..2177c35fa93dd 100644 --- a/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy +++ b/mlir/test/Examples/Toy/Ch4/transpose_transpose.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch4 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s # User defined generic function that operates on unknown shaped arguments def transpose_transpose(x) { @@ -11,15 +11,7 @@ def main() { print(b); } -# CHECK-LABEL: func @transpose_transpose( -# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> -# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> - # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> -# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> -# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> -# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: toy.print [[VAL_1]] : tensor<2x3xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy index 318bd07b36d3f..453efa3ef3123 100644 --- a/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch4/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch4 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -8,9 +8,9 @@ def main() { } # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> -# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant +# CHECK-SAME: dense<[ +# CHECK-SAME: [1.000000e+00], [2.000000e+00] +# CHECK-SAME: ]> : tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy index b038352a3dc00..c0659c86af020 100644 --- a/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy +++ b/mlir/test/Examples/Toy/Ch5/transpose_transpose.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch5 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch5 %s -emit=mlir -opt 2>&1 | FileCheck %s # User defined generic function that operates on unknown shaped arguments def transpose_transpose(x) { @@ -11,15 +11,7 @@ def main() { print(b); } -# CHECK-LABEL: func @transpose_transpose( -# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> -# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> - # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> -# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> -# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> -# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: toy.print [[VAL_1]] : tensor<2x3xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy index 48828c4c10f73..453efa3ef3123 100644 --- a/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch5 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -8,9 +8,9 @@ def main() { } # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> -# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant +# CHECK-SAME: dense<[ +# CHECK-SAME: [1.000000e+00], [2.000000e+00] +# CHECK-SAME: ]> : tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy index 5ddfbc23a851a..ac710fe08d1ad 100644 --- a/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy +++ b/mlir/test/Examples/Toy/Ch6/transpose_transpose.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch6 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch6 %s -emit=mlir -opt 2>&1 | FileCheck %s # User defined generic function that operates on unknown shaped arguments def transpose_transpose(x) { @@ -11,15 +11,7 @@ def main() { print(b); } -# CHECK-LABEL: func @transpose_transpose( -# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> -# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> - # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> -# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> -# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> -# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: toy.print [[VAL_1]] : tensor<2x3xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy index 6fa9f68b68ca5..453efa3ef3123 100644 --- a/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch6 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -8,9 +8,9 @@ def main() { } # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> -# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant +# CHECK-SAME: dense<[ +# CHECK-SAME: [1.000000e+00], [2.000000e+00] +# CHECK-SAME: ]> : tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy b/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy index 804cdb879884a..f268425341c9c 100644 --- a/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy +++ b/mlir/test/Examples/Toy/Ch7/transpose_transpose.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch7 %s -emit=mlir -opt 2>&1 | FileCheck %s # User defined generic function that operates on unknown shaped arguments def transpose_transpose(x) { @@ -11,15 +11,7 @@ def main() { print(b); } -# CHECK-LABEL: func @transpose_transpose( -# CHECK-SAME: [[VAL_0:%.*]]: tensor<*xf64>) -> tensor<*xf64> -# CHECK: [[VAL_1:%.*]] = toy.transpose([[VAL_0]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.transpose([[VAL_1]] : tensor<*xf64>) to tensor<*xf64> -# CHECK-NEXT: toy.return [[VAL_2]] : tensor<*xf64> - # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_3:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> -# CHECK-NEXT: [[VAL_4:%.*]] = toy.reshape([[VAL_3]] : tensor<2x3xf64>) to tensor<2x3xf64> -# CHECK-NEXT: [[VAL_5:%.*]] = toy.generic_call @transpose_transpose([[VAL_4]]) : (tensor<2x3xf64>) -> tensor<*xf64> -# CHECK-NEXT: toy.print [[VAL_5]] : tensor<*xf64> +# CHECK-NEXT: [[VAL_1:%.*]] = toy.constant dense<{{\[\[}}1.000000e+00, 2.000000e+00, 3.000000e+00], [4.000000e+00, 5.000000e+00, 6.000000e+00]]> : tensor<2x3xf64> +# CHECK-NEXT: toy.print [[VAL_1]] : tensor<2x3xf64> # CHECK-NEXT: toy.return \ No newline at end of file diff --git a/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy index 73209d8f5ffec..453efa3ef3123 100644 --- a/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch7 %s -emit=mlir 2>&1 | FileCheck %s +# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -8,9 +8,9 @@ def main() { } # CHECK-LABEL: func @main() -# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant dense<[1.000000e+00, 2.000000e+00]> : tensor<2xf64> -# CHECK-NEXT: [[VAL_1:%.*]] = toy.reshape([[VAL_0]] : tensor<2xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_2:%.*]] = toy.reshape([[VAL_1]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: [[VAL_3:%.*]] = toy.reshape([[VAL_2]] : tensor<2x1xf64>) to tensor<2x1xf64> -# CHECK-NEXT: toy.print [[VAL_3]] : tensor<2x1xf64> +# CHECK-NEXT: [[VAL_0:%.*]] = toy.constant +# CHECK-SAME: dense<[ +# CHECK-SAME: [1.000000e+00], [2.000000e+00] +# CHECK-SAME: ]> : tensor<2x1xf64> +# CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> # CHECK-NEXT: toy.return \ No newline at end of file From a0d5e5496621700b26d234a948f9c99b08a8a319 Mon Sep 17 00:00:00 2001 From: Lucy Fox Date: Fri, 17 Apr 2020 17:41:51 -0700 Subject: [PATCH 20/56] [MLIR] Update tutorial to add missing tests and bring directory paths and code snippets up to date. Summary: The tests referred to in Chapter 3 of the tutorial were missing from the tutorial test directory; this adds those missing tests. This also cleans up some stale directory paths and code snippets used throughout the tutorial. Differential Revision: https://reviews.llvm.org/D76809 --- mlir/test/Examples/Toy/Ch5/trivial_reshape.toy | 4 ++-- mlir/test/Examples/Toy/Ch6/trivial_reshape.toy | 4 ++-- mlir/test/Examples/Toy/Ch7/trivial_reshape.toy | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy index 453efa3ef3123..1addb06022e0a 100644 --- a/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch5/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s +# RUN: toyc-ch5 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -13,4 +13,4 @@ def main() { # CHECK-SAME: [1.000000e+00], [2.000000e+00] # CHECK-SAME: ]> : tensor<2x1xf64> # CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> -# CHECK-NEXT: toy.return \ No newline at end of file +# CHECK-NEXT: toy.return diff --git a/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy index 453efa3ef3123..17832ace37827 100644 --- a/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch6/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s +# RUN: toyc-ch6 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -13,4 +13,4 @@ def main() { # CHECK-SAME: [1.000000e+00], [2.000000e+00] # CHECK-SAME: ]> : tensor<2x1xf64> # CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> -# CHECK-NEXT: toy.return \ No newline at end of file +# CHECK-NEXT: toy.return diff --git a/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy b/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy index 453efa3ef3123..5ca8c4b6e41ae 100644 --- a/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy +++ b/mlir/test/Examples/Toy/Ch7/trivial_reshape.toy @@ -1,4 +1,4 @@ -# RUN: toyc-ch4 %s -emit=mlir -opt 2>&1 | FileCheck %s +# RUN: toyc-ch7 %s -emit=mlir -opt 2>&1 | FileCheck %s def main() { var a<2,1> = [1, 2]; @@ -13,4 +13,4 @@ def main() { # CHECK-SAME: [1.000000e+00], [2.000000e+00] # CHECK-SAME: ]> : tensor<2x1xf64> # CHECK-NEXT: toy.print [[VAL_0]] : tensor<2x1xf64> -# CHECK-NEXT: toy.return \ No newline at end of file +# CHECK-NEXT: toy.return From 31a166e4cb913ff10af23b0968963d52b05a3ac5 Mon Sep 17 00:00:00 2001 From: Craig Topper Date: Fri, 17 Apr 2020 20:45:58 -0700 Subject: [PATCH 21/56] [X86] Clean up some mir tests with INLINEASM to avoid regdef or to correct the immediate for the regdef. The immediate used for the regdef is the encoding for the register class in the enum generated by tablegen. This encoding will change any time a new register class is added. Since the number is part of the input, this means it can become stale. This change modifies some test to avoid this kind of immediate all together. And updates one test to use the current encoding of GR64. --- .../CodeGen/MIR/X86/inline-asm-registers.mir | 8 +- llvm/test/CodeGen/X86/stack-folding-adx.mir | 161 +++++++++--------- llvm/test/CodeGen/X86/stack-folding-bmi2.mir | 36 ++-- .../X86/stack-folding-fp-nofpexcept.mir | 17 +- 4 files changed, 109 insertions(+), 113 deletions(-) diff --git a/llvm/test/CodeGen/MIR/X86/inline-asm-registers.mir b/llvm/test/CodeGen/MIR/X86/inline-asm-registers.mir index fd1e7aaa32098..3b5746926c899 100644 --- a/llvm/test/CodeGen/MIR/X86/inline-asm-registers.mir +++ b/llvm/test/CodeGen/MIR/X86/inline-asm-registers.mir @@ -28,8 +28,8 @@ body: | liveins: $rdi, $rsi ; CHECK-LABEL: name: test - ; CHECK: INLINEASM &foo, 0 /* attdialect */, 2818058 /* regdef:GR32_TC */, def $rsi, 2818058 /* regdef:GR32_TC */, def dead $rdi, - INLINEASM &foo, 0, 2818058, def $rsi, 2818058, def dead $rdi, 2147549193, killed $rdi, 2147483657, killed $rsi, 12, implicit-def dead early-clobber $eflags + ; CHECK: INLINEASM &foo, 0 /* attdialect */, 4325386 /* regdef:GR64 */, def $rsi, 4325386 /* regdef:GR64 */, def dead $rdi, + INLINEASM &foo, 0, 4325386, def $rsi, 4325386, def dead $rdi, 2147549193, killed $rdi, 2147483657, killed $rsi, 12, implicit-def dead early-clobber $eflags $rax = MOV64rr killed $rsi RETQ killed $rax ... @@ -45,8 +45,8 @@ body: | ; Verify that the register ties are preserved. ; CHECK-LABEL: name: test2 - ; CHECK: INLINEASM &foo, 0 /* attdialect */, 2818058 /* regdef:GR32_TC */, def $rsi, 2818058 /* regdef:GR32_TC */, def dead $rdi, 2147549193 /* reguse tiedto:$1 */, killed $rdi(tied-def 5), 2147483657 /* reguse tiedto:$0 */, killed $rsi(tied-def 3), 12 /* clobber */, implicit-def dead early-clobber $eflags - INLINEASM &foo, 0, 2818058, def $rsi, 2818058, def dead $rdi, 2147549193, killed $rdi(tied-def 5), 2147483657, killed $rsi(tied-def 3), 12, implicit-def dead early-clobber $eflags + ; CHECK: INLINEASM &foo, 0 /* attdialect */, 4325386 /* regdef:GR64 */, def $rsi, 4325386 /* regdef:GR64 */, def dead $rdi, 2147549193 /* reguse tiedto:$1 */, killed $rdi(tied-def 5), 2147483657 /* reguse tiedto:$0 */, killed $rsi(tied-def 3), 12 /* clobber */, implicit-def dead early-clobber $eflags + INLINEASM &foo, 0, 4325386, def $rsi, 4325386, def dead $rdi, 2147549193, killed $rdi(tied-def 5), 2147483657, killed $rsi(tied-def 3), 12, implicit-def dead early-clobber $eflags $rax = MOV64rr killed $rsi RETQ killed $rax ... diff --git a/llvm/test/CodeGen/X86/stack-folding-adx.mir b/llvm/test/CodeGen/X86/stack-folding-adx.mir index 902d4b84e0c0d..10bfd48a9a1cf 100644 --- a/llvm/test/CodeGen/X86/stack-folding-adx.mir +++ b/llvm/test/CodeGen/X86/stack-folding-adx.mir @@ -4,45 +4,46 @@ --- | ; Function Attrs: nounwind define i8 @stack_fold_adcx32(i8 %a0, i32 %a1, i32 %a2, i8* %a3) #0 { - %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() - %2 = call { i8, i32 } @llvm.x86.addcarry.32(i8 %a0, i32 %a1, i32 %a2) - %3 = extractvalue { i8, i32 } %2, 1 - %4 = bitcast i8* %a3 to i32* - store i32 %3, i32* %4, align 1 - %5 = extractvalue { i8, i32 } %2, 0 - ret i8 %5 + tail call void asm sideeffect "nop", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() + %1 = call { i8, i32 } @llvm.x86.addcarry.32(i8 %a0, i32 %a1, i32 %a2) + %2 = extractvalue { i8, i32 } %1, 1 + %3 = bitcast i8* %a3 to i32* + store i32 %2, i32* %3, align 1 + %4 = extractvalue { i8, i32 } %1, 0 + ret i8 %4 } ; Function Attrs: nounwind define i8 @stack_fold_adcx64(i8 %a0, i64 %a1, i64 %a2, i8* %a3) #0 { - %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() - %2 = call { i8, i64 } @llvm.x86.addcarry.64(i8 %a0, i64 %a1, i64 %a2) - %3 = extractvalue { i8, i64 } %2, 1 - %4 = bitcast i8* %a3 to i64* - store i64 %3, i64* %4, align 1 - %5 = extractvalue { i8, i64 } %2, 0 - ret i8 %5 + tail call void asm sideeffect "nop", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() + %1 = call { i8, i64 } @llvm.x86.addcarry.64(i8 %a0, i64 %a1, i64 %a2) + %2 = extractvalue { i8, i64 } %1, 1 + %3 = bitcast i8* %a3 to i64* + store i64 %2, i64* %3, align 1 + %4 = extractvalue { i8, i64 } %1, 0 + ret i8 %4 } + ; Function Attrs: nounwind define i8 @stack_fold_adox32(i8 %a0, i32 %a1, i32 %a2, i8* %a3) #0 { - %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() - %2 = call { i8, i32 } @llvm.x86.addcarry.32(i8 %a0, i32 %a1, i32 %a2) - %3 = extractvalue { i8, i32 } %2, 1 - %4 = bitcast i8* %a3 to i32* - store i32 %3, i32* %4, align 1 - %5 = extractvalue { i8, i32 } %2, 0 - ret i8 %5 + tail call void asm sideeffect "nop", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() + %1 = call { i8, i32 } @llvm.x86.addcarry.32(i8 %a0, i32 %a1, i32 %a2) + %2 = extractvalue { i8, i32 } %1, 1 + %3 = bitcast i8* %a3 to i32* + store i32 %2, i32* %3, align 1 + %4 = extractvalue { i8, i32 } %1, 0 + ret i8 %4 } ; Function Attrs: nounwind define i8 @stack_fold_adox64(i8 %a0, i64 %a1, i64 %a2, i8* %a3) #0 { - %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() - %2 = call { i8, i64 } @llvm.x86.addcarry.64(i8 %a0, i64 %a1, i64 %a2) - %3 = extractvalue { i8, i64 } %2, 1 - %4 = bitcast i8* %a3 to i64* - store i64 %3, i64* %4, align 1 - %5 = extractvalue { i8, i64 } %2, 0 - ret i8 %5 + tail call void asm sideeffect "nop", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() + %1 = call { i8, i64 } @llvm.x86.addcarry.64(i8 %a0, i64 %a1, i64 %a2) + %2 = extractvalue { i8, i64 } %1, 1 + %3 = bitcast i8* %a3 to i64* + store i64 %2, i64* %3, align 1 + %4 = extractvalue { i8, i64 } %1, 0 + ret i8 %4 } ; Function Attrs: nounwind readnone @@ -68,11 +69,10 @@ registers: - { id: 1, class: gr32 } - { id: 2, class: gr32 } - { id: 3, class: gr64 } - - { id: 4, class: fr64 } + - { id: 4, class: gr8 } - { id: 5, class: gr8 } - - { id: 6, class: gr8 } - - { id: 7, class: gr32 } - - { id: 8, class: gr8 } + - { id: 6, class: gr32 } + - { id: 7, class: gr8 } liveins: - { reg: '$edi', virtual-reg: '%0' } - { reg: '$esi', virtual-reg: '%1' } @@ -88,26 +88,26 @@ body: | ; CHECK: MOV32mr %stack.1, 1, $noreg, 0, $noreg, $edx :: (store 4 into %stack.1) ; CHECK: MOV32mr %stack.2, 1, $noreg, 0, $noreg, $esi :: (store 4 into %stack.2) ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 3145738 /* regdef:GR32_CB */, def dead %4, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, -1, implicit-def $eflags ; CHECK: [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm %stack.2, 1, $noreg, 0, $noreg :: (load 4 from %stack.2) ; CHECK: [[ADCX32rm:%[0-9]+]]:gr32 = ADCX32rm [[ADCX32rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 4 from %stack.1) ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 2, implicit killed $eflags ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) - ; CHECK: MOV32mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADCX32rm]] :: (store 4 into %ir.4, align 1) + ; CHECK: MOV32mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADCX32rm]] :: (store 4 into %ir.3, align 1) ; CHECK: $al = COPY [[SETCCr]] ; CHECK: RET 0, $al %3:gr64 = COPY $rcx %2:gr32 = COPY $edx - %7:gr32 = COPY $esi + %6:gr32 = COPY $esi %0:gr32 = COPY $edi - INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, -1, implicit-def $eflags - %7:gr32 = ADCX32rr %7, %2, implicit-def $eflags, implicit killed $eflags - %8:gr8 = SETCCr 2, implicit killed $eflags - MOV32mr %3, 1, $noreg, 0, $noreg, %7 :: (store 4 into %ir.4, align 1) - $al = COPY %8 + %6:gr32 = ADCX32rr %6, %2, implicit-def $eflags, implicit killed $eflags + %7:gr8 = SETCCr 2, implicit killed $eflags + MOV32mr %3, 1, $noreg, 0, $noreg, %6 :: (store 4 into %ir.3, align 1) + $al = COPY %7 RET 0, killed $al ... @@ -120,11 +120,10 @@ registers: - { id: 1, class: gr64 } - { id: 2, class: gr64 } - { id: 3, class: gr64 } - - { id: 4, class: fr64 } + - { id: 4, class: gr8 } - { id: 5, class: gr8 } - - { id: 6, class: gr8 } - - { id: 7, class: gr64 } - - { id: 8, class: gr8 } + - { id: 6, class: gr64 } + - { id: 7, class: gr8 } liveins: - { reg: '$edi', virtual-reg: '%0' } - { reg: '$rsi', virtual-reg: '%1' } @@ -140,26 +139,26 @@ body: | ; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, $rdx :: (store 8 into %stack.1) ; CHECK: MOV64mr %stack.2, 1, $noreg, 0, $noreg, $rsi :: (store 8 into %stack.2) ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 3145738 /* regdef:GR32_CB */, def dead %4, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, -1, implicit-def $eflags ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.2, 1, $noreg, 0, $noreg :: (load 8 from %stack.2) ; CHECK: [[ADCX64rm:%[0-9]+]]:gr64 = ADCX64rm [[ADCX64rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 8 from %stack.1) ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 2, implicit killed $eflags ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) - ; CHECK: MOV64mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADCX64rm]] :: (store 8 into %ir.4, align 1) + ; CHECK: MOV64mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADCX64rm]] :: (store 8 into %ir.3, align 1) ; CHECK: $al = COPY [[SETCCr]] ; CHECK: RET 0, $al %3:gr64 = COPY $rcx %2:gr64 = COPY $rdx - %7:gr64 = COPY $rsi + %6:gr64 = COPY $rsi %0:gr32 = COPY $edi - INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, -1, implicit-def $eflags - %7:gr64 = ADCX64rr %7, %2, implicit-def $eflags, implicit killed $eflags - %8:gr8 = SETCCr 2, implicit killed $eflags - MOV64mr %3, 1, $noreg, 0, $noreg, %7 :: (store 8 into %ir.4, align 1) - $al = COPY %8 + %6:gr64 = ADCX64rr %6, %2, implicit-def $eflags, implicit killed $eflags + %7:gr8 = SETCCr 2, implicit killed $eflags + MOV64mr %3, 1, $noreg, 0, $noreg, %6 :: (store 8 into %ir.3, align 1) + $al = COPY %7 RET 0, killed $al ... @@ -172,11 +171,10 @@ registers: - { id: 1, class: gr32 } - { id: 2, class: gr32 } - { id: 3, class: gr64 } - - { id: 4, class: fr64 } + - { id: 4, class: gr8 } - { id: 5, class: gr8 } - - { id: 6, class: gr8 } - - { id: 7, class: gr32 } - - { id: 8, class: gr8 } + - { id: 6, class: gr32 } + - { id: 7, class: gr8 } liveins: - { reg: '$edi', virtual-reg: '%0' } - { reg: '$esi', virtual-reg: '%1' } @@ -192,26 +190,26 @@ body: | ; CHECK: MOV32mr %stack.1, 1, $noreg, 0, $noreg, $edx :: (store 4 into %stack.1) ; CHECK: MOV32mr %stack.2, 1, $noreg, 0, $noreg, $esi :: (store 4 into %stack.2) ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 3145738 /* regdef:GR32_CB */, def dead %4, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) - ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, 127, implicit-def $eflags + ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, -1, implicit-def $eflags ; CHECK: [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm %stack.2, 1, $noreg, 0, $noreg :: (load 4 from %stack.2) ; CHECK: [[ADOX32rm:%[0-9]+]]:gr32 = ADOX32rm [[ADOX32rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 4 from %stack.1) - ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 0, implicit killed $eflags + ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 2, implicit killed $eflags ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) - ; CHECK: MOV32mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADOX32rm]] :: (store 4 into %ir.4, align 1) + ; CHECK: MOV32mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADOX32rm]] :: (store 4 into %ir.3, align 1) ; CHECK: $al = COPY [[SETCCr]] ; CHECK: RET 0, $al %3:gr64 = COPY $rcx %2:gr32 = COPY $edx - %7:gr32 = COPY $esi + %6:gr32 = COPY $esi %0:gr32 = COPY $edi - INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 - dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, 127, implicit-def $eflags - %7:gr32 = ADOX32rr %7, %2, implicit-def $eflags, implicit killed $eflags - %8:gr8 = SETCCr 0, implicit killed $eflags - MOV32mr %3, 1, $noreg, 0, $noreg, %7 :: (store 4 into %ir.4, align 1) - $al = COPY %8 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, -1, implicit-def $eflags + %6:gr32 = ADOX32rr %6, %2, implicit-def $eflags, implicit killed $eflags + %7:gr8 = SETCCr 2, implicit killed $eflags + MOV32mr %3, 1, $noreg, 0, $noreg, %6 :: (store 4 into %ir.3, align 1) + $al = COPY %7 RET 0, killed $al ... @@ -224,11 +222,10 @@ registers: - { id: 1, class: gr64 } - { id: 2, class: gr64 } - { id: 3, class: gr64 } - - { id: 4, class: fr64 } + - { id: 4, class: gr8 } - { id: 5, class: gr8 } - - { id: 6, class: gr8 } - - { id: 7, class: gr64 } - - { id: 8, class: gr8 } + - { id: 6, class: gr64 } + - { id: 7, class: gr8 } liveins: - { reg: '$edi', virtual-reg: '%0' } - { reg: '$rsi', virtual-reg: '%1' } @@ -244,26 +241,26 @@ body: | ; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, $rdx :: (store 8 into %stack.1) ; CHECK: MOV64mr %stack.2, 1, $noreg, 0, $noreg, $rsi :: (store 8 into %stack.2) ; CHECK: MOV32mr %stack.3, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.3) - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 3145738 /* regdef:GR32_CB */, def dead %4, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 ; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.3, 1, $noreg, 0, $noreg :: (load 4 from %stack.3) - ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, 127, implicit-def $eflags + ; CHECK: dead [[MOV32rm]].sub_8bit:gr32 = ADD8ri [[MOV32rm]].sub_8bit, -1, implicit-def $eflags ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.2, 1, $noreg, 0, $noreg :: (load 8 from %stack.2) ; CHECK: [[ADOX64rm:%[0-9]+]]:gr64 = ADOX64rm [[ADOX64rm]], %stack.1, 1, $noreg, 0, $noreg, implicit-def $eflags, implicit killed $eflags :: (load 8 from %stack.1) - ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 0, implicit killed $eflags + ; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 2, implicit killed $eflags ; CHECK: [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0) - ; CHECK: MOV64mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADOX64rm]] :: (store 8 into %ir.4, align 1) + ; CHECK: MOV64mr [[MOV64rm]], 1, $noreg, 0, $noreg, [[ADOX64rm]] :: (store 8 into %ir.3, align 1) ; CHECK: $al = COPY [[SETCCr]] ; CHECK: RET 0, $al %3:gr64 = COPY $rcx %2:gr64 = COPY $rdx - %7:gr64 = COPY $rsi + %6:gr64 = COPY $rsi %0:gr32 = COPY $edi - INLINEASM &nop, 1, 3145738, def dead %4, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 - dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, 127, implicit-def $eflags - %7:gr64 = ADOX64rr %7, %2, implicit-def $eflags, implicit killed $eflags - %8:gr8 = SETCCr 0, implicit killed $eflags - MOV64mr %3, 1, $noreg, 0, $noreg, %7 :: (store 8 into %ir.4, align 1) - $al = COPY %8 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + dead %0.sub_8bit:gr32 = ADD8ri %0.sub_8bit, -1, implicit-def $eflags + %6:gr64 = ADOX64rr %6, %2, implicit-def $eflags, implicit killed $eflags + %7:gr8 = SETCCr 2, implicit killed $eflags + MOV64mr %3, 1, $noreg, 0, $noreg, %6 :: (store 8 into %ir.3, align 1) + $al = COPY %7 RET 0, killed $al ... diff --git a/llvm/test/CodeGen/X86/stack-folding-bmi2.mir b/llvm/test/CodeGen/X86/stack-folding-bmi2.mir index 8f8d074eb1b7b..dbbb93ee1a610 100644 --- a/llvm/test/CodeGen/X86/stack-folding-bmi2.mir +++ b/llvm/test/CodeGen/X86/stack-folding-bmi2.mir @@ -4,24 +4,24 @@ --- | ; Function Attrs: nounwind define i32 @stack_fold_mulx_u32(i32 %a0, i32 %a1) #0 { - %1 = tail call i32 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() - %2 = zext i32 %a0 to i128 - %3 = zext i32 %a1 to i128 - %4 = mul i128 %2, %3 - %5 = lshr i128 %4, 32 - %6 = trunc i128 %5 to i32 - ret i32 %6 + tail call void asm sideeffect "nop", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() + %1 = zext i32 %a0 to i128 + %2 = zext i32 %a1 to i128 + %3 = mul i128 %1, %2 + %4 = lshr i128 %3, 32 + %5 = trunc i128 %4 to i32 + ret i32 %5 } ; Function Attrs: nounwind define i64 @stack_fold_mulx_u64(i64 %a0, i64 %a1) #0 { - %1 = tail call i64 asm sideeffect "nop", "=x,~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() - %2 = zext i64 %a0 to i128 - %3 = zext i64 %a1 to i128 - %4 = mul i128 %2, %3 - %5 = lshr i128 %4, 64 - %6 = trunc i128 %5 to i64 - ret i64 %6 + tail call void asm sideeffect "nop", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() + %1 = zext i64 %a0 to i128 + %2 = zext i64 %a1 to i128 + %3 = mul i128 %1, %2 + %4 = lshr i128 %3, 64 + %5 = trunc i128 %4 to i64 + ret i64 %5 } ; Function Attrs: nounwind @@ -52,14 +52,14 @@ body: | ; CHECK: liveins: $edi, $esi ; CHECK: MOV32mr %stack.0, 1, $noreg, 0, $noreg, $esi :: (store 4 into %stack.0) ; CHECK: MOV32mr %stack.1, 1, $noreg, 0, $noreg, $edi :: (store 4 into %stack.1) - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 4063242 /* regdef:LOW32_ADDR_ACCESS_RBP_with_sub_8bit_with_sub_32bit */, def dead %2, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 ; CHECK: $edx = MOV32rm %stack.1, 1, $noreg, 0, $noreg :: (load 4 from %stack.1) ; CHECK: %3:gr32, dead %4:gr32 = MULX32rm %stack.0, 1, $noreg, 0, $noreg, implicit $edx :: (load 4 from %stack.0) ; CHECK: $eax = COPY %3 ; CHECK: RET 0, $eax %1:gr32 = COPY $esi %0:gr32 = COPY $edi - INLINEASM &nop, 1, 4063242, def dead %2, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 $edx = COPY %0 %3:gr32, dead %4:gr32 = MULX32rr %1, implicit killed $edx $eax = COPY %3 @@ -87,14 +87,14 @@ body: | ; CHECK: liveins: $rdi, $rsi ; CHECK: MOV64mr %stack.0, 1, $noreg, 0, $noreg, $rsi :: (store 8 into %stack.0) ; CHECK: MOV64mr %stack.1, 1, $noreg, 0, $noreg, $rdi :: (store 8 into %stack.1) - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 4063242 /* regdef:LOW32_ADDR_ACCESS_RBP_with_sub_8bit_with_sub_32bit */, def dead %2, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 ; CHECK: $rdx = MOV64rm %stack.1, 1, $noreg, 0, $noreg :: (load 8 from %stack.1) ; CHECK: %3:gr64, dead %4:gr64 = MULX64rm %stack.0, 1, $noreg, 0, $noreg, implicit $rdx :: (load 8 from %stack.0) ; CHECK: $rax = COPY %3 ; CHECK: RET 0, $rax %1:gr64 = COPY $rsi %0:gr64 = COPY $rdi - INLINEASM &nop, 1, 4063242, def dead %2, 12, implicit-def dead early-clobber $rax, 12, implicit-def dead early-clobber $rbx, 12, implicit-def dead early-clobber $rcx, 12, implicit-def dead early-clobber $rdx, 12, implicit-def dead early-clobber $rsi, 12, implicit-def dead early-clobber $rdi, 12, implicit-def dead early-clobber $rbp, 12, implicit-def dead early-clobber $r8, 12, implicit-def dead early-clobber $r9, 12, implicit-def dead early-clobber $r10, 12, implicit-def dead early-clobber $r11, 12, implicit-def dead early-clobber $r12, 12, implicit-def dead early-clobber $r13, 12, implicit-def dead early-clobber $r14, 12, implicit-def dead early-clobber $r15 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $rax, 12 /* clobber */, implicit-def dead early-clobber $rbx, 12 /* clobber */, implicit-def dead early-clobber $rcx, 12 /* clobber */, implicit-def dead early-clobber $rdx, 12 /* clobber */, implicit-def dead early-clobber $rsi, 12 /* clobber */, implicit-def dead early-clobber $rdi, 12 /* clobber */, implicit-def dead early-clobber $rbp, 12 /* clobber */, implicit-def dead early-clobber $r8, 12 /* clobber */, implicit-def dead early-clobber $r9, 12 /* clobber */, implicit-def dead early-clobber $r10, 12 /* clobber */, implicit-def dead early-clobber $r11, 12 /* clobber */, implicit-def dead early-clobber $r12, 12 /* clobber */, implicit-def dead early-clobber $r13, 12 /* clobber */, implicit-def dead early-clobber $r14, 12 /* clobber */, implicit-def dead early-clobber $r15 $rdx = COPY %0 %3:gr64, dead %4:gr64 = MULX64rr %1, implicit killed $rdx $rax = COPY %3 diff --git a/llvm/test/CodeGen/X86/stack-folding-fp-nofpexcept.mir b/llvm/test/CodeGen/X86/stack-folding-fp-nofpexcept.mir index f3f945a8e54fe..96cd0aa516e2e 100644 --- a/llvm/test/CodeGen/X86/stack-folding-fp-nofpexcept.mir +++ b/llvm/test/CodeGen/X86/stack-folding-fp-nofpexcept.mir @@ -5,9 +5,9 @@ source_filename = "test.ll" target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" define <2 x double> @stack_fold_addpd(<2 x double> %a0, <2 x double> %a1) { - %1 = tail call <2 x i64> asm sideeffect "nop", "=x,~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{flags}"() - %2 = fadd <2 x double> %a0, %a1 - ret <2 x double> %2 + tail call void asm sideeffect "nop", "~{xmm1},~{xmm2},~{xmm3},~{xmm4},~{xmm5},~{xmm6},~{xmm7},~{xmm8},~{xmm9},~{xmm10},~{xmm11},~{xmm12},~{xmm13},~{xmm14},~{xmm15},~{flags}"() + %1 = fadd <2 x double> %a0, %a1 + ret <2 x double> %1 } ; Function Attrs: nounwind declare void @llvm.stackprotector(i8*, i8**) #0 @@ -23,7 +23,6 @@ registers: - { id: 0, class: vr128 } - { id: 1, class: vr128 } - { id: 2, class: vr128 } - - { id: 3, class: vr128 } liveins: - { reg: '$xmm0', virtual-reg: '%0' } - { reg: '$xmm1', virtual-reg: '%1' } @@ -38,15 +37,15 @@ body: | ; CHECK: liveins: $xmm0, $xmm1 ; CHECK: MOVAPSmr %stack.0, 1, $noreg, 0, $noreg, $xmm1 :: (store 16 into %stack.0) ; CHECK: [[COPY:%[0-9]+]]:vr128 = COPY $xmm0 - ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 7405578 /* regdef:VR128 */, def dead %2, 12 /* clobber */, implicit-def dead early-clobber $xmm2, 12 /* clobber */, implicit-def dead early-clobber $xmm3, 12 /* clobber */, implicit-def dead early-clobber $xmm4, 12 /* clobber */, implicit-def dead early-clobber $xmm5, 12 /* clobber */, implicit-def dead early-clobber $xmm6, 12 /* clobber */, implicit-def dead early-clobber $xmm7, 12 /* clobber */, implicit-def dead early-clobber $xmm8, 12 /* clobber */, implicit-def dead early-clobber $xmm9, 12 /* clobber */, implicit-def dead early-clobber $xmm10, 12 /* clobber */, implicit-def dead early-clobber $xmm11, 12 /* clobber */, implicit-def dead early-clobber $xmm12, 12 /* clobber */, implicit-def dead early-clobber $xmm13, 12 /* clobber */, implicit-def dead early-clobber $xmm14, 12 /* clobber */, implicit-def dead early-clobber $xmm15, 12 /* clobber */, implicit-def dead early-clobber $eflags + ; CHECK: INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $xmm1, 12 /* clobber */, implicit-def dead early-clobber $xmm2, 12 /* clobber */, implicit-def dead early-clobber $xmm3, 12 /* clobber */, implicit-def dead early-clobber $xmm4, 12 /* clobber */, implicit-def dead early-clobber $xmm5, 12 /* clobber */, implicit-def dead early-clobber $xmm6, 12 /* clobber */, implicit-def dead early-clobber $xmm7, 12 /* clobber */, implicit-def dead early-clobber $xmm8, 12 /* clobber */, implicit-def dead early-clobber $xmm9, 12 /* clobber */, implicit-def dead early-clobber $xmm10, 12 /* clobber */, implicit-def dead early-clobber $xmm11, 12 /* clobber */, implicit-def dead early-clobber $xmm12, 12 /* clobber */, implicit-def dead early-clobber $xmm13, 12 /* clobber */, implicit-def dead early-clobber $xmm14, 12 /* clobber */, implicit-def dead early-clobber $xmm15, 12 /* clobber */, implicit-def dead early-clobber $eflags ; CHECK: [[COPY]]:vr128 = nofpexcept ADDPDrm [[COPY]], %stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 16 from %stack.0) ; CHECK: $xmm0 = COPY [[COPY]] ; CHECK: RET 0, $xmm0 %1:vr128 = COPY $xmm1 - %3:vr128 = COPY $xmm0 - INLINEASM &nop, 1, 7405578, def dead %2, 12, implicit-def dead early-clobber $xmm2, 12, implicit-def dead early-clobber $xmm3, 12, implicit-def dead early-clobber $xmm4, 12, implicit-def dead early-clobber $xmm5, 12, implicit-def dead early-clobber $xmm6, 12, implicit-def dead early-clobber $xmm7, 12, implicit-def dead early-clobber $xmm8, 12, implicit-def dead early-clobber $xmm9, 12, implicit-def dead early-clobber $xmm10, 12, implicit-def dead early-clobber $xmm11, 12, implicit-def dead early-clobber $xmm12, 12, implicit-def dead early-clobber $xmm13, 12, implicit-def dead early-clobber $xmm14, 12, implicit-def dead early-clobber $xmm15, 12, implicit-def dead early-clobber $eflags - %3:vr128 = nofpexcept ADDPDrr %3, %1, implicit $mxcsr - $xmm0 = COPY %3 + %2:vr128 = COPY $xmm0 + INLINEASM &nop, 1 /* sideeffect attdialect */, 12 /* clobber */, implicit-def dead early-clobber $xmm1, 12 /* clobber */, implicit-def dead early-clobber $xmm2, 12 /* clobber */, implicit-def dead early-clobber $xmm3, 12 /* clobber */, implicit-def dead early-clobber $xmm4, 12 /* clobber */, implicit-def dead early-clobber $xmm5, 12 /* clobber */, implicit-def dead early-clobber $xmm6, 12 /* clobber */, implicit-def dead early-clobber $xmm7, 12 /* clobber */, implicit-def dead early-clobber $xmm8, 12 /* clobber */, implicit-def dead early-clobber $xmm9, 12 /* clobber */, implicit-def dead early-clobber $xmm10, 12 /* clobber */, implicit-def dead early-clobber $xmm11, 12 /* clobber */, implicit-def dead early-clobber $xmm12, 12 /* clobber */, implicit-def dead early-clobber $xmm13, 12 /* clobber */, implicit-def dead early-clobber $xmm14, 12 /* clobber */, implicit-def dead early-clobber $xmm15, 12 /* clobber */, implicit-def dead early-clobber $eflags + %2:vr128 = nofpexcept ADDPDrr %2, %1, implicit $mxcsr + $xmm0 = COPY %2 RET 0, $xmm0 ... From fb42d3afad1d9f09bcb90680baa77a39ecb99140 Mon Sep 17 00:00:00 2001 From: Brad Moody Date: Sat, 18 Apr 2020 00:09:30 -0500 Subject: [PATCH 22/56] [ADT] Fix bug in BitVector and SmallBitVector DenseMap hashing. BitVectors and SmallBitVectors with equal contents but different capacities were getting different hashes. Reviewed By: aganea Differential Revision: https://reviews.llvm.org/D77038 --- llvm/include/llvm/ADT/BitVector.h | 4 +++- llvm/include/llvm/ADT/SmallBitVector.h | 10 ++++++--- llvm/unittests/ADT/BitVectorTest.cpp | 30 ++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/ADT/BitVector.h b/llvm/include/llvm/ADT/BitVector.h index 89158f213110d..a8d0f07af94a2 100644 --- a/llvm/include/llvm/ADT/BitVector.h +++ b/llvm/include/llvm/ADT/BitVector.h @@ -759,7 +759,9 @@ class BitVector { } bool isInvalid() const { return Size == (unsigned)-1; } - ArrayRef getData() const { return Bits; } + ArrayRef getData() const { + return Bits.take_front(NumBitWords(size())); + } //===--------------------------------------------------------------------===// // Portable bit mask operations. diff --git a/llvm/include/llvm/ADT/SmallBitVector.h b/llvm/include/llvm/ADT/SmallBitVector.h index b7367d68bdae8..14545e2b612d7 100644 --- a/llvm/include/llvm/ADT/SmallBitVector.h +++ b/llvm/include/llvm/ADT/SmallBitVector.h @@ -668,8 +668,11 @@ class SmallBitVector { } bool isInvalid() const { return X == (uintptr_t)-1; } - ArrayRef getData() const { - return isSmall() ? makeArrayRef(X) : getPointer()->getData(); + ArrayRef getData(uintptr_t &Store) const { + if (!isSmall()) + return getPointer()->getData(); + Store = getSmallBits(); + return makeArrayRef(Store); } private: @@ -717,8 +720,9 @@ template <> struct DenseMapInfo { return V; } static unsigned getHashValue(const SmallBitVector &V) { + uintptr_t Store; return DenseMapInfo>>::getHashValue( - std::make_pair(V.size(), V.getData())); + std::make_pair(V.size(), V.getData(Store))); } static bool isEqual(const SmallBitVector &LHS, const SmallBitVector &RHS) { if (LHS.isInvalid() || RHS.isInvalid()) diff --git a/llvm/unittests/ADT/BitVectorTest.cpp b/llvm/unittests/ADT/BitVectorTest.cpp index 7c9417966b163..efefd2b90be8c 100644 --- a/llvm/unittests/ADT/BitVectorTest.cpp +++ b/llvm/unittests/ADT/BitVectorTest.cpp @@ -1204,4 +1204,34 @@ TYPED_TEST(BitVectorTest, DenseSet) { EXPECT_EQ(true, Set.erase(A)); EXPECT_EQ(0U, Set.size()); } + +/// Test that capacity doesn't affect hashing. +TYPED_TEST(BitVectorTest, DenseMapHashing) { + using DMI = DenseMapInfo; + { + TypeParam A; + A.resize(200); + A.set(100); + + TypeParam B; + B.resize(200); + B.set(100); + B.reserve(1000); + + EXPECT_EQ(DMI::getHashValue(A), DMI::getHashValue(B)); + } + { + TypeParam A; + A.resize(20); + A.set(10); + + TypeParam B; + B.resize(20); + B.set(10); + B.reserve(1000); + + EXPECT_EQ(DMI::getHashValue(A), DMI::getHashValue(B)); + } +} + } // namespace From 8d5024f7fe721513c4332048e6836cd408581a61 Mon Sep 17 00:00:00 2001 From: Andrew Litteken Date: Thu, 9 Apr 2020 18:06:38 -0700 Subject: [PATCH 23/56] fix to outline cfi instruction when can be grouped in a tail call [MachineOutliner] fix test for excluding CFI and add test to include CFI in outlining New test to check that we only outline CFI instruction if all CFI Instructions in the function would be captured by the outlining adding x86 tests analagous to AARCH64 cfi tests Revision: https://reviews.llvm.org/D77852 --- llvm/lib/CodeGen/MachineOutliner.cpp | 9 +- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 45 ++++++++-- llvm/lib/Target/X86/X86InstrInfo.cpp | 32 +++++++ .../machine-outliner-cfi-tail-some.mir | 84 +++++++++++++++++ .../AArch64/machine-outliner-cfi-tail.mir | 69 ++++++++++++++ .../CodeGen/AArch64/machine-outliner-cfi.mir | 36 ++++++-- .../AArch64/machine-outliner-remarks.ll | 6 +- .../X86/machine-outliner-cfi-tail-some.mir | 90 +++++++++++++++++++ .../CodeGen/X86/machine-outliner-cfi-tail.mir | 77 ++++++++++++++++ 9 files changed, 433 insertions(+), 15 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail-some.mir create mode 100644 llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail.mir create mode 100644 llvm/test/CodeGen/X86/machine-outliner-cfi-tail-some.mir create mode 100644 llvm/test/CodeGen/X86/machine-outliner-cfi-tail.mir diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp index d63f194f7e662..bd30bd41f07cd 100644 --- a/llvm/lib/CodeGen/MachineOutliner.cpp +++ b/llvm/lib/CodeGen/MachineOutliner.cpp @@ -1160,9 +1160,17 @@ MachineFunction *MachineOutliner::createOutlinedFunction( // Insert the new function into the module. MF.insert(MF.begin(), &MBB); + MachineFunction *OriginalMF = FirstCand.front()->getMF(); + const std::vector &Instrs = + OriginalMF->getFrameInstructions(); for (auto I = FirstCand.front(), E = std::next(FirstCand.back()); I != E; ++I) { MachineInstr *NewMI = MF.CloneMachineInstr(&*I); + if (I->isCFIInstruction()) { + unsigned CFIIndex = NewMI->getOperand(0).getCFIIndex(); + MCCFIInstruction CFI = Instrs[CFIIndex]; + (void)MF.addFrameInst(CFI); + } NewMI->dropMemRefs(MF); // Don't keep debug information for outlined instructions. @@ -1331,7 +1339,6 @@ bool MachineOutliner::outline(Module &M, } LLVM_DEBUG(dbgs() << "OutlinedSomething = " << OutlinedSomething << "\n";); - return OutlinedSomething; } diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 6ae21d5ef343f..fffb436ab583f 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -24,9 +24,9 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" @@ -5862,6 +5862,35 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo( return C.getMF()->getFunction().hasFnAttribute("branch-target-enforcement"); }); + // We check to see if CFI Instructions are present, and if they are + // we find the number of CFI Instructions in the candidates. + unsigned CFICount = 0; + MachineBasicBlock::iterator MBBI = RepeatedSequenceLocs[0].front(); + for (unsigned Loc = RepeatedSequenceLocs[0].getStartIdx(); + Loc < RepeatedSequenceLocs[0].getEndIdx() + 1; Loc++) { + const std::vector &CFIInstructions = + RepeatedSequenceLocs[0].getMF()->getFrameInstructions(); + if (MBBI->isCFIInstruction()) { + unsigned CFIIndex = MBBI->getOperand(0).getCFIIndex(); + MCCFIInstruction CFI = CFIInstructions[CFIIndex]; + CFICount++; + } + MBBI++; + } + + // We compare the number of found CFI Instructions to the number of CFI + // instructions in the parent function for each candidate. We must check this + // since if we outline one of the CFI instructions in a function, we have to + // outline them all for correctness. If we do not, the address offsets will be + // incorrect between the two sections of the program. + for (outliner::Candidate &C : RepeatedSequenceLocs) { + std::vector CFIInstructions = + C.getMF()->getFrameInstructions(); + + if (CFICount > 0 && CFICount != CFIInstructions.size()) + return outliner::OutlinedFunction(); + } + // Returns true if an instructions is safe to fix up, false otherwise. auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) { if (MI.isCall()) @@ -6037,6 +6066,11 @@ outliner::OutlinedFunction AArch64InstrInfo::getOutliningCandidateInfo( } } + // If we have CFI instructions, we can only outline if the outlined section + // can be a tail call + if (FrameID != MachineOutlinerTailCall && CFICount > 0) + return outliner::OutlinedFunction(); + return outliner::OutlinedFunction(RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID); } @@ -6159,12 +6193,13 @@ AArch64InstrInfo::getOutliningType(MachineBasicBlock::iterator &MIT, return outliner::InstrType::Illegal; // We can only outline these if we will tail call the outlined function, or - // fix up the CFI offsets. For the sake of safety, don't outline CFI - // instructions. + // fix up the CFI offsets. Currently, CFI instructions are outlined only if + // in a tail call. // - // FIXME: If the proper fixups are implemented, this should be possible. + // FIXME: If the proper fixups for the offset are implemented, this should be + // possible. if (MI.isCFIInstruction()) - return outliner::InstrType::Illegal; + return outliner::InstrType::Legal; // Don't allow debug values to impact outlining type. if (MI.isDebugInstr() || MI.isIndirectDebugValue()) diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 0197630a2670e..6270d70b84fb5 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -8682,6 +8682,35 @@ outliner::OutlinedFunction X86InstrInfo::getOutliningCandidateInfo( return Sum + 1; }); + // We check to see if CFI Instructions are present, and if they are + // we find the number of CFI Instructions in the candidates. + unsigned CFICount = 0; + MachineBasicBlock::iterator MBBI = RepeatedSequenceLocs[0].front(); + for (unsigned Loc = RepeatedSequenceLocs[0].getStartIdx(); + Loc < RepeatedSequenceLocs[0].getEndIdx() + 1; Loc++) { + const std::vector &CFIInstructions = + RepeatedSequenceLocs[0].getMF()->getFrameInstructions(); + if (MBBI->isCFIInstruction()) { + unsigned CFIIndex = MBBI->getOperand(0).getCFIIndex(); + MCCFIInstruction CFI = CFIInstructions[CFIIndex]; + CFICount++; + } + MBBI++; + } + + // We compare the number of found CFI Instructions to the number of CFI + // instructions in the parent function for each candidate. We must check this + // since if we outline one of the CFI instructions in a function, we have to + // outline them all for correctness. If we do not, the address offsets will be + // incorrect between the two sections of the program. + for (outliner::Candidate &C : RepeatedSequenceLocs) { + std::vector CFIInstructions = + C.getMF()->getFrameInstructions(); + + if (CFICount > 0 && CFICount != CFIInstructions.size()) + return outliner::OutlinedFunction(); + } + // FIXME: Use real size in bytes for call and ret instructions. if (RepeatedSequenceLocs[0].back()->isTerminator()) { for (outliner::Candidate &C : RepeatedSequenceLocs) @@ -8693,6 +8722,9 @@ outliner::OutlinedFunction X86InstrInfo::getOutliningCandidateInfo( ); } + if (CFICount > 0) + return outliner::OutlinedFunction(); + for (outliner::Candidate &C : RepeatedSequenceLocs) C.setCallInfo(MachineOutlinerDefault, 1); diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail-some.mir b/llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail-some.mir new file mode 100644 index 0000000000000..67d411962ce4f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail-some.mir @@ -0,0 +1,84 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=aarch64-apple-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s + +# Outlining CFI instructions is unsafe if we cannot outline all of the CFI +# instructions from a function. This shows that we choose not to outline the +# CFI instructions since function foo has a CFI Instruction that would not +# be caught. + +--- | + define void @foo() #0 { ret void } + define void @bar() #0 { ret void } + define void @baz() #0 { ret void } + attributes #0 = { noredzone } +... +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + ; CHECK-LABEL: name: foo + ; CHECK: liveins: $lr + ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w28, 16 + ; CHECK: $w9 = ORRWri $wzr, 1 + ; CHECK: $w10 = ORRWri $wzr, 2 + ; CHECK: $w11 = ORRWri $wzr, 3 + ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + frame-setup CFI_INSTRUCTION def_cfa $w28, 16 + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w12 = ORRWri $wzr, 1 + $w13 = ORRWri $wzr, 2 + $w14 = ORRWri $wzr, 3 + $w15 = ORRWri $wzr, 4 + RET undef $lr +... +--- +name: bar +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + ; CHECK-LABEL: name: bar + ; CHECK: liveins: $lr + ; CHECK: $w9 = ORRWri $wzr, 1 + ; CHECK: $w10 = ORRWri $wzr, 2 + ; CHECK: $w11 = ORRWri $wzr, 3 + ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w12 = ORRWri $wzr, 1 + $w13 = ORRWri $wzr, 2 + $w14 = ORRWri $wzr, 3 + $w15 = ORRWri $wzr, 4 + RET undef $lr +... +--- +name: baz +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + ; CHECK-LABEL: name: baz + ; CHECK: liveins: $lr + ; CHECK: $w9 = ORRWri $wzr, 1 + ; CHECK: $w10 = ORRWri $wzr, 2 + ; CHECK: $w11 = ORRWri $wzr, 3 + ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w12 = ORRWri $wzr, 1 + $w13 = ORRWri $wzr, 2 + $w14 = ORRWri $wzr, 3 + $w15 = ORRWri $wzr, 4 + RET undef $lr diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail.mir b/llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail.mir new file mode 100644 index 0000000000000..c788cf5708402 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/machine-outliner-cfi-tail.mir @@ -0,0 +1,69 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=aarch64-apple-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s + +# Outlining CFI instructions is unsafe if it is not tail called, but otherwise, +# it requires fixups. Show that we include CFI instructions in tail call +# outlined sequences right now. + +--- | + define void @foo() #0 { ret void } + define void @bar() #0 { ret void } + define void @baz() #0 { ret void } + attributes #0 = { noredzone } +... +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + ; CHECK-LABEL: name: foo + ; CHECK: liveins: $lr + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w9, implicit-def $w10, implicit-def $w11, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w12 = ORRWri $wzr, 1 + $w13 = ORRWri $wzr, 2 + $w14 = ORRWri $wzr, 3 + $w15 = ORRWri $wzr, 4 + RET undef $lr +... +--- +name: bar +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + ; CHECK-LABEL: name: bar + ; CHECK: liveins: $lr + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w9, implicit-def $w10, implicit-def $w11, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w12 = ORRWri $wzr, 1 + $w13 = ORRWri $wzr, 2 + $w14 = ORRWri $wzr, 3 + $w15 = ORRWri $wzr, 4 + RET undef $lr +... +--- +name: baz +tracksRegLiveness: true +body: | + bb.0: + liveins: $lr + ; CHECK-LABEL: name: baz + ; CHECK: liveins: $lr + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w9, implicit-def $w10, implicit-def $w11, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 + frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w12 = ORRWri $wzr, 1 + $w13 = ORRWri $wzr, 2 + $w14 = ORRWri $wzr, 3 + $w15 = ORRWri $wzr, 4 + RET undef $lr diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-cfi.mir b/llvm/test/CodeGen/AArch64/machine-outliner-cfi.mir index 707785a566a21..5d98646f2c747 100644 --- a/llvm/test/CodeGen/AArch64/machine-outliner-cfi.mir +++ b/llvm/test/CodeGen/AArch64/machine-outliner-cfi.mir @@ -1,9 +1,9 @@ # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py # RUN: llc -mtriple=aarch64-apple-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s -# Outlining CFI instructions is unsafe. It is possible if the call is tail -# called, but otherwise, it requires fixups. Show that we don't include CFI -# instructions in outlined sequences right now. +# Outlining CFI instructions is unsafe if it is not tail called, but otherwise, +# it requires fixups. Show that we don't include CFI instructions in non +# tail call outlined sequences right now. --- | define void @foo() #0 { ret void } @@ -19,9 +19,17 @@ body: | liveins: $lr ; CHECK-LABEL: name: foo ; CHECK: liveins: $lr + ; CHECK: $w9 = ORRWri $wzr, 1 + ; CHECK: $w10 = ORRWri $wzr, 2 + ; CHECK: $w11 = ORRWri $wzr, 3 ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w29, 16 - ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15 + ; CHECK: $w20 = ORRWri $wzr, 1 + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w20 = ORRWri $wzr, 1 $w12 = ORRWri $wzr, 1 $w13 = ORRWri $wzr, 2 $w14 = ORRWri $wzr, 3 @@ -36,9 +44,17 @@ body: | liveins: $lr ; CHECK-LABEL: name: bar ; CHECK: liveins: $lr + ; CHECK: $w9 = ORRWri $wzr, 1 + ; CHECK: $w10 = ORRWri $wzr, 2 + ; CHECK: $w11 = ORRWri $wzr, 3 ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w29, 16 - ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15 + ; CHECK: $w21 = ORRWri $wzr, 1 + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w21 = ORRWri $wzr, 1 $w12 = ORRWri $wzr, 1 $w13 = ORRWri $wzr, 2 $w14 = ORRWri $wzr, 3 @@ -53,9 +69,17 @@ body: | liveins: $lr ; CHECK-LABEL: name: baz ; CHECK: liveins: $lr + ; CHECK: $w9 = ORRWri $wzr, 1 + ; CHECK: $w10 = ORRWri $wzr, 2 + ; CHECK: $w11 = ORRWri $wzr, 3 ; CHECK: frame-setup CFI_INSTRUCTION def_cfa $w29, 16 - ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15 + ; CHECK: $w22 = ORRWri $wzr, 1 + ; CHECK: TCRETURNdi @OUTLINED_FUNCTION_0, 0, implicit $sp, implicit-def $w12, implicit-def $w13, implicit-def $w14, implicit-def $w15, implicit $wzr, implicit $sp + $w9 = ORRWri $wzr, 1 + $w10 = ORRWri $wzr, 2 + $w11 = ORRWri $wzr, 3 frame-setup CFI_INSTRUCTION def_cfa $w29, 16 + $w22 = ORRWri $wzr, 1 $w12 = ORRWri $wzr, 1 $w13 = ORRWri $wzr, 2 $w14 = ORRWri $wzr, 3 diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll b/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll index ce768adbfeaf5..06bfe9fd31268 100644 --- a/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll +++ b/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll @@ -4,7 +4,7 @@ ; CHECK-SAME: Bytes from outlining all occurrences (16) >= ; CHECK-SAME: Unoutlined instruction bytes (16) ; CHECK-SAME: (Also found at: ) -; CHECK: remark: :0:0: Saved 36 bytes by outlining 11 instructions +; CHECK: remark: :0:0: Saved 40 bytes by outlining 13 instructions ; CHECK-SAME: from 2 locations. (Found at: , ; CHECK-SAME: ) ; RUN: llc %s -enable-machine-outliner -mtriple=aarch64-unknown-unknown -o /dev/null -pass-remarks-missed=machine-outliner -pass-remarks-output=%t.yaml @@ -38,10 +38,10 @@ ; YAML-NEXT: Function: OUTLINED_FUNCTION_0 ; YAML-NEXT: Args: ; YAML-NEXT: - String: 'Saved ' -; YAML-NEXT: - OutliningBenefit: '36' +; YAML-NEXT: - OutliningBenefit: '40' ; YAML-NEXT: - String: ' bytes by ' ; YAML-NEXT: - String: 'outlining ' -; YAML-NEXT: - Length: '11' +; YAML-NEXT: - Length: '13' ; YAML-NEXT: - String: ' instructions ' ; YAML-NEXT: - String: 'from ' ; YAML-NEXT: - NumOccurrences: '2' diff --git a/llvm/test/CodeGen/X86/machine-outliner-cfi-tail-some.mir b/llvm/test/CodeGen/X86/machine-outliner-cfi-tail-some.mir new file mode 100644 index 0000000000000..328ee19c71921 --- /dev/null +++ b/llvm/test/CodeGen/X86/machine-outliner-cfi-tail-some.mir @@ -0,0 +1,90 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=x86_64-apple-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s + +# Outlining CFI instructions is unsafe if we cannot outline all of the CFI +# instructions from a function. This shows that we choose not to outline the +# CFI instructions since function foo has a CFI Instruction that would not +# be caught. + +--- | + define void @foo() #0 { ret void } + define void @bar() #0 { ret void } + define void @baz() #0 { ret void } + attributes #0 = { noredzone } +... +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: foo + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rbp + ; CHECK: CALL64pcrel32 @OUTLINED_FUNCTION_1, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $ebx, implicit-def $ecx, implicit $rsp, implicit $ssp + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rsp + ; CHECK: TAILJMPd64 @OUTLINED_FUNCTION_0, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $edi, implicit-def $edx, implicit-def $esi, implicit $rsp, implicit $ssp + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rbp + $eax = MOV32ri 1 + $ebx = MOV32ri 2 + $ecx = MOV32ri 3 + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rsp + $esi = MOV32ri 1 + $edx = MOV32ri 2 + $edi = MOV32ri 3 + $eax = MOV32ri 4 + RETQ +... +--- +name: bar +tracksRegLiveness: true +body: | + bb.0: + ;liveins: $lr + ; CHECK-LABEL: name: bar + ; CHECK: CALL64pcrel32 @OUTLINED_FUNCTION_1, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $ebx, implicit-def $ecx, implicit $rsp, implicit $ssp + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rsp + ; CHECK: TAILJMPd64 @OUTLINED_FUNCTION_0, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $edi, implicit-def $edx, implicit-def $esi, implicit $rsp, implicit $ssp + $eax = MOV32ri 1 + $ebx = MOV32ri 2 + $ecx = MOV32ri 3 + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rsp + $esi = MOV32ri 1 + $edx = MOV32ri 2 + $edi = MOV32ri 3 + $eax = MOV32ri 4 + RETQ +... +--- +name: baz +tracksRegLiveness: true +body: | + bb.0: + ;liveins: $lr + ; CHECK-LABEL: name: baz + ; CHECK: CALL64pcrel32 @OUTLINED_FUNCTION_1, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $ebx, implicit-def $ecx, implicit $rsp, implicit $ssp + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rsp + ; CHECK: TAILJMPd64 @OUTLINED_FUNCTION_0, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $edi, implicit-def $edx, implicit-def $esi, implicit $rsp, implicit $ssp + $eax = MOV32ri 1 + $ebx = MOV32ri 2 + $ecx = MOV32ri 3 + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rsp + $esi = MOV32ri 1 + $edx = MOV32ri 2 + $edi = MOV32ri 3 + $eax = MOV32ri 4 + RETQ diff --git a/llvm/test/CodeGen/X86/machine-outliner-cfi-tail.mir b/llvm/test/CodeGen/X86/machine-outliner-cfi-tail.mir new file mode 100644 index 0000000000000..117205698cea8 --- /dev/null +++ b/llvm/test/CodeGen/X86/machine-outliner-cfi-tail.mir @@ -0,0 +1,77 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -mtriple=x86_64-apple-unknown -run-pass=machine-outliner -verify-machineinstrs %s -o - | FileCheck %s + +# Outlining CFI instructions is unsafe if we cannot outline all of the CFI +# instructions from a function. This shows that we choose to outline the +# CFI instructions if they can be included in a tail call. + +--- | + define void @foo() #0 { ret void } + define void @bar() #0 { ret void } + define void @baz() #0 { ret void } + attributes #0 = { noredzone } +... +--- +name: foo +tracksRegLiveness: true +body: | + bb.0: + ; CHECK-LABEL: name: foo + ; CHECK: $ecx = MOV32ri 3 + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rsp + ; CHECK: TAILJMPd64 @OUTLINED_FUNCTION_0, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $edi, implicit-def $edx, implicit-def $esi, implicit $rsp, implicit $ssp + $ecx = MOV32ri 3 + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rsp + $esi = MOV32ri 1 + $edx = MOV32ri 2 + $edi = MOV32ri 3 + $eax = MOV32ri 4 + RETQ +... +--- +name: bar +tracksRegLiveness: true +body: | + bb.0: + ;liveins: $lr + ; CHECK-LABEL: name: bar + ; CHECK: $ecx = MOV32ri 3 + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rsp + ; CHECK: TAILJMPd64 @OUTLINED_FUNCTION_0, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $edi, implicit-def $edx, implicit-def $esi, implicit $rsp, implicit $ssp + $ecx = MOV32ri 3 + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rsp + $esi = MOV32ri 1 + $edx = MOV32ri 2 + $edi = MOV32ri 3 + $eax = MOV32ri 4 + RETQ +... +--- +name: baz +tracksRegLiveness: true +body: | + bb.0: + ;liveins: $lr + ; CHECK-LABEL: name: baz + ; CHECK: $ecx = MOV32ri 3 + ; CHECK: CFI_INSTRUCTION def_cfa_offset 16 + ; CHECK: CFI_INSTRUCTION offset $rbp, -16 + ; CHECK: CFI_INSTRUCTION def_cfa_register $rsp + ; CHECK: TAILJMPd64 @OUTLINED_FUNCTION_0, implicit $rsp, implicit $ssp, implicit-def $eax, implicit-def $edi, implicit-def $edx, implicit-def $esi, implicit $rsp, implicit $ssp + $ecx = MOV32ri 3 + CFI_INSTRUCTION def_cfa_offset 16 + CFI_INSTRUCTION offset $rbp, -16 + CFI_INSTRUCTION def_cfa_register $rsp + $esi = MOV32ri 1 + $edx = MOV32ri 2 + $edi = MOV32ri 3 + $eax = MOV32ri 4 + RETQ From c8248dc3bb36bea61ac6d87bd02c39c6a781b011 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 8 Apr 2020 14:03:40 -0700 Subject: [PATCH 24/56] Change deprecated -fsanitize-recover flag to apply to all sanitizers, not just UBSan. Summary: This flag has been deprecated, with an on-by-default warning encouraging users to explicitly specify whether they mean "all" or ubsan for 5 years (released in Clang 3.7). Change it to mean what we wanted and undeprecate it. Also make the argument to -fsanitize-trap optional, and likewise default it to 'all', and express the aliases for these flags in the .td file rather than in code. (Plus documentation updates for the above.) Reviewers: kcc Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D77753 --- clang/docs/ReleaseNotes.rst | 5 ++++ clang/docs/UndefinedBehaviorSanitizer.rst | 4 +++ clang/docs/UsersManual.rst | 8 +++--- clang/include/clang/Driver/Options.td | 34 ++++++++++++++--------- clang/lib/Driver/SanitizerArgs.cpp | 29 +------------------ clang/test/Driver/fsanitize.c | 4 +-- 6 files changed, 37 insertions(+), 47 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 54deba7bbd0e8..6ed00a5be9367 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -110,6 +110,11 @@ Modified Compiler Flags - Duplicate qualifiers on asm statements (ex. `asm volatile volatile ("")`) no longer produces a warning via -Wduplicate-decl-specifier, but now an error (this matches GCC's behavior). +- The deprecated argument ``-f[no-]sanitize-recover`` has changed to mean + ``-f[no-]sanitize-recover=all`` instead of + ``-f[no-]sanitize-recover=undefined,integer`` and is no longer deprecated. +- The argument to ``-f[no-]sanitize-trap=...`` is now optional and defaults to + ``all``. New Pragmas in Clang -------------------- diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst index 0f6a42a2113f5..493b9478bdf35 100644 --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -54,6 +54,10 @@ and define the desired behavior for each kind of check: * ``-fno-sanitize-recover=...``: print a verbose error report and exit the program; * ``-fsanitize-trap=...``: execute a trap instruction (doesn't require UBSan run-time support). +Note that the ``trap`` / ``recover`` options do not enable the corresponding +sanitizer, and in general need to be accompanied by a suitable ``-fsanitize=`` +flag. + For example if you compile/link your program as: .. code-block:: console diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index f50f8888f477e..60319833c901b 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -1466,7 +1466,7 @@ are listed below. **-f[no-]sanitize-recover=check1,check2,...** -**-f[no-]sanitize-recover=all** +**-f[no-]sanitize-recover[=all]** Controls which checks enabled by ``-fsanitize=`` flag are non-fatal. If the check is fatal, program will halt after the first error @@ -1492,6 +1492,8 @@ are listed below. **-f[no-]sanitize-trap=check1,check2,...** +**-f[no-]sanitize-trap[=all]** + Controls which checks enabled by the ``-fsanitize=`` flag trap. This option is intended for use in cases where the sanitizer runtime cannot be used (for instance, when building libc or a kernel module), or where @@ -1499,9 +1501,7 @@ are listed below. This flag is only compatible with :doc:`control flow integrity ` schemes and :doc:`UndefinedBehaviorSanitizer` - checks other than ``vptr``. If this flag - is supplied together with ``-fsanitize=undefined``, the ``vptr`` sanitizer - will be implicitly disabled. + checks other than ``vptr``. This flag is enabled by default for sanitizers in the ``cfi`` group. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 226876d84b96d..fcfc3a387de89 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1083,27 +1083,35 @@ def fsanitize_hwaddress_abi_EQ : Joined<["-"], "fsanitize-hwaddress-abi=">, Group, HelpText<"Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor). This option is currently unused.">; -def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group; -def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, - Flags<[CoreOption, DriverOption]>, - Group; def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">, Group, HelpText<"Enable recovery for specified sanitizers">; -def fno_sanitize_recover_EQ - : CommaJoined<["-"], "fno-sanitize-recover=">, - Group, - Flags<[CoreOption, DriverOption]>, - HelpText<"Disable recovery for specified sanitizers">; +def fno_sanitize_recover_EQ : CommaJoined<["-"], "fno-sanitize-recover=">, + Group, Flags<[CoreOption, DriverOption]>, + HelpText<"Disable recovery for specified sanitizers">; +def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group, + Alias, AliasArgs<["all"]>; +def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, + Flags<[CoreOption, DriverOption]>, Group, + Alias, AliasArgs<["all"]>; def fsanitize_trap_EQ : CommaJoined<["-"], "fsanitize-trap=">, Group, HelpText<"Enable trapping for specified sanitizers">; def fno_sanitize_trap_EQ : CommaJoined<["-"], "fno-sanitize-trap=">, Group, Flags<[CoreOption, DriverOption]>, HelpText<"Disable trapping for specified sanitizers">; -def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, - Group; -def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, - Group; +def fsanitize_trap : Flag<["-"], "fsanitize-trap">, Group, + Alias, AliasArgs<["all"]>, + HelpText<"Enable trapping for all sanitizers">; +def fno_sanitize_trap : Flag<["-"], "fno-sanitize-trap">, Group, + Alias, AliasArgs<["all"]>, + Flags<[CoreOption, DriverOption]>, + HelpText<"Disable trapping for all sanitizers">; +def fsanitize_undefined_trap_on_error + : Flag<["-"], "fsanitize-undefined-trap-on-error">, Group, + Alias, AliasArgs<["undefined"]>; +def fno_sanitize_undefined_trap_on_error + : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group, + Alias, AliasArgs<["undefined"]>; def fsanitize_minimal_runtime : Flag<["-"], "fsanitize-minimal-runtime">, Group; def fno_sanitize_minimal_runtime : Flag<["-"], "fno-sanitize-minimal-runtime">, diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index 7e05fda4e7bf7..78a4d9486562c 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -56,8 +56,6 @@ static const SanitizerMask Unrecoverable = SanitizerKind::Unreachable | SanitizerKind::Return; static const SanitizerMask AlwaysRecoverable = SanitizerKind::KernelAddress | SanitizerKind::KernelHWAddress; -static const SanitizerMask LegacyFsanitizeRecoverMask = - SanitizerKind::Undefined | SanitizerKind::Integer; static const SanitizerMask NeedsLTO = SanitizerKind::CFI; static const SanitizerMask TrappingSupported = (SanitizerKind::Undefined & ~SanitizerKind::Vptr) | @@ -221,16 +219,6 @@ static SanitizerMask parseSanitizeTrapArgs(const Driver &D, } else if (Arg->getOption().matches(options::OPT_fno_sanitize_trap_EQ)) { Arg->claim(); TrapRemove |= expandSanitizerGroups(parseArgValues(D, Arg, true)); - } else if (Arg->getOption().matches( - options::OPT_fsanitize_undefined_trap_on_error)) { - Arg->claim(); - TrappingKinds |= - expandSanitizerGroups(SanitizerKind::UndefinedGroup & ~TrapRemove) & - ~TrapRemove; - } else if (Arg->getOption().matches( - options::OPT_fno_sanitize_undefined_trap_on_error)) { - Arg->claim(); - TrapRemove |= expandSanitizerGroups(SanitizerKind::UndefinedGroup); } } @@ -541,18 +529,7 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, SanitizerMask DiagnosedUnrecoverableKinds; SanitizerMask DiagnosedAlwaysRecoverableKinds; for (const auto *Arg : Args) { - const char *DeprecatedReplacement = nullptr; - if (Arg->getOption().matches(options::OPT_fsanitize_recover)) { - DeprecatedReplacement = - "-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all"; - RecoverableKinds |= expandSanitizerGroups(LegacyFsanitizeRecoverMask); - Arg->claim(); - } else if (Arg->getOption().matches(options::OPT_fno_sanitize_recover)) { - DeprecatedReplacement = "-fno-sanitize-recover=undefined,integer' or " - "'-fno-sanitize-recover=all"; - RecoverableKinds &= ~expandSanitizerGroups(LegacyFsanitizeRecoverMask); - Arg->claim(); - } else if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { + if (Arg->getOption().matches(options::OPT_fsanitize_recover_EQ)) { SanitizerMask Add = parseArgValues(D, Arg, true); // Report error if user explicitly tries to recover from unrecoverable // sanitizer. @@ -581,10 +558,6 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC, RecoverableKinds &= ~expandSanitizerGroups(Remove); Arg->claim(); } - if (DeprecatedReplacement) { - D.Diag(diag::warn_drv_deprecated_arg) << Arg->getAsString(Args) - << DeprecatedReplacement; - } } RecoverableKinds &= Kinds; RecoverableKinds &= ~Unrecoverable; diff --git a/clang/test/Driver/fsanitize.c b/clang/test/Driver/fsanitize.c index f02f94d8c5a8f..e7094ef93afc9 100644 --- a/clang/test/Driver/fsanitize.c +++ b/clang/test/Driver/fsanitize.c @@ -3,6 +3,7 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP +// RUN: %clang -target x86_64-linux-gnu -fsanitize-trap -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // CHECK-UNDEFINED-TRAP-NOT: -fsanitize-recover // CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" @@ -366,6 +367,7 @@ // CHECK-PARTIAL-RECOVER: "-fsanitize-recover={{((shift-base),?){1}"}} // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=address -fsanitize-recover=all -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER-ASAN +// RUN: %clang -target x86_64-linux-gnu %s -fsanitize=address -fsanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-RECOVER-ASAN // CHECK-RECOVER-ASAN: "-fsanitize-recover=address" // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover=foobar,object-size,unreachable -### 2>&1 | FileCheck %s --check-prefix=CHECK-DIAG-RECOVER @@ -373,8 +375,6 @@ // CHECK-DIAG-RECOVER: unsupported argument 'unreachable' to option 'fsanitize-recover=' // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover -fno-sanitize-recover -### 2>&1 | FileCheck %s --check-prefix=CHECK-DEPRECATED-RECOVER -// CHECK-DEPRECATED-RECOVER: argument '-fsanitize-recover' is deprecated, use '-fsanitize-recover=undefined,integer' or '-fsanitize-recover=all' instead -// CHECK-DEPRECATED-RECOVER: argument '-fno-sanitize-recover' is deprecated, use '-fno-sanitize-recover=undefined,integer' or '-fno-sanitize-recover=all' instead // CHECK-DEPRECATED-RECOVER-NOT: is deprecated // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=kernel-address -fno-sanitize-recover=kernel-address -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-KASAN From fc76b4ad3da3c1f5fdc34370a55d613b3ca7af73 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 17 Apr 2020 16:23:41 -0700 Subject: [PATCH 25/56] Rename IsMissingRequirement to IsUnimportable and set it for shadowed modules too. This more accurately reflects the semantics of this flag, as distinct from "IsAvailable", which (in an explicit modules world) only describes whether a module is buildable, not whether it's importable. --- clang/include/clang/Basic/Module.h | 27 +++++++++-- clang/lib/Basic/Module.cpp | 62 +++++++++++++++---------- clang/lib/Frontend/CompilerInstance.cpp | 2 +- clang/lib/Lex/ModuleMap.cpp | 8 ++-- clang/lib/Serialization/ASTReader.cpp | 6 +-- 5 files changed, 69 insertions(+), 36 deletions(-) diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index c47eb4587a574..b14f6b59dd8c8 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -207,8 +207,10 @@ class Module { /// A module with the same name that shadows this module. Module *ShadowingModule = nullptr; - /// Whether this module is missing a feature from \c Requirements. - unsigned IsMissingRequirement : 1; + /// Whether this module has declared itself unimportable, either because + /// it's missing a requirement from \p Requirements or because it's been + /// shadowed by another module. + unsigned IsUnimportable : 1; /// Whether we tried and failed to load a module file for this module. unsigned HasIncompatibleModuleFile : 1; @@ -384,6 +386,25 @@ class Module { ~Module(); + /// Determine whether this module has been declared unimportable. + bool isUnimportable() const { return IsUnimportable; } + + /// Determine whether this module has been declared unimportable. + /// + /// \param LangOpts The language options used for the current + /// translation unit. + /// + /// \param Target The target options used for the current translation unit. + /// + /// \param Req If this module is unimportable because of a missing + /// requirement, this parameter will be set to one of the requirements that + /// is not met for use of this module. + /// + /// \param ShadowingModule If this module is unimportable because it is + /// shadowed, this parameter will be set to the shadowing module. + bool isUnimportable(const LangOptions &LangOpts, const TargetInfo &Target, + Requirement &Req, Module *&ShadowingModule) const; + /// Determine whether this module is available for use within the /// current translation unit. bool isAvailable() const { return IsAvailable; } @@ -535,7 +556,7 @@ class Module { const TargetInfo &Target); /// Mark this module and all of its submodules as unavailable. - void markUnavailable(bool MissingRequirement = false); + void markUnavailable(bool Unimportable); /// Find the submodule with the given name. /// diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 5fd7d304f8f42..22e1da4e18591 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -37,7 +37,7 @@ using namespace clang; Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, bool IsExplicit, unsigned VisibilityID) : Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent), - VisibilityID(VisibilityID), IsMissingRequirement(false), + VisibilityID(VisibilityID), IsUnimportable(false), HasIncompatibleModuleFile(false), IsAvailable(true), IsFromModuleFile(false), IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), IsInferred(false), @@ -46,17 +46,12 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, NoUndeclaredIncludes(false), ModuleMapIsPrivate(false), HasUmbrellaDir(false), NameVisibility(Hidden) { if (Parent) { - if (!Parent->isAvailable()) - IsAvailable = false; - if (Parent->IsSystem) - IsSystem = true; - if (Parent->IsExternC) - IsExternC = true; - if (Parent->NoUndeclaredIncludes) - NoUndeclaredIncludes = true; - if (Parent->ModuleMapIsPrivate) - ModuleMapIsPrivate = true; - IsMissingRequirement = Parent->IsMissingRequirement; + IsAvailable = Parent->isAvailable(); + IsUnimportable = Parent->isUnimportable(); + IsSystem = Parent->IsSystem; + IsExternC = Parent->IsExternC; + NoUndeclaredIncludes = Parent->NoUndeclaredIncludes; + ModuleMapIsPrivate = Parent->ModuleMapIsPrivate; Parent->SubModuleIndex[Name] = Parent->SubModules.size(); Parent->SubModules.push_back(this); @@ -132,25 +127,42 @@ static bool hasFeature(StringRef Feature, const LangOptions &LangOpts, return HasFeature; } -bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, - Requirement &Req, - UnresolvedHeaderDirective &MissingHeader, - Module *&ShadowingModule) const { - if (IsAvailable) - return true; +bool Module::isUnimportable(const LangOptions &LangOpts, + const TargetInfo &Target, Requirement &Req, + Module *&ShadowingModule) const { + if (!IsUnimportable) + return false; for (const Module *Current = this; Current; Current = Current->Parent) { if (Current->ShadowingModule) { ShadowingModule = Current->ShadowingModule; - return false; + return true; } for (unsigned I = 0, N = Current->Requirements.size(); I != N; ++I) { if (hasFeature(Current->Requirements[I].first, LangOpts, Target) != Current->Requirements[I].second) { Req = Current->Requirements[I]; - return false; + return true; } } + } + + llvm_unreachable("could not find a reason why module is unimportable"); +} + +bool Module::isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, + Requirement &Req, + UnresolvedHeaderDirective &MissingHeader, + Module *&ShadowingModule) const { + if (IsAvailable) + return true; + + if (isUnimportable(LangOpts, Target, Req, ShadowingModule)) + return false; + + // FIXME: All missing headers are listed on the top-level module. Should we + // just look there? + for (const Module *Current = this; Current; Current = Current->Parent) { if (!Current->MissingHeaders.empty()) { MissingHeader = Current->MissingHeaders.front(); return false; @@ -287,12 +299,12 @@ void Module::addRequirement(StringRef Feature, bool RequiredState, if (hasFeature(Feature, LangOpts, Target) == RequiredState) return; - markUnavailable(/*MissingRequirement*/true); + markUnavailable(/*Unimportable*/true); } -void Module::markUnavailable(bool MissingRequirement) { - auto needUpdate = [MissingRequirement](Module *M) { - return M->IsAvailable || (!M->IsMissingRequirement && MissingRequirement); +void Module::markUnavailable(bool Unimportable) { + auto needUpdate = [Unimportable](Module *M) { + return M->IsAvailable || (!M->IsUnimportable && Unimportable); }; if (!needUpdate(this)) @@ -308,7 +320,7 @@ void Module::markUnavailable(bool MissingRequirement) { continue; Current->IsAvailable = false; - Current->IsMissingRequirement |= MissingRequirement; + Current->IsUnimportable |= Unimportable; for (submodule_iterator Sub = Current->submodule_begin(), SubEnd = Current->submodule_end(); Sub != SubEnd; ++Sub) { diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 470429cfb4de9..0140a756b7dde 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -1576,7 +1576,7 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { Stack.push_back(M); while (!Stack.empty()) { Module *Current = Stack.pop_back_val(); - if (Current->IsMissingRequirement) continue; + if (Current->IsUnimportable) continue; Current->IsAvailable = true; Stack.insert(Stack.end(), Current->submodule_begin(), Current->submodule_end()); diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index bff4e115bfa3f..2c79bb28d8d8e 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -282,7 +282,7 @@ void ModuleMap::resolveHeader(Module *Mod, // resolved. (Such a module still can't be built though, except from // preprocessed source.) if (!Header.Size && !Header.ModTime) - Mod->markUnavailable(); + Mod->markUnavailable(/*Unimportable=*/false); } } @@ -1094,7 +1094,7 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework, new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework, /*IsExplicit=*/false, NumCreatedModules++); Result->ShadowingModule = ShadowingModule; - Result->IsAvailable = false; + Result->markUnavailable(/*Unimportable*/true); ModuleScopeIDs[Result] = CurrentModuleScopeID; ShadowModules.push_back(Result); @@ -2096,9 +2096,9 @@ void ModuleMapParser::parseModuleDecl() { // If the module meets all requirements but is still unavailable, mark the // whole tree as unavailable to prevent it from building. - if (!ActiveModule->IsAvailable && !ActiveModule->IsMissingRequirement && + if (!ActiveModule->IsAvailable && !ActiveModule->IsUnimportable && ActiveModule->Parent) { - ActiveModule->getTopLevelModule()->markUnavailable(); + ActiveModule->getTopLevelModule()->markUnavailable(/*Unimportable=*/false); ActiveModule->getTopLevelModule()->MissingHeaders.append( ActiveModule->MissingHeaders.begin(), ActiveModule->MissingHeaders.end()); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 62dd233aab3fa..e2f89f51693e0 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5539,9 +5539,9 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { // imported module file. CurrentModule->Requirements.clear(); CurrentModule->MissingHeaders.clear(); - CurrentModule->IsMissingRequirement = - ParentModule && ParentModule->IsMissingRequirement; - CurrentModule->IsAvailable = !CurrentModule->IsMissingRequirement; + CurrentModule->IsUnimportable = + ParentModule && ParentModule->IsUnimportable; + CurrentModule->IsAvailable = !CurrentModule->IsUnimportable; break; } From 6bc7502385cc2a06954082a7d0e6418e610d35f4 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Fri, 17 Apr 2020 20:25:15 -0700 Subject: [PATCH 26/56] When making modules transitively visible, don't take into account whether they have missing header files. Whether a module's headers happen to be present on the local file system should make no difference to whether we make its contents visible when importing another module that re-exports it. If we have an up-to-date AST file that we can load, that's all that matters. This fixes the ability to header syntax checking for modular headers in C++20 mode (or in prior modes where -fmodules-local-submodule-visibility is enabled but -fmodules is not). --- clang/lib/Basic/Module.cpp | 4 ++-- clang/lib/Lex/ModuleMap.cpp | 3 +++ clang/lib/Serialization/ASTReader.cpp | 4 ++-- clang/lib/Serialization/ASTWriter.cpp | 3 ++- .../Modules/Inputs/missing-header-local-visibility/a.h | 2 ++ .../Modules/Inputs/missing-header-local-visibility/all.h | 2 ++ .../Modules/Inputs/missing-header-local-visibility/b.h | 2 ++ .../missing-header-local-visibility/module.modulemap | 6 ++++++ .../Modules/Inputs/missing-header-local-visibility/x.h | 4 ++++ clang/test/Modules/missing-header-local-visibility.cpp | 7 +++++++ 10 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 clang/test/Modules/Inputs/missing-header-local-visibility/a.h create mode 100644 clang/test/Modules/Inputs/missing-header-local-visibility/all.h create mode 100644 clang/test/Modules/Inputs/missing-header-local-visibility/b.h create mode 100644 clang/test/Modules/Inputs/missing-header-local-visibility/module.modulemap create mode 100644 clang/test/Modules/Inputs/missing-header-local-visibility/x.h create mode 100644 clang/test/Modules/missing-header-local-visibility.cpp diff --git a/clang/lib/Basic/Module.cpp b/clang/lib/Basic/Module.cpp index 22e1da4e18591..b3daaa3a44422 100644 --- a/clang/lib/Basic/Module.cpp +++ b/clang/lib/Basic/Module.cpp @@ -654,8 +654,8 @@ void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc, SmallVector Exports; V.M->getExportedModules(Exports); for (Module *E : Exports) { - // Don't recurse to unavailable submodules. - if (E->isAvailable()) + // Don't import non-importable modules. + if (!E->isUnimportable()) VisitModule({E, &V}); } diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 2c79bb28d8d8e..4f7d5ab137e64 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -544,6 +544,9 @@ void ModuleMap::diagnoseHeaderInclusion(Module *RequestingModule, static bool isBetterKnownHeader(const ModuleMap::KnownHeader &New, const ModuleMap::KnownHeader &Old) { // Prefer available modules. + // FIXME: Considering whether the module is available rather than merely + // importable is non-hermetic and can result in surprising behavior for + // prebuilt modules. Consider only checking for importability here. if (New.getModule()->isAvailable() && !Old.getModule()->isAvailable()) return true; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index e2f89f51693e0..873115835e5c5 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4033,8 +4033,8 @@ void ASTReader::makeModuleVisible(Module *Mod, continue; } - if (!Mod->isAvailable()) { - // Modules that aren't available cannot be made visible. + if (Mod->isUnimportable()) { + // Modules that aren't importable cannot be made visible. continue; } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 18a92aaadd52d..31d004f6c946c 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1729,7 +1729,8 @@ void ASTWriter::WriteHeaderSearch(const HeaderSearch &HS) { llvm::SmallVector Worklist(1, WritingModule); while (!Worklist.empty()) { Module *M = Worklist.pop_back_val(); - if (!M->isAvailable()) + // We don't care about headers in unimportable submodules. + if (M->isUnimportable()) continue; // Map to disk files where possible, to pick up any missing stat diff --git a/clang/test/Modules/Inputs/missing-header-local-visibility/a.h b/clang/test/Modules/Inputs/missing-header-local-visibility/a.h new file mode 100644 index 0000000000000..3ff0ea836a29e --- /dev/null +++ b/clang/test/Modules/Inputs/missing-header-local-visibility/a.h @@ -0,0 +1,2 @@ +#include "x.h" +X a(); diff --git a/clang/test/Modules/Inputs/missing-header-local-visibility/all.h b/clang/test/Modules/Inputs/missing-header-local-visibility/all.h new file mode 100644 index 0000000000000..600af314ec35e --- /dev/null +++ b/clang/test/Modules/Inputs/missing-header-local-visibility/all.h @@ -0,0 +1,2 @@ +#include "a.h" +#include "b.h" diff --git a/clang/test/Modules/Inputs/missing-header-local-visibility/b.h b/clang/test/Modules/Inputs/missing-header-local-visibility/b.h new file mode 100644 index 0000000000000..0fdb1154eb391 --- /dev/null +++ b/clang/test/Modules/Inputs/missing-header-local-visibility/b.h @@ -0,0 +1,2 @@ +#include "a.h" +X b(); diff --git a/clang/test/Modules/Inputs/missing-header-local-visibility/module.modulemap b/clang/test/Modules/Inputs/missing-header-local-visibility/module.modulemap new file mode 100644 index 0000000000000..0f21ceeeb29ea --- /dev/null +++ b/clang/test/Modules/Inputs/missing-header-local-visibility/module.modulemap @@ -0,0 +1,6 @@ +module M { + module A { header "a.h" export * } + module B { header "b.h" export * } + module X { header "x.h" header "missing.h" export * } + module All { header "all.h" export * } +} diff --git a/clang/test/Modules/Inputs/missing-header-local-visibility/x.h b/clang/test/Modules/Inputs/missing-header-local-visibility/x.h new file mode 100644 index 0000000000000..0498c5d2aabc4 --- /dev/null +++ b/clang/test/Modules/Inputs/missing-header-local-visibility/x.h @@ -0,0 +1,4 @@ +#ifndef X_H +#define X_H +struct X {}; +#endif diff --git a/clang/test/Modules/missing-header-local-visibility.cpp b/clang/test/Modules/missing-header-local-visibility.cpp new file mode 100644 index 0000000000000..e282a1babed75 --- /dev/null +++ b/clang/test/Modules/missing-header-local-visibility.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility %s +// RUN: %clang_cc1 -fmodules-local-submodule-visibility -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility -x c++-header %S/Inputs/missing-header-local-visibility/all.h +// RUN: %clang_cc1 -fmodule-name=M -std=c++2a -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility -x c++-header %s +// RUN: %clang_cc1 -fmodule-name=M -std=c++2a -fimplicit-module-maps -I%S/Inputs/missing-header-local-visibility -x c++-header %S/Inputs/missing-header-local-visibility/all.h + +#include "a.h" +#include "b.h" From 6919b708a180b8791d8d21b289958f1f061c71e3 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Fri, 17 Apr 2020 17:34:08 -0700 Subject: [PATCH 27/56] [CMake] Set UBSAN_LINK_FLAGS for ubsan This variable is being used, but it's not being set (it's only set for ubsan_minimal, but not ubsan). This addresses a regression that was introduced in D78325. Differential Revision: https://reviews.llvm.org/D78410 --- compiler-rt/lib/ubsan/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler-rt/lib/ubsan/CMakeLists.txt b/compiler-rt/lib/ubsan/CMakeLists.txt index 164f7aadcc0c1..174a216c8804a 100644 --- a/compiler-rt/lib/ubsan/CMakeLists.txt +++ b/compiler-rt/lib/ubsan/CMakeLists.txt @@ -52,6 +52,8 @@ set(UBSAN_CXXFLAGS ${SANITIZER_COMMON_CFLAGS}) append_rtti_flag(ON UBSAN_CXXFLAGS) append_list_if(SANITIZER_CAN_USE_CXXABI -DUBSAN_CAN_USE_CXXABI UBSAN_CXXFLAGS) +set(UBSAN_LINK_FLAGS ${SANITIZER_COMMON_LINK_FLAGS}) + set(UBSAN_DYNAMIC_LIBS ${SANITIZER_CXX_ABI_LIBRARIES} ${SANITIZER_COMMON_LINK_LIBS}) append_list_if(COMPILER_RT_HAS_LIBDL dl UBSAN_DYNAMIC_LIBS) From eef9cb1628898adb5652a32eb95b53c544de0d6f Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sat, 18 Apr 2020 08:32:12 +0200 Subject: [PATCH 28/56] [lldb] [testsuite] Fix TestFixIts.py on Linux Since D77214 there is a testsuite regression for TestFixIts.py on Fedora 31 x86_64. File "/home/jkratoch/redhat/llvm-monorepo/lldb/test/API/commands/expression/fixits/TestFixIts.py", line 148, in test_with_target self.assertEquals(value.GetError().GetCString(), "error: No value") AssertionError: 'error: error: Multiple internal symbols found for \'d\'\nid = {0x00000d2a}, ran [truncated]... != 'error: No value' That is because Fedora glibc incl. libm.so contains also ELF debug symbols and there exists a 'd' symbol: (gdb) p d $1 = {i = {0, 1076887552}, d = 16} (gdb) p &d $2 = (const number *) 0x7ffff78e8bc0 (gdb) info sym 0x7ffff78e8bc0 d in section .rodata of /lib64/libm.so.6 $ nm /lib64/libm.so.6 |grep ' d$' 00000000000bfbc0 r d 00000000000caa20 r d 00000000000caa20 r d 00000000000caa20 r d glibc-build$ for i in `find -name "*.o"`;do nm 2>/dev/null $i|grep ' d$' && echo $i;done 0000000000000080 r d ./math/s_atan-fma4.o 0000000000000080 r d ./math/s_atan-avx.o 0000000000000080 r d ./math/s_atan.o --- lldb/test/API/commands/expression/fixits/TestFixIts.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lldb/test/API/commands/expression/fixits/TestFixIts.py b/lldb/test/API/commands/expression/fixits/TestFixIts.py index 9ce5415b732e7..9907c25577883 100644 --- a/lldb/test/API/commands/expression/fixits/TestFixIts.py +++ b/lldb/test/API/commands/expression/fixits/TestFixIts.py @@ -107,11 +107,11 @@ def test_with_multiple_retries(self): struct S1 : public T { using T::TypeDef; int f() { - Data d; - d.m = 123; + Data data; + data.m = 123; // The first error as the using above requires a 'typename '. // Will trigger a Fix-It that puts 'typename' in the right place. - typename S1::TypeDef i = &d; + typename S1::TypeDef i = &data; // i has the type "Data *", so this should be i.m. // The second run will change the . to -> via the Fix-It. return i.m; From 0d3149f43173967d6f4e4c5c904a05e1022071d4 Mon Sep 17 00:00:00 2001 From: Shengchen Kan Date: Sat, 18 Apr 2020 14:40:46 +0800 Subject: [PATCH 29/56] [MC][X86] Disable branch align in non-text section Summary: The instruction in non-text section can not be executed, so they will not affect performance. In addition, their encoding values are treated as data, so we should not touch them. Reviewers: MaskRay, reames, LuoYuanke, jyknight Reviewed By: MaskRay Subscribers: annita.zhang, hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D77971 --- .../Target/X86/MCTargetDesc/X86AsmBackend.cpp | 4 ++++ llvm/test/MC/X86/align-branch-section-type.s | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 llvm/test/MC/X86/align-branch-section-type.s diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 356eb0a7be0fb..a7ed81dee6d25 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -566,6 +566,10 @@ bool X86AsmBackend::canPadBranches(MCObjectStreamer &OS) const { return false; assert(allowAutoPadding() && "incorrect initialization!"); + // We only pad in text section. + if (!OS.getCurrentSectionOnly()->getKind().isText()) + return false; + // To be Done: Currently don't deal with Bundle cases. if (OS.getAssembler().isBundlingEnabled()) return false; diff --git a/llvm/test/MC/X86/align-branch-section-type.s b/llvm/test/MC/X86/align-branch-section-type.s new file mode 100644 index 0000000000000..7a5c10b83d9ea --- /dev/null +++ b/llvm/test/MC/X86/align-branch-section-type.s @@ -0,0 +1,18 @@ +# RUN: llvm-mc -filetype=obj -triple x86_64 --x86-align-branch-boundary=32 --x86-align-branch=ret %s | llvm-readobj -S | FileCheck %s + +## Check we only pad in a text section + +# CHECK-LABEL: Name: text +# CHECK: AddressAlignment: 32 +.section text, "ax" +ret + +# CHECK-LABEL: Name: excluded +# CHECK: AddressAlignment: 1 +.section excluded, "e" +ret + +# CHECK-LABEL: Name: tls +# CHECK: AddressAlignment: 1 +.section tls, "awT" +ret From c1c01212c49a0792c0594662db84be271e29cba6 Mon Sep 17 00:00:00 2001 From: Anchu Rajendran Date: Sat, 18 Apr 2020 11:39:34 +0530 Subject: [PATCH 30/56] [flang]Implemented Semantic Checkes for 5 data constraints Summary: C874, C875, C878, C880 and C881 checks are implemented. Differential Revision: https://reviews.llvm.org/D78008 --- flang/lib/Semantics/check-data.cpp | 91 +++++++++++++++++++++++++++++- flang/lib/Semantics/check-data.h | 5 ++ flang/test/Semantics/data03.f90 | 83 +++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 2 deletions(-) create mode 100644 flang/test/Semantics/data03.f90 diff --git a/flang/lib/Semantics/check-data.cpp b/flang/lib/Semantics/check-data.cpp index 6178eb7360cae..c1cc880583de2 100644 --- a/flang/lib/Semantics/check-data.cpp +++ b/flang/lib/Semantics/check-data.cpp @@ -10,6 +10,59 @@ namespace Fortran::semantics { +template void DataChecker::CheckIfConstantSubscript(const T &x) { + evaluate::ExpressionAnalyzer exprAnalyzer{context_}; + if (MaybeExpr checked{exprAnalyzer.Analyze(x)}) { + if (!evaluate::IsConstantExpr(*checked)) { // C875,C881 + context_.Say(parser::FindSourceLocation(x), + "Data object must have constant bounds"_err_en_US); + } + } +} + +void DataChecker::CheckSubscript(const parser::SectionSubscript &subscript) { + std::visit(common::visitors{ + [&](const parser::SubscriptTriplet &triplet) { + CheckIfConstantSubscript(std::get<0>(triplet.t)); + CheckIfConstantSubscript(std::get<1>(triplet.t)); + CheckIfConstantSubscript(std::get<2>(triplet.t)); + }, + [&](const parser::IntExpr &intExpr) { + CheckIfConstantSubscript(intExpr); + }, + }, + subscript.u); +} + +// Returns false if DataRef has no subscript +bool DataChecker::CheckAllSubscriptsInDataRef( + const parser::DataRef &dataRef, parser::CharBlock source) { + return std::visit( + common::visitors{ + [&](const parser::Name &) { return false; }, + [&](const common::Indirection + &structureComp) { + return CheckAllSubscriptsInDataRef( + structureComp.value().base, source); + }, + [&](const common::Indirection &arrayElem) { + for (auto &subscript : arrayElem.value().subscripts) { + CheckSubscript(subscript); + } + CheckAllSubscriptsInDataRef(arrayElem.value().base, source); + return true; + }, + [&](const common::Indirection + &coindexedObj) { // C874 + context_.Say(source, + "Data object must not be a coindexed variable"_err_en_US); + CheckAllSubscriptsInDataRef(coindexedObj.value().base, source); + return true; + }, + }, + dataRef.u); +} + void DataChecker::Leave(const parser::DataStmtConstant &dataConst) { if (auto *structure{ std::get_if(&dataConst.u)}) { @@ -25,10 +78,44 @@ void DataChecker::Leave(const parser::DataStmtConstant &dataConst) { } } } - // TODO: C886 and C887 for data-stmt-constant } -// TODO: C874-C881 +// TODO: C876, C877, C879 +void DataChecker::Leave(const parser::DataImpliedDo &dataImpliedDo) { + for (const auto &object : + std::get>(dataImpliedDo.t)) { + if (const auto *designator{parser::Unwrap(object)}) { + if (auto *dataRef{std::get_if(&designator->u)}) { + evaluate::ExpressionAnalyzer exprAnalyzer{context_}; + if (MaybeExpr checked{exprAnalyzer.Analyze(*dataRef)}) { + if (evaluate::IsConstantExpr(*checked)) { // C878 + context_.Say(designator->source, + "Data implied do object must be a variable"_err_en_US); + } + } + if (!CheckAllSubscriptsInDataRef(*dataRef, + designator->source)) { // C880 + context_.Say(designator->source, + "Data implied do object must be subscripted"_err_en_US); + } + } + } + } +} + +void DataChecker::Leave(const parser::DataStmtObject &dataObject) { + if (std::get_if>(&dataObject.u)) { + if (const auto *designator{ + parser::Unwrap(dataObject)}) { + if (auto *dataRef{std::get_if(&designator->u)}) { + CheckAllSubscriptsInDataRef(*dataRef, designator->source); + } + } else { // C875 + context_.Say(parser::FindSourceLocation(dataObject), + "Data object variable must not be a function reference"_err_en_US); + } + } +} void DataChecker::Leave(const parser::DataStmtRepeat &dataRepeat) { if (const auto *designator{parser::Unwrap(dataRepeat)}) { diff --git a/flang/lib/Semantics/check-data.h b/flang/lib/Semantics/check-data.h index 5d66c8e74e550..6624574fe9211 100644 --- a/flang/lib/Semantics/check-data.h +++ b/flang/lib/Semantics/check-data.h @@ -20,9 +20,14 @@ class DataChecker : public virtual BaseChecker { DataChecker(SemanticsContext &context) : context_{context} {} void Leave(const parser::DataStmtRepeat &); void Leave(const parser::DataStmtConstant &); + void Leave(const parser::DataStmtObject &); + void Leave(const parser::DataImpliedDo &); private: SemanticsContext &context_; + template void CheckIfConstantSubscript(const T &); + void CheckSubscript(const parser::SectionSubscript &); + bool CheckAllSubscriptsInDataRef(const parser::DataRef &, parser::CharBlock); }; } // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_CHECK_DATA_H_ diff --git a/flang/test/Semantics/data03.f90 b/flang/test/Semantics/data03.f90 new file mode 100644 index 0000000000000..6548c047e438b --- /dev/null +++ b/flang/test/Semantics/data03.f90 @@ -0,0 +1,83 @@ +! RUN: %B/test/Semantics/test_errors.sh %s %flang %t +!Testing data constraints : C874 - C875, C878 - C881 +module m + contains + function f(i) + integer ::i + integer ::result + result = i *1024 + end + subroutine CheckObject + type specialNumbers + integer one + integer numbers(5) + end type + type large + integer elt(10) + integer val + type(specialNumbers) nums + type(specialNumbers) numsArray(5) + end type + type(specialNumbers), parameter ::newNums = & + specialNumbers(1, (/ 1, 2, 3, 4, 5 /)) + type(specialNumbers), parameter ::newNumsArray(2) = & + (/ SpecialNumbers(1, (/ 1, 2, 3, 4, 5 /)), & + SpecialNumbers(1, (/ 1, 2, 3,4, 5 /)) /) + type(specialNumbers) nums + type(large) largeArray(5) + type(large) largeNumber + real :: a[*] + real :: b(5) + integer :: x + real, parameter:: c(5) = (/ 1, 2, 3, 4, 5 /) + integer :: d(10, 10) + character :: name(12) + integer :: ind = 2 + !C874 + !ERROR: Data object must not be a coindexed variable + DATA a[1] / 1 / + !C874 + !ERROR: Data object must not be a coindexed variable + DATA(a[i], i = 1, 5) / 5 * 1 / + !C875 + !ERROR: Data object variable must not be a function reference + DATA f(1) / 1 / + !C875 + !ERROR: Data object must have constant bounds + DATA b(ind) / 1 / + !C875 + !ERROR: Data object must have constant bounds + DATA name( : ind) / 'Ancd' / + !C875 + !ERROR: Data object must have constant bounds + DATA name(ind:) / 'Ancd' / + !C878 + !ERROR: Data implied do object must be a variable + DATA(c(i), i = 1, 5) / 5 * 1 / + !C878 + !ERROR: Data implied do object must be a variable + DATA(newNumsArray(i), i = 1, 2) & + / specialNumbers(1, 2 * (/ 1, 2, 3, 4, 5 /)) / + !C880 + !ERROR: Data implied do object must be subscripted + DATA(nums % one, i = 1, 5) / 5 * 1 / + !C880 + !OK: Correct use + DATA(largeArray(j) % nums % one, j = 1, 10) / 10 * 1 / + !C880 + !OK: Correct use + DATA(largeNumber % numsArray(j) % one, j = 1, 10) / 10 * 1 / + !C881 + !ERROR: Data object must have constant bounds + DATA(b(x), i = 1, 5) / 5 * 1 / + !C881 + !OK: Correct use + DATA(nums % numbers(i), i = 1, 5) / 5 * 1 / + !C881 + !OK: Correct use + DATA((d(i, j), i = 1, 10), j = 1, 10) / 100 * 1 / + !C881 + !OK: Correct use + DATA(d(i, 1), i = 1, 10) / 10 * 1 / + end + end From 60ce987bf31d6249c1f19e454f53b9d228925dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Marques?= Date: Sat, 18 Apr 2020 09:26:15 +0100 Subject: [PATCH 31/56] [RISCV][PowerPC] Fix google/benchmark benchmark::cycleclock::Now Cherrypick the upstream fix commit a77d5f7 onto llvm/utils/benchmark and libcxx/utils/google-benchmark. This fixes LLVM's 32-bit RISC-V compilation, and the issues mentioned in https://github.com/google/benchmark/pull/955 An additional cherrypick of ecc1685 fixes some minor formatting issues introduced by the preceding commit. Differential Revision: https://reviews.llvm.org/D78084 --- libcxx/utils/google-benchmark/README.LLVM | 8 ++++ .../utils/google-benchmark/src/cycleclock.h | 44 ++++++++++++------- llvm/utils/benchmark/README.LLVM | 6 +++ llvm/utils/benchmark/src/cycleclock.h | 44 ++++++++++++------- 4 files changed, 72 insertions(+), 30 deletions(-) diff --git a/libcxx/utils/google-benchmark/README.LLVM b/libcxx/utils/google-benchmark/README.LLVM index 05c5e3ee34326..ea92eee202ce8 100644 --- a/libcxx/utils/google-benchmark/README.LLVM +++ b/libcxx/utils/google-benchmark/README.LLVM @@ -14,3 +14,11 @@ Changes: is applied on top of https://github.com/google/benchmark/commit/4528c76b718acc9b57956f63069c699ae21edcab to fix cross-build from linux to windows via MinGW. +* https://github.com/google/benchmark/commit/a77d5f70efaebe2b7e8c10134526a23a7ce7ef35 + and + https://github.com/google/benchmark/commit/ecc1685340f58f7fe6b707036bc0bb1fccabb0c1 + are applied on top of + https://github.com/google/benchmark/commit/8e48105d465c586068dd8e248fe75a8971c6ba3a + to fix timestamp-related inline asm issues and 32-bit RISC-V build failures. + The second cherrypicked commit fixes formatting issues introduced by the + preceding change. diff --git a/libcxx/utils/google-benchmark/src/cycleclock.h b/libcxx/utils/google-benchmark/src/cycleclock.h index d5d62c4c7fe17..179c67cd614a6 100644 --- a/libcxx/utils/google-benchmark/src/cycleclock.h +++ b/libcxx/utils/google-benchmark/src/cycleclock.h @@ -84,13 +84,21 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { return (high << 32) | low; #elif defined(__powerpc__) || defined(__ppc__) // This returns a time-base, which is not always precisely a cycle-count. - int64_t tbl, tbu0, tbu1; - asm("mftbu %0" : "=r"(tbu0)); - asm("mftb %0" : "=r"(tbl)); - asm("mftbu %0" : "=r"(tbu1)); - tbl &= -static_cast(tbu0 == tbu1); - // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage) - return (tbu1 << 32) | tbl; +#if defined(__powerpc64__) || defined(__ppc64__) + int64_t tb; + asm volatile("mfspr %0, 268" : "=r"(tb)); + return tb; +#else + uint32_t tbl, tbu0, tbu1; + asm volatile( + "mftbu %0\n" + "mftbl %1\n" + "mftbu %2" + : "=r"(tbu0), "=r"(tbl), "=r"(tbu1)); + tbl &= -static_cast(tbu0 == tbu1); + // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is no longer needed) + return (static_cast(tbu1) << 32) | tbl; +#endif #elif defined(__sparc__) int64_t tick; asm(".byte 0x83, 0x41, 0x00, 0x00"); @@ -167,16 +175,22 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { #elif defined(__riscv) // RISC-V // Use RDCYCLE (and RDCYCLEH on riscv32) #if __riscv_xlen == 32 - uint64_t cycles_low, cycles_hi0, cycles_hi1; - asm("rdcycleh %0" : "=r"(cycles_hi0)); - asm("rdcycle %0" : "=r"(cycles_lo)); - asm("rdcycleh %0" : "=r"(cycles_hi1)); - // This matches the PowerPC overflow detection, above - cycles_lo &= -static_cast(cycles_hi0 == cycles_hi1); - return (cycles_hi1 << 32) | cycles_lo; + uint32_t cycles_lo, cycles_hi0, cycles_hi1; + // This asm also includes the PowerPC overflow handling strategy, as above. + // Implemented in assembly because Clang insisted on branching. + asm volatile( + "rdcycleh %0\n" + "rdcycle %1\n" + "rdcycleh %2\n" + "sub %0, %0, %2\n" + "seqz %0, %0\n" + "sub %0, zero, %0\n" + "and %1, %1, %0\n" + : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1)); + return (static_cast(cycles_hi1) << 32) | cycles_lo; #else uint64_t cycles; - asm("rdcycle %0" : "=r"(cycles)); + asm volatile("rdcycle %0" : "=r"(cycles)); return cycles; #endif #else diff --git a/llvm/utils/benchmark/README.LLVM b/llvm/utils/benchmark/README.LLVM index e3668ce5c082c..b370925b95434 100644 --- a/llvm/utils/benchmark/README.LLVM +++ b/llvm/utils/benchmark/README.LLVM @@ -27,3 +27,9 @@ Changes: is applied on top of v1.4.1 to add RISC-V timer support. * https://github.com/google/benchmark/commit/8e48105d465c586068dd8e248fe75a8971c6ba3a is applied on top of v1.4.1 to fix cross-build from linux to windows via MinGW. +* https://github.com/google/benchmark/commit/a77d5f70efaebe2b7e8c10134526a23a7ce7ef35 + and + https://github.com/google/benchmark/commit/ecc1685340f58f7fe6b707036bc0bb1fccabb0c1 + are applied on top of the previous cherrypick to fix timestamp-related inline + asm issues and 32-bit RISC-V build failures. The second cherrypicked commit + fixes formatting issues introduced by the preceding change. diff --git a/llvm/utils/benchmark/src/cycleclock.h b/llvm/utils/benchmark/src/cycleclock.h index 7b54b2530378b..1b0f09359c9b4 100644 --- a/llvm/utils/benchmark/src/cycleclock.h +++ b/llvm/utils/benchmark/src/cycleclock.h @@ -84,13 +84,21 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { return (high << 32) | low; #elif defined(__powerpc__) || defined(__ppc__) // This returns a time-base, which is not always precisely a cycle-count. - int64_t tbl, tbu0, tbu1; - asm("mftbu %0" : "=r"(tbu0)); - asm("mftb %0" : "=r"(tbl)); - asm("mftbu %0" : "=r"(tbu1)); - tbl &= -static_cast(tbu0 == tbu1); - // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is garbage) - return (tbu1 << 32) | tbl; +#if defined(__powerpc64__) || defined(__ppc64__) + int64_t tb; + asm volatile("mfspr %0, 268" : "=r"(tb)); + return tb; +#else + uint32_t tbl, tbu0, tbu1; + asm volatile( + "mftbu %0\n" + "mftbl %1\n" + "mftbu %2" + : "=r"(tbu0), "=r"(tbl), "=r"(tbu1)); + tbl &= -static_cast(tbu0 == tbu1); + // high 32 bits in tbu1; low 32 bits in tbl (tbu0 is no longer needed) + return (static_cast(tbu1) << 32) | tbl; +#endif #elif defined(__sparc__) int64_t tick; asm(".byte 0x83, 0x41, 0x00, 0x00"); @@ -167,16 +175,22 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { #elif defined(__riscv) // RISC-V // Use RDCYCLE (and RDCYCLEH on riscv32) #if __riscv_xlen == 32 - uint64_t cycles_low, cycles_hi0, cycles_hi1; - asm("rdcycleh %0" : "=r"(cycles_hi0)); - asm("rdcycle %0" : "=r"(cycles_lo)); - asm("rdcycleh %0" : "=r"(cycles_hi1)); - // This matches the PowerPC overflow detection, above - cycles_lo &= -static_cast(cycles_hi0 == cycles_hi1); - return (cycles_hi1 << 32) | cycles_lo; + uint32_t cycles_lo, cycles_hi0, cycles_hi1; + // This asm also includes the PowerPC overflow handling strategy, as above. + // Implemented in assembly because Clang insisted on branching. + asm volatile( + "rdcycleh %0\n" + "rdcycle %1\n" + "rdcycleh %2\n" + "sub %0, %0, %2\n" + "seqz %0, %0\n" + "sub %0, zero, %0\n" + "and %1, %1, %0\n" + : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1)); + return (static_cast(cycles_hi1) << 32) | cycles_lo; #else uint64_t cycles; - asm("rdcycle %0" : "=r"(cycles)); + asm volatile("rdcycle %0" : "=r"(cycles)); return cycles; #endif #else From 239093f30c342bc8a3feec1536a3154e394e55ca Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Sat, 18 Apr 2020 10:44:33 +0200 Subject: [PATCH 32/56] [lldb] [testsuite] Fix a regression of TestCppScope.py This is a regression since: [lldb][NFC] Modernize lang/cpp/scope test acb0b99c8e4f1dc65a7f1e26da9db77239a67da7 rGacb0b99c8e4f File "/home/jkratoch/redhat/llvm-monorepo/lldb/test/API/lang/cpp/scope/TestCppScope.py", line 19, in test self.assertEqual(global_var_names, expected_var_names) AssertionError: Lists differ: ['C::a', 'A::a', 'B::a', '::a'... != ['A::a', 'B::a', 'C::a', '::a'... First differing element 0: C::a A::a - ['C::a', 'A::a', 'B::a', '::a'] + ['A::a', 'B::a', 'C::a', '::a'] ManualDWARFIndex using NameToDIE does not sort alphabetically: // This is only for uniqueness, not lexicographical ordering, so we can // just compare pointers. return uintptr_t(lhs.GetCString()) < uintptr_t(rhs.GetCString()); --- lldb/test/API/lang/cpp/scope/TestCppScope.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/lang/cpp/scope/TestCppScope.py b/lldb/test/API/lang/cpp/scope/TestCppScope.py index 1320bd2185f8f..a61f9488e2151 100644 --- a/lldb/test/API/lang/cpp/scope/TestCppScope.py +++ b/lldb/test/API/lang/cpp/scope/TestCppScope.py @@ -14,8 +14,9 @@ def test(self): # Test that global variables contain the right scope operators. global_vars = self.frame().GetVariables(False, False, True, False) - global_var_names = [v.GetName() for v in global_vars] - expected_var_names = ["A::a", "B::a", "C::a", "::a"] + # ManualDWARFIndex using NameToDIE does not sort alphabetically. + global_var_names = sorted([v.GetName() for v in global_vars]) + expected_var_names = ["::a", "A::a", "B::a", "C::a"] self.assertEqual(global_var_names, expected_var_names) # Test lookup in scopes. From 4ee45ab60f8639375296f8b7b96e2eb5e8a2c9d3 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 18 Apr 2020 10:19:04 +0100 Subject: [PATCH 33/56] [LV] Invalidate cost model decisions along with interleave groups. Cost-modeling decisions are tied to the compute interleave groups (widening decisions, scalar and uniform values). When invalidating the interleave groups, those decisions also need to be invalidated. Otherwise there is a mis-match during VPlan construction. VPWidenMemoryRecipes created initially are left around w/o converting them into VPInterleave recipes. Such a conversion indeed should not take place, and these gather/scatter recipes may in fact be right. The crux is leaving around obsolete CM_Interleave (and dependent) markings of instructions along with their costs, instead of recalculating decisions, costs, and recipes. Alternatively to forcing a complete recompute later on, we could try to selectively invalidate the decisions connected to the interleave groups. But we would likely need to run the uniform/scalar value detection parts again anyways and the extra complexity is probably not worth it. Fixes PR45572. Reviewers: gilr, rengolin, Ayal, hsaito Reviewed By: Ayal Differential Revision: https://reviews.llvm.org/D78298 --- llvm/include/llvm/Analysis/VectorUtils.h | 16 +++- llvm/lib/Analysis/VectorUtils.cpp | 2 + .../Transforms/Vectorize/LoopVectorize.cpp | 20 +++- ...-cm-after-invalidating-interleavegroups.ll | 96 +++++++++++++++++++ 4 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 llvm/test/Transforms/LoopVectorize/Hexagon/invalidate-cm-after-invalidating-interleavegroups.ll diff --git a/llvm/include/llvm/Analysis/VectorUtils.h b/llvm/include/llvm/Analysis/VectorUtils.h index 2b680e8131c42..89a2ea2922090 100644 --- a/llvm/include/llvm/Analysis/VectorUtils.h +++ b/llvm/include/llvm/Analysis/VectorUtils.h @@ -698,7 +698,7 @@ class InterleavedAccessInfo { const LoopAccessInfo *LAI) : PSE(PSE), TheLoop(L), DT(DT), LI(LI), LAI(LAI) {} - ~InterleavedAccessInfo() { reset(); } + ~InterleavedAccessInfo() { invalidateGroups(); } /// Analyze the interleaved accesses and collect them in interleave /// groups. Substitute symbolic strides using \p Strides. @@ -709,16 +709,24 @@ class InterleavedAccessInfo { /// Invalidate groups, e.g., in case all blocks in loop will be predicated /// contrary to original assumption. Although we currently prevent group /// formation for predicated accesses, we may be able to relax this limitation - /// in the future once we handle more complicated blocks. - void reset() { + /// in the future once we handle more complicated blocks. Returns true if any + /// groups were invalidated. + bool invalidateGroups() { + if (InterleaveGroups.empty()) { + assert( + !RequiresScalarEpilogue && + "RequiresScalarEpilog should not be set without interleave groups"); + return false; + } + InterleaveGroupMap.clear(); for (auto *Ptr : InterleaveGroups) delete Ptr; InterleaveGroups.clear(); RequiresScalarEpilogue = false; + return true; } - /// Check if \p Instr belongs to any interleave group. bool isInterleaved(Instruction *Instr) const { return InterleaveGroupMap.find(Instr) != InterleaveGroupMap.end(); diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp index 0d411485ddd9b..7cbcb17a9a3d9 100644 --- a/llvm/lib/Analysis/VectorUtils.cpp +++ b/llvm/lib/Analysis/VectorUtils.cpp @@ -1243,6 +1243,8 @@ void InterleavedAccessInfo::invalidateGroupsRequiringScalarEpilogue() { if (Group->requiresScalarEpilogue()) DelSet.insert(Group); } + assert(!DelSet.empty() && "At least one group must be invalidated, as a " + "scalar epilogue was required"); for (auto *Ptr : DelSet) { LLVM_DEBUG( dbgs() diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp index 7eaab8b0b739a..27e3c93f7af89 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorize.cpp @@ -1309,6 +1309,13 @@ class LoopVectorizationCostModel { /// i.e. either vector version isn't available, or is too expensive. unsigned getVectorCallCost(CallInst *CI, unsigned VF, bool &NeedToScalarize); + /// Invalidates decisions already taken by the cost model. + void invalidateCostModelingDecisions() { + WideningDecisions.clear(); + Uniforms.clear(); + Scalars.clear(); + } + private: unsigned NumPredStores = 0; @@ -4977,8 +4984,13 @@ Optional LoopVectorizationCostModel::computeMaxVF() { // Invalidate interleave groups that require an epilogue if we can't mask // the interleave-group. - if (!useMaskedInterleavedAccesses(TTI)) + if (!useMaskedInterleavedAccesses(TTI)) { + assert(WideningDecisions.empty() && Uniforms.empty() && Scalars.empty() && + "No decisions should have been taken at this point"); + // Note: There is no need to invalidate any cost modeling decisions here, as + // non where taken so far. InterleaveInfo.invalidateGroupsRequiringScalarEpilogue(); + } unsigned MaxVF = computeFeasibleMaxVF(TC); if (TC > 0 && TC % MaxVF == 0) { @@ -6517,7 +6529,11 @@ Optional LoopVectorizationPlanner::plan(unsigned UserVF) { dbgs() << "LV: Invalidate all interleaved groups due to fold-tail by masking " "which requires masked-interleaved support.\n"); - CM.InterleaveInfo.reset(); + if (CM.InterleaveInfo.invalidateGroups()) + // Invalidating interleave groups also requires invalidating all decisions + // based on them, which includes widening decisions and uniform and scalar + // values. + CM.invalidateCostModelingDecisions(); } if (UserVF) { diff --git a/llvm/test/Transforms/LoopVectorize/Hexagon/invalidate-cm-after-invalidating-interleavegroups.ll b/llvm/test/Transforms/LoopVectorize/Hexagon/invalidate-cm-after-invalidating-interleavegroups.ll new file mode 100644 index 0000000000000..5ce7eab251565 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/Hexagon/invalidate-cm-after-invalidating-interleavegroups.ll @@ -0,0 +1,96 @@ +; RUN: opt -loop-vectorize -hexagon-autohvx=1 -force-vector-width=64 -prefer-predicate-over-epilog -S %s | FileCheck %s + +target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048" +target triple = "hexagon" + +; Test for PR45572. + +; Check that interleave groups and decisions based on them are correctly +; invalidated with tail-folding on platforms where masked interleaved accesses +; are disabled. + +; Make sure a vector body has been created, 64 element vectors are used and a block predicate has been computed. +; Also make sure the loads are not widened. + +; CHECK-LABEL: @test1 +; CHECK: vector.body: +; CHECK: %induction = add <64 x i32> +; CHECK: icmp ule <64 x i32> %induction +; CHECK-NOT: load <{{.*}} x i32> + + +define void @test1(i32* %arg, i32 %N) #0 { +entry: + %tmp = alloca i8 + br label %loop + +loop: ; preds = %bb2, %bb + %iv = phi i32 [ %iv.next, %loop], [ 0, %entry ] + %idx.mul = mul nuw nsw i32 %iv, 7 + %idx.start = add nuw nsw i32 %idx.mul, 1 + %tmp6 = getelementptr inbounds i32, i32* %arg, i32 %idx.start + %tmp7 = load i32, i32* %tmp6, align 4 + %tmp8 = add nuw nsw i32 %idx.start, 1 + %tmp9 = getelementptr inbounds i32, i32* %arg, i32 %tmp8 + %tmp10 = load i32, i32* %tmp9, align 4 + %tmp11 = add nuw nsw i32 %idx.start, 2 + %tmp12 = getelementptr inbounds i32, i32* %arg, i32 %tmp11 + %tmp13 = load i32, i32* %tmp12, align 4 + %tmp14 = add nuw nsw i32 %idx.start, 3 + %tmp15 = getelementptr inbounds i32, i32* %arg, i32 %tmp14 + %tmp16 = load i32, i32* %tmp15, align 4 + %tmp18 = add nuw nsw i32 %idx.start, 4 + %tmp19 = getelementptr inbounds i32, i32* %arg, i32 %tmp18 + %tmp20 = load i32, i32* %tmp19, align 4 + %tmp21 = add nuw nsw i32 %idx.start, 5 + %tmp22 = getelementptr inbounds i32, i32* %arg, i32 %tmp21 + %tmp23 = load i32, i32* %tmp22, align 4 + %tmp25 = add nuw nsw i32 %idx.start, 6 + %tmp26 = getelementptr inbounds i32, i32* %arg, i32 %tmp25 + %tmp27 = load i32, i32* %tmp26, align 4 + store i8 0, i8* %tmp, align 1 + %iv.next= add nuw nsw i32 %iv, 1 + %exit.cond = icmp eq i32 %iv.next, %N + br i1 %exit.cond, label %exit, label %loop + +exit: ; preds = %loop + ret void +} + +; The loop below only requires tail folding due to interleave groups with gaps. +; Make sure the loads are not widened. + +; CHECK-LABEL: @test2 +; CHECK: vector.body: +; CHECK-NOT: load <{{.*}} x i32> +define void @test2(i32* %arg) #1 { +entry: + %tmp = alloca i8 + br label %loop + +loop: ; preds = %bb2, %bb + %iv = phi i32 [ %iv.next, %loop], [ 0, %entry ] + %idx.start = mul nuw nsw i32 %iv, 5 + %tmp6 = getelementptr inbounds i32, i32* %arg, i32 %idx.start + %tmp7 = load i32, i32* %tmp6, align 4 + %tmp8 = add nuw nsw i32 %idx.start, 1 + %tmp9 = getelementptr inbounds i32, i32* %arg, i32 %tmp8 + %tmp10 = load i32, i32* %tmp9, align 4 + %tmp11 = add nuw nsw i32 %idx.start, 2 + %tmp12 = getelementptr inbounds i32, i32* %arg, i32 %tmp11 + %tmp13 = load i32, i32* %tmp12, align 4 + %tmp14 = add nuw nsw i32 %idx.start, 3 + %tmp15 = getelementptr inbounds i32, i32* %arg, i32 %tmp14 + %tmp16 = load i32, i32* %tmp15, align 4 + store i8 0, i8* %tmp, align 1 + %iv.next= add nuw nsw i32 %iv, 1 + %exit.cond = icmp eq i32 %iv.next, 128 + br i1 %exit.cond, label %exit, label %loop + +exit: ; preds = %loop + ret void +} + + +attributes #0 = { "target-features"="+hvx,+hvx-length128b" } +attributes #1 = { optsize "target-features"="+hvx,+hvx-length128b" } From f005f6c2343438b3760f2d6b5f396f42050cbd4d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 18 Apr 2020 11:22:44 +0200 Subject: [PATCH 34/56] Revert "ADT: SmallVector size/capacity use word-size integers when elements are small" This reverts commit b8d08e961df1d229872c785ebdbc8367432e9752. This change causes a 1% compile-time and 1% memory usage regression: http://llvm-compile-time-tracker.com/compare.php?from=73b7dd1fb3c17a4ac4b1f1e603f26fa708009649&to=b8d08e961df1d229872c785ebdbc8367432e9752&stat=instructions http://llvm-compile-time-tracker.com/compare.php?from=73b7dd1fb3c17a4ac4b1f1e603f26fa708009649&to=b8d08e961df1d229872c785ebdbc8367432e9752&stat=max-rss --- llvm/include/llvm/ADT/SmallVector.h | 98 +++++------------------------ llvm/lib/Support/SmallVector.cpp | 30 ++++++++- 2 files changed, 43 insertions(+), 85 deletions(-) diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index 0e5a56f085f0b..28b514d530dc9 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -16,10 +16,10 @@ #include "llvm/ADT/iterator_range.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" -#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/MemAlloc.h" #include "llvm/Support/type_traits.h" +#include "llvm/Support/ErrorHandling.h" #include #include #include @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -35,23 +34,11 @@ namespace llvm { -/// This is all the stuff common to all SmallVectors. -/// -/// The template parameter specifies the type which should be used to hold the -/// Size and Capacity of the SmallVector, so it can be adjusted. -/// Using 32 bit size is desirable to shink the size of the SmallVector. -/// Using 64 bit size is desirable for cases like SmallVector, where a -/// 32 bit size would limit the vector to ~4GB. SmallVectors are used for -/// buffering bitcode output - which can exceed 4GB. -template class SmallVectorBase { +/// This is all the non-templated stuff common to all SmallVectors. +class SmallVectorBase { protected: void *BeginX; - Size_T Size = 0, Capacity; - - /// The maximum value of the Size_T used. - static constexpr size_t SizeTypeMax() { - return std::numeric_limits::max(); - } + unsigned Size = 0, Capacity; SmallVectorBase() = delete; SmallVectorBase(void *FirstEl, size_t TotalCapacity) @@ -59,39 +46,7 @@ template class SmallVectorBase { /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. - /// This function will report a fatal error if it cannot increase capacity. - void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize) { - // Ensure we can fit the new capacity. - // This is only going to be applicable if the when the capacity is 32 bit. - if (MinCapacity > SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity overflow during allocation"); - - // Ensure we can meet the guarantee of space for at least one more element. - // The above check alone will not catch the case where grow is called with a - // default MinCapacity of 0, but the current capacity cannot be increased. - // This is only going to be applicable if the when the capacity is 32 bit. - if (capacity() == SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity unable to grow"); - - // In theory 2*capacity can overflow if the capacity is 64 bit, but the - // original capacity would never be large enough for this to be a problem. - size_t NewCapacity = 2 * capacity() + 1; // Always grow. - NewCapacity = std::min(std::max(NewCapacity, MinCapacity), SizeTypeMax()); - - void *NewElts; - if (BeginX == FirstEl) { - NewElts = safe_malloc(NewCapacity * TSize); - - // Copy the elements over. No need to run dtors on PODs. - memcpy(NewElts, this->BeginX, size() * TSize); - } else { - // If this wasn't grown from the inline copy, grow the allocated space. - NewElts = safe_realloc(this->BeginX, NewCapacity * TSize); - } - - this->BeginX = NewElts; - this->Capacity = NewCapacity; - } + void grow_pod(void *FirstEl, size_t MinCapacity, size_t TSize); public: size_t size() const { return Size; } @@ -114,13 +69,9 @@ template class SmallVectorBase { } }; -template -using SmallVectorSizeType = - typename std::conditional::type; - /// Figure out the offset of the first element. template struct SmallVectorAlignmentAndSize { - AlignedCharArrayUnion>> Base; + AlignedCharArrayUnion Base; AlignedCharArrayUnion FirstEl; }; @@ -128,10 +79,7 @@ template struct SmallVectorAlignmentAndSize { /// the type T is a POD. The extra dummy template argument is used by ArrayRef /// to avoid unnecessarily requiring T to be complete. template -class SmallVectorTemplateCommon - : public SmallVectorBase> { - using Base = SmallVectorBase>; - +class SmallVectorTemplateCommon : public SmallVectorBase { /// Find the address of the first element. For this pointer math to be valid /// with small-size of 0 for T with lots of alignment, it's important that /// SmallVectorStorage is properly-aligned even for small-size of 0. @@ -143,20 +91,21 @@ class SmallVectorTemplateCommon // Space after 'FirstEl' is clobbered, do not add any instance vars after it. protected: - SmallVectorTemplateCommon(size_t Size) : Base(getFirstEl(), Size) {} + SmallVectorTemplateCommon(size_t Size) + : SmallVectorBase(getFirstEl(), Size) {} void grow_pod(size_t MinCapacity, size_t TSize) { - Base::grow_pod(getFirstEl(), MinCapacity, TSize); + SmallVectorBase::grow_pod(getFirstEl(), MinCapacity, TSize); } /// Return true if this is a smallvector which has not had dynamic /// memory allocated for it. - bool isSmall() const { return this->BeginX == getFirstEl(); } + bool isSmall() const { return BeginX == getFirstEl(); } /// Put this vector in a state of being small. void resetToSmall() { - this->BeginX = getFirstEl(); - this->Size = this->Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. + BeginX = getFirstEl(); + Size = Capacity = 0; // FIXME: Setting Capacity to 0 is suspect. } public: @@ -174,10 +123,6 @@ class SmallVectorTemplateCommon using pointer = T *; using const_pointer = const T *; - using Base::capacity; - using Base::empty; - using Base::size; - // forward iterator creation methods. iterator begin() { return (iterator)this->BeginX; } const_iterator begin() const { return (const_iterator)this->BeginX; } @@ -191,9 +136,7 @@ class SmallVectorTemplateCommon const_reverse_iterator rend() const { return const_reverse_iterator(begin());} size_type size_in_bytes() const { return size() * sizeof(T); } - size_type max_size() const { - return std::min(this->SizeTypeMax(), size_type(-1) / sizeof(T)); - } + size_type max_size() const { return size_type(-1) / sizeof(T); } size_t capacity_in_bytes() const { return capacity() * sizeof(T); } @@ -288,21 +231,12 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon { // Define this out-of-line to dissuade the C++ compiler from inlining it. template void SmallVectorTemplateBase::grow(size_t MinSize) { - // Ensure we can fit the new capacity. - // This is only going to be applicable if the when the capacity is 32 bit. - if (MinSize > this->SizeTypeMax()) + if (MinSize > UINT32_MAX) report_bad_alloc_error("SmallVector capacity overflow during allocation"); - // Ensure we can meet the guarantee of space for at least one more element. - // The above check alone will not catch the case where grow is called with a - // default MinCapacity of 0, but the current capacity cannot be increased. - // This is only going to be applicable if the when the capacity is 32 bit. - if (this->capacity() == this->SizeTypeMax()) - report_bad_alloc_error("SmallVector capacity unable to grow"); - // Always grow, even from zero. size_t NewCapacity = size_t(NextPowerOf2(this->capacity() + 2)); - NewCapacity = std::min(std::max(NewCapacity, MinSize), this->SizeTypeMax()); + NewCapacity = std::min(std::max(NewCapacity, MinSize), size_t(UINT32_MAX)); T *NewElts = static_cast(llvm::safe_malloc(NewCapacity*sizeof(T))); // Move the elements over. diff --git a/llvm/lib/Support/SmallVector.cpp b/llvm/lib/Support/SmallVector.cpp index 0d1765ab3e5ca..36f0a81f6b00d 100644 --- a/llvm/lib/Support/SmallVector.cpp +++ b/llvm/lib/Support/SmallVector.cpp @@ -36,6 +36,30 @@ static_assert(sizeof(SmallVector) >= alignof(Struct32B), static_assert(sizeof(SmallVector) == sizeof(unsigned) * 2 + sizeof(void *) * 2, "wasted space in SmallVector size 1"); -static_assert(sizeof(SmallVector) == - sizeof(void *) * 2 + sizeof(void *), - "1 byte elements have word-sized type for size and capacity"); + +/// grow_pod - This is an implementation of the grow() method which only works +/// on POD-like datatypes and is out of line to reduce code duplication. +void SmallVectorBase::grow_pod(void *FirstEl, size_t MinCapacity, + size_t TSize) { + // Ensure we can fit the new capacity in 32 bits. + if (MinCapacity > UINT32_MAX) + report_bad_alloc_error("SmallVector capacity overflow during allocation"); + + size_t NewCapacity = 2 * capacity() + 1; // Always grow. + NewCapacity = + std::min(std::max(NewCapacity, MinCapacity), size_t(UINT32_MAX)); + + void *NewElts; + if (BeginX == FirstEl) { + NewElts = safe_malloc(NewCapacity * TSize); + + // Copy the elements over. No need to run dtors on PODs. + memcpy(NewElts, this->BeginX, size() * TSize); + } else { + // If this wasn't grown from the inline copy, grow the allocated space. + NewElts = safe_realloc(this->BeginX, NewCapacity * TSize); + } + + this->BeginX = NewElts; + this->Capacity = NewCapacity; +} From e7ae732a4436b8275460ebf0414bc0de7e521e66 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 10:12:13 +0100 Subject: [PATCH 35/56] [cmake] LLVMFrontendOpenMP - fix include/llvm/Frontend/OpenMP header path Correctly pick up the OMP*.h headers in MSVC projects --- llvm/lib/Frontend/OpenMP/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Frontend/OpenMP/CMakeLists.txt b/llvm/lib/Frontend/OpenMP/CMakeLists.txt index 609b8ad0756bb..7c332c106c190 100644 --- a/llvm/lib/Frontend/OpenMP/CMakeLists.txt +++ b/llvm/lib/Frontend/OpenMP/CMakeLists.txt @@ -5,7 +5,7 @@ add_llvm_component_library(LLVMFrontendOpenMP ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend - ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenMP/OMP + ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend/OpenMP DEPENDS intrinsics_gen From 2aef5b62c98a369f7a10bb7062bf937f53a2e31f Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 10:15:08 +0100 Subject: [PATCH 36/56] [cmake] LLVMAsmParser - add include/llvm/ASMParser header path Copy + paste typo meant we were picking up the include/llvm/Analysis path instead --- llvm/lib/AsmParser/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/AsmParser/CMakeLists.txt b/llvm/lib/AsmParser/CMakeLists.txt index a501956f4ebac..2056a77fd76e7 100644 --- a/llvm/lib/AsmParser/CMakeLists.txt +++ b/llvm/lib/AsmParser/CMakeLists.txt @@ -5,7 +5,7 @@ add_llvm_component_library(LLVMAsmParser Parser.cpp ADDITIONAL_HEADER_DIRS - ${LLVM_MAIN_INCLUDE_DIR}/llvm/Analysis + ${LLVM_MAIN_INCLUDE_DIR}/llvm/ASMParser DEPENDS intrinsics_gen From 5c16da387ee6556b5b577edd3e4ff53e68f94826 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 11:50:04 +0100 Subject: [PATCH 37/56] [cmake] LLVMGlobalISel - add include/llvm/CodeGen/GlobalISel header path Pick up the GlobalISel headers in MSVC projects --- llvm/lib/CodeGen/GlobalISel/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index ed6a45afb7aa6..c04cf367ba419 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -23,6 +23,9 @@ add_llvm_component_library(LLVMGlobalISel RegisterBankInfo.cpp Utils.cpp + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen/GlobalISel + DEPENDS intrinsics_gen ) From 2333ea1e705ad595ca6bc1a3fc2c451d11d8f26c Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 11:55:01 +0100 Subject: [PATCH 38/56] [cmake] LLVMMIRParser - add include/llvm/CodeGen/LLVMMIRParser header path Pick up the CodeGen/MIRParser headers in MSVC projects --- llvm/lib/CodeGen/MIRParser/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm/lib/CodeGen/MIRParser/CMakeLists.txt b/llvm/lib/CodeGen/MIRParser/CMakeLists.txt index f44adee7fee46..cc31f39e030f0 100644 --- a/llvm/lib/CodeGen/MIRParser/CMakeLists.txt +++ b/llvm/lib/CodeGen/MIRParser/CMakeLists.txt @@ -3,6 +3,9 @@ add_llvm_component_library(LLVMMIRParser MIParser.cpp MIRParser.cpp + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen/MIRParser + DEPENDS intrinsics_gen ) From f1f2acf9e15f72fcf60ca8158a17f507182630a1 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 12:09:21 +0100 Subject: [PATCH 39/56] [cmake] LLVMDWARFLinker - add include/llvm/DWARFLinker header path Pick up the DWARFLinker headers in MSVC projects --- llvm/lib/DWARFLinker/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/llvm/lib/DWARFLinker/CMakeLists.txt b/llvm/lib/DWARFLinker/CMakeLists.txt index 724ed7613ae65..b7ec782eb1055 100644 --- a/llvm/lib/DWARFLinker/CMakeLists.txt +++ b/llvm/lib/DWARFLinker/CMakeLists.txt @@ -4,6 +4,9 @@ add_llvm_component_library(LLVMDWARFLinker DWARFLinker.cpp DWARFStreamer.cpp + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/DWARFLinker + DEPENDS intrinsics_gen ) From a140a9b11289350e08514abd8533c940659acd67 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 12:09:46 +0100 Subject: [PATCH 40/56] [cmake] LLVMPasses - add include/llvm header path Pick up all the Pass headers in the root for MSVC projects --- llvm/lib/Passes/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/lib/Passes/CMakeLists.txt b/llvm/lib/Passes/CMakeLists.txt index 8752159f427f1..371a21c113dcb 100644 --- a/llvm/lib/Passes/CMakeLists.txt +++ b/llvm/lib/Passes/CMakeLists.txt @@ -8,6 +8,7 @@ add_llvm_component_library(LLVMPasses StandardInstrumentations.cpp ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm ${LLVM_MAIN_INCLUDE_DIR}/llvm/Passes DEPENDS From 0b242151016a9a235e61ba4324f8f107e299b554 Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 12:27:02 +0100 Subject: [PATCH 41/56] IRReader.h - remove unnecessary StringRef forward declaration. NFC. We need to include StringRef.h. --- llvm/include/llvm/IRReader/IRReader.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/IRReader/IRReader.h b/llvm/include/llvm/IRReader/IRReader.h index 05171300b602d..dc9f21e5f94f4 100644 --- a/llvm/include/llvm/IRReader/IRReader.h +++ b/llvm/include/llvm/IRReader/IRReader.h @@ -19,7 +19,6 @@ namespace llvm { -class StringRef; class MemoryBuffer; class MemoryBufferRef; class Module; From a348de480d34257ffe394ab51b880c9aef243d80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Marques?= Date: Sat, 18 Apr 2020 12:51:25 +0100 Subject: [PATCH 42/56] [CMake][NFC] Clean up CheckAtomic.cmake `CheckAtomic.cmake` was skipping the test of whether atomics work in MSVC without an atomics library (they do), but not setting the value of `HAVE_CXX_ATOMICS_WITHOUT_LIB`. That caused build issues when trying to land D69869. I fixed that issue in f128f442a3d, by adding an `elseif(MSVC)`, as was being done below in the 64-bit atomics check. That minimal fix did work, but it kept various inconsistencies between the original atomics check and the 64-bit one. This patch now makes the checks follow the same structure, cleaning them up. Differential Revision: https://reviews.llvm.org/D74767 --- llvm/cmake/modules/CheckAtomic.cmake | 39 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/llvm/cmake/modules/CheckAtomic.cmake b/llvm/cmake/modules/CheckAtomic.cmake index 5d22a131e5cb2..d0b75f3bcc9c7 100644 --- a/llvm/cmake/modules/CheckAtomic.cmake +++ b/llvm/cmake/modules/CheckAtomic.cmake @@ -39,46 +39,45 @@ int main() { endfunction(check_working_cxx_atomics64) -# This isn't necessary on MSVC, so avoid command-line switch annoyance -# by only running on GCC-like hosts. -if (LLVM_COMPILER_IS_GCC_COMPATIBLE) +# Check for (non-64-bit) atomic operations. +if(MSVC) + set(HAVE_CXX_ATOMICS_WITHOUT_LIB True) +elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE) # First check if atomics work without the library. check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) # If not, check if the library exists, and atomics work with it. if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) - if( HAVE_LIBATOMIC ) + if(HAVE_LIBATOMIC) list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) if (NOT HAVE_CXX_ATOMICS_WITH_LIB) - message(FATAL_ERROR "Host compiler must support std::atomic!") + message(FATAL_ERROR "Host compiler must support std::atomic!") endif() else() message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") endif() endif() -elseif(MSVC) - set(HAVE_CXX_ATOMICS_WITHOUT_LIB True) endif() # Check for 64 bit atomic operations. if(MSVC) set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) -else() +elseif(LLVM_COMPILER_IS_GCC_COMPATIBLE) + # First check if atomics work without the library. check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) -endif() - -# If not, check if the library exists, and atomics work with it. -if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) - check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) - if(HAVE_CXX_LIBATOMICS64) - list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") - check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) - if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) - message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") + # If not, check if the library exists, and atomics work with it. + if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) + check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) + if(HAVE_CXX_LIBATOMICS64) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) + message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") endif() - else() - message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") endif() endif() From b7cdb138afaaf5d0ddc0d7e899e5239b6faab43c Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 18 Apr 2020 13:31:17 +0100 Subject: [PATCH 43/56] [ValueLattice] Use 8 bits for Tag. Suggested as follow-up in D78145 post-commit to be more machine friendly. --- llvm/include/llvm/Analysis/ValueLattice.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/Analysis/ValueLattice.h b/llvm/include/llvm/Analysis/ValueLattice.h index 6f054fd1ffc85..51ddd103fcfb5 100644 --- a/llvm/include/llvm/Analysis/ValueLattice.h +++ b/llvm/include/llvm/Analysis/ValueLattice.h @@ -75,7 +75,7 @@ class ValueLatticeElement { overdefined, }; - ValueLatticeElementTy Tag : 6; + ValueLatticeElementTy Tag : 8; /// Number of times a constant range has been extended with widening enabled. unsigned NumRangeExtensions : 8; From 9b95186c3024c8e57b942703d4d69c3cd6d053dc Mon Sep 17 00:00:00 2001 From: Simon Pilgrim Date: Sat, 18 Apr 2020 13:36:37 +0100 Subject: [PATCH 44/56] HeatUtils.h - remove unnecessary includes. NFC. Replace with BlockFrequencyInfo/Function forward declarations Move BlockFrequencyInfo.h include to HeatUtils.cpp --- llvm/include/llvm/Analysis/HeatUtils.h | 10 ++++------ llvm/lib/Analysis/HeatUtils.cpp | 3 ++- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/Analysis/HeatUtils.h b/llvm/include/llvm/Analysis/HeatUtils.h index ed6044c422a24..9ecca6a69097f 100644 --- a/llvm/include/llvm/Analysis/HeatUtils.h +++ b/llvm/include/llvm/Analysis/HeatUtils.h @@ -14,16 +14,14 @@ #ifndef LLVM_ANALYSIS_HEATUTILS_H #define LLVM_ANALYSIS_HEATUTILS_H -#include "llvm/Analysis/BlockFrequencyInfo.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/Module.h" - +#include #include namespace llvm { +class BlockFrequencyInfo; +class Function; + // Returns the maximum frequency of a BB in a function. uint64_t getMaxFreq(const Function &F, const BlockFrequencyInfo *BFI); diff --git a/llvm/lib/Analysis/HeatUtils.cpp b/llvm/lib/Analysis/HeatUtils.cpp index aac4fe15068db..dad2ef33f93c0 100644 --- a/llvm/lib/Analysis/HeatUtils.cpp +++ b/llvm/lib/Analysis/HeatUtils.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/HeatUtils.h" +#include "llvm/Analysis/BlockFrequencyInfo.h" #include "llvm/IR/Instructions.h" namespace llvm { @@ -61,4 +62,4 @@ std::string getHeatColor(double percent) { return heatPalette[colorId]; } -} // namespace llvm \ No newline at end of file +} // namespace llvm From 034e8d58a800608c5ee2b95c4b132b546a82d4df Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 18 Apr 2020 13:48:53 +0100 Subject: [PATCH 45/56] [SCCP] Drop unused early exit from visitReturnInst (NFC). There are no lattice values associated with return instructions directly. They will never get marked as overdefined. --- llvm/lib/Transforms/Scalar/SCCP.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index f5b3ebd1a0024..6bb19383964cb 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -746,11 +746,6 @@ void SCCPSolver::visitPHINode(PHINode &PN) { void SCCPSolver::visitReturnInst(ReturnInst &I) { if (I.getNumOperands() == 0) return; // ret void - // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would - // discover a concrete value later. - if (isOverdefined(ValueState[&I])) - return (void)markOverdefined(&I); - Function *F = I.getParent()->getParent(); Value *ResultOp = I.getOperand(0); From 9cd68bfa0e49f755a0cc90b27025fa2e48083050 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 14 Apr 2020 18:55:39 +0100 Subject: [PATCH 46/56] [SCCP] Add additional tests for structs, conditional prop and widening. This patch adds a few additional test cases with cases subsequent patches will improve on. --- .../test/Transforms/SCCP/conditions-ranges.ll | 153 ++++++ .../Transforms/SCCP/constant-range-struct.ll | 164 +++++++ llvm/test/Transforms/SCCP/widening.ll | 437 ++++++++++++++++++ 3 files changed, 754 insertions(+) create mode 100644 llvm/test/Transforms/SCCP/constant-range-struct.ll diff --git a/llvm/test/Transforms/SCCP/conditions-ranges.ll b/llvm/test/Transforms/SCCP/conditions-ranges.ll index f23bdfabc698f..400c49e337df7 100644 --- a/llvm/test/Transforms/SCCP/conditions-ranges.ll +++ b/llvm/test/Transforms/SCCP/conditions-ranges.ll @@ -1059,3 +1059,156 @@ false: call void @use(i1 %c.5) ret void } + +define void @f19_conditions_chained_and_nested_and(i32 %a, i32 %b) { +; CHECK-LABEL: @f19_conditions_chained_and_nested_and( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[LT_A:%.*]] = icmp ult i32 [[A:%.*]], 100 +; CHECK-NEXT: [[LT_B:%.*]] = icmp ult i32 [[B:%.*]], 1000 +; CHECK-NEXT: [[BC:%.*]] = and i1 [[LT_A]], [[LT_B]] +; CHECK-NEXT: br i1 [[BC]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: [[GT_A:%.*]] = icmp ugt i32 [[A]], 30 +; CHECK-NEXT: [[GT_B:%.*]] = icmp ugt i32 [[B]], 300 +; CHECK-NEXT: [[BC_2:%.*]] = and i1 [[GT_A]], [[GT_B]] +; CHECK-NEXT: br i1 [[BC_2]], label [[TRUE_2:%.*]], label [[FALSE]] +; CHECK: true.2: +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: call void @use(i1 true) +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i32 [[A]], 31 +; CHECK-NEXT: call void @use(i1 [[C_1]]) +; CHECK-NEXT: [[C_2:%.*]] = icmp ugt i32 [[A]], 31 +; CHECK-NEXT: call void @use(i1 [[C_2]]) +; CHECK-NEXT: [[C_3:%.*]] = icmp ugt i32 [[A]], 50 +; CHECK-NEXT: call void @use(i1 [[C_3]]) +; CHECK-NEXT: [[C_4:%.*]] = icmp eq i32 [[B]], 301 +; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: [[C_5:%.*]] = icmp ugt i32 [[B]], 301 +; CHECK-NEXT: call void @use(i1 [[C_5]]) +; CHECK-NEXT: [[C_6:%.*]] = icmp ugt i32 [[B]], 500 +; CHECK-NEXT: call void @use(i1 [[C_6]]) +; CHECK-NEXT: ret void +; CHECK: false: +; CHECK-NEXT: ret void +; +entry: + %lt.a = icmp ult i32 %a, 100 + %lt.b = icmp ult i32 %b, 1000 + %bc = and i1 %lt.a, %lt.b + br i1 %bc, label %true, label %false + +true: + %gt.a = icmp ugt i32 %a, 30 + %gt.b = icmp ugt i32 %b, 300 + %bc.2 = and i1 %gt.a, %gt.b + br i1 %bc.2, label %true.2, label %false + +true.2: + ; Conditions below are false. + %f.1 = icmp eq i32 %a, 0 + call void @use(i1 %f.1) + %f.2 = icmp eq i32 %a, 20 + call void @use(i1 %f.2) + %f.3 = icmp ugt i32 %a, 100 + call void @use(i1 %f.3) + %f.4 = icmp eq i32 %b, 0 + call void @use(i1 %f.4) + %f.5 = icmp eq i32 %b, 300 + call void @use(i1 %f.5) + %f.6 = icmp ugt i32 %b, 1000 + call void @use(i1 %f.6) + + + ; Conditions below are true. + %t.1 = icmp ult i32 %a, 100 + call void @use(i1 %t.1) + %t.2 = icmp ne i32 %a, 20 + call void @use(i1 %t.2) + %t.3 = icmp ult i32 %b, 1000 + call void @use(i1 %t.3) + %t.4 = icmp ne i32 %b, 300 + call void @use(i1 %t.4) + + + ; Conditions below cannot be simplified. + %c.1 = icmp eq i32 %a, 31 + call void @use(i1 %c.1) + %c.2 = icmp ugt i32 %a, 31 + call void @use(i1 %c.2) + %c.3 = icmp ugt i32 %a, 50 + call void @use(i1 %c.3) + %c.4 = icmp eq i32 %b, 301 + call void @use(i1 %c.4) + %c.5 = icmp ugt i32 %b, 301 + call void @use(i1 %c.5) + %c.6 = icmp ugt i32 %b, 500 + call void @use(i1 %c.6) + + ret void + +false: + ret void +} + +declare i64 @get_i64() + +declare i1 @cond() + +define void @f20_ne_0_nuked_by_and(i32 %arg) local_unnamed_addr #0 { +; CHECK-LABEL: @f20_ne_0_nuked_by_and( +; CHECK-NEXT: bb11: +; CHECK-NEXT: br label [[BB122:%.*]] +; CHECK: bb122: +; CHECK-NEXT: [[TMP123:%.*]] = phi i32 [ 256, [[BB11:%.*]] ], [ [[TMP136:%.*]], [[BB135:%.*]] ] +; CHECK-NEXT: [[TMP127:%.*]] = call i64 @get_i64() +; CHECK-NEXT: [[TMP128:%.*]] = trunc i64 [[TMP127]] to i32 +; CHECK-NEXT: [[TMP131:%.*]] = icmp ne i32 [[TMP128]], 0 +; CHECK-NEXT: [[TMP132:%.*]] = icmp sgt i32 [[TMP123]], [[TMP128]] +; CHECK-NEXT: [[TMP133:%.*]] = and i1 [[TMP131]], [[TMP132]] +; CHECK-NEXT: br i1 [[TMP133]], label [[BB134:%.*]], label [[BB135]] +; CHECK: bb134: +; CHECK-NEXT: br label [[BB135]] +; CHECK: bb135: +; CHECK-NEXT: [[TMP136]] = phi i32 [ [[TMP123]], [[BB122]] ], [ [[TMP128]], [[BB134]] ] +; CHECK-NEXT: [[BC:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[BC]], label [[BB139:%.*]], label [[BB122]] +; CHECK: bb139: +; CHECK-NEXT: call void @use(i1 false) +; CHECK-NEXT: ret void +; +bb11: ; preds = %bb1 + br label %bb122 + +bb122: ; preds = %bb135, %bb120 + %tmp123 = phi i32 [ 256, %bb11 ], [ %tmp136, %bb135 ] + %tmp127 = call i64 @get_i64() + %tmp128 = trunc i64 %tmp127 to i32 + %tmp131 = icmp ne i32 %tmp128, 0 + %tmp132 = icmp sgt i32 %tmp123, %tmp128 + %tmp133 = and i1 %tmp131, %tmp132 + br i1 %tmp133, label %bb134, label %bb135 + +bb134: ; preds = %bb122 + br label %bb135 + +bb135: ; preds = %bb134, %bb122 + %tmp136 = phi i32 [ %tmp123, %bb122 ], [ %tmp128, %bb134 ] + %bc = call i1 @cond() + br i1 %bc, label %bb139, label %bb122 + +bb139: ; preds = %bb135 + %tmp140 = icmp eq i32 %tmp136, 0 + call void @use(i1 %tmp140) + ret void + +bb142: ; preds = %bb139 + ret void +} diff --git a/llvm/test/Transforms/SCCP/constant-range-struct.ll b/llvm/test/Transforms/SCCP/constant-range-struct.ll new file mode 100644 index 0000000000000..d3c5e5513b9ed --- /dev/null +++ b/llvm/test/Transforms/SCCP/constant-range-struct.ll @@ -0,0 +1,164 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt %s -ipsccp -S | FileCheck %s + +declare i1 @cond() +declare void @use(i1) + +define internal {i64, i64} @struct1() { +; CHECK-LABEL: @struct1( +; CHECK-NEXT: [[C:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: false: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[R:%.*]] = phi { i64, i64 } [ { i64 20, i64 200 }, [[TRUE]] ], [ { i64 30, i64 300 }, [[FALSE]] ] +; CHECK-NEXT: ret { i64, i64 } [[R]] +; + %c = call i1 @cond() + br i1 %c, label %true, label %false + +true: + %s.1 = insertvalue {i64, i64} undef, i64 20, 0 + %s.2 = insertvalue {i64, i64} %s.1, i64 200, 1 + br label %exit + +false: + %s.3 = insertvalue {i64, i64} undef, i64 30, 0 + %s.4 = insertvalue {i64, i64} %s.3, i64 300, 1 + br label %exit + +exit: + %r = phi {i64, i64} [ %s.2, %true], [ %s.4, %false ] + ret {i64, i64} %r +} + +define void @struct1_caller() { +; CHECK-LABEL: @struct1_caller( +; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct1() +; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0 +; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1 +; CHECK-NEXT: [[T_1:%.*]] = icmp ne i64 [[V1]], 10 +; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: [[T_2:%.*]] = icmp ult i64 [[V1]], 100 +; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: [[T_3:%.*]] = icmp ne i64 [[V2]], 0 +; CHECK-NEXT: call void @use(i1 [[T_3]]) +; CHECK-NEXT: [[T_4:%.*]] = icmp ult i64 [[V2]], 301 +; CHECK-NEXT: call void @use(i1 [[T_4]]) +; CHECK-NEXT: ret void +; + %s = call {i64, i64} @struct1() + %v1 = extractvalue {i64, i64} %s, 0 + %v2 = extractvalue {i64, i64} %s, 1 + + %t.1 = icmp ne i64 %v1, 10 + call void @use(i1 %t.1) + %t.2 = icmp ult i64 %v1, 100 + call void @use(i1 %t.2) + %t.3 = icmp ne i64 %v2, 0 + call void @use(i1 %t.3) + %t.4 = icmp ult i64 %v2, 301 + call void @use(i1 %t.4) + + ret void +} + +define internal {i64, i64} @struct2() { +; CHECK-LABEL: @struct2( +; CHECK-NEXT: [[C:%.*]] = call i1 @cond() +; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; CHECK: true: +; CHECK-NEXT: br label [[EXIT:%.*]] +; CHECK: false: +; CHECK-NEXT: br label [[EXIT]] +; CHECK: exit: +; CHECK-NEXT: [[V1:%.*]] = phi i64 [ 20, [[TRUE]] ], [ 30, [[FALSE]] ] +; CHECK-NEXT: [[V2:%.*]] = phi i64 [ 200, [[TRUE]] ], [ 300, [[FALSE]] ] +; CHECK-NEXT: [[S_1:%.*]] = insertvalue { i64, i64 } undef, i64 [[V1]], 0 +; CHECK-NEXT: [[S_2:%.*]] = insertvalue { i64, i64 } [[S_1]], i64 [[V2]], 1 +; CHECK-NEXT: ret { i64, i64 } [[S_2]] +; + %c = call i1 @cond() + br i1 %c, label %true, label %false + +true: + br label %exit + +false: + br label %exit + +exit: + %v1 = phi i64 [ 20, %true ], [ 30, %false ] + %v2 = phi i64 [ 200, %true ], [ 300, %false ] + %s.1 = insertvalue {i64, i64} undef, i64 %v1, 0 + %s.2 = insertvalue {i64, i64} %s.1, i64 %v2, 1 + ret {i64, i64} %s.2 +} + +define void @struct2_caller() { +; CHECK-LABEL: @struct2_caller( +; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct2() +; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0 +; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1 +; CHECK-NEXT: [[T_1:%.*]] = icmp ne i64 [[V1]], 10 +; CHECK-NEXT: call void @use(i1 [[T_1]]) +; CHECK-NEXT: [[T_2:%.*]] = icmp ult i64 [[V1]], 100 +; CHECK-NEXT: call void @use(i1 [[T_2]]) +; CHECK-NEXT: [[T_3:%.*]] = icmp ne i64 [[V2]], 0 +; CHECK-NEXT: call void @use(i1 [[T_3]]) +; CHECK-NEXT: [[T_4:%.*]] = icmp ult i64 [[V2]], 301 +; CHECK-NEXT: call void @use(i1 [[T_4]]) +; CHECK-NEXT: [[F_1:%.*]] = icmp eq i64 [[V1]], 10 +; CHECK-NEXT: call void @use(i1 [[F_1]]) +; CHECK-NEXT: [[F_2:%.*]] = icmp ult i64 [[V1]], 19 +; CHECK-NEXT: call void @use(i1 [[F_2]]) +; CHECK-NEXT: [[F_3:%.*]] = icmp eq i64 [[V2]], 50 +; CHECK-NEXT: call void @use(i1 [[F_3]]) +; CHECK-NEXT: [[F_4:%.*]] = icmp ugt i64 [[V2]], 301 +; CHECK-NEXT: call void @use(i1 [[F_4]]) +; CHECK-NEXT: [[C_1:%.*]] = icmp eq i64 [[V1]], 25 +; CHECK-NEXT: call void @use(i1 [[C_1]]) +; CHECK-NEXT: [[C_2:%.*]] = icmp ult i64 [[V1]], 25 +; CHECK-NEXT: call void @use(i1 [[C_2]]) +; CHECK-NEXT: [[C_3:%.*]] = icmp eq i64 [[V2]], 250 +; CHECK-NEXT: call void @use(i1 [[C_3]]) +; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i64 [[V2]], 250 +; CHECK-NEXT: call void @use(i1 [[C_4]]) +; CHECK-NEXT: ret void +; + %s = call {i64, i64} @struct2() + %v1 = extractvalue {i64, i64} %s, 0 + %v2 = extractvalue {i64, i64} %s, 1 + + %t.1 = icmp ne i64 %v1, 10 + call void @use(i1 %t.1) + %t.2 = icmp ult i64 %v1, 100 + call void @use(i1 %t.2) + %t.3 = icmp ne i64 %v2, 0 + call void @use(i1 %t.3) + %t.4 = icmp ult i64 %v2, 301 + call void @use(i1 %t.4) + + %f.1 = icmp eq i64 %v1, 10 + call void @use(i1 %f.1) + %f.2 = icmp ult i64 %v1, 19 + call void @use(i1 %f.2) + %f.3 = icmp eq i64 %v2, 50 + call void @use(i1 %f.3) + %f.4 = icmp ugt i64 %v2, 301 + call void @use(i1 %f.4) + + %c.1 = icmp eq i64 %v1, 25 + call void @use(i1 %c.1) + %c.2 = icmp ult i64 %v1, 25 + call void @use(i1 %c.2) + %c.3 = icmp eq i64 %v2, 250 + call void @use(i1 %c.3) + %c.4 = icmp ugt i64 %v2, 250 + call void @use(i1 %c.4) + + + ret void +} diff --git a/llvm/test/Transforms/SCCP/widening.ll b/llvm/test/Transforms/SCCP/widening.ll index b475e75ed362a..8e4f3b5205962 100644 --- a/llvm/test/Transforms/SCCP/widening.ll +++ b/llvm/test/Transforms/SCCP/widening.ll @@ -442,3 +442,440 @@ loop.body: exit: ret void } + +; In the function below, the condition %c.1 results in a range [7, 6), which +; can be used as a widening bound. It does not fully contain the range we get +; from combining it with the information from %tmp12. +define void @foo(i64* %arg) { +; SCCP-LABEL: @foo( +; SCCP-NEXT: bb: +; SCCP-NEXT: [[TMP:%.*]] = zext i8 undef to i32 +; SCCP-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, i64* [[ARG:%.*]], i32 0 +; SCCP-NEXT: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 8 +; SCCP-NEXT: switch i32 [[TMP]], label [[BB20:%.*]] [ +; SCCP-NEXT: i32 1, label [[BB3:%.*]] +; SCCP-NEXT: i32 2, label [[BB4:%.*]] +; SCCP-NEXT: i32 4, label [[BB19:%.*]] +; SCCP-NEXT: ] +; SCCP: bb3: +; SCCP-NEXT: unreachable +; SCCP: bb4: +; SCCP-NEXT: [[TMP5:%.*]] = add i64 [[TMP2]], 3 +; SCCP-NEXT: [[TMP6:%.*]] = and i64 [[TMP5]], 3 +; SCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]] +; SCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1 +; SCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32 +; SCCP-NEXT: [[TMP10:%.*]] = sext i32 [[TMP9]] to i64 +; SCCP-NEXT: br label [[BB11:%.*]] +; SCCP: bb11: +; SCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ] +; SCCP-NEXT: br label [[BB13:%.*]] +; SCCP: bb13: +; SCCP-NEXT: [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6 +; SCCP-NEXT: br i1 [[C_1]], label [[BB15:%.*]], label [[BB16:%.*]] +; SCCP: bb15: +; SCCP-NEXT: unreachable +; SCCP: bb16: +; SCCP-NEXT: [[TMP17]] = add i64 [[TMP12]], 2 +; SCCP-NEXT: br label [[BB18]] +; SCCP: bb18: +; SCCP-NEXT: br label [[BB11]] +; SCCP: bb19: +; SCCP-NEXT: unreachable +; SCCP: bb20: +; SCCP-NEXT: ret void +; +; IPSCCP-LABEL: @foo( +; IPSCCP-NEXT: bb: +; IPSCCP-NEXT: [[TMP:%.*]] = zext i8 undef to i32 +; IPSCCP-NEXT: [[TMP1:%.*]] = getelementptr inbounds i64, i64* [[ARG:%.*]], i32 0 +; IPSCCP-NEXT: [[TMP2:%.*]] = load i64, i64* [[TMP1]], align 8 +; IPSCCP-NEXT: switch i32 [[TMP]], label [[BB20:%.*]] [ +; IPSCCP-NEXT: i32 1, label [[BB3:%.*]] +; IPSCCP-NEXT: i32 2, label [[BB4:%.*]] +; IPSCCP-NEXT: i32 4, label [[BB19:%.*]] +; IPSCCP-NEXT: ] +; IPSCCP: bb3: +; IPSCCP-NEXT: unreachable +; IPSCCP: bb4: +; IPSCCP-NEXT: [[TMP5:%.*]] = add i64 [[TMP2]], 3 +; IPSCCP-NEXT: [[TMP6:%.*]] = and i64 [[TMP5]], 3 +; IPSCCP-NEXT: [[TMP7:%.*]] = sub i64 3, [[TMP6]] +; IPSCCP-NEXT: [[TMP8:%.*]] = shl i64 [[TMP7]], 1 +; IPSCCP-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i32 +; IPSCCP-NEXT: [[TMP10:%.*]] = sext i32 [[TMP9]] to i64 +; IPSCCP-NEXT: br label [[BB11:%.*]] +; IPSCCP: bb11: +; IPSCCP-NEXT: [[TMP12:%.*]] = phi i64 [ [[TMP10]], [[BB4]] ], [ [[TMP17:%.*]], [[BB18:%.*]] ] +; IPSCCP-NEXT: br label [[BB13:%.*]] +; IPSCCP: bb13: +; IPSCCP-NEXT: [[C_1:%.*]] = icmp eq i64 [[TMP12]], 6 +; IPSCCP-NEXT: br i1 [[C_1]], label [[BB15:%.*]], label [[BB16:%.*]] +; IPSCCP: bb15: +; IPSCCP-NEXT: unreachable +; IPSCCP: bb16: +; IPSCCP-NEXT: [[TMP17]] = add i64 [[TMP12]], 2 +; IPSCCP-NEXT: br label [[BB18]] +; IPSCCP: bb18: +; IPSCCP-NEXT: br label [[BB11]] +; IPSCCP: bb19: +; IPSCCP-NEXT: unreachable +; IPSCCP: bb20: +; IPSCCP-NEXT: ret void +; +bb: + %tmp = zext i8 undef to i32 + %tmp1 = getelementptr inbounds i64, i64* %arg, i32 0 + %tmp2 = load i64, i64* %tmp1, align 8 + switch i32 %tmp, label %bb20 [ + i32 1, label %bb3 + i32 2, label %bb4 + i32 4, label %bb19 + ] + +bb3: ; preds = %bb + unreachable + +bb4: ; preds = %bb + %tmp5 = add i64 %tmp2, 3 + %tmp6 = and i64 %tmp5, 3 + %tmp7 = sub i64 3, %tmp6 + %tmp8 = shl i64 %tmp7, 1 + %tmp9 = trunc i64 %tmp8 to i32 + %tmp10 = sext i32 %tmp9 to i64 + br label %bb11 + +bb11: ; preds = %bb18, %bb4 + %tmp12 = phi i64 [ %tmp10, %bb4 ], [ %tmp17, %bb18 ] + br label %bb13 + +bb13: ; preds = %bb11 + %c.1 = icmp eq i64 %tmp12, 6 + br i1 %c.1, label %bb15, label %bb16 + +bb15: ; preds = %bb13 + unreachable + +bb16: ; preds = %bb13 + %tmp17 = add i64 %tmp12, 2 + br label %bb18 + +bb18: ; preds = %bb16 + br label %bb11 + +bb19: ; preds = %bb + unreachable + +bb20: ; preds = %bb + ret void +} + +; The functions below check that widening with an upper bound does correctly +; return whether the range changed. Make sure we do not eliminate %c.2. + +%struct.baz.1 = type { i32, i32, i8*, i8* } +%struct.blam.2 = type <{ %struct.baz.1, i32, [4 x i8] }> + +@global.11 = linkonce_odr global [4 x i8] zeroinitializer, align 1 + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) #1 + +define linkonce_odr dereferenceable(1) i8* @spam(%struct.baz.1* %arg, i32 %arg1) align 2 { +; SCCP-LABEL: @spam( +; SCCP-NEXT: bb: +; SCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], %struct.baz.1* [[ARG:%.*]], i32 0, i32 3 +; SCCP-NEXT: [[TMP2:%.*]] = load i8*, i8** [[TMP]], align 8 +; SCCP-NEXT: [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64 +; SCCP-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[TMP2]], i64 [[TMP3]] +; SCCP-NEXT: ret i8* [[TMP4]] +; +; IPSCCP-LABEL: @spam( +; IPSCCP-NEXT: bb: +; IPSCCP-NEXT: [[TMP:%.*]] = getelementptr inbounds [[STRUCT_BAZ_1:%.*]], %struct.baz.1* [[ARG:%.*]], i32 0, i32 3 +; IPSCCP-NEXT: [[TMP2:%.*]] = load i8*, i8** [[TMP]], align 8 +; IPSCCP-NEXT: [[TMP3:%.*]] = sext i32 [[ARG1:%.*]] to i64 +; IPSCCP-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, i8* [[TMP2]], i64 [[TMP3]] +; IPSCCP-NEXT: ret i8* [[TMP4]] +; +bb: + %tmp = getelementptr inbounds %struct.baz.1, %struct.baz.1* %arg, i32 0, i32 3 + %tmp2 = load i8*, i8** %tmp, align 8 + %tmp3 = sext i32 %arg1 to i64 + %tmp4 = getelementptr inbounds i8, i8* %tmp2, i64 %tmp3 + ret i8* %tmp4 +} + +define i8* @wobble(%struct.blam.2* %arg, i32 %arg1) align 2 { +; SCCP-LABEL: @wobble( +; SCCP-NEXT: bb: +; SCCP-NEXT: [[TMP:%.*]] = lshr i32 [[ARG1:%.*]], 16 +; SCCP-NEXT: [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]] +; SCCP-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 65535 +; SCCP-NEXT: [[TMP4:%.*]] = mul i32 [[ARG1]], 8 +; SCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], %struct.blam.2* [[ARG:%.*]], i32 0, i32 1 +; SCCP-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8 +; SCCP-NEXT: [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]] +; SCCP-NEXT: br label [[BB8:%.*]] +; SCCP: bb8: +; SCCP-NEXT: [[TMP9:%.*]] = phi i8* [ undef, [[BB:%.*]] ], [ [[TMP17:%.*]], [[BB29:%.*]] ] +; SCCP-NEXT: [[TMP10:%.*]] = phi i16* [ undef, [[BB]] ], [ [[TMP18:%.*]], [[BB29]] ] +; SCCP-NEXT: [[TMP11:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP30:%.*]], [[BB29]] ] +; SCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[TMP11]], 8 +; SCCP-NEXT: br i1 [[C_1]], label [[BB13:%.*]], label [[BB31:%.*]] +; SCCP: bb13: +; SCCP-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 +; SCCP-NEXT: [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]] +; SCCP-NEXT: [[TMP16:%.*]] = mul i32 [[TMP15]], 4 +; SCCP-NEXT: [[TMP17]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP14]], i32 [[TMP16]]) +; SCCP-NEXT: [[TMP18]] = bitcast i8* [[TMP17]] to i16* +; SCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 2 +; SCCP-NEXT: [[TMP20:%.*]] = load i8, i8* [[TMP19]], align 1 +; SCCP-NEXT: [[TMP21:%.*]] = zext i8 [[TMP20]] to i32 +; SCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0 +; SCCP-NEXT: br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]] +; SCCP: bb23: +; SCCP-NEXT: [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16 +; SCCP-NEXT: store i16 [[TMP24]], i16* [[TMP18]], align 2 +; SCCP-NEXT: br label [[BB31]] +; SCCP: bb25: +; SCCP-NEXT: [[TMP26:%.*]] = load i16, i16* [[TMP18]], align 2 +; SCCP-NEXT: [[TMP27:%.*]] = zext i16 [[TMP26]] to i32 +; SCCP-NEXT: [[TMP28:%.*]] = icmp eq i32 [[TMP27]], [[TMP3]] +; SCCP-NEXT: br i1 [[TMP28]], label [[BB31]], label [[BB29]] +; SCCP: bb29: +; SCCP-NEXT: [[TMP30]] = add nsw i32 [[TMP11]], 1 +; SCCP-NEXT: br label [[BB8]] +; SCCP: bb31: +; SCCP-NEXT: [[TMP32:%.*]] = phi i8* [ [[TMP17]], [[BB23]] ], [ [[TMP17]], [[BB25]] ], [ [[TMP9]], [[BB8]] ] +; SCCP-NEXT: [[TMP33:%.*]] = phi i16* [ [[TMP18]], [[BB23]] ], [ [[TMP18]], [[BB25]] ], [ [[TMP10]], [[BB8]] ] +; SCCP-NEXT: [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0 +; SCCP-NEXT: br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]] +; SCCP: bb35: +; SCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds i8, i8* [[TMP32]], i64 1 +; SCCP-NEXT: br label [[BB66:%.*]] +; SCCP: bb37: +; SCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8 +; SCCP-NEXT: br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]] +; SCCP: bb39: +; SCCP-NEXT: [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1 +; SCCP-NEXT: [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16 +; SCCP-NEXT: store i16 [[TMP41]], i16* bitcast ([4 x i8]* @global.11 to i16*), align 1 +; SCCP-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 +; SCCP-NEXT: [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]] +; SCCP-NEXT: [[TMP44:%.*]] = mul i32 [[TMP43]], 4 +; SCCP-NEXT: [[TMP45:%.*]] = add i32 [[TMP44]], 2 +; SCCP-NEXT: [[TMP46:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP45]]) +; SCCP-NEXT: [[TMP47:%.*]] = load i8, i8* [[TMP46]], align 1 +; SCCP-NEXT: [[TMP48:%.*]] = zext i8 [[TMP47]] to i32 +; SCCP-NEXT: [[TMP49:%.*]] = sub i32 [[TMP43]], 1 +; SCCP-NEXT: [[TMP50:%.*]] = mul i32 [[TMP49]], 4 +; SCCP-NEXT: [[TMP51:%.*]] = add i32 [[TMP50]], 2 +; SCCP-NEXT: [[TMP52:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP51]]) +; SCCP-NEXT: [[TMP53:%.*]] = load i8, i8* [[TMP52]], align 1 +; SCCP-NEXT: [[TMP54:%.*]] = zext i8 [[TMP53]] to i32 +; SCCP-NEXT: [[TMP55:%.*]] = icmp sgt i32 [[TMP48]], [[TMP54]] +; SCCP-NEXT: br i1 [[TMP55]], label [[BB56:%.*]], label [[BB60:%.*]] +; SCCP: bb56: +; SCCP-NEXT: [[TMP57:%.*]] = add nsw i32 [[TMP40]], -1 +; SCCP-NEXT: br label [[BB60]] +; SCCP: bb58: +; SCCP-NEXT: [[TMP59:%.*]] = bitcast i16* [[TMP33]] to i8* +; SCCP-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 [[TMP59]], i64 4, i1 false) +; SCCP-NEXT: br label [[BB60]] +; SCCP: bb60: +; SCCP-NEXT: [[TMP61:%.*]] = phi i32 [ [[TMP57]], [[BB56]] ], [ [[TMP40]], [[BB39]] ], [ [[TMP11]], [[BB58]] ] +; SCCP-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 +; SCCP-NEXT: [[TMP63:%.*]] = add i32 [[TMP7]], 1 +; SCCP-NEXT: [[TMP64:%.*]] = mul i32 [[TMP63]], 4 +; SCCP-NEXT: [[TMP65:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP62]], i32 [[TMP64]]) +; SCCP-NEXT: br label [[BB66]] +; SCCP: bb66: +; SCCP-NEXT: [[TMP67:%.*]] = phi i8* [ [[TMP36]], [[BB35]] ], [ null, [[BB60]] ] +; SCCP-NEXT: ret i8* [[TMP67]] +; +; IPSCCP-LABEL: @wobble( +; IPSCCP-NEXT: bb: +; IPSCCP-NEXT: [[TMP:%.*]] = lshr i32 [[ARG1:%.*]], 16 +; IPSCCP-NEXT: [[TMP2:%.*]] = xor i32 [[TMP]], [[ARG1]] +; IPSCCP-NEXT: [[TMP3:%.*]] = and i32 [[TMP2]], 65535 +; IPSCCP-NEXT: [[TMP4:%.*]] = mul i32 [[ARG1]], 8 +; IPSCCP-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2:%.*]], %struct.blam.2* [[ARG:%.*]], i32 0, i32 1 +; IPSCCP-NEXT: [[TMP6:%.*]] = load i32, i32* [[TMP5]], align 8 +; IPSCCP-NEXT: [[TMP7:%.*]] = and i32 [[TMP4]], [[TMP6]] +; IPSCCP-NEXT: br label [[BB8:%.*]] +; IPSCCP: bb8: +; IPSCCP-NEXT: [[TMP9:%.*]] = phi i8* [ undef, [[BB:%.*]] ], [ [[TMP17:%.*]], [[BB29:%.*]] ] +; IPSCCP-NEXT: [[TMP10:%.*]] = phi i16* [ undef, [[BB]] ], [ [[TMP18:%.*]], [[BB29]] ] +; IPSCCP-NEXT: [[TMP11:%.*]] = phi i32 [ 0, [[BB]] ], [ [[TMP30:%.*]], [[BB29]] ] +; IPSCCP-NEXT: [[C_1:%.*]] = icmp slt i32 [[TMP11]], 8 +; IPSCCP-NEXT: br i1 [[C_1]], label [[BB13:%.*]], label [[BB31:%.*]] +; IPSCCP: bb13: +; IPSCCP-NEXT: [[TMP14:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 +; IPSCCP-NEXT: [[TMP15:%.*]] = add i32 [[TMP7]], [[TMP11]] +; IPSCCP-NEXT: [[TMP16:%.*]] = mul i32 [[TMP15]], 4 +; IPSCCP-NEXT: [[TMP17]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP14]], i32 [[TMP16]]) +; IPSCCP-NEXT: [[TMP18]] = bitcast i8* [[TMP17]] to i16* +; IPSCCP-NEXT: [[TMP19:%.*]] = getelementptr inbounds i8, i8* [[TMP17]], i64 2 +; IPSCCP-NEXT: [[TMP20:%.*]] = load i8, i8* [[TMP19]], align 1 +; IPSCCP-NEXT: [[TMP21:%.*]] = zext i8 [[TMP20]] to i32 +; IPSCCP-NEXT: [[TMP22:%.*]] = icmp eq i32 [[TMP21]], 0 +; IPSCCP-NEXT: br i1 [[TMP22]], label [[BB23:%.*]], label [[BB25:%.*]] +; IPSCCP: bb23: +; IPSCCP-NEXT: [[TMP24:%.*]] = trunc i32 [[TMP3]] to i16 +; IPSCCP-NEXT: store i16 [[TMP24]], i16* [[TMP18]], align 2 +; IPSCCP-NEXT: br label [[BB31]] +; IPSCCP: bb25: +; IPSCCP-NEXT: [[TMP26:%.*]] = load i16, i16* [[TMP18]], align 2 +; IPSCCP-NEXT: [[TMP27:%.*]] = zext i16 [[TMP26]] to i32 +; IPSCCP-NEXT: [[TMP28:%.*]] = icmp eq i32 [[TMP27]], [[TMP3]] +; IPSCCP-NEXT: br i1 [[TMP28]], label [[BB31]], label [[BB29]] +; IPSCCP: bb29: +; IPSCCP-NEXT: [[TMP30]] = add nsw i32 [[TMP11]], 1 +; IPSCCP-NEXT: br label [[BB8]] +; IPSCCP: bb31: +; IPSCCP-NEXT: [[TMP32:%.*]] = phi i8* [ [[TMP17]], [[BB23]] ], [ [[TMP17]], [[BB25]] ], [ [[TMP9]], [[BB8]] ] +; IPSCCP-NEXT: [[TMP33:%.*]] = phi i16* [ [[TMP18]], [[BB23]] ], [ [[TMP18]], [[BB25]] ], [ [[TMP10]], [[BB8]] ] +; IPSCCP-NEXT: [[TMP34:%.*]] = icmp eq i32 [[TMP11]], 0 +; IPSCCP-NEXT: br i1 [[TMP34]], label [[BB35:%.*]], label [[BB37:%.*]] +; IPSCCP: bb35: +; IPSCCP-NEXT: [[TMP36:%.*]] = getelementptr inbounds i8, i8* [[TMP32]], i64 1 +; IPSCCP-NEXT: br label [[BB66:%.*]] +; IPSCCP: bb37: +; IPSCCP-NEXT: [[C_2:%.*]] = icmp eq i32 [[TMP11]], 8 +; IPSCCP-NEXT: br i1 [[C_2]], label [[BB39:%.*]], label [[BB58:%.*]] +; IPSCCP: bb39: +; IPSCCP-NEXT: [[TMP40:%.*]] = add nsw i32 [[TMP11]], -1 +; IPSCCP-NEXT: [[TMP41:%.*]] = trunc i32 [[TMP3]] to i16 +; IPSCCP-NEXT: store i16 [[TMP41]], i16* bitcast ([4 x i8]* @global.11 to i16*), align 1 +; IPSCCP-NEXT: [[TMP42:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 +; IPSCCP-NEXT: [[TMP43:%.*]] = add i32 [[TMP7]], [[TMP40]] +; IPSCCP-NEXT: [[TMP44:%.*]] = mul i32 [[TMP43]], 4 +; IPSCCP-NEXT: [[TMP45:%.*]] = add i32 [[TMP44]], 2 +; IPSCCP-NEXT: [[TMP46:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP45]]) +; IPSCCP-NEXT: [[TMP47:%.*]] = load i8, i8* [[TMP46]], align 1 +; IPSCCP-NEXT: [[TMP48:%.*]] = zext i8 [[TMP47]] to i32 +; IPSCCP-NEXT: [[TMP49:%.*]] = sub i32 [[TMP43]], 1 +; IPSCCP-NEXT: [[TMP50:%.*]] = mul i32 [[TMP49]], 4 +; IPSCCP-NEXT: [[TMP51:%.*]] = add i32 [[TMP50]], 2 +; IPSCCP-NEXT: [[TMP52:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP42]], i32 [[TMP51]]) +; IPSCCP-NEXT: [[TMP53:%.*]] = load i8, i8* [[TMP52]], align 1 +; IPSCCP-NEXT: [[TMP54:%.*]] = zext i8 [[TMP53]] to i32 +; IPSCCP-NEXT: [[TMP55:%.*]] = icmp sgt i32 [[TMP48]], [[TMP54]] +; IPSCCP-NEXT: br i1 [[TMP55]], label [[BB56:%.*]], label [[BB60:%.*]] +; IPSCCP: bb56: +; IPSCCP-NEXT: [[TMP57:%.*]] = add nsw i32 [[TMP40]], -1 +; IPSCCP-NEXT: br label [[BB60]] +; IPSCCP: bb58: +; IPSCCP-NEXT: [[TMP59:%.*]] = bitcast i16* [[TMP33]] to i8* +; IPSCCP-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 [[TMP59]], i64 4, i1 false) +; IPSCCP-NEXT: br label [[BB60]] +; IPSCCP: bb60: +; IPSCCP-NEXT: [[TMP61:%.*]] = phi i32 [ [[TMP57]], [[BB56]] ], [ [[TMP40]], [[BB39]] ], [ [[TMP11]], [[BB58]] ] +; IPSCCP-NEXT: [[TMP62:%.*]] = getelementptr inbounds [[STRUCT_BLAM_2]], %struct.blam.2* [[ARG]], i32 0, i32 0 +; IPSCCP-NEXT: [[TMP63:%.*]] = add i32 [[TMP7]], 1 +; IPSCCP-NEXT: [[TMP64:%.*]] = mul i32 [[TMP63]], 4 +; IPSCCP-NEXT: [[TMP65:%.*]] = call dereferenceable(1) i8* @spam(%struct.baz.1* [[TMP62]], i32 [[TMP64]]) +; IPSCCP-NEXT: br label [[BB66]] +; IPSCCP: bb66: +; IPSCCP-NEXT: [[TMP67:%.*]] = phi i8* [ [[TMP36]], [[BB35]] ], [ null, [[BB60]] ] +; IPSCCP-NEXT: ret i8* [[TMP67]] +; +bb: + %tmp = lshr i32 %arg1, 16 + %tmp2 = xor i32 %tmp, %arg1 + %tmp3 = and i32 %tmp2, 65535 + %tmp4 = mul i32 %arg1, 8 + %tmp5 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 1 + %tmp6 = load i32, i32* %tmp5, align 8 + %tmp7 = and i32 %tmp4, %tmp6 + br label %bb8 + +bb8: ; preds = %bb29, %bb + %tmp9 = phi i8* [ undef, %bb ], [ %tmp17, %bb29 ] + %tmp10 = phi i16* [ undef, %bb ], [ %tmp18, %bb29 ] + %tmp11 = phi i32 [ 0, %bb ], [ %tmp30, %bb29 ] + %c.1 = icmp slt i32 %tmp11, 8 + br i1 %c.1, label %bb13, label %bb31 + +bb13: ; preds = %bb8 + %tmp14 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0 + %tmp15 = add i32 %tmp7, %tmp11 + %tmp16 = mul i32 %tmp15, 4 + %tmp17 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp14, i32 %tmp16) + %tmp18 = bitcast i8* %tmp17 to i16* + %tmp19 = getelementptr inbounds i8, i8* %tmp17, i64 2 + %tmp20 = load i8, i8* %tmp19, align 1 + %tmp21 = zext i8 %tmp20 to i32 + %tmp22 = icmp eq i32 %tmp21, 0 + br i1 %tmp22, label %bb23, label %bb25 + +bb23: ; preds = %bb13 + %tmp24 = trunc i32 %tmp3 to i16 + store i16 %tmp24, i16* %tmp18, align 2 + br label %bb31 + +bb25: ; preds = %bb13 + %tmp26 = load i16, i16* %tmp18, align 2 + %tmp27 = zext i16 %tmp26 to i32 + %tmp28 = icmp eq i32 %tmp27, %tmp3 + br i1 %tmp28, label %bb31, label %bb29 + +bb29: ; preds = %bb25 + %tmp30 = add nsw i32 %tmp11, 1 + br label %bb8 + +bb31: ; preds = %bb25, %bb23, %bb8 + %tmp32 = phi i8* [ %tmp17, %bb23 ], [ %tmp17, %bb25 ], [ %tmp9, %bb8 ] + %tmp33 = phi i16* [ %tmp18, %bb23 ], [ %tmp18, %bb25 ], [ %tmp10, %bb8 ] + %tmp34 = icmp eq i32 %tmp11, 0 + br i1 %tmp34, label %bb35, label %bb37 + +bb35: ; preds = %bb31 + %tmp36 = getelementptr inbounds i8, i8* %tmp32, i64 1 + br label %bb66 + +bb37: ; preds = %bb31 + %c.2 = icmp eq i32 %tmp11, 8 + br i1 %c.2, label %bb39, label %bb58 + +bb39: ; preds = %bb37 + %tmp40 = add nsw i32 %tmp11, -1 + %tmp41 = trunc i32 %tmp3 to i16 + store i16 %tmp41, i16* bitcast ([4 x i8]* @global.11 to i16*), align 1 + %tmp42 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0 + %tmp43 = add i32 %tmp7, %tmp40 + %tmp44 = mul i32 %tmp43, 4 + %tmp45 = add i32 %tmp44, 2 + %tmp46 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp42, i32 %tmp45) + %tmp47 = load i8, i8* %tmp46, align 1 + %tmp48 = zext i8 %tmp47 to i32 + %tmp49 = sub i32 %tmp43, 1 + %tmp50 = mul i32 %tmp49, 4 + %tmp51 = add i32 %tmp50, 2 + %tmp52 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp42, i32 %tmp51) + %tmp53 = load i8, i8* %tmp52, align 1 + %tmp54 = zext i8 %tmp53 to i32 + %tmp55 = icmp sgt i32 %tmp48, %tmp54 + br i1 %tmp55, label %bb56, label %bb60 + +bb56: ; preds = %bb39 + %tmp57 = add nsw i32 %tmp40, -1 + br label %bb60 + +bb58: ; preds = %bb37 + %tmp59 = bitcast i16* %tmp33 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 getelementptr inbounds ([4 x i8], [4 x i8]* @global.11, i64 0, i64 0), i8* align 2 %tmp59, i64 4, i1 false) + br label %bb60 + +bb60: ; preds = %bb58, %bb56, %bb39 + %tmp61 = phi i32 [ %tmp57, %bb56 ], [ %tmp40, %bb39 ], [ %tmp11, %bb58 ] + %tmp62 = getelementptr inbounds %struct.blam.2, %struct.blam.2* %arg, i32 0, i32 0 + %tmp63 = add i32 %tmp7, 1 + %tmp64 = mul i32 %tmp63, 4 + %tmp65 = call dereferenceable(1) i8* @spam(%struct.baz.1* %tmp62, i32 %tmp64) + br label %bb66 + +bb66: ; preds = %bb60, %bb35 + %tmp67 = phi i8* [ %tmp36, %bb35 ], [ null, %bb60 ] + ret i8* %tmp67 +} From ac00376a13e9b637a8bc6b9e2ae6fd668e01b0f9 Mon Sep 17 00:00:00 2001 From: vgxbj Date: Fri, 10 Apr 2020 20:24:21 +0800 Subject: [PATCH 47/56] [Object] Change uint32_t getSymbolFlags() to Expected getSymbolFlags(). This change enables getSymbolFlags() to return errors which benefit error reporting in clients. Differential Revision: https://reviews.llvm.org/D77860 --- .../Orc/RTDyldObjectLinkingLayer.h | 9 ++++- llvm/include/llvm/Object/COFF.h | 2 +- llvm/include/llvm/Object/COFFImportFile.h | 2 +- llvm/include/llvm/Object/ELFObjectFile.h | 27 +++++++++---- llvm/include/llvm/Object/IRObjectFile.h | 2 +- llvm/include/llvm/Object/MachO.h | 2 +- llvm/include/llvm/Object/ObjectFile.h | 6 ++- llvm/include/llvm/Object/SymbolicFile.h | 6 +-- llvm/include/llvm/Object/TapiFile.h | 2 +- llvm/include/llvm/Object/Wasm.h | 2 +- llvm/include/llvm/Object/XCOFFObjectFile.h | 2 +- llvm/lib/ExecutionEngine/Orc/Mangling.cpp | 9 ++++- .../Orc/RTDyldObjectLinkingLayer.cpp | 14 ++++++- .../ExecutionEngine/RuntimeDyld/JITSymbol.cpp | 17 ++++++-- .../RuntimeDyld/RuntimeDyld.cpp | 28 ++++++++----- llvm/lib/Object/ArchiveWriter.cpp | 11 +++-- llvm/lib/Object/COFFObjectFile.cpp | 2 +- llvm/lib/Object/IRObjectFile.cpp | 2 +- llvm/lib/Object/MachOObjectFile.cpp | 6 +-- llvm/lib/Object/ObjectFile.cpp | 13 +++--- llvm/lib/Object/TapiFile.cpp | 2 +- llvm/lib/Object/WasmObjectFile.cpp | 2 +- llvm/lib/Object/XCOFFObjectFile.cpp | 2 +- llvm/tools/dsymutil/DebugMap.cpp | 7 +++- llvm/tools/dsymutil/MachODebugMapParser.cpp | 2 +- llvm/tools/llvm-nm/llvm-nm.cpp | 40 +++++++++++++------ llvm/tools/llvm-objdump/MachODump.cpp | 3 +- llvm/tools/llvm-objdump/llvm-objdump.cpp | 3 +- llvm/tools/llvm-size/llvm-size.cpp | 34 +++++++++++----- llvm/tools/sancov/sancov.cpp | 7 +++- 30 files changed, 185 insertions(+), 81 deletions(-) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h index 3c4ba1a87959d..9ada0871cf0cb 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h @@ -304,8 +304,15 @@ class LegacyRTDyldObjectLinkingLayer : public LegacyRTDyldObjectLinkingLayerBase private: void buildInitialSymbolTable(const OwnedObject &Obj) { for (auto &Symbol : Obj.getBinary()->symbols()) { - if (Symbol.getFlags() & object::SymbolRef::SF_Undefined) + if (Expected SymbolFlagsOrErr = Symbol.getFlags()) { + if (*SymbolFlagsOrErr & object::SymbolRef::SF_Undefined) + continue; + } else { + // FIXME: Raise an error for bad symbols. + consumeError(SymbolFlagsOrErr.takeError()); continue; + } + Expected SymbolName = Symbol.getName(); // FIXME: Raise an error for bad symbols. if (!SymbolName) { diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h index f1386924eccaa..3d0afa12bf387 100644 --- a/llvm/include/llvm/Object/COFF.h +++ b/llvm/include/llvm/Object/COFF.h @@ -896,7 +896,7 @@ class COFFObjectFile : public ObjectFile { uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; void moveSectionNext(DataRefImpl &Sec) const override; diff --git a/llvm/include/llvm/Object/COFFImportFile.h b/llvm/include/llvm/Object/COFFImportFile.h index 5aa8364111180..f38bd898a444b 100644 --- a/llvm/include/llvm/Object/COFFImportFile.h +++ b/llvm/include/llvm/Object/COFFImportFile.h @@ -43,7 +43,7 @@ class COFFImportFile : public SymbolicFile { return Error::success(); } - uint32_t getSymbolFlags(DataRefImpl Symb) const override { + Expected getSymbolFlags(DataRefImpl Symb) const override { return SymbolRef::SF_Global; } diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index c6212be6daa93..3fbfa9ca42d90 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -261,7 +261,7 @@ template class ELFObjectFile : public ELFObjectFileBase { uint64_t getSymbolValueImpl(DataRefImpl Symb) const override; uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; uint8_t getSymbolBinding(DataRefImpl Symb) const override; uint8_t getSymbolOther(DataRefImpl Symb) const override; uint8_t getSymbolELFType(DataRefImpl Symb) const override; @@ -609,7 +609,7 @@ ELFObjectFile::getSymbolType(DataRefImpl Symb) const { } template -uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { +Expected ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { const Elf_Sym *ESym = getSymbol(Sym); uint32_t Result = SymbolRef::SF_None; @@ -626,12 +626,23 @@ uint32_t ELFObjectFile::getSymbolFlags(DataRefImpl Sym) const { if (ESym->getType() == ELF::STT_FILE || ESym->getType() == ELF::STT_SECTION) Result |= SymbolRef::SF_FormatSpecific; - auto DotSymtabSecSyms = EF.symbols(DotSymtabSec); - if (DotSymtabSecSyms && ESym == (*DotSymtabSecSyms).begin()) - Result |= SymbolRef::SF_FormatSpecific; - auto DotDynSymSecSyms = EF.symbols(DotDynSymSec); - if (DotDynSymSecSyms && ESym == (*DotDynSymSecSyms).begin()) - Result |= SymbolRef::SF_FormatSpecific; + if (Expected SymbolsOrErr = + EF.symbols(DotSymtabSec)) { + // Set the SF_FormatSpecific flag for the 0-index null symbol. + if (ESym == SymbolsOrErr->begin()) + Result |= SymbolRef::SF_FormatSpecific; + } else + // TODO: Test this error. + return SymbolsOrErr.takeError(); + + if (Expected SymbolsOrErr = + EF.symbols(DotDynSymSec)) { + // Set the SF_FormatSpecific flag for the 0-index null symbol. + if (ESym == SymbolsOrErr->begin()) + Result |= SymbolRef::SF_FormatSpecific; + } else + // TODO: Test this error. + return SymbolsOrErr.takeError(); if (EF.getHeader()->e_machine == ELF::EM_ARM) { if (Expected NameOrErr = getSymbolName(Sym)) { diff --git a/llvm/include/llvm/Object/IRObjectFile.h b/llvm/include/llvm/Object/IRObjectFile.h index 08b92f1bae50b..338b1941eca1b 100644 --- a/llvm/include/llvm/Object/IRObjectFile.h +++ b/llvm/include/llvm/Object/IRObjectFile.h @@ -38,7 +38,7 @@ class IRObjectFile : public SymbolicFile { ~IRObjectFile() override; void moveSymbolNext(DataRefImpl &Symb) const override; Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; basic_symbol_iterator symbol_end() const override; diff --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h index 351ee419d6aa5..f48e0f1dcd584 100644 --- a/llvm/include/llvm/Object/MachO.h +++ b/llvm/include/llvm/Object/MachO.h @@ -287,7 +287,7 @@ class MachOObjectFile : public ObjectFile { uint32_t getSymbolAlignment(DataRefImpl Symb) const override; uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override; Expected getSymbolType(DataRefImpl Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; Expected getSymbolSection(DataRefImpl Symb) const override; unsigned getSymbolSectionID(SymbolRef Symb) const; unsigned getSectionID(SectionRef Sec) const; diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h index ef82c057012f5..e7d1dcaec9c17 100644 --- a/llvm/include/llvm/Object/ObjectFile.h +++ b/llvm/include/llvm/Object/ObjectFile.h @@ -296,7 +296,11 @@ class ObjectFile : public SymbolicFile { ObjectFile(const ObjectFile &other) = delete; uint64_t getCommonSymbolSize(DataRefImpl Symb) const { - assert(getSymbolFlags(Symb) & SymbolRef::SF_Common); + Expected SymbolFlagsOrErr = getSymbolFlags(Symb); + if (!SymbolFlagsOrErr) + // TODO: Actually report errors helpfully. + report_fatal_error(SymbolFlagsOrErr.takeError()); + assert(*SymbolFlagsOrErr & SymbolRef::SF_Common); return getCommonSymbolSizeImpl(Symb); } diff --git a/llvm/include/llvm/Object/SymbolicFile.h b/llvm/include/llvm/Object/SymbolicFile.h index 1398fa134c81c..442eeddc58376 100644 --- a/llvm/include/llvm/Object/SymbolicFile.h +++ b/llvm/include/llvm/Object/SymbolicFile.h @@ -129,7 +129,7 @@ class BasicSymbolRef { Error printName(raw_ostream &OS) const; /// Get symbol flags (bitwise OR of SymbolRef::Flags) - uint32_t getFlags() const; + Expected getFlags() const; DataRefImpl getRawDataRefImpl() const; const SymbolicFile *getObject() const; @@ -147,7 +147,7 @@ class SymbolicFile : public Binary { virtual Error printSymbolName(raw_ostream &OS, DataRefImpl Symb) const = 0; - virtual uint32_t getSymbolFlags(DataRefImpl Symb) const = 0; + virtual Expected getSymbolFlags(DataRefImpl Symb) const = 0; virtual basic_symbol_iterator symbol_begin() const = 0; @@ -196,7 +196,7 @@ inline Error BasicSymbolRef::printName(raw_ostream &OS) const { return OwningObject->printSymbolName(OS, SymbolPimpl); } -inline uint32_t BasicSymbolRef::getFlags() const { +inline Expected BasicSymbolRef::getFlags() const { return OwningObject->getSymbolFlags(SymbolPimpl); } diff --git a/llvm/include/llvm/Object/TapiFile.h b/llvm/include/llvm/Object/TapiFile.h index bc2e04e1cc96e..b20cd1a37aa0e 100644 --- a/llvm/include/llvm/Object/TapiFile.h +++ b/llvm/include/llvm/Object/TapiFile.h @@ -33,7 +33,7 @@ class TapiFile : public SymbolicFile { Error printSymbolName(raw_ostream &OS, DataRefImpl DRI) const override; - uint32_t getSymbolFlags(DataRefImpl DRI) const override; + Expected getSymbolFlags(DataRefImpl DRI) const override; basic_symbol_iterator symbol_begin() const override; diff --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h index 87d82558562a9..dc90c891ab95f 100644 --- a/llvm/include/llvm/Object/Wasm.h +++ b/llvm/include/llvm/Object/Wasm.h @@ -154,7 +154,7 @@ class WasmObjectFile : public ObjectFile { uint32_t getNumSections() const { return Sections.size(); } void moveSymbolNext(DataRefImpl &Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index 84596b7a97fcc..47aa861b3793e 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -268,7 +268,7 @@ class XCOFFObjectFile : public ObjectFile { // Interface inherited from base classes. void moveSymbolNext(DataRefImpl &Symb) const override; - uint32_t getSymbolFlags(DataRefImpl Symb) const override; + Expected getSymbolFlags(DataRefImpl Symb) const override; basic_symbol_iterator symbol_begin() const override; basic_symbol_iterator symbol_end() const override; diff --git a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp index b85f7290fd161..606304741cf75 100644 --- a/llvm/lib/ExecutionEngine/Orc/Mangling.cpp +++ b/llvm/lib/ExecutionEngine/Orc/Mangling.cpp @@ -93,12 +93,17 @@ getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer) { SymbolFlagsMap SymbolFlags; for (auto &Sym : (*Obj)->symbols()) { + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) + // TODO: Test this error. + return SymFlagsOrErr.takeError(); + // Skip symbols not defined in this object file. - if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) + if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined) continue; // Skip symbols that are not global. - if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) + if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) continue; // Skip symbols that have type SF_File. diff --git a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp index e0582f73b2fcb..5ded369f3bd39 100644 --- a/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp +++ b/llvm/lib/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.cpp @@ -125,8 +125,16 @@ void RTDyldObjectLinkingLayer::emit(MaterializationResponsibility R, return; } + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) { + // TODO: Test this error. + ES.reportError(SymFlagsOrErr.takeError()); + R.failMaterialization(); + return; + } + // Don't include symbols that aren't global. - if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) { + if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global)) { if (auto SymName = Sym.getName()) InternalSymbols->insert(*SymName); else { @@ -200,7 +208,9 @@ Error RTDyldObjectLinkingLayer::onObjLoad( // check whether the symbol is in a comdat section and if so mark it as // weak. for (auto &Sym : COFFObj->symbols()) { - if (Sym.getFlags() & object::BasicSymbolRef::SF_Undefined) + // getFlags() on COFF symbols can't fail. + uint32_t SymFlags = cantFail(Sym.getFlags()); + if (SymFlags & object::BasicSymbolRef::SF_Undefined) continue; auto Name = Sym.getName(); if (!Name) diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp index 031a055a79594..b445d3d49d7e4 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/JITSymbol.cpp @@ -55,12 +55,17 @@ JITSymbolFlags llvm::JITSymbolFlags::fromSummary(GlobalValueSummary *S) { Expected llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { + Expected SymbolFlagsOrErr = Symbol.getFlags(); + if (!SymbolFlagsOrErr) + // TODO: Test this error. + return SymbolFlagsOrErr.takeError(); + JITSymbolFlags Flags = JITSymbolFlags::None; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Weak) Flags |= JITSymbolFlags::Weak; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Common) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Common) Flags |= JITSymbolFlags::Common; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Exported) Flags |= JITSymbolFlags::Exported; auto SymbolType = Symbol.getType(); @@ -75,8 +80,12 @@ llvm::JITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(const object::SymbolRef &Symbol) { + Expected SymbolFlagsOrErr = Symbol.getFlags(); + if (!SymbolFlagsOrErr) + // TODO: Actually report errors helpfully. + report_fatal_error(SymbolFlagsOrErr.takeError()); ARMJITSymbolFlags Flags; - if (Symbol.getFlags() & object::BasicSymbolRef::SF_Thumb) + if (*SymbolFlagsOrErr & object::BasicSymbolRef::SF_Thumb) Flags |= ARMJITSymbolFlags::Thumb; return Flags; } diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp index 5cc8ef58e906f..7e9b0690cceab 100644 --- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp +++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp @@ -214,8 +214,12 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { { JITSymbolResolver::LookupSet Symbols; for (auto &Sym : Obj.symbols()) { - uint32_t Flags = Sym.getFlags(); - if ((Flags & SymbolRef::SF_Common) || (Flags & SymbolRef::SF_Weak)) { + Expected FlagsOrErr = Sym.getFlags(); + if (!FlagsOrErr) + // TODO: Test this error. + return FlagsOrErr.takeError(); + if ((*FlagsOrErr & SymbolRef::SF_Common) || + (*FlagsOrErr & SymbolRef::SF_Weak)) { // Get symbol name. if (auto NameOrErr = Sym.getName()) Symbols.insert(*NameOrErr); @@ -234,10 +238,13 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { LLVM_DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - uint32_t Flags = I->getFlags(); + Expected FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + // TODO: Test this error. + return FlagsOrErr.takeError(); // Skip undefined symbols. - if (Flags & SymbolRef::SF_Undefined) + if (*FlagsOrErr & SymbolRef::SF_Undefined) continue; // Get the symbol type. @@ -287,7 +294,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { } } - if (Flags & SymbolRef::SF_Absolute && + if (*FlagsOrErr & SymbolRef::SF_Absolute && SymType != object::SymbolRef::ST_File) { uint64_t Addr = 0; if (auto AddrOrErr = I->getAddress()) @@ -300,7 +307,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { LLVM_DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)Addr) - << " flags: " << Flags << "\n"); + << " flags: " << *FlagsOrErr << "\n"); GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, *JITSymFlags); } else if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || @@ -332,7 +339,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { LLVM_DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << " SID: " << SectionID << " Offset: " << format("%p", (uintptr_t)SectOffset) - << " flags: " << Flags << "\n"); + << " flags: " << *FlagsOrErr << "\n"); GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, SectOffset, *JITSymFlags); } @@ -592,8 +599,11 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, uint32_t CommonAlign = 1; for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { - uint32_t Flags = I->getFlags(); - if (Flags & SymbolRef::SF_Common) { + Expected FlagsOrErr = I->getFlags(); + if (!FlagsOrErr) + // TODO: Test this error. + return FlagsOrErr.takeError(); + if (*FlagsOrErr & SymbolRef::SF_Common) { // Add the common symbols to a list. We'll allocate them all below. uint64_t Size = I->getCommonSize(); uint32_t Align = I->getAlignment(); diff --git a/llvm/lib/Object/ArchiveWriter.cpp b/llvm/lib/Object/ArchiveWriter.cpp index 7e3416feba49e..6f92c547164ba 100644 --- a/llvm/lib/Object/ArchiveWriter.cpp +++ b/llvm/lib/Object/ArchiveWriter.cpp @@ -264,12 +264,15 @@ static sys::TimePoint now(bool Deterministic) { } static bool isArchiveSymbol(const object::BasicSymbolRef &S) { - uint32_t Symflags = S.getFlags(); - if (Symflags & object::SymbolRef::SF_FormatSpecific) + Expected SymFlagsOrErr = S.getFlags(); + if (!SymFlagsOrErr) + // TODO: Actually report errors helpfully. + report_fatal_error(SymFlagsOrErr.takeError()); + if (*SymFlagsOrErr & object::SymbolRef::SF_FormatSpecific) return false; - if (!(Symflags & object::SymbolRef::SF_Global)) + if (!(*SymFlagsOrErr & object::SymbolRef::SF_Global)) return false; - if (Symflags & object::SymbolRef::SF_Undefined) + if (*SymFlagsOrErr & object::SymbolRef::SF_Undefined) return false; return true; } diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp index 1fd95451e72d7..ebb29ff8c9f1f 100644 --- a/llvm/lib/Object/COFFObjectFile.cpp +++ b/llvm/lib/Object/COFFObjectFile.cpp @@ -209,7 +209,7 @@ Expected COFFObjectFile::getSymbolType(DataRefImpl Ref) const { return SymbolRef::ST_Other; } -uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { +Expected COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { COFFSymbolRef Symb = getCOFFSymbol(Ref); uint32_t Result = SymbolRef::SF_None; diff --git a/llvm/lib/Object/IRObjectFile.cpp b/llvm/lib/Object/IRObjectFile.cpp index 931e842edb448..befba5d57127b 100644 --- a/llvm/lib/Object/IRObjectFile.cpp +++ b/llvm/lib/Object/IRObjectFile.cpp @@ -47,7 +47,7 @@ Error IRObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { return Error::success(); } -uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { return SymTab.getSymbolFlags(getSym(Symb)); } diff --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp index c0aa0b8b3ee31..4d85e6f40ec41 100644 --- a/llvm/lib/Object/MachOObjectFile.cpp +++ b/llvm/lib/Object/MachOObjectFile.cpp @@ -1804,8 +1804,8 @@ Expected MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { } uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { - uint32_t flags = getSymbolFlags(DRI); - if (flags & SymbolRef::SF_Common) { + uint32_t Flags = cantFail(getSymbolFlags(DRI)); + if (Flags & SymbolRef::SF_Common) { MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI); return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); } @@ -1840,7 +1840,7 @@ MachOObjectFile::getSymbolType(DataRefImpl Symb) const { return SymbolRef::ST_Other; } -uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { +Expected MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI); uint8_t MachOType = Entry.n_type; diff --git a/llvm/lib/Object/ObjectFile.cpp b/llvm/lib/Object/ObjectFile.cpp index 1453f9d88130f..fe90378114461 100644 --- a/llvm/lib/Object/ObjectFile.cpp +++ b/llvm/lib/Object/ObjectFile.cpp @@ -55,11 +55,14 @@ bool SectionRef::containsSymbol(SymbolRef S) const { } uint64_t ObjectFile::getSymbolValue(DataRefImpl Ref) const { - uint32_t Flags = getSymbolFlags(Ref); - if (Flags & SymbolRef::SF_Undefined) - return 0; - if (Flags & SymbolRef::SF_Common) - return getCommonSymbolSize(Ref); + if (Expected FlagsOrErr = getSymbolFlags(Ref)) { + if (*FlagsOrErr & SymbolRef::SF_Undefined) + return 0; + if (*FlagsOrErr & SymbolRef::SF_Common) + return getCommonSymbolSize(Ref); + } else + // TODO: Actually report errors helpfully. + report_fatal_error(FlagsOrErr.takeError()); return getSymbolValueImpl(Ref); } diff --git a/llvm/lib/Object/TapiFile.cpp b/llvm/lib/Object/TapiFile.cpp index c409bd8e59951..bbc341295db72 100644 --- a/llvm/lib/Object/TapiFile.cpp +++ b/llvm/lib/Object/TapiFile.cpp @@ -86,7 +86,7 @@ Error TapiFile::printSymbolName(raw_ostream &OS, DataRefImpl DRI) const { return Error::success(); } -uint32_t TapiFile::getSymbolFlags(DataRefImpl DRI) const { +Expected TapiFile::getSymbolFlags(DataRefImpl DRI) const { const auto *Sym = reinterpret_cast(DRI.p); return Sym->Flags; } diff --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp index 2993fd1d55595..3608d95a2d27f 100644 --- a/llvm/lib/Object/WasmObjectFile.cpp +++ b/llvm/lib/Object/WasmObjectFile.cpp @@ -1266,7 +1266,7 @@ const wasm::WasmObjectHeader &WasmObjectFile::getHeader() const { void WasmObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; } -uint32_t WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected WasmObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = SymbolRef::SF_None; const WasmSymbol &Sym = getWasmSymbol(Symb); diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index 3ec19c09616ff..4d2b7f3372bcc 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -392,7 +392,7 @@ void XCOFFObjectFile::getRelocationTypeName( Result.append(Res.begin(), Res.end()); } -uint32_t XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { +Expected XCOFFObjectFile::getSymbolFlags(DataRefImpl Symb) const { uint32_t Result = 0; llvm_unreachable("Not yet implemented!"); return Result; diff --git a/llvm/tools/dsymutil/DebugMap.cpp b/llvm/tools/dsymutil/DebugMap.cpp index 41067106e02c7..3cd1bb0f7b307 100644 --- a/llvm/tools/dsymutil/DebugMap.cpp +++ b/llvm/tools/dsymutil/DebugMap.cpp @@ -256,9 +256,12 @@ MappingTraits::YamlDMO::denormalize(IO &IO) { for (const auto &Sym : Object->symbols()) { uint64_t Address = Sym.getValue(); Expected Name = Sym.getName(); - if (!Name || (Sym.getFlags() & - (SymbolRef::SF_Absolute | SymbolRef::SF_Common))) { + Expected FlagsOrErr = Sym.getFlags(); + if (!Name || !FlagsOrErr || + (*FlagsOrErr & (SymbolRef::SF_Absolute | SymbolRef::SF_Common))) { // TODO: Actually report errors helpfully. + if (!FlagsOrErr) + consumeError(FlagsOrErr.takeError()); if (!Name) consumeError(Name.takeError()); continue; diff --git a/llvm/tools/dsymutil/MachODebugMapParser.cpp b/llvm/tools/dsymutil/MachODebugMapParser.cpp index a9d6c876860c3..42b3f2ecb2b7a 100644 --- a/llvm/tools/dsymutil/MachODebugMapParser.cpp +++ b/llvm/tools/dsymutil/MachODebugMapParser.cpp @@ -493,7 +493,7 @@ void MachODebugMapParser::loadCurrentObjectFileSymbols( // relocations will use the symbol itself, and won't need an // object file address. The object file address field is optional // in the DebugMap, leave it unassigned for these symbols. - uint32_t Flags = Sym.getFlags(); + uint32_t Flags = cantFail(Sym.getFlags()); if (Flags & SymbolRef::SF_Absolute) { CurrentObjectAddresses[*Name] = None; } else if (Flags & SymbolRef::SF_Common) { diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp index e0485514d935d..4e8840569fa8d 100644 --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -306,13 +306,17 @@ struct NMSymbol { static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { bool ADefined; + // Symbol flags have been checked in the caller. + uint32_t AFlags = cantFail(A.Sym.getFlags()); if (A.Sym.getRawDataRefImpl().p) - ADefined = !(A.Sym.getFlags() & SymbolRef::SF_Undefined); + ADefined = !(AFlags & SymbolRef::SF_Undefined); else ADefined = A.TypeChar != 'U'; bool BDefined; + // Symbol flags have been checked in the caller. + uint32_t BFlags = cantFail(B.Sym.getFlags()); if (B.Sym.getRawDataRefImpl().p) - BDefined = !(B.Sym.getFlags() & SymbolRef::SF_Undefined); + BDefined = !(BFlags & SymbolRef::SF_Undefined); else BDefined = B.TypeChar != 'U'; return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < @@ -366,7 +370,7 @@ static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S, uint64_t NValue = 0; MachOObjectFile *MachO = dyn_cast(&Obj); if (Obj.isIR()) { - uint32_t SymFlags = S.Sym.getFlags(); + uint32_t SymFlags = cantFail(S.Sym.getFlags()); if (SymFlags & SymbolRef::SF_Global) NType |= MachO::N_EXT; if (SymFlags & SymbolRef::SF_Hidden) @@ -794,9 +798,15 @@ static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, if (Optional Opt = demangle(S.Name, MachO)) Name = *Opt; } - if (S.Sym.getRawDataRefImpl().p) - SymFlags = S.Sym.getFlags(); - else + if (S.Sym.getRawDataRefImpl().p) { + Expected SymFlagsOrErr = S.Sym.getFlags(); + if (!SymFlagsOrErr) { + // TODO: Test this error. + error(SymFlagsOrErr.takeError(), Obj.getFileName()); + return; + } + SymFlags = *SymFlagsOrErr; + } else SymFlags = S.SymFlags; bool Undefined = SymFlags & SymbolRef::SF_Undefined; @@ -1037,14 +1047,14 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { } static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { - uint32_t Flags = I->getFlags(); + uint32_t Flags = cantFail(I->getFlags()); if (Flags & SymbolRef::SF_Executable) return 't'; return 'd'; } static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { - uint32_t Flags = I->getFlags(); + uint32_t Flags = cantFail(I->getFlags()); // FIXME: should we print 'b'? At the IR level we cannot be sure if this // will be in bss or not, but we could approximate. if (Flags & SymbolRef::SF_Executable) @@ -1076,7 +1086,8 @@ static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) { // section and name, to be used in format=sysv output. static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, StringRef &SecName) { - uint32_t Symflags = I->getFlags(); + // Symbol Flags have been checked in the caller. + uint32_t Symflags = cantFail(I->getFlags()); if (ELFObjectFileBase *ELFObj = dyn_cast(&Obj)) { if (Symflags & object::SymbolRef::SF_Absolute) SecName = "*ABS*"; @@ -1205,10 +1216,15 @@ static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, } if (!(MachO && DyldInfoOnly)) { for (BasicSymbolRef Sym : Symbols) { - uint32_t SymFlags = Sym.getFlags(); - if (!DebugSyms && (SymFlags & SymbolRef::SF_FormatSpecific)) + Expected SymFlagsOrErr = Sym.getFlags(); + if (!SymFlagsOrErr) { + // TODO: Test this error. + error(SymFlagsOrErr.takeError(), Obj.getFileName()); + return; + } + if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) continue; - if (WithoutAliases && (SymFlags & SymbolRef::SF_Indirect)) + if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect)) continue; // If a "-s segname sectname" option was specified and this is a Mach-O // file and this section appears in this file, Nsect will be non-zero then diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index aa71998c2f660..6a66a16b7004a 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/tools/llvm-objdump/MachODump.cpp @@ -7562,7 +7562,8 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, symbolTableWorked = true; DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); - bool IsThumb = MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb; + uint32_t SymbolFlags = cantFail(MachOOF->getSymbolFlags(Symb)); + bool IsThumb = SymbolFlags & SymbolRef::SF_Thumb; // We only need the dedicated Thumb target if there's a real choice // (i.e. we're not targeting M-class) and the function is Thumb. diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index fc4de6be1f907..c264ea6461bc2 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1929,7 +1929,8 @@ void printSymbol(const ObjectFile *O, const SymbolRef &Symbol, return; SymbolRef::Type Type = unwrapOrError(Symbol.getType(), FileName, ArchiveName, ArchitectureName); - uint32_t Flags = Symbol.getFlags(); + uint32_t Flags = + unwrapOrError(Symbol.getFlags(), FileName, ArchiveName, ArchitectureName); // Don't ask a Mach-O STAB symbol for its section unless you know that // STAB symbol's section field refers to a valid section index. Otherwise diff --git a/llvm/tools/llvm-size/llvm-size.cpp b/llvm/tools/llvm-size/llvm-size.cpp index 46ece5a6f0c9d..87fe4693b56aa 100644 --- a/llvm/tools/llvm-size/llvm-size.cpp +++ b/llvm/tools/llvm-size/llvm-size.cpp @@ -196,11 +196,17 @@ static bool considerForSize(ObjectFile *Obj, SectionRef Section) { } /// Total size of all ELF common symbols -static uint64_t getCommonSize(ObjectFile *Obj) { +static Expected getCommonSize(ObjectFile *Obj) { uint64_t TotalCommons = 0; - for (auto &Sym : Obj->symbols()) - if (Obj->getSymbolFlags(Sym.getRawDataRefImpl()) & SymbolRef::SF_Common) + for (auto &Sym : Obj->symbols()) { + Expected SymFlagsOrErr = + Obj->getSymbolFlags(Sym.getRawDataRefImpl()); + if (!SymFlagsOrErr) + // TODO: Test this error. + return SymFlagsOrErr.takeError(); + if (*SymFlagsOrErr & SymbolRef::SF_Common) TotalCommons += Obj->getCommonSymbolSize(Sym.getRawDataRefImpl()); + } return TotalCommons; } @@ -435,10 +441,14 @@ static void printObjectSectionSizes(ObjectFile *Obj) { } if (ELFCommons) { - uint64_t CommonSize = getCommonSize(Obj); - total += CommonSize; - outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(), - CommonSize, static_cast(0)); + if (Expected CommonSizeOrErr = getCommonSize(Obj)) { + total += *CommonSizeOrErr; + outs() << format(fmt.str().c_str(), std::string("*COM*").c_str(), + *CommonSizeOrErr, static_cast(0)); + } else { + error(CommonSizeOrErr.takeError(), Obj->getFileName()); + return; + } } // Print total. @@ -469,8 +479,14 @@ static void printObjectSectionSizes(ObjectFile *Obj) { total_bss += size; } - if (ELFCommons) - total_bss += getCommonSize(Obj); + if (ELFCommons) { + if (Expected CommonSizeOrErr = getCommonSize(Obj)) + total_bss += *CommonSizeOrErr; + else { + error(CommonSizeOrErr.takeError(), Obj->getFileName()); + return; + } + } total = total_text + total_data + total_bss; diff --git a/llvm/tools/sancov/sancov.cpp b/llvm/tools/sancov/sancov.cpp index ffdf36f4e0bfa..ed384a2710072 100644 --- a/llvm/tools/sancov/sancov.cpp +++ b/llvm/tools/sancov/sancov.cpp @@ -657,7 +657,12 @@ findSanitizerCovFunctions(const object::ObjectFile &O) { failIfError(NameOrErr); StringRef Name = NameOrErr.get(); - if (!(Symbol.getFlags() & object::BasicSymbolRef::SF_Undefined) && + Expected FlagsOrErr = Symbol.getFlags(); + // TODO: Test this error. + failIfError(FlagsOrErr); + uint32_t Flags = FlagsOrErr.get(); + + if (!(Flags & object::BasicSymbolRef::SF_Undefined) && isCoveragePointSymbol(Name)) { Result.insert(Address); } From a48f0a3c7e9f0f389b6fa35117ae51f1367973f9 Mon Sep 17 00:00:00 2001 From: Denis Khalikov Date: Wed, 15 Apr 2020 22:02:41 +0300 Subject: [PATCH 48/56] [mlir][vulkan-runner] Simplify vulkan launch call op. Summary: Workgroup size is written into the kernel. So to properly modelling vulkan launch, we have to skip local workgroup size for vulkan launch call op. Differential Revision: https://reviews.llvm.org/D78307 --- ...ConvertGPULaunchFuncToVulkanLaunchFunc.cpp | 36 +++++++++++++++---- .../ConvertLaunchFuncToVulkanCalls.cpp | 12 ++++--- .../Conversion/GPUToVulkan/invoke-vulkan.mlir | 10 +++--- .../lower-gpu-launch-vulkan-launch.mlir | 2 +- 4 files changed, 42 insertions(+), 18 deletions(-) diff --git a/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp b/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp index 95133ac196640..b33edb92605c3 100644 --- a/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp +++ b/mlir/lib/Conversion/GPUToVulkan/ConvertGPULaunchFuncToVulkanLaunchFunc.cpp @@ -65,6 +65,11 @@ class ConvertGpuLaunchFuncToVulkanLaunchFunc /// operand is unsupported by Vulkan runtime. LogicalResult declareVulkanLaunchFunc(Location loc, gpu::LaunchFuncOp launchOp); + +private: + /// The number of vulkan launch configuration operands, placed at the leading + /// positions of the operand list. + static constexpr unsigned kVulkanLaunchNumConfigOperands = 3; }; } // anonymous namespace @@ -93,14 +98,23 @@ void ConvertGpuLaunchFuncToVulkanLaunchFunc::runOnOperation() { LogicalResult ConvertGpuLaunchFuncToVulkanLaunchFunc::declareVulkanLaunchFunc( Location loc, gpu::LaunchFuncOp launchOp) { OpBuilder builder(getOperation().getBody()->getTerminator()); - // TODO: Workgroup size is written into the kernel. So to properly modelling - // vulkan launch, we cannot have the local workgroup size configuration here. - SmallVector vulkanLaunchTypes{launchOp.getOperandTypes()}; - // Check that all operands have supported types except those for the launch - // configuration. + // Workgroup size is written into the kernel. So to properly modelling + // vulkan launch, we have to skip local workgroup size configuration here. + SmallVector gpuLaunchTypes(launchOp.getOperandTypes()); + // The first kVulkanLaunchNumConfigOperands of the gpu.launch_func op are the + // same as the config operands for the vulkan launch call op. + SmallVector vulkanLaunchTypes(gpuLaunchTypes.begin(), + gpuLaunchTypes.begin() + + kVulkanLaunchNumConfigOperands); + vulkanLaunchTypes.append(gpuLaunchTypes.begin() + + gpu::LaunchOp::kNumConfigOperands, + gpuLaunchTypes.end()); + + // Check that all operands have supported types except those for the + // launch configuration. for (auto type : - llvm::drop_begin(vulkanLaunchTypes, gpu::LaunchOp::kNumConfigOperands)) { + llvm::drop_begin(vulkanLaunchTypes, kVulkanLaunchNumConfigOperands)) { if (!isSupportedType(type)) return launchOp.emitError() << type << " is unsupported to run on Vulkan"; } @@ -147,10 +161,18 @@ void ConvertGpuLaunchFuncToVulkanLaunchFunc::convertGpuLaunchFunc( if (failed(declareVulkanLaunchFunc(loc, launchOp))) return signalPassFailure(); + SmallVector gpuLaunchOperands(launchOp.getOperands()); + SmallVector vulkanLaunchOperands( + gpuLaunchOperands.begin(), + gpuLaunchOperands.begin() + kVulkanLaunchNumConfigOperands); + vulkanLaunchOperands.append(gpuLaunchOperands.begin() + + gpu::LaunchOp::kNumConfigOperands, + gpuLaunchOperands.end()); + // Create vulkan launch call op. auto vulkanLaunchCallOp = builder.create( loc, ArrayRef{}, builder.getSymbolRefAttr(kVulkanLaunch), - launchOp.getOperands()); + vulkanLaunchOperands); // Set SPIR-V binary shader data as an attribute. vulkanLaunchCallOp.setAttr( diff --git a/mlir/lib/Conversion/GPUToVulkan/ConvertLaunchFuncToVulkanCalls.cpp b/mlir/lib/Conversion/GPUToVulkan/ConvertLaunchFuncToVulkanCalls.cpp index 3182a5d323ef0..4a481bf959da4 100644 --- a/mlir/lib/Conversion/GPUToVulkan/ConvertLaunchFuncToVulkanCalls.cpp +++ b/mlir/lib/Conversion/GPUToVulkan/ConvertLaunchFuncToVulkanCalls.cpp @@ -16,7 +16,6 @@ #include "../PassDetail.h" #include "mlir/Conversion/GPUToVulkan/ConvertGPUToVulkanPass.h" -#include "mlir/Dialect/GPU/GPUDialect.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" #include "mlir/IR/Attributes.h" #include "mlir/IR/Builders.h" @@ -121,7 +120,7 @@ class VulkanLaunchFuncToVulkanCallsPass /// Checks whether the given LLVM::CallOp is a vulkan launch call op. bool isVulkanLaunchCallOp(LLVM::CallOp callOp) { return (callOp.callee() && callOp.callee().getValue() == kVulkanLaunch && - callOp.getNumOperands() >= gpu::LaunchOp::kNumConfigOperands); + callOp.getNumOperands() >= kVulkanLaunchNumConfigOperands); } /// Checks whether the given LLVM::CallOp is a "ci_face" vulkan launch call @@ -129,7 +128,7 @@ class VulkanLaunchFuncToVulkanCallsPass bool isCInterfaceVulkanLaunchCallOp(LLVM::CallOp callOp) { return (callOp.callee() && callOp.callee().getValue() == kCInterfaceVulkanLaunch && - callOp.getNumOperands() >= gpu::LaunchOp::kNumConfigOperands); + callOp.getNumOperands() >= kVulkanLaunchNumConfigOperands); } /// Translates the given `vulkanLaunchCallOp` to the sequence of Vulkan @@ -162,6 +161,9 @@ class VulkanLaunchFuncToVulkanCallsPass // TODO: Use an associative array to support multiple vulkan launch calls. std::pair spirvAttributes; + /// The number of vulkan launch configuration operands, placed at the leading + /// positions of the operand list. + static constexpr unsigned kVulkanLaunchNumConfigOperands = 3; }; } // anonymous namespace @@ -209,7 +211,7 @@ void VulkanLaunchFuncToVulkanCallsPass::collectSPIRVAttributes( void VulkanLaunchFuncToVulkanCallsPass::createBindMemRefCalls( LLVM::CallOp cInterfaceVulkanLaunchCallOp, Value vulkanRuntime) { if (cInterfaceVulkanLaunchCallOp.getNumOperands() == - gpu::LaunchOp::kNumConfigOperands) + kVulkanLaunchNumConfigOperands) return; OpBuilder builder(cInterfaceVulkanLaunchCallOp); Location loc = cInterfaceVulkanLaunchCallOp.getLoc(); @@ -222,7 +224,7 @@ void VulkanLaunchFuncToVulkanCallsPass::createBindMemRefCalls( for (auto en : llvm::enumerate(cInterfaceVulkanLaunchCallOp.getOperands().drop_front( - gpu::LaunchOp::kNumConfigOperands))) { + kVulkanLaunchNumConfigOperands))) { // Create LLVM constant for the descriptor binding index. Value descriptorBinding = builder.create( loc, getInt32Type(), builder.getI32IntegerAttr(en.index())); diff --git a/mlir/test/Conversion/GPUToVulkan/invoke-vulkan.mlir b/mlir/test/Conversion/GPUToVulkan/invoke-vulkan.mlir index 4313eb5548535..f944d007ebaa9 100644 --- a/mlir/test/Conversion/GPUToVulkan/invoke-vulkan.mlir +++ b/mlir/test/Conversion/GPUToVulkan/invoke-vulkan.mlir @@ -40,11 +40,11 @@ module attributes {gpu.container_module} { %19 = llvm.extractvalue %15[2] : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> %20 = llvm.extractvalue %15[3, 0] : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> %21 = llvm.extractvalue %15[4, 0] : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> - llvm.call @vulkanLaunch(%16, %16, %16, %16, %16, %16, %17, %18, %19, %20, %21) {spirv_blob = "\03\02#\07\00", spirv_entry_point = "kernel"} - : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm<"float*">, !llvm<"float*">, !llvm.i64, !llvm.i64, !llvm.i64) -> () + llvm.call @vulkanLaunch(%16, %16, %16, %17, %18, %19, %20, %21) {spirv_blob = "\03\02#\07\00", spirv_entry_point = "kernel"} + : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm<"float*">, !llvm<"float*">, !llvm.i64, !llvm.i64, !llvm.i64) -> () llvm.return } - llvm.func @vulkanLaunch(%arg0: !llvm.i64, %arg1: !llvm.i64, %arg2: !llvm.i64, %arg3: !llvm.i64, %arg4: !llvm.i64, %arg5: !llvm.i64, %arg6: !llvm<"float*">, %arg7: !llvm<"float*">, %arg8: !llvm.i64, %arg9: !llvm.i64, %arg10: !llvm.i64) { + llvm.func @vulkanLaunch(%arg0: !llvm.i64, %arg1: !llvm.i64, %arg2: !llvm.i64, %arg6: !llvm<"float*">, %arg7: !llvm<"float*">, %arg8: !llvm.i64, %arg9: !llvm.i64, %arg10: !llvm.i64) { %0 = llvm.mlir.undef : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> %1 = llvm.insertvalue %arg6, %0[0] : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> %2 = llvm.insertvalue %arg7, %1[1] : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> @@ -54,8 +54,8 @@ module attributes {gpu.container_module} { %6 = llvm.mlir.constant(1 : index) : !llvm.i64 %7 = llvm.alloca %6 x !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }"> : (!llvm.i64) -> !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }*"> llvm.store %5, %7 : !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }*"> - llvm.call @_mlir_ciface_vulkanLaunch(%arg0, %arg1, %arg2, %arg3, %arg4, %arg5, %7) : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }*">) -> () + llvm.call @_mlir_ciface_vulkanLaunch(%arg0, %arg1, %arg2, %7) : (!llvm.i64, !llvm.i64, !llvm.i64, !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }*">) -> () llvm.return } - llvm.func @_mlir_ciface_vulkanLaunch(!llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm.i64, !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }*">) + llvm.func @_mlir_ciface_vulkanLaunch(!llvm.i64, !llvm.i64, !llvm.i64, !llvm<"{ float*, float*, i64, [1 x i64], [1 x i64] }*">) } diff --git a/mlir/test/Conversion/GPUToVulkan/lower-gpu-launch-vulkan-launch.mlir b/mlir/test/Conversion/GPUToVulkan/lower-gpu-launch-vulkan-launch.mlir index 8e09a199f2796..30dc3a4780366 100644 --- a/mlir/test/Conversion/GPUToVulkan/lower-gpu-launch-vulkan-launch.mlir +++ b/mlir/test/Conversion/GPUToVulkan/lower-gpu-launch-vulkan-launch.mlir @@ -2,7 +2,7 @@ // CHECK: %[[resource:.*]] = alloc() : memref<12xf32> // CHECK: %[[index:.*]] = constant 1 : index -// CHECK: call @vulkanLaunch(%[[index]], %[[index]], %[[index]], %[[index]], %[[index]], %[[index]], %[[resource]]) {spirv_blob = "{{.*}}", spirv_entry_point = "kernel"} +// CHECK: call @vulkanLaunch(%[[index]], %[[index]], %[[index]], %[[resource]]) {spirv_blob = "{{.*}}", spirv_entry_point = "kernel"} module attributes {gpu.container_module} { spv.module Logical GLSL450 requires #spv.vce { From 87383e408d41623ada41e2bbc371b037fa29e894 Mon Sep 17 00:00:00 2001 From: Tobias Hieta Date: Sat, 18 Apr 2020 08:06:37 -0700 Subject: [PATCH 49/56] [ELF][ARM] Increase default max-page-size from 4096 to 6536 See http://lists.llvm.org/pipermail/llvm-dev/2020-April/140549.html For the record, GNU ld changed to 64k max page size in 2014 https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=7572ca8989ead4c3425a1500bc241eaaeffa2c89 "[RFC] ld/ARM: Increase maximum page size to 64kB" Android driver forced 4k page size in AArch64 (D55029) and ARM (D77746). A binary linked with max-page-size=4096 does not run on a system with a higher page size configured. There are some systems out there that do this and it leads to the binary getting `Killed!` by the kernel. In the non-linker-script cases, when linked with -z noseparate-code (default), the max-page-size increase should not cause any size difference. There may be some VMA usage differences, though. Reviewed By: psmith, MaskRay Differential Revision: https://reviews.llvm.org/D77330 --- lld/ELF/Arch/ARM.cpp | 1 + lld/test/ELF/Inputs/far-arm-abs.s | 8 +- lld/test/ELF/Inputs/far-long-arm-abs.s | 8 +- lld/test/ELF/arm-abs32-dyn.s | 22 +- lld/test/ELF/arm-adr.s | 68 ++--- lld/test/ELF/arm-bl-v6.s | 36 +-- lld/test/ELF/arm-branch-rangethunk.s | 64 +++-- .../ELF/arm-branch-undef-weak-plt-thunk.s | 26 +- lld/test/ELF/arm-branch.s | 44 ++-- lld/test/ELF/arm-copy.s | 24 +- lld/test/ELF/arm-execute-only.s | 14 +- lld/test/ELF/arm-exidx-add-missing.s | 52 ++-- lld/test/ELF/arm-exidx-canunwind.s | 26 +- lld/test/ELF/arm-exidx-dedup.s | 56 ++-- lld/test/ELF/arm-exidx-emit-relocs.s | 22 +- lld/test/ELF/arm-exidx-gc.s | 72 ++--- lld/test/ELF/arm-exidx-order.s | 104 ++++---- lld/test/ELF/arm-exidx-shared.s | 6 +- lld/test/ELF/arm-fix-cortex-a8-blx.s | 12 +- lld/test/ELF/arm-fix-cortex-a8-nopatch.s | 56 ++-- lld/test/ELF/arm-fix-cortex-a8-recognize.s | 114 ++++---- lld/test/ELF/arm-fix-cortex-a8-thunk-align.s | 14 +- lld/test/ELF/arm-fpic-got.s | 14 +- lld/test/ELF/arm-gnu-ifunc-plt.s | 82 +++--- lld/test/ELF/arm-gnu-ifunc.s | 46 ++-- lld/test/ELF/arm-got-relative.s | 16 +- lld/test/ELF/arm-gotoff.s | 8 +- lld/test/ELF/arm-icf-exidx.s | 8 +- lld/test/ELF/arm-mov-relocs.s | 106 ++++---- lld/test/ELF/arm-pie-relative.s | 4 +- lld/test/ELF/arm-plt-reloc.s | 86 +++--- lld/test/ELF/arm-sbrel32.s | 10 +- lld/test/ELF/arm-target1.s | 4 +- lld/test/ELF/arm-target2.s | 8 +- lld/test/ELF/arm-thumb-adr.s | 18 +- lld/test/ELF/arm-thumb-interwork-abs.s | 16 +- lld/test/ELF/arm-thumb-interwork-notfunc.s | 88 +++---- lld/test/ELF/arm-thumb-interwork-shared.s | 24 +- lld/test/ELF/arm-thumb-interwork-thunk-v5.s | 32 +-- lld/test/ELF/arm-thumb-ldrlit.s | 18 +- lld/test/ELF/arm-thumb-no-undefined-thunk.s | 6 +- lld/test/ELF/arm-thumb-plt-range-thunk-os.s | 8 +- lld/test/ELF/arm-thumb-plt-reloc.s | 96 +++---- lld/test/ELF/arm-thumb-thunk-empty-pass.s | 12 +- lld/test/ELF/arm-thumb-thunk-symbols.s | 6 +- lld/test/ELF/arm-thumb-undefined-weak.s | 40 +-- lld/test/ELF/arm-thunk-largesection.s | 39 ++- lld/test/ELF/arm-thunk-multipass-plt.s | 76 +++--- lld/test/ELF/arm-thunk-nosuitable.s | 16 +- lld/test/ELF/arm-thunk-re-add.s | 18 +- lld/test/ELF/arm-tls-gd-nonpreemptible.s | 20 +- lld/test/ELF/arm-tls-gd32.s | 58 ++--- lld/test/ELF/arm-tls-ie32.s | 44 ++-- lld/test/ELF/arm-tls-ldm32.s | 30 +-- lld/test/ELF/arm-tls-le32.s | 32 +-- lld/test/ELF/arm-tls-norelax-gd-ie.s | 16 +- lld/test/ELF/arm-tls-norelax-gd-le.s | 16 +- lld/test/ELF/arm-tls-norelax-ie-le.s | 12 +- lld/test/ELF/arm-tls-norelax-ld-le.s | 2 +- lld/test/ELF/arm-undefined-weak.s | 36 +-- .../ELF/global-offset-table-position-arm.s | 4 +- lld/test/ELF/pack-dyn-relocs-arm2.s | 68 ++--- lld/test/ELF/pack-dyn-relocs.s | 246 +++++++++--------- 63 files changed, 1165 insertions(+), 1173 deletions(-) diff --git a/lld/ELF/Arch/ARM.cpp b/lld/ELF/Arch/ARM.cpp index e353bbf40d8fc..195f7936f5d31 100644 --- a/lld/ELF/Arch/ARM.cpp +++ b/lld/ELF/Arch/ARM.cpp @@ -65,6 +65,7 @@ ARM::ARM() { ipltEntrySize = 16; trapInstr = {0xd4, 0xd4, 0xd4, 0xd4}; needsThunks = true; + defaultMaxPageSize = 65536; } uint32_t ARM::calcEFlags() const { diff --git a/lld/test/ELF/Inputs/far-arm-abs.s b/lld/test/ELF/Inputs/far-arm-abs.s index 68d6aabe00b83..47882592029ed 100644 --- a/lld/test/ELF/Inputs/far-arm-abs.s +++ b/lld/test/ELF/Inputs/far-arm-abs.s @@ -1,13 +1,13 @@ .global far .type far,%function -far = 0x201001c +far = 0x202001c .global too_far1 .type too_far1,%function -too_far1 = 0x2020008 +too_far1 = 0x2030008 .global too_far2 .type too_far2,%function -too_far2 = 0x202000c +too_far2 = 0x203000c .global too_far3 .type too_far3,%function -too_far3 = 0x2020010 +too_far3 = 0x2030010 diff --git a/lld/test/ELF/Inputs/far-long-arm-abs.s b/lld/test/ELF/Inputs/far-long-arm-abs.s index 10d9d0292eab6..61c11e6690c83 100644 --- a/lld/test/ELF/Inputs/far-long-arm-abs.s +++ b/lld/test/ELF/Inputs/far-long-arm-abs.s @@ -1,13 +1,13 @@ .global far .type far,%function -far = 0x201001c +far = 0x202001c .global too_far1 .type too_far1,%function -too_far1 = 0x2020014 +too_far1 = 0x2030014 .global too_far2 .type too_far2,%function -too_far2 = 0x2020020 +too_far2 = 0x2030020 .global too_far3 .type too_far3,%function -too_far3 = 0x202002c +too_far3 = 0x203002c \ No newline at end of file diff --git a/lld/test/ELF/arm-abs32-dyn.s b/lld/test/ELF/arm-abs32-dyn.s index 97870accf75c9..5d4aae71d003b 100644 --- a/lld/test/ELF/arm-abs32-dyn.s +++ b/lld/test/ELF/arm-abs32-dyn.s @@ -1,8 +1,8 @@ // REQUIRES: arm // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux %s -o %t.o -// Creates a R_ARM_ABS32 relocation against foo and bar, bar has hidden -// visibility so we expect a R_ARM_RELATIVE +/// Creates a R_ARM_ABS32 relocation against foo and bar, bar has hidden +/// visibility so we expect a R_ARM_RELATIVE .syntax unified .globl foo foo: @@ -14,9 +14,9 @@ bar: .word foo .word bar -// In PIC mode, if R_ARM_TARGET1 represents R_ARM_ABS32 (the default), an -// R_ARM_TARGET1 to a non-preemptable symbol also creates an R_ARM_RELATIVE in -// a writable section. +/// In PIC mode, if R_ARM_TARGET1 represents R_ARM_ABS32 (the default), an +/// R_ARM_TARGET1 to a non-preemptable symbol also creates an R_ARM_RELATIVE in +/// a writable section. .word bar(target1) // RUN: ld.lld -shared -o %t.so %t.o @@ -24,18 +24,18 @@ bar: // RUN: llvm-readelf -x .data %t.so | FileCheck --check-prefix=HEX %s // CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x3204 R_ARM_RELATIVE -// CHECK-NEXT: 0x3208 R_ARM_RELATIVE -// CHECK-NEXT: 0x3200 R_ARM_ABS32 foo 0x0 +// CHECK-NEXT: 0x30204 R_ARM_RELATIVE +// CHECK-NEXT: 0x30208 R_ARM_RELATIVE +// CHECK-NEXT: 0x30200 R_ARM_ABS32 foo 0x0 // CHECK-NEXT: } // CHECK: Symbols [ // CHECK: Symbol { // CHECK: Name: bar -// CHECK-NEXT: Value: 0x11A8 +// CHECK-NEXT: Value: 0x101A8 // CHECK: Symbol { // CHECK: Name: foo -// CHECK-NEXT: Value: 0x11A8 +// CHECK-NEXT: Value: 0x101A8 -// HEX: 0x00003200 00000000 a8110000 a8110000 +// HEX: 0x00030200 00000000 a8010100 a8010100 diff --git a/lld/test/ELF/arm-adr.s b/lld/test/ELF/arm-adr.s index 383a3cad30150..1fb8505f71f50 100644 --- a/lld/test/ELF/arm-adr.s +++ b/lld/test/ELF/arm-adr.s @@ -75,37 +75,37 @@ arm_func: afunc: bx lr -// CHECK: 00011410 : -// CHECK-NEXT: 11410: andeq r0, r0, r0 - -// CHECK: 00011414 : -// CHECK-NEXT: 11414: andeq r0, r0, r0 - -// CHECK: 00011800 <_start>: -/// 0x11800 + 0x8 - 0x3f8 = 0x11410 = dat1 -// CHECK-NEXT: 11800: sub r0, pc, #1016 -/// 0x11804 + 0x8 - 0x3f8 = 0x11414 = dat2 -// CHECK-NEXT: 11804: sub r0, pc, #1016 -/// 0x11808 + 0x8 + 0x400 = 0x11c10 = dat3 -// CHECK-NEXT: 11808: add r0, pc, #1024 -/// 0x1180c + 0x8 + 0x400 = 0x11c14 = dat4 -// CHECK-NEXT: 1180c: add r0, pc, #1024 - -// CHECK: 00011c10 : -// CHECK-NEXT: 11c10: andeq r0, r0, r0 - -// CHECK: 00011c14 : -// CHECK-NEXT: 11c14: andeq r0, r0, r0 - -// CHECK: 00011c18 : -// CHECK-NEXT: 11c18: bx lr - -// CHECK: 00011c1c : -/// 0x11c1c + 0x8 - 0xb = 11c19 = tfunc -// CHECK-NEXT: 11c1c: sub r0, pc, #11 -/// 0x11c20 + 0x8 = 0x11c28 = afunc -// CHECK-NEXT: 11c20: add r0, pc, #0 -// CHECK-NEXT: 11c24: bx lr - -// CHECK: 00011c28 : -// CHECK-NEXT: 11c28: bx lr +// CHECK: 00020410 : +// CHECK-NEXT: 20410: andeq r0, r0, r0 + +// CHECK: 00020414 : +// CHECK-NEXT: 20414: andeq r0, r0, r0 + +// CHECK: 00020800 <_start>: +/// 0x20800 + 0x8 - 0x3f8 = 0x11410 = dat1 +// CHECK-NEXT: 20800: sub r0, pc, #1016 +/// 0x20804 + 0x8 - 0x3f8 = 0x11414 = dat2 +// CHECK-NEXT: 20804: sub r0, pc, #1016 +/// 0x20808 + 0x8 + 0x400 = 0x11c10 = dat3 +// CHECK-NEXT: 20808: add r0, pc, #1024 +/// 0x2080c + 0x8 + 0x400 = 0x11c14 = dat4 +// CHECK-NEXT: 2080c: add r0, pc, #1024 + +// CHECK: 00020c10 : +// CHECK-NEXT: 20c10: andeq r0, r0, r0 + +// CHECK: 00020c14 : +// CHECK-NEXT: 20c14: andeq r0, r0, r0 + +// CHECK: 00020c18 : +// CHECK-NEXT: 20c18: bx lr + +// CHECK: 00020c1c : +/// 0x20c1c + 0x8 - 0xb = 11c19 = tfunc +// CHECK-NEXT: 20c1c: sub r0, pc, #11 +/// 0x20c20 + 0x8 = 0x11c28 = afunc +// CHECK-NEXT: 20c20: add r0, pc, #0 +// CHECK-NEXT: 20c24: bx lr + +// CHECK: 00020c28 : +// CHECK-NEXT: 20c28: bx lr diff --git a/lld/test/ELF/arm-bl-v6.s b/lld/test/ELF/arm-bl-v6.s index 353ec56296470..e8b2668a74cdf 100644 --- a/lld/test/ELF/arm-bl-v6.s +++ b/lld/test/ELF/arm-bl-v6.s @@ -1,19 +1,19 @@ // REQUIRES: arm // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 -// RUN: llvm-objdump -d --triple=armv6-none-linux-gnueabi --start-address=0x12000 --stop-address=0x12008 %t2 | FileCheck --check-prefix=CHECK-ARM1 %s -// RUN: llvm-objdump -d --triple=thumbv6-none-linux-gnueabi %t2 --start-address=0x12008 --stop-address=0x1200c | FileCheck --check-prefix=CHECK-THUMB1 %s -// RUN: llvm-objdump -d --triple=armv6-none-linux-gnueabi --start-address=0x21200c --stop-address=0x212014 %t2 | FileCheck --check-prefix=CHECK-ARM2 %s -// RUN: llvm-objdump -d --triple=thumbv6-none-linux-gnueabi %t2 --start-address=0x613000 --stop-address=0x613002 | FileCheck --check-prefix=CHECK-THUMB2 %s +// RUN: llvm-objdump -d --triple=armv6-none-linux-gnueabi --start-address=0x21000 --stop-address=0x21008 %t2 | FileCheck --check-prefix=CHECK-ARM1 %s +// RUN: llvm-objdump -d --triple=thumbv6-none-linux-gnueabi %t2 --start-address=0x21008 --stop-address=0x2100c | FileCheck --check-prefix=CHECK-THUMB1 %s +// RUN: llvm-objdump -d --triple=armv6-none-linux-gnueabi --start-address=0x22100c --stop-address=0x221014 %t2 | FileCheck --check-prefix=CHECK-ARM2 %s +// RUN: llvm-objdump -d --triple=thumbv6-none-linux-gnueabi %t2 --start-address=0x622000 --stop-address=0x622002 | FileCheck --check-prefix=CHECK-THUMB2 %s -// On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the -// extended range encoding is not supported. The following example has a Thumb -// BL that is out of range on ARM v6 and requires a range extension thunk. -// As v6 does not support MOVT or MOVW instructions the Thunk must not -// use these instructions either. +/// On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the +/// extended range encoding is not supported. The following example has a Thumb +/// BL that is out of range on ARM v6 and requires a range extension thunk. +/// As v6 does not support MOVT or MOVW instructions the Thunk must not +/// use these instructions either. -// ARM v6 supports blx so we shouldn't see the blx not supported warning. +/// ARM v6 supports blx so we shouldn't see the blx not supported warning. // CHECK-NOT: warning: lld uses blx instruction, no object with architecture supporting feature detected. .text .syntax unified @@ -28,8 +28,8 @@ _start: // CHECK-ARM1: Disassembly of section .text: // CHECK-ARM1-EMPTY: // CHECK-ARM1-NEXT: <_start>: -// CHECK-ARM1-NEXT: 12000: 00 00 00 fa blx #0 -// CHECK-ARM1-NEXT: 12004: 1e ff 2f e1 bx lr +// CHECK-ARM1-NEXT: 21000: 00 00 00 fa blx #0 +// CHECK-ARM1-NEXT: 21004: 1e ff 2f e1 bx lr .thumb .section .text.2, "ax", %progbits .globl thumbfunc @@ -38,16 +38,16 @@ thumbfunc: bl farthumbfunc // CHECK-THUMB1: : -// CHECK-THUMB1-NEXT: 12008: 00 f2 00 e8 blx #2097152 -// 6 Megabytes, enough to make farthumbfunc out of range of caller -// on a v6 Arm, but not on a v7 Arm. +// CHECK-THUMB1-NEXT: 21008: 00 f2 00 e8 blx #2097152 +/// 6 Megabytes, enough to make farthumbfunc out of range of caller +/// on a v6 Arm, but not on a v7 Arm. .section .text.3, "ax", %progbits .space 0x200000 // CHECK-ARM2: <__ARMv5ABSLongThunk_farthumbfunc>: -// CHECK-ARM2-NEXT: 21200c: 04 f0 1f e5 ldr pc, [pc, #-4] +// CHECK-ARM2-NEXT: 22100c: 04 f0 1f e5 ldr pc, [pc, #-4] // CHECK-ARM2: <$d>: -// CHECK-ARM2-NEXT: 212010: 01 30 61 00 .word 0x00613001 +// CHECK-ARM2-NEXT: 221010: 01 20 62 00 .word 0x00622001 .section .text.4, "ax", %progbits .space 0x200000 @@ -62,4 +62,4 @@ thumbfunc: farthumbfunc: bx lr // CHECK-THUMB2: : -// CHECK-THUMB2-NEXT: 613000: 70 47 bx lr +// CHECK-THUMB2-NEXT: 622000: 70 47 bx lr diff --git a/lld/test/ELF/arm-branch-rangethunk.s b/lld/test/ELF/arm-branch-rangethunk.s index 81c0618871f4b..7a208006e9c56 100644 --- a/lld/test/ELF/arm-branch-rangethunk.s +++ b/lld/test/ELF/arm-branch-rangethunk.s @@ -2,50 +2,46 @@ // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar // RUN: ld.lld %t %tfar -o %t2 -// RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=SHORT %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=SHORT %s // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-long-arm-abs.s -o %tfarlong // RUN: ld.lld %t %tfarlong -o %t3 -// RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=LONG %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=LONG %s .syntax unified .section .text, "ax",%progbits .globl _start .balign 0x10000 .type _start,%function _start: - // address of too_far symbols are just out of range of ARM branch with - // 26-bit immediate field and an addend of -8 + /// address of too_far symbols are just out of range of ARM branch with + /// 26-bit immediate field and an addend of -8 bl too_far1 b too_far2 beq too_far3 -// SHORT: Disassembly of section .text: -// SHORT-EMPTY: -// SHORT-NEXT: <_start>: -// SHORT-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1> -// SHORT-NEXT: 20004: 01 00 00 ea b #4 <__ARMv7ABSLongThunk_too_far2> -// SHORT-NEXT: 20008: 01 00 00 0a beq #4 <__ARMv7ABSLongThunk_too_far3> -// SHORT: <__ARMv7ABSLongThunk_too_far1>: -// SHORT-NEXT: 2000c: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff4> -// SHORT: <__ARMv7ABSLongThunk_too_far2>: -// SHORT-NEXT: 20010: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff8> -// SHORT: <__ARMv7ABSLongThunk_too_far3>: -// SHORT-NEXT: 20014: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffffc> +// SHORT: 00030000 <_start>: +// SHORT-NEXT: 30000: bl #4 <__ARMv7ABSLongThunk_too_far1> +// SHORT-NEXT: 30004: b #4 <__ARMv7ABSLongThunk_too_far2> +// SHORT-NEXT: 30008: beq #4 <__ARMv7ABSLongThunk_too_far3> +// SHORT: 0003000c <__ARMv7ABSLongThunk_too_far1>: +// SHORT-NEXT: 3000c: b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff4> +// SHORT: 00030010 <__ARMv7ABSLongThunk_too_far2>: +// SHORT-NEXT: 30010: b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffff8> +// SHORT: 00030014 <__ARMv7ABSLongThunk_too_far3>: +// SHORT-NEXT: 30014: b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffffc> -// LONG: Disassembly of section .text: -// LONG-EMPTY: -// LONG-NEXT: <_start>: -// LONG-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1> -// LONG-NEXT: 20004: 03 00 00 ea b #12 <__ARMv7ABSLongThunk_too_far2> -// LONG-NEXT: 20008: 05 00 00 0a beq #20 <__ARMv7ABSLongThunk_too_far3> -// LONG: <__ARMv7ABSLongThunk_too_far1>: -// LONG-NEXT: 2000c: 14 c0 00 e3 movw r12, #20 -// LONG-NEXT: 20010: 02 c2 40 e3 movt r12, #514 -// LONG-NEXT: 20014: 1c ff 2f e1 bx r12 -// LONG: <__ARMv7ABSLongThunk_too_far2>: -// LONG-NEXT: 20018: 20 c0 00 e3 movw r12, #32 -// LONG-NEXT: 2001c: 02 c2 40 e3 movt r12, #514 -// LONG-NEXT: 20020: 1c ff 2f e1 bx r12 -// LONG: <__ARMv7ABSLongThunk_too_far3>: -// LONG-NEXT: 20024: 2c c0 00 e3 movw r12, #44 -// LONG-NEXT: 20028: 02 c2 40 e3 movt r12, #514 -// LONG-NEXT: 2002c: 1c ff 2f e1 bx r12 +// LONG: 00030000 <_start>: +// LONG-NEXT: 30000: bl #4 <__ARMv7ABSLongThunk_too_far1> +// LONG-NEXT: 30004: b #12 <__ARMv7ABSLongThunk_too_far2> +// LONG-NEXT: 30008: beq #20 <__ARMv7ABSLongThunk_too_far3> +// LONG: 0003000c <__ARMv7ABSLongThunk_too_far1>: +// LONG-NEXT: 3000c: movw r12, #20 +// LONG-NEXT: 30010: movt r12, #515 +// LONG-NEXT: 30014: bx r12 +// LONG: 00030018 <__ARMv7ABSLongThunk_too_far2>: +// LONG-NEXT: 30018: movw r12, #32 +// LONG-NEXT: 3001c: movt r12, #515 +// LONG-NEXT: 30020: bx r12 +// LONG: 00030024 <__ARMv7ABSLongThunk_too_far3>: +// LONG-NEXT: 30024: movw r12, #44 +// LONG-NEXT: 30028: movt r12, #515 +// LONG-NEXT: 3002c: bx r12 \ No newline at end of file diff --git a/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s b/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s index 9a4a41fd800b0..1f6acd2ca5216 100644 --- a/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s +++ b/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s @@ -3,10 +3,10 @@ // RUN: ld.lld %t1.o --shared -soname=t1.so -o %t1.so // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o // RUN: ld.lld %t.o %t1.so -o %t -// RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi --start-address=0x111e4 --stop-address=0x11204 %t | FileCheck %s +// RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi --start-address=0x201e4 --stop-address=0x20204 %t | FileCheck %s -// When we are dynamic linking, undefined weak references have a PLT entry so -// we must create a thunk for the branch to the PLT entry. +/// When we are dynamic linking, undefined weak references have a PLT entry so +/// we must create a thunk for the branch to the PLT entry. .text .globl bar2 @@ -16,21 +16,21 @@ _start: .type _start, %function b undefined_weak_we_expect_a_plt_entry_for bl bar2 -// Create 32 Mb gap between the call to the weak reference and the PLT so that -// the b and bl need a range-extension thunk. +/// Create 32 Mb gap between the call to the weak reference and the PLT so that +/// the b and bl need a range-extension thunk. .section .text.1, "ax", %progbits .space 32 * 1024 * 1024 // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 111e4: 00 00 00 ea b #0 <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for> -// CHECK-NEXT: 111e8: 02 00 00 eb bl #8 <__ARMv7ABSLongThunk_bar2> +// CHECK-NEXT: 201e4: 00 00 00 ea b #0 <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for> +// CHECK-NEXT: 201e8: 02 00 00 eb bl #8 <__ARMv7ABSLongThunk_bar2> // CHECK: <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>: -// CHECK-NEXT: 111ec: 30 c2 01 e3 movw r12, #4656 -// CHECK-NEXT: 111f0: 01 c2 40 e3 movt r12, #513 -// CHECK-NEXT: 111f4: 1c ff 2f e1 bx r12 +// CHECK-NEXT: 201ec: 30 c2 00 e3 movw r12, #560 +// CHECK-NEXT: 201f0: 02 c2 40 e3 movt r12, #514 +// CHECK-NEXT: 201f4: 1c ff 2f e1 bx r12 // CHECK: <__ARMv7ABSLongThunk_bar2>: -// CHECK-NEXT: 111f8: 40 c2 01 e3 movw r12, #4672 -// CHECK-NEXT: 111fc: 01 c2 40 e3 movt r12, #513 -// CHECK-NEXT: 11200: 1c ff 2f e1 bx r12 +// CHECK-NEXT: 201f8: 40 c2 00 e3 movw r12, #576 +// CHECK-NEXT: 201fc: 02 c2 40 e3 movt r12, #514 +// CHECK-NEXT: 20200: 1c ff 2f e1 bx r12 diff --git a/lld/test/ELF/arm-branch.s b/lld/test/ELF/arm-branch.s index c2fab0571bcb0..27d6313bd301f 100644 --- a/lld/test/ELF/arm-branch.s +++ b/lld/test/ELF/arm-branch.s @@ -7,7 +7,7 @@ // RUN: .caller : { *(.text) } \ // RUN: .callee2 : { *(.callee_high) } } " > %t.script // RUN: ld.lld --script %t.script %t %tfar -o %t2 -// RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s .syntax unified .section .callee_low, "ax",%progbits .align 2 @@ -37,25 +37,23 @@ _start: callee_high: bx lr -// CHECK: Disassembly of section .caller: -// CHECK-EMPTY: -// CHECK-NEXT: <_start>: -// S(callee_low) = 0xb4 P = 0x10000 A = -8 = -0xff54 = -65364 -// CHECK-NEXT: 10000: 2b c0 ff eb bl #-65364 -// S(callee_low) = 0xb4 P = 0x10004 A = -8 = -0xff58 = -65368 -// CHECK-NEXT: 10004: 2a c0 ff ea b #-65368 -// S(callee_low) = 0xb4 P = 0x10008 A = -8 = -0xff5c -65372 -// CHECK-NEXT: 10008: 29 c0 ff 0a beq #-65372 -// S(callee_high) = 0x10028 P = 0x1000c A = -8 = 0x14 = 20 -// CHECK-NEXT: 1000c: 05 00 00 eb bl #20 -// S(callee_high) = 0x10028 P = 0x10010 A = -8 = 0x10 = 16 -// CHECK-NEXT: 10010: 04 00 00 ea b #16 -// S(callee_high) = 0x10028 P = 0x10014 A = -8 = 0x0c =12 -// CHECK-NEXT: 10014: 03 00 00 1a bne #12 -// S(far) = 0x201001c P = 0x10018 A = -8 = 0x1fffffc = 33554428 -// CHECK-NEXT: 10018: ff ff 7f eb bl #33554428 -// S(far) = 0x201001c P = 0x1001c A = -8 = 0x1fffff8 = 33554424 -// CHECK-NEXT: 1001c: fe ff 7f ea b #33554424 -// S(far) = 0x201001c P = 0x10020 A = -8 = 0x1fffff4 = 33554420 -// CHECK-NEXT: 10020: fd ff 7f ca bgt #33554420 -// CHECK-NEXT: 10024: 1e ff 2f e1 bx lr +// CHECK: 00010000 <_start>: +/// S(callee_low) = 0xb4 P = 0x10000 A = -8 = -0xff54 = -65364 +// CHECK-NEXT: 10000: bl #-65364 +/// S(callee_low) = 0xb4 P = 0x10004 A = -8 = -0xff58 = -65368 +// CHECK-NEXT: 10004: b #-65368 +/// S(callee_low) = 0xb4 P = 0x10008 A = -8 = -0xff5c -65372 +// CHECK-NEXT: 10008: beq #-65372 +/// S(callee_high) = 0x10028 P = 0x1000c A = -8 = 0x14 = 20 +// CHECK-NEXT: 1000c: bl #28 +/// S(callee_high) = 0x10028 P = 0x10010 A = -8 = 0x10 = 16 +// CHECK-NEXT: 10010: b #24 +/// S(callee_high) = 0x10028 P = 0x10014 A = -8 = 0x0c =12 +// CHECK-NEXT: 10014: bne #20 +/// S(far) = 0x201001c P = 0x10018 A = -8 = 0x1fffffc = 33554428 +// CHECK-NEXT: 10018: bl #8 +/// S(far) = 0x201001c P = 0x1001c A = -8 = 0x1fffff8 = 33554424 +// CHECK-NEXT: 1001c: b #4 +/// S(far) = 0x201001c P = 0x10020 A = -8 = 0x1fffff4 = 33554420 +// CHECK-NEXT: 10020: bgt #0 +// CHECK-NEXT: 10024: bx lr diff --git a/lld/test/ELF/arm-copy.s b/lld/test/ELF/arm-copy.s index afdfb9f93dbd8..7cbc1cfde2391 100644 --- a/lld/test/ELF/arm-copy.s +++ b/lld/test/ELF/arm-copy.s @@ -25,7 +25,7 @@ _start: // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x13220 +// CHECK-NEXT: Address: 0x40220 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 8 // CHECK-NEXT: Link: @@ -35,13 +35,13 @@ _start: // CHECK: Relocations [ // CHECK-NEXT: Section {{.*}} .rel.dyn { // CHECK-NEXT: Relocation { -// CHECK-NEXT: Offset: 0x13220 +// CHECK-NEXT: Offset: 0x40220 // CHECK-NEXT: Type: R_ARM_COPY // CHECK-NEXT: Symbol: y // CHECK-NEXT: Addend: 0x0 // CHECK-NEXT: } // CHECK-NEXT: Relocation { -// CHECK-NEXT: Offset: 0x13224 +// CHECK-NEXT: Offset: 0x40224 // CHECK-NEXT: Type: R_ARM_COPY // CHECK-NEXT: Symbol: z // CHECK-NEXT: Addend: 0x0 @@ -50,14 +50,14 @@ _start: // CHECK: Symbols [ // CHECK: Name: y -// CHECK-NEXT: Value: 0x13220 +// CHECK-NEXT: Value: 0x40220 // CHECK-NEXT: Size: 4 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object // CHECK-NEXT: Other: // CHECK-NEXT: Section: .bss // CHECK: Name: z -// CHECK-NEXT: Value: 0x13224 +// CHECK-NEXT: Value: 0x40224 // CHECK-NEXT: Size: 4 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object @@ -67,13 +67,13 @@ _start: // CODE: Disassembly of section .text: // CODE-EMPTY: // CODE-NEXT: <_start>: -// S + A = 0x13220 + 0 = 65536 * 1 + 12832 -// CODE-NEXT: 111b4: movw r2, #12832 -// CODE-NEXT: 111b8: movt r2, #1 -// CODE-NEXT: 111bc: ldr r3, [pc, #4] -// CODE-NEXT: 111c0: ldr r3, [r3] +/// S + A = 0x40220 + 0 = 65536 * 1 + 544 +// CODE-NEXT: 201b4: movw r2, #544 +// CODE-NEXT: 201b8: movt r2, #4 +// CODE-NEXT: 201bc: ldr r3, [pc, #4] +// CODE-NEXT: 201c0: ldr r3, [r3] // RODATA: Contents of section .rodata: -// S(z) = 0x13004 -// RODATA-NEXT: 101b0 24320100 +/// S(z) = 0x40004 +// RODATA-NEXT: 101b0 24020400 diff --git a/lld/test/ELF/arm-execute-only.s b/lld/test/ELF/arm-execute-only.s index 1d38cae6ec663..483d33d19fcd4 100644 --- a/lld/test/ELF/arm-execute-only.s +++ b/lld/test/ELF/arm-execute-only.s @@ -10,19 +10,19 @@ // RUN: ld.lld %t.o %t2.o -o %t.so -shared // RUN: llvm-readelf -l %t.so | FileCheck --check-prefix=DIFF --implicit-check-not=LOAD %s -// CHECK: LOAD 0x000000 0x00000000 0x00000000 0x0016d 0x0016d R 0x1000 -// CHECK: LOAD 0x000170 0x00001170 0x00001170 0x{{.*}} 0x{{.*}} R E 0x1000 -// CHECK: LOAD 0x000174 0x00002174 0x00002174 0x{{.*}} 0x{{.*}} E 0x1000 -// CHECK: LOAD 0x000178 0x00003178 0x00003178 0x00038 0x00038 RW 0x1000 +// CHECK: LOAD 0x000000 0x00000000 0x00000000 0x0016d 0x0016d R 0x10000 +// CHECK: LOAD 0x000170 0x00010170 0x00010170 0x{{.*}} 0x{{.*}} R E 0x10000 +// CHECK: LOAD 0x000174 0x00020174 0x00020174 0x{{.*}} 0x{{.*}} E 0x10000 +// CHECK: LOAD 0x000178 0x00030178 0x00030178 0x00038 0x00038 RW 0x10000 // CHECK: 01 .dynsym .gnu.hash .hash .dynstr // CHECK: 02 .text // CHECK: 03 .foo // CHECK: 04 .dynamic -// DIFF: LOAD 0x000000 0x00000000 0x00000000 0x0014d 0x0014d R 0x1000 -// DIFF: LOAD 0x000150 0x00001150 0x00001150 0x0000c 0x0000c R E 0x1000 -// DIFF: LOAD 0x00015c 0x0000215c 0x0000215c 0x00038 0x00038 RW 0x1000 +// DIFF: LOAD 0x000000 0x00000000 0x00000000 0x0014d 0x0014d R 0x10000 +// DIFF: LOAD 0x000150 0x00010150 0x00010150 0x0000c 0x0000c R E 0x10000 +// DIFF: LOAD 0x00015c 0x0002015c 0x0002015c 0x00038 0x00038 RW 0x10000 // DIFF: 01 .dynsym .gnu.hash .hash .dynstr // DIFF: 02 .text .foo diff --git a/lld/test/ELF/arm-exidx-add-missing.s b/lld/test/ELF/arm-exidx-add-missing.s index da3c271f2355e..856b1d2932047 100644 --- a/lld/test/ELF/arm-exidx-add-missing.s +++ b/lld/test/ELF/arm-exidx-add-missing.s @@ -5,17 +5,17 @@ // RUN: ld.lld %t -o %t3 // RUN: llvm-objdump -s %t3 | FileCheck %s --check-prefix=CHECK-MERGE -// The ARM.exidx section is a table of 8-byte entries of the form: -// | PREL31 Relocation to start of function | Unwinding information | -// The range of addresses covered by the table entry is terminated by the -// next table entry. This means that an executable section without a .ARM.exidx -// section does not terminate the range of addresses. To fix this the linker -// synthesises an EXIDX_CANTUNWIND entry for each section without a .ARM.exidx -// section. +/// The ARM.exidx section is a table of 8-byte entries of the form: +/// | PREL31 Relocation to start of function | Unwinding information | +/// The range of addresses covered by the table entry is terminated by the +/// next table entry. This means that an executable section without a .ARM.exidx +/// section does not terminate the range of addresses. To fix this the linker +/// synthesises an EXIDX_CANTUNWIND entry for each section without a .ARM.exidx +/// section. .syntax unified - // Expect inline unwind instructions + /// Expect inline unwind instructions .section .text.01, "ax", %progbits .global f1 f1: @@ -25,18 +25,18 @@ f1: .setfp r7, sp, #0 .fnend - // Expect no unwind information from assembler. The linker must - // synthesise an EXIDX_CANTUNWIND entry to prevent an exception - // thrown through f2 from matching against the unwind instructions - // for f1. + /// Expect no unwind information from assembler. The linker must + /// synthesise an EXIDX_CANTUNWIND entry to prevent an exception + /// thrown through f2 from matching against the unwind instructions + /// for f1. .section .text.02, "ax", %progbits .global f2 f2: bx lr - // Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker - // generated EXIDX_CANTUNWIND as if the assembler had generated it. + /// Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker + /// generated EXIDX_CANTUNWIND as if the assembler had generated it. .section .text.03, "ax",%progbits .global f3 f3: @@ -45,22 +45,22 @@ f3: .cantunwind .fnend - // Dummy implementation of personality routines to satisfy reference - // from exception tables, linker will generate EXIDX_CANTUNWIND. + /// Dummy implementation of personality routines to satisfy reference + /// from exception tables, linker will generate EXIDX_CANTUNWIND. .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits .global __aeabi_unwind_cpp_pr0 __aeabi_unwind_cpp_pr0: bx lr -// f1, f2 -// CHECK: 100d4 28100000 08849780 24100000 01000000 -// f3, __aeabi_unwind_cpp_pr0 -// CHECK-NEXT: 100e4 20100000 01000000 1c100000 01000000 -// sentinel -// CHECK-NEXT: 100f4 18100000 01000000 +/// f1, f2 +// CHECK: 100d4 28000100 08849780 24000100 01000000 +/// f3, __aeabi_unwind_cpp_pr0 +// CHECK-NEXT: 100e4 20000100 01000000 1c000100 01000000 +/// sentinel +// CHECK-NEXT: 100f4 18000100 01000000 -// f1, (f2, f3, __aeabi_unwind_cpp_pr0) -// CHECK-MERGE: 100d4 18100000 08849780 14100000 01000000 -// sentinel -// CHECK-MERGE-NEXT: 100e4 18100000 01000000 +/// f1, (f2, f3, __aeabi_unwind_cpp_pr0) +// CHECK-MERGE: 100d4 18000100 08849780 14000100 01000000 +/// sentinel +// CHECK-MERGE-NEXT: 100e4 18000100 01000000 diff --git a/lld/test/ELF/arm-exidx-canunwind.s b/lld/test/ELF/arm-exidx-canunwind.s index 765892ef544d9..0c87b828cd818 100644 --- a/lld/test/ELF/arm-exidx-canunwind.s +++ b/lld/test/ELF/arm-exidx-canunwind.s @@ -55,26 +55,26 @@ _start: // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 11108: bl #4 +// CHECK-NEXT: 20108: bl #4 // CHECK-NEXT: bl #4 // CHECK-NEXT: bx lr // CHECK: : -// CHECK-NEXT: 11114: bx lr +// CHECK-NEXT: 20114: bx lr // CHECK: : -// CHECK-NEXT: 11118: bx lr +// CHECK-NEXT: 20118: bx lr // CHECK: <__gxx_personality_v0>: -// CHECK-NEXT: 1111c: bx lr +// CHECK-NEXT: 2011c: bx lr // CHECK: <__aeabi_unwind_cpp_pr0>: -// CHECK-NEXT: 11120: bx lr +// CHECK-NEXT: 20120: bx lr -// 100d4 + 0x1034 = 0x11108 = main (linker generated cantunwind) -// 100dc + 0x1038 = 0x11114 = func1 (inline unwinding data) -// CHECK-EXIDX: 100d4 34100000 01000000 38100000 08849780 -// 100e4 + 0x1034 = 0x11118 = func2 (100e8 + 14 = 100fc = .ARM.extab entry) -// 100ec + 0x1030 = 0x1111c = __gxx_personality_v0 (linker generated cantunwind) -// CHECK-EXIDX-NEXT: 100e4 34100000 14000000 30100000 01000000 -// 100f4 + 0x1030 = 1101c = sentinel -// CHECK-EXIDX-NEXT: 100f4 30100000 01000000 +/// 100d4 + 0x10034 = 0x20108 = main (linker generated cantunwind) +/// 100dc + 0x10038 = 0x20114 = func1 (inline unwinding data) +// CHECK-EXIDX: 100d4 34000100 01000000 38000100 08849780 +/// 100e4 + 0x10034 = 0x20118 = func2 (100e8 + 14 = 100fc = .ARM.extab entry) +/// 100ec + 0x10030 = 0x2011c = __gxx_personality_v0 (linker generated cantunwind) +// CHECK-EXIDX-NEXT: 100e4 34000100 14000000 30000100 01000000 +/// 100f4 + 0x10030 = 1101c = sentinel +// CHECK-EXIDX-NEXT: 100f4 30000100 01000000 // CHECK-PT: Name: .ARM.exidx // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) diff --git a/lld/test/ELF/arm-exidx-dedup.s b/lld/test/ELF/arm-exidx-dedup.s index b0ad82e5ea12c..33c85ed54c8d4 100644 --- a/lld/test/ELF/arm-exidx-dedup.s +++ b/lld/test/ELF/arm-exidx-dedup.s @@ -5,29 +5,29 @@ // RUN: ld.lld %t -o %t3 // RUN: llvm-objdump -s %t3 | FileCheck %s -// Test that lld can at least remove duplicate .ARM.exidx sections. A more -// fine grained implementation will be able to remove duplicate entries within -// a .ARM.exidx section. +/// Test that lld can at least remove duplicate .ARM.exidx sections. A more +/// fine grained implementation will be able to remove duplicate entries within +/// a .ARM.exidx section. -// With duplicate entries +/// With duplicate entries // CHECK-DUPS: Contents of section .ARM.exidx: -// CHECK-DUPS-NEXT: 100d4 78100000 01000000 74100000 01000000 -// CHECK-DUPS-NEXT: 100e4 70100000 01000000 6c100000 01000000 -// CHECK-DUPS-NEXT: 100f4 68100000 08849780 64100000 08849780 -// CHECK-DUPS-NEXT: 10104 60100000 08849780 5c100000 24000000 -// CHECK-DUPS-NEXT: 10114 58100000 28000000 54100000 01000000 -// CHECK-DUPS-NEXT: 10124 50100000 01000000 4c100000 01000000 +// CHECK-DUPS-NEXT: 100d4 78000100 01000000 74000100 01000000 +// CHECK-DUPS-NEXT: 100e4 70000100 01000000 6c000100 01000000 +// CHECK-DUPS-NEXT: 100f4 68000100 08849780 64000100 08849780 +// CHECK-DUPS-NEXT: 10104 60000100 08849780 5c000100 24000000 +// CHECK-DUPS-NEXT: 10114 58000100 28000000 54000100 01000000 +// CHECK-DUPS-NEXT: 10124 50000100 01000000 4c000100 01000000 // CHECK-DUPS-NEXT: Contents of section .ARM.extab: -// After duplicate entry removal +/// After duplicate entry removal // CHECK: Contents of section .ARM.exidx: -// CHECK-NEXT: 100d4 48100000 01000000 50100000 08849780 -// CHECK-NEXT: 100e4 54100000 1c000000 50100000 20000000 -// CHECK-NEXT: 100f4 4c100000 01000000 4c100000 01000000 +// CHECK-NEXT: 100d4 48000100 01000000 50000100 08849780 +// CHECK-NEXT: 100e4 54000100 1c000000 50000100 20000000 +// CHECK-NEXT: 100f4 4c000100 01000000 4c000100 01000000 // CHECK-NEXT: Contents of section .ARM.extab: .syntax unified - // Expect 1 EXIDX_CANTUNWIND entry. + /// Expect 1 EXIDX_CANTUNWIND entry. .section .text.00, "ax", %progbits .globl _start _start: @@ -36,7 +36,7 @@ _start: .cantunwind .fnend - // Expect .ARM.exidx.text.01 to be identical to .ARM.exidx.text.00 + /// Expect .ARM.exidx.text.01 to be identical to .ARM.exidx.text.00 .section .text.01, "ax", %progbits .globl f1 f1: @@ -45,8 +45,8 @@ f1: .cantunwind .fnend - // Expect 2 EXIDX_CANTUNWIND entries, these can be duplicated into - // .ARM.exid.text.00 + /// Expect 2 EXIDX_CANTUNWIND entries, these can be duplicated into + /// .ARM.exid.text.00 .section .text.02, "ax", %progbits .globl f2 f2: @@ -62,7 +62,7 @@ f3: .cantunwind .fnend - // Expect inline unwind instructions, not a duplicate of previous entry. + /// Expect inline unwind instructions, not a duplicate of previous entry. .section .text.03, "ax", %progbits .global f4 f4: @@ -72,8 +72,8 @@ f4: .setfp r7, sp, #0 .fnend - // Expect 2 inline unwind entries that are a duplicate of - // .ARM.exidx.text.03 + /// Expect 2 inline unwind entries that are a duplicate of + /// .ARM.exidx.text.03 .section .text.04, "ax", %progbits .global f5 f5: @@ -91,8 +91,8 @@ f6: .setfp r7, sp, #0 .fnend - // Expect a section with a reference to an .ARM.extab. Not a duplicate - // of previous inline table entry. + /// Expect a section with a reference to an .ARM.extab. Not a duplicate + /// of previous inline table entry. .section .text.05, "ax",%progbits .global f7 f7: @@ -103,8 +103,8 @@ f7: .long 0 .fnend - // Expect a reference to an identical .ARM.extab. We do not try to - // deduplicate references to .ARM.extab sections. + /// Expect a reference to an identical .ARM.extab. We do not try to + /// deduplicate references to .ARM.extab sections. .section .text.06, "ax",%progbits .global f8 f8: @@ -115,9 +115,9 @@ f8: .long 0 .fnend -// Dummy implementation of personality routines to satisfy reference from -// exception tables -// Expect Linker generated EXIDX_CANTUNWIND tables +/// Dummy implementation of personality routines to satisfy reference from +/// exception tables +/// Expect Linker generated EXIDX_CANTUNWIND tables .section .text.__gcc_personality_v0, "ax", %progbits .global __gxx_personality_v0 __gxx_personality_v0: diff --git a/lld/test/ELF/arm-exidx-emit-relocs.s b/lld/test/ELF/arm-exidx-emit-relocs.s index f0d2941bf38fd..52c208272114d 100644 --- a/lld/test/ELF/arm-exidx-emit-relocs.s +++ b/lld/test/ELF/arm-exidx-emit-relocs.s @@ -4,13 +4,13 @@ // RUN: llvm-objdump -s --triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s // RUN: llvm-readelf --relocs %t2 | FileCheck -check-prefix=CHECK-RELOCS %s -// LLD does not support --emit-relocs for .ARM.exidx sections as the relocations -// from synthetic table entries won't be represented. Given the known use cases -// of --emit-relocs, relocating kernels, and binary analysis, the former doesn't -// use exceptions and the latter can derive the relocations from the table if -// they need them. +/// LLD does not support --emit-relocs for .ARM.exidx sections as the relocations +/// from synthetic table entries won't be represented. Given the known use cases +/// of --emit-relocs, relocating kernels, and binary analysis, the former doesn't +/// use exceptions and the latter can derive the relocations from the table if +/// they need them. .syntax unified - // Will produce an ARM.exidx entry with inline unwinding instructions + /// Will produce an ARM.exidx entry with inline unwinding instructions .section .text.func1, "ax",%progbits .global func1 func1: @@ -22,7 +22,7 @@ func1: .syntax unified .section .text.func2, "ax",%progbits -// A function with the same inline unwinding instructions, expect merge. +/// A function with the same inline unwinding instructions, expect merge. .global func2 func2: .fnstart @@ -49,7 +49,7 @@ func26: .syntax unified .section .text.func3, "ax",%progbits -// A function with the same inline unwinding instructions, expect merge. +/// A function with the same inline unwinding instructions, expect merge. .global func3 func3: .fnstart @@ -64,8 +64,8 @@ __aeabi_unwind_cpp_pr0: bx lr // CHECK: Contents of section .ARM.exidx: -// CHECK-NEXT: 100d4 28100000 08849780 28100000 01000000 -// CHECK-NEXT: 100e4 28100000 08849780 24100000 01000000 -// CHECK-NEXT: 100f4 20100000 01000000 +// CHECK-NEXT: 100d4 28000100 08849780 28000100 01000000 +// CHECK-NEXT: 100e4 28000100 08849780 24000100 01000000 +// CHECK-NEXT: 100f4 20000100 01000000 // CHECK-RELOCS-NOT: Relocation section '.rel.ARM.exidx' diff --git a/lld/test/ELF/arm-exidx-gc.s b/lld/test/ELF/arm-exidx-gc.s index 117f2cfb51734..4b04b246827cd 100644 --- a/lld/test/ELF/arm-exidx-gc.s +++ b/lld/test/ELF/arm-exidx-gc.s @@ -4,11 +4,11 @@ // RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi --no-show-raw-insn %t2 | FileCheck %s // RUN: llvm-objdump -s --triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXIDX %s -// Test the behavior of .ARM.exidx sections under garbage collection -// A .ARM.exidx section is live if it has a relocation to a live executable -// section. -// A .ARM.exidx section may have a relocation to a .ARM.extab section, if the -// .ARM.exidx is live then the .ARM.extab section is live +/// Test the behavior of .ARM.exidx sections under garbage collection +/// A .ARM.exidx section is live if it has a relocation to a live executable +/// section. +/// A .ARM.exidx section may have a relocation to a .ARM.extab section, if the +/// .ARM.exidx is live then the .ARM.extab section is live .syntax unified .section .text.func1, "ax",%progbits @@ -28,9 +28,9 @@ unusedfunc1: .cantunwind .fnend - // Unwinding instructions for .text2 too large for an inline entry ARM.exidx - // entry. A separate .ARM.extab section is created to hold the unwind entries - // The .ARM.exidx table entry has a reference to the .ARM.extab section. + /// Unwinding instructions for .text2 too large for an inline entry ARM.exidx + /// entry. A separate .ARM.extab section is created to hold the unwind entries + /// The .ARM.exidx table entry has a reference to the .ARM.extab section. .section .text.func2, "ax",%progbits .global func2 func2: @@ -41,8 +41,8 @@ func2: .section .text.func2 .fnend - // An unused function with a reference to a .ARM.extab section. Both should - // be removed by gc. + /// An unused function with a reference to a .ARM.extab section. Both should + /// be removed by gc. .section .text.unusedfunc2, "ax",%progbits .global unusedfunc2 unusedfunc2: @@ -53,8 +53,8 @@ unusedfunc2: .section .text.unusedfunc2 .fnend - // Dummy implementation of personality routines to satisfy reference from - // exception tables + /// Dummy implementation of personality routines to satisfy reference from + /// exception tables .section .text.__gcc_personality_v0, "ax", %progbits .global __gxx_personality_v0 __gxx_personality_v0: @@ -87,40 +87,40 @@ _start: bl func2 bx lr -// GC should have only removed unusedfunc1 and unusedfunc2 the personality -// routines are kept alive by references from live .ARM.exidx and .ARM.extab -// sections +/// GC should have only removed unusedfunc1 and unusedfunc2 the personality +/// routines are kept alive by references from live .ARM.exidx and .ARM.extab +/// sections // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 1110c: bl #4 -// CHECK-NEXT: 11110: bl #4 -// CHECK-NEXT: 11114: bx lr +// CHECK-NEXT: 2010c: bl #4 +// CHECK-NEXT: 20110: bl #4 +// CHECK-NEXT: 20114: bx lr // CHECK: : -// CHECK-NEXT: 11118: bx lr +// CHECK-NEXT: 20118: bx lr // CHECK: : -// CHECK-NEXT: 1111c: bx lr +// CHECK-NEXT: 2011c: bx lr // CHECK: <__gxx_personality_v0>: -// CHECK-NEXT: 11120: bx lr +// CHECK-NEXT: 20120: bx lr // CHECK: <__aeabi_unwind_cpp_pr0>: -// CHECK-NEXT: 11124: bx lr +// CHECK-NEXT: 20124: bx lr -// GC should have removed table entries for unusedfunc1, unusedfunc2 -// and __gxx_personality_v1 +/// GC should have removed table entries for unusedfunc1, unusedfunc2 +/// and __gxx_personality_v1 // CHECK-NOT: unusedfunc1 // CHECK-NOT: unusedfunc2 // CHECK-NOT: __gxx_personality_v1 -// CHECK-EXIDX: Contents of section .ARM.exidx: -// 100d4 + 1038 = 1110c = _start -// 100dc + 103c = 11118 = func1 -// CHECK-EXIDX-NEXT: 100d4 38100000 01000000 3c100000 08849780 -// 100e4 + 1038 = 1111c = func2 (100e8 + 1c = 10104 = .ARM.extab) -// 100ec + 1034 = 11120 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 100e4 38100000 1c000000 34100000 01000000 -// 100f4 + 1030 = 11018 = __aeabi_unwind_cpp_pr0 -// 100fc + 102c = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0) -// CHECK-EXIDX-NEXT: 100f4 30100000 01000000 2c100000 01000000 +/// CHECK-EXIDX: Contents of section .ARM.exidx: +/// 100d4 + 1038 = 1110c = _start +/// 100dc + 103c = 11118 = func1 +// CHECK-EXIDX-NEXT: 100d4 38000100 01000000 3c000100 08849780 +/// 100e4 + 1038 = 1111c = func2 (100e8 + 1c = 10104 = .ARM.extab) +/// 100ec + 1034 = 11120 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 100e4 38000100 1c000000 34000100 01000000 +/// 100f4 + 1030 = 11018 = __aeabi_unwind_cpp_pr0 +/// 100fc + 102c = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0) +// CHECK-EXIDX-NEXT: 100f4 30000100 01000000 2c000100 01000000 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab: -// 10104 + 101c = 11120 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 10104 1c100000 b0b0b000 +/// 10104 + 101c = 11120 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 10104 1c000100 b0b0b000 diff --git a/lld/test/ELF/arm-exidx-order.s b/lld/test/ELF/arm-exidx-order.s index 7cae2b2acc7c5..efff7b5473968 100644 --- a/lld/test/ELF/arm-exidx-order.s +++ b/lld/test/ELF/arm-exidx-order.s @@ -13,12 +13,12 @@ // RUN: llvm-objdump -d --triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=CHECK-SCRIPT %s // RUN: llvm-objdump -s --triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=CHECK-SCRIPT-EXIDX %s -// Each assembler created .ARM.exidx section has the SHF_LINK_ORDER flag set -// with the sh_link containing the section index of the executable section -// containing the function it describes. The linker must combine the .ARM.exidx -// InputSections in the same order that it has combined the executable section, -// such that the combined .ARM.exidx OutputSection can be used as a binary -// search table. +/// Each assembler created .ARM.exidx section has the SHF_LINK_ORDER flag set +/// with the sh_link containing the section index of the executable section +/// containing the function it describes. The linker must combine the .ARM.exidx +/// InputSections in the same order that it has combined the executable section, +/// such that the combined .ARM.exidx OutputSection can be used as a binary +/// search table. .syntax unified .section .text, "ax",%progbits @@ -51,60 +51,60 @@ f3: .cantunwind .fnend -// Check default no linker script order. +/// Check default no linker script order. // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK: <_start>: -// CHECK-NEXT: 11124: bx lr +// CHECK-NEXT: 20124: bx lr // CHECK: : -// CHECK-NEXT: 11128: bx lr +// CHECK-NEXT: 20128: bx lr // CHECK: : -// CHECK-NEXT: 1112c: bx lr +// CHECK-NEXT: 2012c: bx lr // CHECK: : -// CHECK-NEXT: 11130: bx lr +// CHECK-NEXT: 20130: bx lr // CHECK: : -// CHECK-NEXT: 11134: bx lr +// CHECK-NEXT: 20134: bx lr // CHECK: : -// CHECK-NEXT: 11138: bx lr +// CHECK-NEXT: 20138: bx lr // CHECK: Disassembly of section .func1: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 1113c: bx lr +// CHECK-NEXT: 2013c: bx lr // CHECK: Disassembly of section .func2: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 11140: bx lr +// CHECK-NEXT: 20140: bx lr // CHECK: Disassembly of section .func3: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 11144: bx lr +// CHECK-NEXT: 20144: bx lr -// Each .ARM.exidx section has two 4 byte fields -// Field 1 is the 31-bit offset to the function. The top bit is used to -// indicate whether Field 2 is a pointer or an inline table entry. -// Field 2 is either a pointer to a .ARM.extab section or an inline table -// In this example all Field 2 entries are inline can't unwind (0x1) -// We expect to see the entries in the same order as the functions +/// Each .ARM.exidx section has two 4 byte fields +/// Field 1 is the 31-bit offset to the function. The top bit is used to +/// indicate whether Field 2 is a pointer or an inline table entry. +/// Field 2 is either a pointer to a .ARM.extab section or an inline table +/// In this example all Field 2 entries are inline can't unwind (0x1) +/// We expect to see the entries in the same order as the functions // CHECK-EXIDX: Contents of section .ARM.exidx: -// 100d4 + 1050 = 11124 = _start -// 100dc + 104c = 11128 = f1 -// CHECK-EXIDX-NEXT: 100d4 50100000 01000000 4c100000 01000000 -// 100e4 + 1048 = 1112c = f2 -// 100ec + 1044 = 11130 = f3 -// CHECK-EXIDX-NEXT: 100e4 48100000 01000000 44100000 01000000 -// 100f4 + 1040 = 11134 = func4 -// 100fc + 103c = 11138 = func5 -// CHECK-EXIDX-NEXT: 100f4 40100000 01000000 3c100000 01000000 -// 10104 + 1038 = 1113c = func1 -// 1010c + 1034 = 11140 = func2 -// CHECK-EXIDX-NEXT: 10104 38100000 01000000 34100000 01000000 -// 10114 + 1030 = 11144 = func3 -// CHECK-EXIDX-NEXT: 10114 30100000 01000000 +/// 100d4 + 1050 = 11124 = _start +/// 100dc + 104c = 11128 = f1 +// CHECK-EXIDX-NEXT: 100d4 50000100 01000000 4c000100 01000000 +/// 100e4 + 1048 = 1112c = f2 +/// 100ec + 1044 = 11130 = f3 +// CHECK-EXIDX-NEXT: 100e4 48000100 01000000 44000100 01000000 +/// 100f4 + 1040 = 11134 = func4 +/// 100fc + 103c = 11138 = func5 +// CHECK-EXIDX-NEXT: 100f4 40000100 01000000 3c000100 01000000 +/// 10104 + 1038 = 1113c = func1 +/// 1010c + 1034 = 11140 = func2 +// CHECK-EXIDX-NEXT: 10104 38000100 01000000 34000100 01000000 +/// 10114 + 1030 = 11144 = func3 +// CHECK-EXIDX-NEXT: 10114 30000100 01000000 -// Check that PT_ARM_EXIDX program header has been generated that describes -// the .ARM.exidx output section +/// Check that PT_ARM_EXIDX program header has been generated that describes +/// the .ARM.exidx output section // CHECK-PT: Name: .ARM.exidx // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) // CHECK-PT-NEXT: Flags [ @@ -128,8 +128,8 @@ f3: // CHECK-PT-NEXT: } -// Check linker script order. The .ARM.exidx section will be inserted after -// the .text section but before the orphan sections +/// Check linker script order. The .ARM.exidx section will be inserted after +/// the .text section but before the orphan sections // CHECK-SCRIPT: Disassembly of section .text: // CHECK-SCRIPT-EMPTY: @@ -161,20 +161,20 @@ f3: // CHECK-SCRIPT-NEXT: : // CHECK-SCRIPT-NEXT: 11020: 1e ff 2f e1 bx lr -// Check that the .ARM.exidx section is sorted in order as the functions -// The offset in field 1, is 32-bit so in the binary the most significant bit -// 11024 - 24 = 11000 func4 -// 1102c - 28 = 11004 func5 +/// Check that the .ARM.exidx section is sorted in order as the functions +/// The offset in field 1, is 32-bit so in the binary the most significant bit +/// 11024 - 24 = 11000 func4 +/// 1102c - 28 = 11004 func5 // CHECK-SCRIPT-EXIDX: 11024 dcffff7f 01000000 d8ffff7f 01000000 -// 11034 - 2c = 11008 _start -// 1103c - 30 = 1100c f1 +/// 11034 - 2c = 11008 _start +/// 1103c - 30 = 1100c f1 // CHECK-SCRIPT-EXIDX-NEXT: 11034 d4ffff7f 01000000 d0ffff7f 01000000 -// 11044 - 34 = 11010 f2 -// 1104c - 38 = 11014 f3 +/// 11044 - 34 = 11010 f2 +/// 1104c - 38 = 11014 f3 // CHECK-SCRIPT-EXIDX-NEXT: 11044 ccffff7f 01000000 c8ffff7f 01000000 -// 11054 - 3c = 11018 func1 -// 1105c - 40 = 1101c func2 +/// 11054 - 3c = 11018 func1 +/// 1105c - 40 = 1101c func2 // CHECK-SCRIPT-EXIDX-NEXT: 11054 c4ffff7f 01000000 c0ffff7f 01000000 -// 11064 - 44 = 11020 func3 -// 11068 - 48 = 11024 func3 + sizeof(func3) +/// 11064 - 44 = 11020 func3 +/// 11068 - 48 = 11024 func3 + sizeof(func3) // CHECK-SCRIPT-EXIDX-NEXT: 11064 bcffff7f 01000000 b8ffff7f 01000000 diff --git a/lld/test/ELF/arm-exidx-shared.s b/lld/test/ELF/arm-exidx-shared.s index 8f7e7ae2f05f6..fce605d6d96aa 100644 --- a/lld/test/ELF/arm-exidx-shared.s +++ b/lld/test/ELF/arm-exidx-shared.s @@ -38,8 +38,8 @@ __aeabi_unwind_cpp_pr0: // CHECK: Relocations [ // CHECK-NEXT: Section {{.*}} .rel.plt { -// CHECK-NEXT: 0x32DC R_ARM_JUMP_SLOT __gxx_personality_v0 +// CHECK-NEXT: 0x302DC R_ARM_JUMP_SLOT __gxx_personality_v0 // CHECK-EXTAB: Contents of section .ARM.extab: -// 0x0238 + 0x1038 = 0x1270 = __gxx_personality_v0(PLT) -// CHECK-EXTAB-NEXT: 0238 38100000 b0b0b000 00000000 +// 0x0238 + 0x1038 = 0x1270 = __gxx_personality_v0(PLT) +// CHECK-EXTAB-NEXT: 0238 38000100 b0b0b000 00000000 diff --git a/lld/test/ELF/arm-fix-cortex-a8-blx.s b/lld/test/ELF/arm-fix-cortex-a8-blx.s index 8de8de187ea54..636094fd798bb 100644 --- a/lld/test/ELF/arm-fix-cortex-a8-blx.s +++ b/lld/test/ELF/arm-fix-cortex-a8-blx.s @@ -1,13 +1,13 @@ // REQUIRES: arm // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf --arm-add-build-attributes %s -o %t.o // RUN: ld.lld --fix-cortex-a8 -verbose %t.o -o %t2 2>&1 | FileCheck %s -// RUN: llvm-objdump -d --no-show-raw-insn --start-address=0x12ffa --stop-address=0x13008 %t2 | FileCheck --check-prefix=CHECK-PATCH %s +// RUN: llvm-objdump -d --no-show-raw-insn --start-address=0x21ffa --stop-address=0x22008 %t2 | FileCheck --check-prefix=CHECK-PATCH %s /// Test that the patch can work on an unrelocated BLX. Neither clang or GCC /// will emit these without a relocation, but they could be produced by ELF /// processing tools. -// CHECK: ld.lld: detected cortex-a8-657419 erratum sequence starting at 12FFE in unpatched output. +// CHECK: ld.lld: detected cortex-a8-657419 erratum sequence starting at 21FFE in unpatched output. .syntax unified .text @@ -27,7 +27,7 @@ _start: .inst.n 0xf7ff .inst.n 0xe800 -// CHECK-PATCH: 12ffa: nop.w -// CHECK-PATCH-NEXT: 12ffe: blx #4 -// CHECK-PATCH: 00013004 <__CortexA8657417_12FFE>: -// CHECK-PATCH-NEXT: 13004: b #-4104 +// CHECK-PATCH: 21ffa: nop.w +// CHECK-PATCH-NEXT: 21ffe: blx #4 +// CHECK-PATCH: 00022004 <__CortexA8657417_21FFE>: +// CHECK-PATCH-NEXT: 22004: b #-4104 diff --git a/lld/test/ELF/arm-fix-cortex-a8-nopatch.s b/lld/test/ELF/arm-fix-cortex-a8-nopatch.s index 76bcb3e165f73..2f9e1962a868b 100644 --- a/lld/test/ELF/arm-fix-cortex-a8-nopatch.s +++ b/lld/test/ELF/arm-fix-cortex-a8-nopatch.s @@ -1,13 +1,13 @@ // REQUIRES: arm // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf --arm-add-build-attributes %s -o %t.o // RUN: ld.lld --fix-cortex-a8 -verbose %t.o -o %t2 -// RUN: llvm-objdump -d %t2 --start-address=0x12ffa --stop-address=0x13002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE1 %s -// RUN: llvm-objdump -d %t2 --start-address=0x13ffa --stop-address=0x14002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE2 %s -// RUN: llvm-objdump -d %t2 --start-address=0x14ffa --stop-address=0x15002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE3 %s -// RUN: llvm-objdump -d %t2 --start-address=0x15ffa --stop-address=0x16006 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE4 %s -// RUN: llvm-objdump -d %t2 --start-address=0x16ffe --stop-address=0x17002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE5 %s -// RUN: llvm-objdump -d %t2 --start-address=0x18000 --stop-address=0x18004 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE6 %s -// RUN: llvm-objdump -d %t2 --start-address=0x19002 --stop-address=0x19006 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE7 %s +// RUN: llvm-objdump -d %t2 --start-address=0x21ffa --stop-address=0x22002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE1 %s +// RUN: llvm-objdump -d %t2 --start-address=0x22ffa --stop-address=0x23002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE2 %s +// RUN: llvm-objdump -d %t2 --start-address=0x23ffa --stop-address=0x24002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE3 %s +// RUN: llvm-objdump -d %t2 --start-address=0x24ffa --stop-address=0x25006 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE4 %s +// RUN: llvm-objdump -d %t2 --start-address=0x25ffe --stop-address=0x26002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE5 %s +// RUN: llvm-objdump -d %t2 --start-address=0x27000 --stop-address=0x28004 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE6 %s +// RUN: llvm-objdump -d %t2 --start-address=0x28002 --stop-address=0x29006 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE7 %s /// Test boundary conditions of the cortex-a8 erratum. The following cases /// should not trigger the Erratum @@ -27,9 +27,9 @@ target: b.w target b.w target -// CALLSITE1: 00012ffa : -// CALLSITE1-NEXT: 12ffa: b.w #-4 -// CALLSITE1-NEXT: 12ffe: b.w #-8 +// CALLSITE1: 00021ffa : +// CALLSITE1-NEXT: 21ffa: b.w #-4 +// CALLSITE1-NEXT: 21ffe: b.w #-8 .space 4088 .type target2, %function @@ -40,10 +40,10 @@ target2: nop bl target2 -// CALLSITE2: 00013ffa : -// CALLSITE2-NEXT: 13ffa: nop -// CALLSITE2-NEXT: 13ffc: nop -// CALLSITE2-NEXT: 13ffe: bl #-8 +// CALLSITE2: 00022ffa : +// CALLSITE2-NEXT: 22ffa: nop +// CALLSITE2-NEXT: 22ffc: nop +// CALLSITE2-NEXT: 22ffe: bl #-8 .space 4088 .type target3, %function @@ -54,9 +54,9 @@ target3: nop.w beq.w target2 -// CALLSITE3: 00014ffa : -// CALLSITE3-NEXT: 14ffa: nop.w -// CALLSITE3-NEXT: 14ffe: beq.w #-4104 +// CALLSITE3: 00023ffa : +// CALLSITE3-NEXT: 23ffa: nop.w +// CALLSITE3-NEXT: 23ffe: beq.w #-4104 .space 4088 .type source4, %function @@ -69,11 +69,11 @@ source4: target4: nop.w -// CALLSITE4: 00015ffa : -// CALLSITE4-NEXT: 15ffa: nop.w -// CALLSITE4-NEXT: 15ffe: beq.w #0 -// CALLSITE4: 00016002 : -// CALLSITE4-NEXT: 16002: nop.w +// CALLSITE4: 00024ffa : +// CALLSITE4-NEXT: 24ffa: nop.w +// CALLSITE4-NEXT: 24ffe: beq.w #0 +// CALLSITE4: 00025002 : +// CALLSITE4-NEXT: 25002: nop.w .space 4084 .type target5, %function @@ -89,8 +89,8 @@ target5: source5: beq.w target5 -// CALLSITE5: 00016ffe : -// CALLSITE5-NEXT: 16ffe: beq.w #-8 +// CALLSITE5: 00025ffe : +// CALLSITE5-NEXT: 25ffe: beq.w #-8 /// Edge case where two word sequence starts at offset 0xffc, check that /// we don't match. In this case the branch will be completely in the 2nd @@ -104,8 +104,8 @@ source5: target6: bl target6 -// CALLSITE6: 00018000 : -// CALLSITE6-NEXT: 18000: bl #-4 +// CALLSITE6: 00027000 : +// CALLSITE6-NEXT: 27000: bl #-4 /// Edge case where two word sequence starts at offset 0xffe, check that /// we don't match. In this case the branch will be completely in the 2nd @@ -119,5 +119,5 @@ target6: target7: bl target7 -// CALLSITE7: 00019002 : -// CALLSITE7: 19002: bl #-4 +// CALLSITE7: 00028002 : +// CALLSITE7: 28002: bl #-4 diff --git a/lld/test/ELF/arm-fix-cortex-a8-recognize.s b/lld/test/ELF/arm-fix-cortex-a8-recognize.s index fb9ba3e45074f..7b1f08b16a72d 100644 --- a/lld/test/ELF/arm-fix-cortex-a8-recognize.s +++ b/lld/test/ELF/arm-fix-cortex-a8-recognize.s @@ -1,25 +1,25 @@ // REQUIRES: arm // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf --arm-add-build-attributes %s -o %t.o // RUN: ld.lld --fix-cortex-a8 -verbose %t.o -o %t2 2>&1 | FileCheck %s -// RUN: llvm-objdump -d %t2 --start-address=0x1a004 --stop-address=0x1a024 --no-show-raw-insn | FileCheck --check-prefix=CHECK-PATCHES %s -// RUN: llvm-objdump -d %t2 --start-address=0x12ffa --stop-address=0x13002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE1 %s -// RUN: llvm-objdump -d %t2 --start-address=0x13ffa --stop-address=0x14002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE2 %s -// RUN: llvm-objdump -d %t2 --start-address=0x14ffa --stop-address=0x15002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE3 %s -// RUN: llvm-objdump -d %t2 --start-address=0x15ff4 --stop-address=0x16002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE4 %s -// RUN: llvm-objdump -d %t2 --start-address=0x16ffa --stop-address=0x17002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE5 %s -// RUN: llvm-objdump -d %t2 --start-address=0x17ffa --stop-address=0x18002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE6 %s -// RUN: llvm-objdump -d %t2 --start-address=0x18ffa --stop-address=0x19002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE7 %s -// RUN: llvm-objdump -d %t2 --start-address=0x19ff4 --stop-address=0x1a002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE8 %s +// RUN: llvm-objdump -d %t2 --start-address=0x29004 --stop-address=0x29024 --no-show-raw-insn | FileCheck --check-prefix=CHECK-PATCHES %s +// RUN: llvm-objdump -d %t2 --start-address=0x21ffa --stop-address=0x22002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE1 %s +// RUN: llvm-objdump -d %t2 --start-address=0x22ffa --stop-address=0x23002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE2 %s +// RUN: llvm-objdump -d %t2 --start-address=0x23ffa --stop-address=0x24002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE3 %s +// RUN: llvm-objdump -d %t2 --start-address=0x24ff4 --stop-address=0x25002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE4 %s +// RUN: llvm-objdump -d %t2 --start-address=0x25ffa --stop-address=0x26002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE5 %s +// RUN: llvm-objdump -d %t2 --start-address=0x26ffa --stop-address=0x27002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE6 %s +// RUN: llvm-objdump -d %t2 --start-address=0x27ffa --stop-address=0x28002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE7 %s +// RUN: llvm-objdump -d %t2 --start-address=0x28ff4 --stop-address=0x29002 --no-show-raw-insn | FileCheck --check-prefix=CALLSITE8 %s // RUN: ld.lld --fix-cortex-a8 -verbose -r %t.o -o %t3 2>&1 | FileCheck --check-prefix=CHECK-RELOCATABLE-LLD %s // RUN: llvm-objdump --no-show-raw-insn -d %t3 --start-address=0xffa --stop-address=0x1002 | FileCheck --check-prefix=CHECK-RELOCATABLE %s -// CHECK: ld.lld: detected cortex-a8-657419 erratum sequence starting at 12FFE in unpatched output. -// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 13FFE in unpatched output. -// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 14FFE in unpatched output. -// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 15FFE in unpatched output. -// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 16FFE in unpatched output. -// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 17FFE in unpatched output. -// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 18FFE in unpatched output. +// CHECK: ld.lld: detected cortex-a8-657419 erratum sequence starting at 22FFE in unpatched output. +// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 23FFE in unpatched output. +// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 24FFE in unpatched output. +// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 25FFE in unpatched output. +// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 26FFE in unpatched output. +// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 27FFE in unpatched output. +// CHECK-NEXT: ld.lld: detected cortex-a8-657419 erratum sequence starting at 28FFE in unpatched output. /// We do not detect errors when doing a relocatable link as we don't know what /// the final addresses are. @@ -53,9 +53,9 @@ target: nop.w b.w target -// CALLSITE1: 00012ffa : -// CALLSITE1-NEXT: 12ffa: nop.w -// CALLSITE1-NEXT: 12ffe: b.w #28674 +// CALLSITE1: 00021ffa : +// CALLSITE1-NEXT: 21ffa: nop.w +// CALLSITE1-NEXT: 21ffe: b.w #28674 /// Expect no patch when doing a relocatable link ld -r. // CHECK-RELOCATABLE: 00000ffa : // CHECK-RELOCATABLE-NEXT: ffa: nop.w @@ -70,9 +70,9 @@ target2: nop.w bl target2 -// CALLSITE2: 00013ffa : -// CALLSITE2-NEXT: 13ffa: nop.w -// CALLSITE2-NEXT: 13ffe: bl #24582 +// CALLSITE2: 00022ffa : +// CALLSITE2-NEXT: 22ffa: nop.w +// CALLSITE2-NEXT: 22ffe: bl #24582 .space 4088 .type target3, %function @@ -83,9 +83,9 @@ target3: nop.w beq.w target3 -// CALLSITE3: 00014ffa : -// CALLSITE3-NEXT: 14ffa: nop.w -// CALLSITE3-NEXT: 14ffe: beq.w #20490 +// CALLSITE3: 00023ffa : +// CALLSITE3-NEXT: 23ffa: nop.w +// CALLSITE3-NEXT: 23ffe: beq.w #20490 .space 4082 .type target4, %function @@ -102,11 +102,11 @@ target4: blx target4 /// Target = 0x19010 __CortexA8657417_15FFE -// CALLSITE4: 00015ff4 : -// CALLSITE4-NEXT: 15ff4: bx lr -// CALLSITE4: 15ff8: 00 00 .short 0x0000 -// CALLSITE4: 15ffa: nop.w -// CALLSITE4-NEXT: 15ffe: blx #16400 +// CALLSITE4: 00024ff4 : +// CALLSITE4-NEXT: 24ff4: bx lr +// CALLSITE4: 24ff8: 00 00 .short 0x0000 +// CALLSITE4: 24ffa: nop.w +// CALLSITE4-NEXT: 24ffe: blx #16400 /// Separate sections for source and destination of branches to force /// a relocation. @@ -125,8 +125,8 @@ target5: b.w target5 /// Target = 0x19014 __CortexA8657417_16FFE -// CALLSITE5: 16ffa: nop.w -// CALLSITE5-NEXT: 16ffe: b.w #12306 +// CALLSITE5: 25ffa: nop.w +// CALLSITE5-NEXT: 25ffe: b.w #12306 .section .text.2, "ax", %progbits .balign 2 @@ -143,8 +143,8 @@ target6: bl target6 /// Target = 0x19018 __CortexA8657417_17FFE -// CALLSITE6: 17ffa: nop.w -// CALLSITE6-NEXT: 17ffe: bl #8214 +// CALLSITE6: 26ffa: nop.w +// CALLSITE6-NEXT: 26ffe: bl #8214 .section .text.4, "ax", %progbits .global target7 @@ -159,8 +159,8 @@ target7: nop.w bne.w target7 -// CALLSITE7: 18ffa: nop.w -// CALLSITE7-NEXT: 18ffe: bne.w #4122 +// CALLSITE7: 27ffa: nop.w +// CALLSITE7-NEXT: 27ffe: bne.w #4122 .section .text.6, "ax", %progbits .space 4082 @@ -180,32 +180,32 @@ target8: nop.w bl target8 -// CALLSITE8: 00019ff4 : -// CALLSITE8-NEXT: 19ff4: bx lr -// CALLSITE8: 19ff8: 00 00 .short 0x0000 -// CALLSITE8: 19ffa: nop.w -// CALLSITE8-NEXT: 19ffe: blx #32 +// CALLSITE8: 00028ff4 : +// CALLSITE8-NEXT: 28ff4: bx lr +// CALLSITE8: 28ff8: 00 00 .short 0x0000 +// CALLSITE8: 28ffa: nop.w +// CALLSITE8-NEXT: 28ffe: blx #32 -// CHECK-PATCHES: 0001a004 <__CortexA8657417_12FFE>: -// CHECK-PATCHES-NEXT: 1a004: b.w #-28686 +// CHECK-PATCHES: 00029004 <__CortexA8657417_21FFE>: +// CHECK-PATCHES-NEXT: 29004: b.w #-28686 -// CHECK-PATCHES: 0001a008 <__CortexA8657417_13FFE>: -// CHECK-PATCHES-NEXT: 1a008: b.w #-24594 +// CHECK-PATCHES: 00029008 <__CortexA8657417_22FFE>: +// CHECK-PATCHES-NEXT: 29008: b.w #-24594 -// CHECK-PATCHES: 0001a00c <__CortexA8657417_14FFE>: -// CHECK-PATCHES-NEXT: 1a00c: b.w #-20502 +// CHECK-PATCHES: 0002900c <__CortexA8657417_23FFE>: +// CHECK-PATCHES-NEXT: 2900c: b.w #-20502 -// CHECK-PATCHES: 0001a010 <__CortexA8657417_15FFE>: -// CHECK-PATCHES-NEXT: 1a010: b #-16420 +// CHECK-PATCHES: 00029010 <__CortexA8657417_24FFE>: +// CHECK-PATCHES-NEXT: 29010: b #-16420 -// CHECK-PATCHES: 0001a014 <__CortexA8657417_16FFE>: -// CHECK-PATCHES-NEXT: 1a014: b.w #-16406 +// CHECK-PATCHES: 00029014 <__CortexA8657417_25FFE>: +// CHECK-PATCHES-NEXT: 29014: b.w #-16406 -// CHECK-PATCHES: 0001a018 <__CortexA8657417_17FFE>: -// CHECK-PATCHES-NEXT: 1a018: b.w #-12314 +// CHECK-PATCHES: 00029018 <__CortexA8657417_26FFE>: +// CHECK-PATCHES-NEXT: 29018: b.w #-12314 -// CHECK-PATCHES: 0001a01c <__CortexA8657417_18FFE>: -// CHECK-PATCHES-NEXT: 1a01c: b.w #-8222 +// CHECK-PATCHES: 0002901c <__CortexA8657417_27FFE>: +// CHECK-PATCHES-NEXT: 2901c: b.w #-8222 -// CHECK-PATCHES: 0001a020 <__CortexA8657417_19FFE>: -// CHECK-PATCHES-NEXT: 1a020: b #-52 +// CHECK-PATCHES: 00029020 <__CortexA8657417_28FFE>: +// CHECK-PATCHES-NEXT: 29020: b #-52 diff --git a/lld/test/ELF/arm-fix-cortex-a8-thunk-align.s b/lld/test/ELF/arm-fix-cortex-a8-thunk-align.s index 12485297dbb17..183b397733e3d 100644 --- a/lld/test/ELF/arm-fix-cortex-a8-thunk-align.s +++ b/lld/test/ELF/arm-fix-cortex-a8-thunk-align.s @@ -22,13 +22,13 @@ thumb_target: b.w thumb_target /// Expect thunk and patch to be inserted here -// CHECK: 00003004 <__ThumbV7PILongThunk_arm_func>: -// CHECK-NEXT: 3004: movw r12, #4088 -// CHECK-NEXT: movt r12, #256 -// CHECK-NEXT: add r12, pc -// CHECK-NEXT: bx r12 -// CHECK: 00004004 <__CortexA8657417_2FFE>: -// CHECK-NEXT: 4004: b.w #-8196 +// CHECK: 00012004 <__ThumbV7PILongThunk_arm_func>: +// CHECK-NEXT: 12004: movw r12, #4088 +// CHECK-NEXT: movt r12, #256 +// CHECK-NEXT: add r12, pc +// CHECK-NEXT: bx r12 +// CHECK: 00013004 <__CortexA8657417_11FFE>: +// CHECK-NEXT: 13004: b.w #-8196 .section .text.02 /// Take us over thunk section spacing .space 16 * 1024 * 1024 diff --git a/lld/test/ELF/arm-fpic-got.s b/lld/test/ELF/arm-fpic-got.s index 6d9eb4b0326e2..8a7bb663030aa 100644 --- a/lld/test/ELF/arm-fpic-got.s +++ b/lld/test/ELF/arm-fpic-got.s @@ -36,7 +36,7 @@ val: // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x12128 +// CHECK-NEXT: Address: 0x30128 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 4 // CHECK-NEXT: Link: @@ -45,7 +45,7 @@ val: // CHECK-NEXT: EntrySize: // SYMBOLS: Name: val -// SYMBOLS-NEXT: Value: 0x1312C +// SYMBOLS-NEXT: Value: 0x4012C // SYMBOLS-NEXT: Size: 4 // SYMBOLS-NEXT: Binding: Global // SYMBOLS-NEXT: Type: Object @@ -55,10 +55,10 @@ val: // CODE: Disassembly of section .text: // CODE-EMPTY: // CODE-NEXT: <_start>: -// CODE-NEXT: 11114: ldr r0, [pc, #8] -// CODE-NEXT: 11118: ldr r0, [pc, r0] -// CODE-NEXT: 1111c: ldr r0, [r0] -// CODE-NEXT: 11120: bx lr +// CODE-NEXT: 20114: ldr r0, [pc, #8] +// CODE-NEXT: 20118: ldr r0, [pc, r0] +// CODE-NEXT: 2011c: ldr r0, [r0] +// CODE-NEXT: 20120: bx lr // CODE: <$d.1>: // 0x11124 + 0x1008 + 8 = 0x12128 = .got -// CODE-NEXT: 11124: 08 10 00 00 +// CODE-NEXT: 20124: 08 00 01 00 diff --git a/lld/test/ELF/arm-gnu-ifunc-plt.s b/lld/test/ELF/arm-gnu-ifunc-plt.s index 35e2fd7b31b81..0a415c936755f 100644 --- a/lld/test/ELF/arm-gnu-ifunc-plt.s +++ b/lld/test/ELF/arm-gnu-ifunc-plt.s @@ -10,75 +10,75 @@ // Check that the IRELATIVE relocations are last in the .got // CHECK: Relocations [ // CHECK-NEXT: Section (5) .rel.dyn { -// CHECK-NEXT: 0x122E0 R_ARM_GLOB_DAT bar2 0x0 -// CHECK-NEXT: 0x122E4 R_ARM_GLOB_DAT zed2 0x0 -// CHECK-NEXT: 0x122E8 R_ARM_IRELATIVE - 0x0 -// CHECK-NEXT: 0x122EC R_ARM_IRELATIVE - 0x0 +// CHECK-NEXT: 0x302E0 R_ARM_GLOB_DAT bar2 0x0 +// CHECK-NEXT: 0x302E4 R_ARM_GLOB_DAT zed2 0x0 +// CHECK-NEXT: 0x302E8 R_ARM_IRELATIVE - 0x0 +// CHECK-NEXT: 0x302EC R_ARM_IRELATIVE - 0x0 // CHECK-NEXT: } // CHECK-NEXT: Section (6) .rel.plt { -// CHECK-NEXT: 0x132FC R_ARM_JUMP_SLOT bar2 0x0 -// CHECK-NEXT: 0x13300 R_ARM_JUMP_SLOT zed2 0x0 +// CHECK-NEXT: 0x402FC R_ARM_JUMP_SLOT bar2 0x0 +// CHECK-NEXT: 0x40300 R_ARM_JUMP_SLOT zed2 0x0 // CHECK-NEXT: } // CHECK-NEXT: ] // Check that the GOT entries refer back to the ifunc resolver // GOTPLT: Contents of section .got: -// GOTPLT-NEXT: 122e0 00000000 00000000 dc110100 e0110100 +// GOTPLT-NEXT: 302e0 00000000 00000000 dc010200 e0010200 // GOTPLT: Contents of section .got.plt: -// GOTPLT-NEXT: 132f0 00000000 00000000 00000000 00120100 -// GOTPLT-NEXT: 13300 00120100 +// GOTPLT-NEXT: 402f0 00000000 00000000 00000000 00020200 +// GOTPLT-NEXT: 40300 00020200 // DISASM: Disassembly of section .text: // DISASM-EMPTY: // DISASM-NEXT: : -// DISASM-NEXT: 111dc: bx lr +// DISASM-NEXT: 201dc: bx lr // DISASM: : -// DISASM-NEXT: 111e0: bx lr +// DISASM-NEXT: 201e0: bx lr // DISASM: <_start>: -// DISASM-NEXT: 111e4: bl #84 -// DISASM-NEXT: 111e8: bl #96 +// DISASM-NEXT: 201e4: bl #84 +// DISASM-NEXT: 201e8: bl #96 // DISASM: <$d.1>: -// DISASM-NEXT: 111ec: 00 00 00 00 .word 0x00000000 -// DISASM-NEXT: 111f0: 04 00 00 00 .word 0x00000004 -// DISASM: 111f4: bl #36 -// DISASM-NEXT: 111f8: bl #48 +// DISASM-NEXT: 201ec: 00 00 00 00 .word 0x00000000 +// DISASM-NEXT: 201f0: 04 00 00 00 .word 0x00000004 +// DISASM: 201f4: bl #36 +// DISASM-NEXT: 201f8: bl #48 // DISASM-EMPTY: // DISASM-NEXT: Disassembly of section .plt: // DISASM-EMPTY: // DISASM-NEXT: <$a>: -// DISASM-NEXT: 11200: str lr, [sp, #-4]! -// DISASM-NEXT: 11204: add lr, pc, #0, #12 -// DISASM-NEXT: 11208: add lr, lr, #8192 -// DISASM-NEXT: 1120c: ldr pc, [lr, #236]! +// DISASM-NEXT: 20200: str lr, [sp, #-4]! +// DISASM-NEXT: 20204: add lr, pc, #0, #12 +// DISASM-NEXT: 20208: add lr, lr, #32 +// DISASM-NEXT: 2020c: ldr pc, [lr, #236]! // DISASM: <$d>: -// DISASM-NEXT: 11210: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DISASM-NEXT: 11214: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DISASM-NEXT: 11218: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DISASM-NEXT: 1121c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 20210: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 20214: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 20218: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2021c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM: <$a>: -// DISASM-NEXT: 11220: add r12, pc, #0, #12 -// DISASM-NEXT: 11224: add r12, r12, #8192 -// DISASM-NEXT: 11228: ldr pc, [r12, #212]! +// DISASM-NEXT: 20220: add r12, pc, #0, #12 +// DISASM-NEXT: 20224: add r12, r12, #32 +// DISASM-NEXT: 20228: ldr pc, [r12, #212]! // DISASM: <$d>: -// DISASM-NEXT: 1122c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2022c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM: <$a>: -// DISASM-NEXT: 11230: add r12, pc, #0, #12 -// DISASM-NEXT: 11234: add r12, r12, #8192 -// DISASM-NEXT: 11238: ldr pc, [r12, #200]! +// DISASM-NEXT: 20230: add r12, pc, #0, #12 +// DISASM-NEXT: 20234: add r12, r12, #32 +// DISASM-NEXT: 20238: ldr pc, [r12, #200]! // DISASM: <$d>: -// DISASM-NEXT: 1123c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2023c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM: <$a>: -// DISASM-NEXT: 11240: add r12, pc, #0, #12 -// DISASM-NEXT: 11244: add r12, r12, #4096 -// DISASM-NEXT: 11248: ldr pc, [r12, #160]! +// DISASM-NEXT: 20240: add r12, pc, #0, #12 +// DISASM-NEXT: 20244: add r12, r12, #16 +// DISASM-NEXT: 20248: ldr pc, [r12, #160]! // DISASM: <$d>: -// DISASM-NEXT: 1124c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2024c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM: <$a>: -// DISASM-NEXT: 11250: add r12, pc, #0, #12 -// DISASM-NEXT: 11254: add r12, r12, #4096 -// DISASM-NEXT: 11258: ldr pc, [r12, #148]! +// DISASM-NEXT: 20250: add r12, pc, #0, #12 +// DISASM-NEXT: 20254: add r12, r12, #16 +// DISASM-NEXT: 20258: ldr pc, [r12, #148]! // DISASM: <$d>: -// DISASM-NEXT: 1125c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2025c: d4 d4 d4 d4 .word 0xd4d4d4d4 .syntax unified .text diff --git a/lld/test/ELF/arm-gnu-ifunc.s b/lld/test/ELF/arm-gnu-ifunc.s index 916ea2ccfc7e5..71b80a1840bec 100644 --- a/lld/test/ELF/arm-gnu-ifunc.s +++ b/lld/test/ELF/arm-gnu-ifunc.s @@ -43,7 +43,7 @@ _start: // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_EXECINSTR // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x11130 +// CHECK-NEXT: Address: 0x20130 // CHECK-NEXT: Offset: 0x130 // CHECK-NEXT: Size: 32 // CHECK: Index: 4 @@ -53,13 +53,13 @@ _start: // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x12150 +// CHECK-NEXT: Address: 0x30150 // CHECK-NEXT: Offset: 0x150 // CHECK-NEXT: Size: 8 // CHECK: Relocations [ // CHECK-NEXT: Section (1) .rel.dyn { -// CHECK-NEXT: 0x12150 R_ARM_IRELATIVE -// CHECK-NEXT: 0x12154 R_ARM_IRELATIVE +// CHECK-NEXT: 0x30150 R_ARM_IRELATIVE +// CHECK-NEXT: 0x30154 R_ARM_IRELATIVE // CHECK-NEXT: } // CHECK-NEXT: ] // CHECK: Symbol { @@ -86,7 +86,7 @@ _start: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: _start -// CHECK-NEXT: Value: 0x1110C +// CHECK-NEXT: Value: 0x2010C // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: None @@ -95,7 +95,7 @@ _start: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: bar -// CHECK-NEXT: Value: 0x11108 +// CHECK-NEXT: Value: 0x20108 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: GNU_IFunc @@ -104,7 +104,7 @@ _start: // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: foo -// CHECK-NEXT: Value: 0x11104 +// CHECK-NEXT: Value: 0x20104 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: GNU_IFunc @@ -115,31 +115,31 @@ _start: // DISASM: Disassembly of section .text: // DISASM-EMPTY: // DISASM-NEXT: : -// DISASM-NEXT: 11104: bx lr +// DISASM-NEXT: 20104: bx lr // DISASM: : -// DISASM-NEXT: 11108: bx lr +// DISASM-NEXT: 20108: bx lr // DISASM: <_start>: -// DISASM-NEXT: 1110c: bl #28 -// DISASM-NEXT: 11110: bl #40 +// DISASM-NEXT: 2010c: bl #28 +// DISASM-NEXT: 20110: bl #40 // 1 * 65536 + 244 = 0x100f4 __rel_iplt_start -// DISASM-NEXT: 11114: movw r0, #244 -// DISASM-NEXT: 11118: movt r0, #1 +// DISASM-NEXT: 20114: movw r0, #244 +// DISASM-NEXT: 20118: movt r0, #1 // 1 * 65536 + 260 = 0x10104 __rel_iplt_end -// DISASM-NEXT: 1111c: movw r0, #260 -// DISASM-NEXT: 11120: movt r0, #1 +// DISASM-NEXT: 2011c: movw r0, #260 +// DISASM-NEXT: 20120: movt r0, #1 // DISASM-EMPTY: // DISASM-NEXT: Disassembly of section .iplt: // DISASM-EMPTY: // DISASM-NEXT: <$a>: -// DISASM-NEXT: 11130: add r12, pc, #0, #12 -// DISASM-NEXT: 11134: add r12, r12, #4096 -// DISASM-NEXT: 11138: ldr pc, [r12, #24]! +// DISASM-NEXT: 20130: add r12, pc, #0, #12 +// DISASM-NEXT: 20134: add r12, r12, #16 +// DISASM-NEXT: 20138: ldr pc, [r12, #24]! // DISASM: <$d>: -// DISASM-NEXT: 1113c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2013c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DISASM: <$a>: -// DISASM-NEXT: 11140: add r12, pc, #0, #12 -// DISASM-NEXT: 11144: add r12, r12, #4096 -// DISASM-NEXT: 11148: ldr pc, [r12, #12]! +// DISASM-NEXT: 20140: add r12, pc, #0, #12 +// DISASM-NEXT: 20144: add r12, r12, #16 +// DISASM-NEXT: 20148: ldr pc, [r12, #12]! // DISASM: <$d>: -// DISASM-NEXT: 1114c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DISASM-NEXT: 2014c: d4 d4 d4 d4 .word 0xd4d4d4d4 diff --git a/lld/test/ELF/arm-got-relative.s b/lld/test/ELF/arm-got-relative.s index 32a99491d8869..2ae32349877b6 100644 --- a/lld/test/ELF/arm-got-relative.s +++ b/lld/test/ELF/arm-got-relative.s @@ -28,10 +28,10 @@ function: bx lr // CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x220C R_ARM_GLOB_DAT function 0x0 +// CHECK-NEXT: 0x2020C R_ARM_GLOB_DAT function 0x0 // CHECK: Name: _GLOBAL_OFFSET_TABLE_ -// CHECK-NEXT: Value: 0x220C +// CHECK-NEXT: Value: 0x2020C // CHECK-NEXT: Size: // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None @@ -43,12 +43,12 @@ function: // CODE: Disassembly of section .text: // CODE-EMPTY: // CODE-NEXT: <_start>: -// CODE-NEXT: 11a0: 08 30 9f e5 ldr r3, [pc, #8] -// CODE-NEXT: 11a4: 08 20 9f e5 ldr r2, [pc, #8] -// CODE-NEXT: 11a8: 03 00 8f e0 add r0, pc, r3 -// CODE-NEXT: 11ac: 1e ff 2f e1 bx lr +// CODE-NEXT: 101a0: 08 30 9f e5 ldr r3, [pc, #8] +// CODE-NEXT: 101a4: 08 20 9f e5 ldr r2, [pc, #8] +// CODE-NEXT: 101a8: 03 00 8f e0 add r0, pc, r3 +// CODE-NEXT: 101ac: 1e ff 2f e1 bx lr // CODE: <$d.1>: // (_GLOBAL_OFFSET_TABLE_ = 0x220c) - (0x11a8 + 8) = 0x105c -// CODE-NEXT: 11b0: 5c 10 00 00 +// CODE-NEXT: 101b0: 5c 00 01 00 // (Got(function) - GotBase = 0x0 -// CODE-NEXT: 11b4: 00 00 00 00 +// CODE-NEXT: 101b4: 00 00 00 00 diff --git a/lld/test/ELF/arm-gotoff.s b/lld/test/ELF/arm-gotoff.s index dd64d93b256d1..0a6ea3ab0dad9 100644 --- a/lld/test/ELF/arm-gotoff.s +++ b/lld/test/ELF/arm-gotoff.s @@ -12,7 +12,7 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x12124 +// CHECK-NEXT: Address: 0x30124 // CHECK-NEXT: Offset: 0x124 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Link: @@ -25,7 +25,7 @@ // CHECK-NEXT: SHF_ALLOC // CHECK-NEXT: SHF_WRITE // CHECK-NEXT: ] -// CHECK-NEXT: Address: 0x13124 +// CHECK-NEXT: Address: 0x40124 // CHECK-NEXT: Offset: // CHECK-NEXT: Size: 20 // CHECK-NEXT: Link: @@ -36,7 +36,7 @@ // CHECK: Symbol { // CHECK: Name: bar -// CHECK-NEXT: Value: 0x13124 +// CHECK-NEXT: Value: 0x40124 // CHECK-NEXT: Size: 10 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object @@ -45,7 +45,7 @@ // CHECK-NEXT: } // CHECK-NEXT: Symbol { // CHECK-NEXT: Name: obj -// CHECK-NEXT: Value: 0x1312E +// CHECK-NEXT: Value: 0x4012E // CHECK-NEXT: Size: 10 // CHECK-NEXT: Binding: Global // CHECK-NEXT: Type: Object diff --git a/lld/test/ELF/arm-icf-exidx.s b/lld/test/ELF/arm-icf-exidx.s index ba659b630986c..27ebad6daf920 100644 --- a/lld/test/ELF/arm-icf-exidx.s +++ b/lld/test/ELF/arm-icf-exidx.s @@ -23,12 +23,12 @@ __aeabi_unwind_cpp_pr0: bx lr // CHECK: Contents of section .ARM.exidx: -// CHECK-NEXT: 100d4 18100000 b0b0b080 14100000 01000000 +// CHECK-NEXT: 100d4 18000100 b0b0b080 14000100 01000000 // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 110ec: 1e ff 2f e1 bx lr +// CHECK-NEXT: 200ec: 1e ff 2f e1 bx lr // CHECK: <__aeabi_unwind_cpp_pr0>: -// CHECK-NEXT: 110f0: 00 f0 20 e3 nop -// CHECK-NEXT: 110f4: 1e ff 2f e1 bx lr +// CHECK-NEXT: 200f0: 00 f0 20 e3 nop +// CHECK-NEXT: 200f4: 1e ff 2f e1 bx lr diff --git a/lld/test/ELF/arm-mov-relocs.s b/lld/test/ELF/arm-mov-relocs.s index 50a36a793d822..7b6163cbfff74 100644 --- a/lld/test/ELF/arm-mov-relocs.s +++ b/lld/test/ELF/arm-mov-relocs.s @@ -28,7 +28,7 @@ _start: movw r4, :lower16:label3 + 4 // CHECK-LABEL: Disassembly of section .R_ARM_MOVW_ABS_NC // CHECK-EMPTY: -// CHECK: 12000: movw r0, #0 +// CHECK: 21000: movw r0, #0 // CHECK: movw r1, #4 // CHECK: movw r2, #12 // CHECK: movw r3, #65532 @@ -44,12 +44,12 @@ _start: movt r4, :upper16:label3 + 4 // CHECK-LABEL: Disassembly of section .R_ARM_MOVT_ABS // CHECK-EMPTY: -// CHECK: 12100: movt r0, #2 -// CHECK: movt r1, #2 -// CHECK: movt r2, #2 -// CHECK: movt r3, #2 +// CHECK: 21100: movt r0, #4 +// CHECK: movt r1, #4 +// CHECK: movt r2, #4 +// CHECK: movt r3, #4 /// :upper16:label3 + 4 = :upper16:0x30000 = 3 -// CHECK: movt r4, #3 +// CHECK: movt r4, #5 .section .R_ARM_MOVW_PREL_NC, "ax",%progbits .align 8 @@ -61,15 +61,15 @@ _start: // CHECK-LABEL: Disassembly of section .R_ARM_MOVW_PREL_NC // CHECK-EMPTY: /// :lower16:label - . = 56832 -// CHECK: 12200: movw r0, #56832 +// CHECK: 21200: movw r0, #60928 /// :lower16:label1 - . = 56832 -// CHECK: movw r1, #56832 -/// :lower16:label2 - . + 4 = 56836 -// CHECK: movw r2, #56836 -/// :lower16:label3 - . = 56816 -// CHECK: movw r3, #56816 -/// :lower16:label3 - . + 0x2214 = :lower16:0x20000 = 0 -// CHECK: movw r4, #0 +// CHECK: movw r1, #60928 +/// :lower16:label2 - . + 4 = 60932 +// CHECK: movw r2, #60932 +/// :lower16:label3 - . = 60912 +// CHECK: movw r3, #60912 +/// :lower16:label3 - . + 0x2214 = :lower16:0x20000 = 4096 +// CHECK: movw r4, #4096 .section .R_ARM_MOVT_PREL, "ax",%progbits .align 8 @@ -80,16 +80,16 @@ _start: movt r4, :upper16:label3 + 0x2314 - . // CHECK-LABEL: Disassembly of section .R_ARM_MOVT_PREL // CHECK-EMPTY: -/// :upper16:label - . = :upper16:0xdd00 = 0 -// CHECK: 12300: movt r0, #0 -/// :upper16:label1 - . = :upper16:0xdd00 = 0 -// CHECK: movt r1, #0 -/// :upper16:label2 - . + 4 = :upper16:0xdd04 = 0 -// CHECK: movt r2, #0 -/// :upper16:label3 - . = :upper16:0x1dcf0 = 1 -// CHECK: movt r3, #1 -/// :upper16:label3 - . + 0x2314 = :upper16:0x20000 = 2 -// CHECK: movt r4, #2 +/// :upper16:label - . = :upper16:0xdd00 = 1 +// CHECK: 21300: movt r0, #1 +/// :upper16:label1 - . = :upper16:0xdd00 = 1 +// CHECK: movt r1, #1 +/// :upper16:label2 - . + 4 = :upper16:0xdd04 = 1 +// CHECK: movt r2, #1 +/// :upper16:label3 - . = :upper16:0x1dcf0 = 2 +// CHECK: movt r3, #2 +/// :upper16:label3 - . + 0x2314 = :upper16:0x20000 = 3 +// CHECK: movt r4, #3 .section .R_ARM_MOVW_BREL_NC, "ax",%progbits .align 8 @@ -102,7 +102,7 @@ _start: // CHECK-EMPTY: // SB = .destination /// :lower16:label - SB = 0 -// CHECK: 12400: movw r0, #0 +// CHECK: 21400: movw r0, #0 /// :lower16:label1 - SB = 4 // CHECK: movw r1, #4 /// :lower16:label2 - SB = 8 @@ -123,7 +123,7 @@ _start: // CHECK-EMPTY: // SB = .destination /// :upper16:label - SB = 0 -// CHECK: 12500: movt r0, #0 +// CHECK: 21500: movt r0, #0 /// :upper16:label1 - SB = 0 // CHECK: movt r1, #0 /// :upper16:label2 - SB = 0 @@ -142,7 +142,7 @@ _start: movw r4, :lower16:label3 + 4 // CHECK-LABEL: Disassembly of section .R_ARM_THM_MOVW_ABS_NC // CHECK-EMPTY: -// CHECK: 12600: movw r0, #0 +// CHECK: 21600: movw r0, #0 // CHECK: movw r1, #4 // CHECK: movw r2, #12 // CHECK: movw r3, #65532 @@ -157,11 +157,11 @@ _start: movt r4, :upper16:label3 + 4 // CHECK-LABEL: Disassembly of section .R_ARM_THM_MOVT_ABS // CHECK-EMPTY: -// CHECK: 12700: movt r0, #2 -// CHECK: movt r1, #2 -// CHECK: movt r2, #2 -// CHECK: movt r3, #2 -// CHECK: movt r4, #3 +// CHECK: 21700: movt r0, #4 +// CHECK: movt r1, #4 +// CHECK: movt r2, #4 +// CHECK: movt r3, #4 +// CHECK: movt r4, #5 .section .R_ARM_THM_MOVW_PREL_NC, "ax",%progbits .align 8 @@ -172,16 +172,16 @@ _start: movw r4, :lower16:label3 + 0x2814 - . // CHECK-LABEL: Disassembly of section .R_ARM_THM_MOVW_PREL_NC // CHECK-EMPTY: -/// :lower16:label - . = 55296 -// CHECK: 12800: movw r0, #55296 -/// :lower16:label1 - . = 55296 -// CHECK: movw r1, #55296 -/// :lower16:label2 - . + 4 = 55300 -// CHECK: movw r2, #55300 -/// :lower16:label3 - . = 55280 -// CHECK: movw r3, #55280 +/// :lower16:label - . = 59392 +// CHECK: 21800: movw r0, #59392 +/// :lower16:label1 - . = 59392 +// CHECK: movw r1, #59392 +/// :lower16:label2 - . + 4 = 59396 +// CHECK: movw r2, #59396 +/// :lower16:label3 - . = 59376 +// CHECK: movw r3, #59376 /// :lower16:label3 - . + 0x2814 = 0x20000 -// CHECK: movw r4, #0 +// CHECK: movw r4, #4096 .section .R_ARM_THM_MOVT_PREL, "ax",%progbits .align 8 @@ -192,16 +192,16 @@ _start: movt r4, :upper16:label3 + 0x2914 - . // CHECK-LABEL: Disassembly of section .R_ARM_THM_MOVT_PREL // CHECK-EMPTY: -/// :upper16:label - . = :upper16:0xd700 = 0 -// CHECK: 12900: movt r0, #0 -/// :upper16:label1 - . = :upper16:0xd700 = 0 -// CHECK: movt r1, #0 -/// :upper16:label2 - . + 4 = :upper16:0xd704 = 0 -// CHECK: movt r2, #0 -/// :upper16:label3 - . = :upper16:0x1d6f0 = 1 -// CHECK: movt r3, #1 -/// :upper16:label3 - . + 0x2914 = :upper16:0x20000 = 2 -// CHECK: movt r4, #2 +/// :upper16:label - . = :upper16:0xd700 = 1 +// CHECK: 21900: movt r0, #1 +/// :upper16:label1 - . = :upper16:0xd700 = 1 +// CHECK: movt r1, #1 +/// :upper16:label2 - . + 4 = :upper16:0xd704 = 1 +// CHECK: movt r2, #1 +/// :upper16:label3 - . = :upper16:0x1d6f0 = 2 +// CHECK: movt r3, #2 +/// :upper16:label3 - . + 0x2914 = :upper16:0x20000 = 3 +// CHECK: movt r4, #3 .section .R_ARM_THM_MOVW_BREL_NC, "ax",%progbits .align 8 @@ -214,7 +214,7 @@ _start: // CHECK-EMPTY: // SB = .destination /// :lower16:label - SB = 0 -// CHECK: 12a00: movw r0, #0 +// CHECK: 21a00: movw r0, #0 /// :lower16:label1 - SB = 4 // CHECK: movw r1, #4 /// :lower16:label2 - SB = 8 @@ -235,7 +235,7 @@ _start: // CHECK-EMPTY: /// SB = .destination /// :upper16:label - SB = 0 -// CHECK: 12b00: movt r0, #0 +// CHECK: 21b00: movt r0, #0 /// :upper16:label1 - SB = 0 // CHECK: movt r1, #0 /// :upper16:label2 - SB = 0 diff --git a/lld/test/ELF/arm-pie-relative.s b/lld/test/ELF/arm-pie-relative.s index 1767bc9dfbe81..e0758895a9dbe 100644 --- a/lld/test/ELF/arm-pie-relative.s +++ b/lld/test/ELF/arm-pie-relative.s @@ -19,7 +19,7 @@ sym: // CHECK: Relocations [ // CHECK-NEXT: Section (5) .rel.dyn { -// CHECK-NEXT: 0x21DC R_ARM_RELATIVE +// CHECK-NEXT: 0x201DC R_ARM_RELATIVE // GOT: section '.got': -// GOT-NEXT: 0x000021dc e0310000 +// GOT-NEXT: 0x000201dc e0010300 diff --git a/lld/test/ELF/arm-plt-reloc.s b/lld/test/ELF/arm-plt-reloc.s index 7cb597ffea785..3adee648dad54 100644 --- a/lld/test/ELF/arm-plt-reloc.s +++ b/lld/test/ELF/arm-plt-reloc.s @@ -22,68 +22,68 @@ _start: // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 110b4: bx lr +// CHECK-NEXT: 200b4: bx lr // CHECK: : -// CHECK-NEXT: 110b8: bx lr +// CHECK-NEXT: 200b8: bx lr // CHECK: : -// CHECK-NEXT: 110bc: bx lr +// CHECK-NEXT: 200bc: bx lr // CHECK: <_start>: -// CHECK-NEXT: 110c0: b #-20 -// CHECK-NEXT: 110c4: bl #-20 -// CHECK-NEXT: 110c8: beq #-20 +// CHECK-NEXT: 200c0: b #-20 +// CHECK-NEXT: 200c4: bl #-20 +// CHECK-NEXT: 200c8: beq #-20 // Expect PLT entries as symbols can be preempted // The .got.plt and .plt displacement is small so we can use small PLT entries. // DSO: Disassembly of section .text: // DSO-EMPTY: // DSO-NEXT: : -// DSO-NEXT: 1214: bx lr +// DSO-NEXT: 10214: bx lr // DSO: : -// DSO-NEXT: 1218: bx lr +// DSO-NEXT: 10218: bx lr // DSO: : -// DSO-NEXT: 121c: bx lr +// DSO-NEXT: 1021c: bx lr // DSO: <_start>: -// S(0x1214) - P(0x1220) + A(-8) = 0x2c = 32 -// DSO-NEXT: 1220: b #40 -// S(0x1218) - P(0x1224) + A(-8) = 0x38 = 56 -// DSO-NEXT: 1224: bl #52 -// S(0x121c) - P(0x1228) + A(-8) = 0x44 = 68 -// DSO-NEXT: 1228: beq #64 +// S(0x10214) - P(0x10220) + A(-8) = 0x2c = 32 +// DSO-NEXT: 10220: b #40 +// S(0x10218) - P(0x10224) + A(-8) = 0x38 = 56 +// DSO-NEXT: 10224: bl #52 +// S(0x1021c) - P(0x10228) + A(-8) = 0x44 = 68 +// DSO-NEXT: 10228: beq #64 // DSO-EMPTY: // DSO-NEXT: Disassembly of section .plt: // DSO-EMPTY: // DSO-NEXT: <$a>: -// DSO-NEXT: 1230: str lr, [sp, #-4]! -// (0x1234 + 8) + (0 RoR 12) + 8192 + 164 = 0x32e0 = .got.plt[2] -// DSO-NEXT: 1234: add lr, pc, #0, #12 -// DSO-NEXT: 1238: add lr, lr, #8192 -// DSO-NEXT: 123c: ldr pc, [lr, #164]! +// DSO-NEXT: 10230: str lr, [sp, #-4]! +// (0x10234 + 8) + (0 RoR 12) + 8192 + 164 = 0x32e0 = .got.plt[2] +// DSO-NEXT: 10234: add lr, pc, #0, #12 +// DSO-NEXT: 10238: add lr, lr, #32 +// DSO-NEXT: 1023c: ldr pc, [lr, #164]! // DSO: <$d>: -// DSO-NEXT: 1240: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DSO-NEXT: 1244: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DSO-NEXT: 1248: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DSO-NEXT: 124c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 10240: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 10244: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 10248: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1024c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO: <$a>: -// (0x1250 + 8) + (0 RoR 12) + 8192 + 140 = 0x32e4 -// DSO-NEXT: 1250: add r12, pc, #0, #12 -// DSO-NEXT: 1254: add r12, r12, #8192 -// DSO-NEXT: 1258: ldr pc, [r12, #140]! +// (0x10250 + 8) + (0 RoR 12) + 8192 + 140 = 0x32e4 +// DSO-NEXT: 10250: add r12, pc, #0, #12 +// DSO-NEXT: 10254: add r12, r12, #32 +// DSO-NEXT: 10258: ldr pc, [r12, #140]! // DSO: <$d>: -// DSO-NEXT: 125c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1025c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO: <$a>: -// (0x1260 + 8) + (0 RoR 12) + 8192 + 128 = 0x32e8 -// DSO-NEXT: 1260: add r12, pc, #0, #12 -// DSO-NEXT: 1264: add r12, r12, #8192 -// DSO-NEXT: 1268: ldr pc, [r12, #128]! +// (0x10260 + 8) + (0 RoR 12) + 8192 + 128 = 0x32e8 +// DSO-NEXT: 10260: add r12, pc, #0, #12 +// DSO-NEXT: 10264: add r12, r12, #32 +// DSO-NEXT: 10268: ldr pc, [r12, #128]! // DSO: <$d>: -// DSO-NEXT: 126c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1026c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO: <$a>: -// (0x1270 + 8) + (0 RoR 12) + 8192 + 116 = 0x32ec -// DSO-NEXT: 1270: add r12, pc, #0, #12 -// DSO-NEXT: 1274: add r12, r12, #8192 -// DSO-NEXT: 1278: ldr pc, [r12, #116]! +// (0x10270 + 8) + (0 RoR 12) + 8192 + 116 = 0x32ec +// DSO-NEXT: 10270: add r12, pc, #0, #12 +// DSO-NEXT: 10274: add r12, r12, #32 +// DSO-NEXT: 10278: ldr pc, [r12, #116]! // DSO: <$d>: -// DSO-NEXT: 127c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1027c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSOREL: Name: .got.plt @@ -92,7 +92,7 @@ _start: // DSOREL-NEXT: SHF_ALLOC // DSOREL-NEXT: SHF_WRITE // DSOREL-NEXT: ] -// DSOREL-NEXT: Address: 0x32D8 +// DSOREL-NEXT: Address: 0x302D8 // DSOREL-NEXT: Offset: // DSOREL-NEXT: Size: 24 // DSOREL-NEXT: Link: @@ -101,9 +101,9 @@ _start: // DSOREL-NEXT: EntrySize: // DSOREL: Relocations [ // DSOREL-NEXT: Section {{.*}} .rel.plt { -// DSOREL-NEXT: 0x32E4 R_ARM_JUMP_SLOT func1 0x0 -// DSOREL-NEXT: 0x32E8 R_ARM_JUMP_SLOT func2 0x0 -// DSOREL-NEXT: 0x32EC R_ARM_JUMP_SLOT func3 0x0 +// DSOREL-NEXT: 0x302E4 R_ARM_JUMP_SLOT func1 0x0 +// DSOREL-NEXT: 0x302E8 R_ARM_JUMP_SLOT func2 0x0 +// DSOREL-NEXT: 0x302EC R_ARM_JUMP_SLOT func3 0x0 // Test a large separation between the .plt and .got.plt // The .got.plt and .plt displacement is large but still within the range diff --git a/lld/test/ELF/arm-sbrel32.s b/lld/test/ELF/arm-sbrel32.s index 0bb2c1eb033eb..4ebafad3f61e6 100644 --- a/lld/test/ELF/arm-sbrel32.s +++ b/lld/test/ELF/arm-sbrel32.s @@ -33,8 +33,8 @@ foo4: .space 4 // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 110d4: 1e ff 2f e1 bx lr -// CHECK: 110d8: 00 00 00 00 .word 0x00000000 -// CHECK-NEXT: 110dc: 04 00 00 00 .word 0x00000004 -// CHECK-NEXT: 110e0: 08 00 00 00 .word 0x00000008 -// CHECK-NEXT: 110e4: 0c 00 00 00 .word 0x0000000c +// CHECK-NEXT: 200d4: 1e ff 2f e1 bx lr +// CHECK: 200d8: 00 00 00 00 .word 0x00000000 +// CHECK-NEXT: 200dc: 04 00 00 00 .word 0x00000004 +// CHECK-NEXT: 200e0: 08 00 00 00 .word 0x00000008 +// CHECK-NEXT: 200e4: 0c 00 00 00 .word 0x0000000c diff --git a/lld/test/ELF/arm-target1.s b/lld/test/ELF/arm-target1.s index 41bb0a3bc5fd3..6d71511194988 100644 --- a/lld/test/ELF/arm-target1.s +++ b/lld/test/ELF/arm-target1.s @@ -26,11 +26,11 @@ // Force generation of $d.0 as section is not all data nop // RELATIVE: SYMBOL TABLE: -// RELATIVE: 00001154 l .text 00000000 patatino +// RELATIVE: 00010154 l .text 00000000 patatino // RELATIVE: Disassembly of section .text: // RELATIVE-EMPTY: // RELATIVE: <$d.0>: -// RELATIVE: 1150: 04 00 00 00 .word 0x00000004 +// RELATIVE: 10150: 04 00 00 00 .word 0x00000004 // ABS: can't create dynamic relocation R_ARM_TARGET1 against symbol: patatino in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output // ABS: >>> defined in {{.*}}.o diff --git a/lld/test/ELF/arm-target2.s b/lld/test/ELF/arm-target2.s index 1ac7b9666342f..5de23853dcd2b 100644 --- a/lld/test/ELF/arm-target2.s +++ b/lld/test/ELF/arm-target2.s @@ -36,15 +36,15 @@ _ZTIi: .word 0 // CHECK: Contents of section .ARM.extab: // 0x1012c + 0x2010 = 0x1213c = .got -// CHECK-NEXT: 10124 14100000 b0b0b000 10200000 +// CHECK-NEXT: 10124 14000100 b0b0b000 10000200 // CHECK-ABS: Contents of section .ARM.extab: // 0x100f0 = .rodata -// CHECK-ABS-NEXT: 100e4 14100000 b0b0b000 f0000100 +// CHECK-ABS-NEXT: 100e4 14000100 b0b0b000 f0000100 // CHECK-REL: Contents of section .ARM.extab: // 0x100ec + 4 = 0x100f0 = .rodata -// CHECK-REL-NEXT: 100e4 14100000 b0b0b000 04000000 +// CHECK-REL-NEXT: 100e4 14000100 b0b0b000 04000000 // CHECK: Contents of section .rodata: // CHECK-NEXT: 10130 00000000 @@ -57,4 +57,4 @@ _ZTIi: .word 0 // CHECK: Contents of section .got: // 10130 = _ZTIi -// CHECK-NEXT: 1213c 30010100 +// CHECK-NEXT: 3013c 30010100 diff --git a/lld/test/ELF/arm-thumb-adr.s b/lld/test/ELF/arm-thumb-adr.s index adeac7d5f21bd..67139179e608f 100644 --- a/lld/test/ELF/arm-thumb-adr.s +++ b/lld/test/ELF/arm-thumb-adr.s @@ -31,14 +31,14 @@ target2: nop bx lr -// CHECK: 000110b4 <_start>: -// CHECK-NEXT: 110b4: adr r0, #0 -// CHECK-NEXT: 110b6: adr r1, #1020 +// CHECK: 000200b4 <_start>: +// CHECK-NEXT: 200b4: adr r0, #0 +// CHECK-NEXT: 200b6: adr r1, #1020 -// CHECK: 000110b8 : -// CHECK-NEXT: 110b8: nop -// CHECK-NEXT: 110ba: bx lr +// CHECK: 000200b8 : +// CHECK-NEXT: 200b8: nop +// CHECK-NEXT: 200ba: bx lr -// CHECK: 000114b4 : -// CHECK-NEXT: 114b4: nop -// CHECK-NEXT: 114b6: bx lr +// CHECK: 000204b4 : +// CHECK-NEXT: 204b4: nop +// CHECK-NEXT: 204b6: bx lr diff --git a/lld/test/ELF/arm-thumb-interwork-abs.s b/lld/test/ELF/arm-thumb-interwork-abs.s index 523660ad292fd..6dd2b87e5690b 100644 --- a/lld/test/ELF/arm-thumb-interwork-abs.s +++ b/lld/test/ELF/arm-thumb-interwork-abs.s @@ -27,12 +27,12 @@ thumb_caller: blx sym // WARN: branch and link relocation: R_ARM_THM_CALL to non STT_FUNC symbol: sym interworking not performed; consider using directive '.type sym, %function' to give symbol type STT_FUNC if interworking between ARM and Thumb is required -// CHECK: 00012000 : -// CHECK-NEXT: 12000: b #4088 -// CHECK-NEXT: 12004: bl #4084 -// CHECK-NEXT: 12008: blx #4080 +// CHECK: 00021000 : +// CHECK-NEXT: 21000: b #-57352 +// CHECK-NEXT: 21004: bl #-57356 +// CHECK-NEXT: 21008: blx #-57360 -// CHECK: 0001200c : -// CHECK-NEXT: 1200c: b.w #4080 -// CHECK-NEXT: 12010: bl #4076 -// CHECK-NEXT: 12014: blx #4076 +// CHECK: 0002100c : +// CHECK-NEXT: 2100c: b.w #-57360 +// CHECK-NEXT: 21010: bl #-57364 +// CHECK-NEXT: 21014: blx #-57364 diff --git a/lld/test/ELF/arm-thumb-interwork-notfunc.s b/lld/test/ELF/arm-thumb-interwork-notfunc.s index 40ef24ff7fcfb..1cccf70b56df3 100644 --- a/lld/test/ELF/arm-thumb-interwork-notfunc.s +++ b/lld/test/ELF/arm-thumb-interwork-notfunc.s @@ -94,48 +94,48 @@ thumb_caller: blx thumb_func_with_notype blx thumb_func_with_explicit_notype -// CHECK: 00012008 <_start>: -// CHECK-NEXT: 12008: b #-16 -// CHECK-NEXT: 1200c: b #-20 -// CHECK-NEXT: 12010: b #-24 -// CHECK-NEXT: 12014: b #-24 -// CHECK-NEXT: 12018: b #-28 -// CHECK-NEXT: 1201c: b #-32 -// CHECK-NEXT: 12020: bl #-40 -// CHECK-NEXT: 12024: bl #-44 -// CHECK-NEXT: 12028: bl #-48 -// CHECK-NEXT: 1202c: bl #-48 -// CHECK-NEXT: 12030: bl #-52 -// CHECK-NEXT: 12034: bl #-56 -// CHECK-NEXT: 12038: blx #-64 -// CHECK-NEXT: 1203c: blx #-68 -// CHECK-NEXT: 12040: blx #-72 -// CHECK-NEXT: 12044: blx #-72 -// CHECK-NEXT: 12048: blx #-76 -// CHECK-NEXT: 1204c: blx #-80 +// CHECK: 00021008 <_start>: +// CHECK-NEXT: 21008: b #-16 +// CHECK-NEXT: 2100c: b #-20 +// CHECK-NEXT: 21010: b #-24 +// CHECK-NEXT: 21014: b #-24 +// CHECK-NEXT: 21018: b #-28 +// CHECK-NEXT: 2101c: b #-32 +// CHECK-NEXT: 21020: bl #-40 +// CHECK-NEXT: 21024: bl #-44 +// CHECK-NEXT: 21028: bl #-48 +// CHECK-NEXT: 2102c: bl #-48 +// CHECK-NEXT: 21030: bl #-52 +// CHECK-NEXT: 21034: bl #-56 +// CHECK-NEXT: 21038: blx #-64 +// CHECK-NEXT: 2103c: blx #-68 +// CHECK-NEXT: 21040: blx #-72 +// CHECK-NEXT: 21044: blx #-72 +// CHECK-NEXT: 21048: blx #-76 +// CHECK-NEXT: 2104c: blx #-80 -// CHECK: 00012050 : -// CHECK-NEXT: 12050: b.w #-84 -// CHECK-NEXT: 12054: b.w #-88 -// CHECK-NEXT: 12058: b.w #-92 -// CHECK-NEXT: 1205c: b.w #-92 -// CHECK-NEXT: 12060: b.w #-96 -// CHECK-NEXT: 12064: b.w #-100 -// CHECK-NEXT: 12068: beq.w #-108 -// CHECK-NEXT: 1206c: beq.w #-112 -// CHECK-NEXT: 12070: beq.w #-116 -// CHECK-NEXT: 12074: beq.w #-116 -// CHECK-NEXT: 12078: beq.w #-120 -// CHECK-NEXT: 1207c: beq.w #-124 -// CHECK-NEXT: 12080: bl #-132 -// CHECK-NEXT: 12084: bl #-136 -// CHECK-NEXT: 12088: bl #-140 -// CHECK-NEXT: 1208c: bl #-140 -// CHECK-NEXT: 12090: bl #-144 -// CHECK-NEXT: 12094: bl #-148 -// CHECK-NEXT: 12098: blx #-156 -// CHECK-NEXT: 1209c: blx #-160 -// CHECK-NEXT: 120a0: blx #-164 -// CHECK-NEXT: 120a4: blx #-164 -// CHECK-NEXT: 120a8: blx #-168 -// CHECK-NEXT: 120ac: blx #-172 +// CHECK: 00021050 : +// CHECK-NEXT: 21050: b.w #-84 +// CHECK-NEXT: 21054: b.w #-88 +// CHECK-NEXT: 21058: b.w #-92 +// CHECK-NEXT: 2105c: b.w #-92 +// CHECK-NEXT: 21060: b.w #-96 +// CHECK-NEXT: 21064: b.w #-100 +// CHECK-NEXT: 21068: beq.w #-108 +// CHECK-NEXT: 2106c: beq.w #-112 +// CHECK-NEXT: 21070: beq.w #-116 +// CHECK-NEXT: 21074: beq.w #-116 +// CHECK-NEXT: 21078: beq.w #-120 +// CHECK-NEXT: 2107c: beq.w #-124 +// CHECK-NEXT: 21080: bl #-132 +// CHECK-NEXT: 21084: bl #-136 +// CHECK-NEXT: 21088: bl #-140 +// CHECK-NEXT: 2108c: bl #-140 +// CHECK-NEXT: 21090: bl #-144 +// CHECK-NEXT: 21094: bl #-148 +// CHECK-NEXT: 21098: blx #-156 +// CHECK-NEXT: 2109c: blx #-160 +// CHECK-NEXT: 210a0: blx #-164 +// CHECK-NEXT: 210a4: blx #-164 +// CHECK-NEXT: 210a8: blx #-168 +// CHECK-NEXT: 210ac: blx #-172 diff --git a/lld/test/ELF/arm-thumb-interwork-shared.s b/lld/test/ELF/arm-thumb-interwork-shared.s index dee44afc11535..45ebcf5d08169 100644 --- a/lld/test/ELF/arm-thumb-interwork-shared.s +++ b/lld/test/ELF/arm-thumb-interwork-shared.s @@ -19,17 +19,17 @@ sym1: // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 11e0: b.w #12 <__ThumbV7PILongThunk_elsewhere> +// CHECK-NEXT: 101e0: b.w #12 <__ThumbV7PILongThunk_elsewhere> // CHECK-NEXT: b.w #20 <__ThumbV7PILongThunk_weakref> // CHECK-NEXT: blx #68 // CHECK-NEXT: blx #80 // CHECK: <__ThumbV7PILongThunk_elsewhere>: -// CHECK-NEXT: 11f0: movw r12, #52 +// CHECK-NEXT: 101f0: movw r12, #52 // CHECK-NEXT: movt r12, #0 // CHECK-NEXT: add r12, pc // CHECK-NEXT: bx r12 // CHECK: <__ThumbV7PILongThunk_weakref>: -// CHECK-NEXT: 11fc: movw r12, #56 +// CHECK-NEXT: 101fc: movw r12, #56 // CHECK-NEXT: movt r12, #0 // CHECK-NEXT: add r12, pc // CHECK-NEXT: bx r12 @@ -37,24 +37,24 @@ sym1: // CHECK: Disassembly of section .plt: // CHECK-EMPTY: // CHECK-NEXT: <$a>: -// CHECK-NEXT: 1210: str lr, [sp, #-4]! +// CHECK-NEXT: 10210: str lr, [sp, #-4]! // CHECK-NEXT: add lr, pc, #0, #12 -// CHECK-NEXT: add lr, lr, #8192 +// CHECK-NEXT: add lr, lr, #32 // CHECK-NEXT: ldr pc, [lr, #148]! // CHECK: <$d>: -// CHECK-NEXT: 1220: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-NEXT: 10220: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK-NEXT: .word 0xd4d4d4d4 // CHECK: <$a>: -// CHECK-NEXT: 1230: add r12, pc, #0, #12 -// CHECK-NEXT: add r12, r12, #8192 +// CHECK-NEXT: 10230: add r12, pc, #0, #12 +// CHECK-NEXT: add r12, r12, #32 // CHECK-NEXT: ldr pc, [r12, #124]! // CHECK: <$d>: -// CHECK-NEXT: 123c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-NEXT: 1023c: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK: <$a>: -// CHECK-NEXT: 1240: add r12, pc, #0, #12 -// CHECK-NEXT: add r12, r12, #8192 +// CHECK-NEXT: 10240: add r12, pc, #0, #12 +// CHECK-NEXT: add r12, r12, #32 // CHECK-NEXT: ldr pc, [r12, #112]! // CHECK: <$d>: -// CHECK-NEXT: 124c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-NEXT: 1024c: d4 d4 d4 d4 .word 0xd4d4d4d4 diff --git a/lld/test/ELF/arm-thumb-interwork-thunk-v5.s b/lld/test/ELF/arm-thumb-interwork-thunk-v5.s index 1e397f7ef8971..4d6e89df18110 100644 --- a/lld/test/ELF/arm-thumb-interwork-thunk-v5.s +++ b/lld/test/ELF/arm-thumb-interwork-thunk-v5.s @@ -27,34 +27,34 @@ _start: bx lr // CHECK: <_start>: -// CHECK-NEXT: 12000: 03 00 00 ea b #12 <__ARMv5ABSLongThunk_thumb_func> -// CHECK-NEXT: 12004: 01 00 00 fa blx #4 -// CHECK-NEXT: 12008: 00 00 00 fa blx #0 -// CHECK-NEXT: 1200c: 1e ff 2f e1 bx lr +// CHECK-NEXT: 21000: 03 00 00 ea b #12 <__ARMv5ABSLongThunk_thumb_func> +// CHECK-NEXT: 21004: 01 00 00 fa blx #4 +// CHECK-NEXT: 21008: 00 00 00 fa blx #0 +// CHECK-NEXT: 2100c: 1e ff 2f e1 bx lr // CHECK: : -// CHECK-NEXT: 12010: 70 47 bx lr +// CHECK-NEXT: 21010: 70 47 bx lr // CHECK: <__ARMv5ABSLongThunk_thumb_func>: -// CHECK-NEXT: 12014: 04 f0 1f e5 ldr pc, [pc, #-4] +// CHECK-NEXT: 21014: 04 f0 1f e5 ldr pc, [pc, #-4] // CHECK: <$d>: -// CHECK-NEXT: 12018: 11 20 01 00 .word 0x00012011 +// CHECK-NEXT: 21018: 11 10 02 00 .word 0x00021011 // CHECK-PI: <_start>: -// CHECK-PI-NEXT: 2000: 03 00 00 ea b #12 <__ARMV5PILongThunk_thumb_func> -// CHECK-PI-NEXT: 2004: 01 00 00 fa blx #4 -// CHECK-PI-NEXT: 2008: 00 00 00 fa blx #0 -// CHECK-PI-NEXT: 200c: 1e ff 2f e1 bx lr +// CHECK-PI-NEXT: 11000: 03 00 00 ea b #12 <__ARMV5PILongThunk_thumb_func> +// CHECK-PI-NEXT: 11004: 01 00 00 fa blx #4 +// CHECK-PI-NEXT: 11008: 00 00 00 fa blx #0 +// CHECK-PI-NEXT: 1100c: 1e ff 2f e1 bx lr // CHECK-PI: : -// CHECK-PI-NEXT: 2010: 70 47 bx lr +// CHECK-PI-NEXT: 11010: 70 47 bx lr // CHECK-PI: <__ARMV5PILongThunk_thumb_func>: -// CHECK-PI-NEXT: 2014: 04 c0 9f e5 ldr r12, [pc, #4] -// CHECK-PI-NEXT: 2018: 0c c0 8f e0 add r12, pc, r12 -// CHECK-PI-NEXT: 201c: 1c ff 2f e1 bx r12 +// CHECK-PI-NEXT: 11014: 04 c0 9f e5 ldr r12, [pc, #4] +// CHECK-PI-NEXT: 11018: 0c c0 8f e0 add r12, pc, r12 +// CHECK-PI-NEXT: 1101c: 1c ff 2f e1 bx r12 // CHECK-PI: <$d>: -// CHECK-PI-NEXT: 2020: f1 ff ff ff .word 0xfffffff1 +// CHECK-PI-NEXT: 11020: f1 ff ff ff .word 0xfffffff1 .section .text.1, "ax", %progbits .thumb diff --git a/lld/test/ELF/arm-thumb-ldrlit.s b/lld/test/ELF/arm-thumb-ldrlit.s index 31eea197e1ada..761a2dee361d2 100644 --- a/lld/test/ELF/arm-thumb-ldrlit.s +++ b/lld/test/ELF/arm-thumb-ldrlit.s @@ -31,14 +31,14 @@ target2: nop bx lr -// CHECK: 000110b4 <_start>: -// CHECK-NEXT: 110b4: ldr r0, [pc, #0] -// CHECK-NEXT: 110b6: ldr r1, [pc, #1020] +// CHECK: 000200b4 <_start>: +// CHECK-NEXT: 200b4: ldr r0, [pc, #0] +// CHECK-NEXT: 200b6: ldr r1, [pc, #1020] -// CHECK: 000110b8 : -// CHECK-NEXT: 110b8: nop -// CHECK-NEXT: 110ba: bx lr +// CHECK: 000200b8 : +// CHECK-NEXT: 200b8: nop +// CHECK-NEXT: 200ba: bx lr -// CHECK: 000114b4 : -// CHECK-NEXT: 114b4: nop -// CHECK-NEXT: 114b6: bx lr +// CHECK: 000204b4 : +// CHECK-NEXT: 204b4: nop +// CHECK-NEXT: 204b6: bx lr diff --git a/lld/test/ELF/arm-thumb-no-undefined-thunk.s b/lld/test/ELF/arm-thumb-no-undefined-thunk.s index 2fbca671e14e3..77af78ce68179 100644 --- a/lld/test/ELF/arm-thumb-no-undefined-thunk.s +++ b/lld/test/ELF/arm-thumb-no-undefined-thunk.s @@ -20,6 +20,6 @@ _start: // CHECK-EMPTY: // CHECK-NEXT: <_start>: // 0x110b8 = next instruction -// CHECK: 110b4: {{.*}} bl #0 -// CHECK-NEXT: 110b8: {{.*}} b.w #0 <_start+0x8> -// CHECK-NEXT: 110bc: {{.*}} b.w #0 <_start+0xc> +// CHECK: 200b4: {{.*}} bl #0 +// CHECK-NEXT: 200b8: {{.*}} b.w #0 <_start+0x8> +// CHECK-NEXT: 200bc: {{.*}} b.w #0 <_start+0xc> diff --git a/lld/test/ELF/arm-thumb-plt-range-thunk-os.s b/lld/test/ELF/arm-thumb-plt-range-thunk-os.s index ba151c9b9db0b..3c61ca1a54bdc 100644 --- a/lld/test/ELF/arm-thumb-plt-range-thunk-os.s +++ b/lld/test/ELF/arm-thumb-plt-range-thunk-os.s @@ -89,7 +89,7 @@ far_nonpreemptible_alias: // CHECK4-NEXT: <$a>: // CHECK4-NEXT: 4000010: 04 e0 2d e5 str lr, [sp, #-4]! // CHECK4-NEXT: 4000014: 00 e6 8f e2 add lr, pc, #0, #12 -// CHECK4-NEXT: 4000018: 02 ea 8e e2 add lr, lr, #8192 +// CHECK4-NEXT: 4000018: 20 ea 8e e2 add lr, lr, #32 // CHECK4-NEXT: 400001c: a4 f0 be e5 ldr pc, [lr, #164]! // CHECK4: <$d>: // CHECK4-NEXT: 4000020: d4 d4 d4 d4 .word 0xd4d4d4d4 @@ -98,19 +98,19 @@ far_nonpreemptible_alias: // CHECK4-NEXT: 400002c: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK4: <$a>: // CHECK4-NEXT: 4000030: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK4-NEXT: 4000034: 02 ca 8c e2 add r12, r12, #8192 +// CHECK4-NEXT: 4000034: 20 ca 8c e2 add r12, r12, #32 // CHECK4-NEXT: 4000038: 8c f0 bc e5 ldr pc, [r12, #140]! // CHECK4: <$d>: // CHECK4-NEXT: 400003c: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK4: <$a>: // CHECK4-NEXT: 4000040: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK4-NEXT: 4000044: 02 ca 8c e2 add r12, r12, #8192 +// CHECK4-NEXT: 4000044: 20 ca 8c e2 add r12, r12, #32 // CHECK4-NEXT: 4000048: 80 f0 bc e5 ldr pc, [r12, #128]! // CHECK4: <$d>: // CHECK4-NEXT: 400004c: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK4: <$a>: // CHECK4-NEXT: 4000050: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK4-NEXT: 4000054: 02 ca 8c e2 add r12, r12, #8192 +// CHECK4-NEXT: 4000054: 20 ca 8c e2 add r12, r12, #32 // CHECK4-NEXT: 4000058: 74 f0 bc e5 ldr pc, [r12, #116]! // CHECK4: <$d>: // CHECK4-NEXT: 400005c: d4 d4 d4 d4 .word 0xd4d4d4d4 diff --git a/lld/test/ELF/arm-thumb-plt-reloc.s b/lld/test/ELF/arm-thumb-plt-reloc.s index f252852ec1477..5d57a67156c70 100644 --- a/lld/test/ELF/arm-thumb-plt-reloc.s +++ b/lld/test/ELF/arm-thumb-plt-reloc.s @@ -25,19 +25,19 @@ _start: // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 110b4: 70 47 bx lr +// CHECK-NEXT: 200b4: 70 47 bx lr // CHECK: : -// CHECK-NEXT: 110b6: 70 47 bx lr +// CHECK-NEXT: 200b6: 70 47 bx lr // CHECK: : -// CHECK-NEXT: 110b8: 70 47 bx lr -// CHECK-NEXT: 110ba: d4 d4 +// CHECK-NEXT: 200b8: 70 47 bx lr +// CHECK-NEXT: 200ba: d4 d4 // CHECK: <_start>: -// . + 4 -12 = 0x110b4 = func1 -// CHECK-NEXT: 110bc: ff f7 fa ff bl #-12 -// . + 4 -14 = 0x110b6 = func2 -// CHECK-NEXT: 110c0: ff f7 f9 ff bl #-14 -// . + 4 -16 = 0x110b8 = func3 -// CHECK-NEXT: 110c4: ff f7 f8 ff bl #-16 +// . + 4 -12 = 0x200b4 = func1 +// CHECK-NEXT: 200bc: ff f7 fa ff bl #-12 +// . + 4 -14 = 0x200b6 = func2 +// CHECK-NEXT: 200c0: ff f7 f9 ff bl #-14 +// . + 4 -16 = 0x200b8 = func3 +// CHECK-NEXT: 200c4: ff f7 f8 ff bl #-16 // Expect PLT entries as symbols can be preempted // .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble @@ -45,54 +45,54 @@ _start: // DSO: Disassembly of section .text: // DSO-EMPTY: // DSO-NEXT: : -// DSO-NEXT: 1214: 70 47 bx lr +// DSO-NEXT: 10214: 70 47 bx lr // DSO: : -// DSO-NEXT: 1216: 70 47 bx lr +// DSO-NEXT: 10216: 70 47 bx lr // DSO: : -// DSO-NEXT: 1218: 70 47 bx lr -// DSO-NEXT: 121a: d4 d4 bmi #-88 +// DSO-NEXT: 10218: 70 47 bx lr +// DSO-NEXT: 1021a: d4 d4 bmi #-88 // DSO: <_start>: -// . + 48 + 4 = 0x1250 = PLT func1 -// DSO-NEXT: 121c: 00 f0 18 e8 blx #48 -// . + 60 + 4 = 0x1260 = PLT func2 -// DSO-NEXT: 1220: 00 f0 1e e8 blx #60 -// . + 72 + 4 = 0x1270 = PLT func3 -// DSO-NEXT: 1224: 00 f0 24 e8 blx #72 +// . + 48 + 4 = 0x10250 = PLT func1 +// DSO-NEXT: 1021c: 00 f0 18 e8 blx #48 +// . + 60 + 4 = 0x10260 = PLT func2 +// DSO-NEXT: 10220: 00 f0 1e e8 blx #60 +// . + 72 + 4 = 0x10270 = PLT func3 +// DSO-NEXT: 10224: 00 f0 24 e8 blx #72 // DSO: Disassembly of section .plt: // DSO-EMPTY: // DSO-NEXT: <$a>: -// DSO-NEXT: 1230: 04 e0 2d e5 str lr, [sp, #-4]! -// (0x1234 + 8) + (0 RoR 12) + 8192 + 164 = 0x32e0 = .got.plt[3] -// DSO-NEXT: 1234: 00 e6 8f e2 add lr, pc, #0, #12 -// DSO-NEXT: 1238: 02 ea 8e e2 add lr, lr, #8192 -// DSO-NEXT: 123c: a4 f0 be e5 ldr pc, [lr, #164]! +// DSO-NEXT: 10230: 04 e0 2d e5 str lr, [sp, #-4]! +// (0x10234 + 8) + (0 RoR 12) + 8192 + 164 = 0x32e0 = .got.plt[3] +// DSO-NEXT: 10234: 00 e6 8f e2 add lr, pc, #0, #12 +// DSO-NEXT: 10238: 20 ea 8e e2 add lr, lr, #32 +// DSO-NEXT: 1023c: a4 f0 be e5 ldr pc, [lr, #164]! // DSO: <$d>: -// DSO-NEXT: 1240: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DSO-NEXT: 1244: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DSO-NEXT: 1248: d4 d4 d4 d4 .word 0xd4d4d4d4 -// DSO-NEXT: 124c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 10240: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 10244: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 10248: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1024c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO: <$a>: -// (0x1250 + 8) + (0 RoR 12) + 8192 + 140 = 0x32e4 -// DSO-NEXT: 1250: 00 c6 8f e2 add r12, pc, #0, #12 -// DSO-NEXT: 1254: 02 ca 8c e2 add r12, r12, #8192 -// DSO-NEXT: 1258: 8c f0 bc e5 ldr pc, [r12, #140]! +// (0x10250 + 8) + (0 RoR 12) + 8192 + 140 = 0x32e4 +// DSO-NEXT: 10250: 00 c6 8f e2 add r12, pc, #0, #12 +// DSO-NEXT: 10254: 20 ca 8c e2 add r12, r12, #32 +// DSO-NEXT: 10258: 8c f0 bc e5 ldr pc, [r12, #140]! // DSO: <$d>: -// DSO-NEXT: 125c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1025c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO: <$a>: -// (0x1260 + 8) + (0 RoR 12) + 8192 + 128 = 0x32e8 -// DSO-NEXT: 1260: 00 c6 8f e2 add r12, pc, #0, #12 -// DSO-NEXT: 1264: 02 ca 8c e2 add r12, r12, #8192 -// DSO-NEXT: 1268: 80 f0 bc e5 ldr pc, [r12, #128]! +// (0x10260 + 8) + (0 RoR 12) + 8192 + 128 = 0x32e8 +// DSO-NEXT: 10260: 00 c6 8f e2 add r12, pc, #0, #12 +// DSO-NEXT: 10264: 20 ca 8c e2 add r12, r12, #32 +// DSO-NEXT: 10268: 80 f0 bc e5 ldr pc, [r12, #128]! // DSO: <$d>: -// DSO-NEXT: 126c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1026c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSO: <$a>: -// (0x1270 + 8) + (0 RoR 12) + 8192 + 116 = 0x32ec -// DSO-NEXT: 1270: 00 c6 8f e2 add r12, pc, #0, #12 -// DSO-NEXT: 1274: 02 ca 8c e2 add r12, r12, #8192 -// DSO-NEXT: 1278: 74 f0 bc e5 ldr pc, [r12, #116]! +// (0x10270 + 8) + (0 RoR 12) + 8192 + 116 = 0x32ec +// DSO-NEXT: 10270: 00 c6 8f e2 add r12, pc, #0, #12 +// DSO-NEXT: 10274: 20 ca 8c e2 add r12, r12, #32 +// DSO-NEXT: 10278: 74 f0 bc e5 ldr pc, [r12, #116]! // DSO: <$d>: -// DSO-NEXT: 127c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// DSO-NEXT: 1027c: d4 d4 d4 d4 .word 0xd4d4d4d4 // DSOREL: Name: .got.plt // DSOREL-NEXT: Type: SHT_PROGBITS @@ -100,7 +100,7 @@ _start: // DSOREL-NEXT: SHF_ALLOC // DSOREL-NEXT: SHF_WRITE // DSOREL-NEXT: ] -// DSOREL-NEXT: Address: 0x32D8 +// DSOREL-NEXT: Address: 0x302D8 // DSOREL-NEXT: Offset: // DSOREL-NEXT: Size: 24 // DSOREL-NEXT: Link: @@ -109,6 +109,6 @@ _start: // DSOREL-NEXT: EntrySize: // DSOREL: Relocations [ // DSOREL-NEXT: Section (5) .rel.plt { -// DSOREL-NEXT: 0x32E4 R_ARM_JUMP_SLOT func1 0x0 -// DSOREL-NEXT: 0x32E8 R_ARM_JUMP_SLOT func2 0x0 -// DSOREL-NEXT: 0x32EC R_ARM_JUMP_SLOT func3 0x0 +// DSOREL-NEXT: 0x302E4 R_ARM_JUMP_SLOT func1 0x0 +// DSOREL-NEXT: 0x302E8 R_ARM_JUMP_SLOT func2 0x0 +// DSOREL-NEXT: 0x302EC R_ARM_JUMP_SLOT func3 0x0 diff --git a/lld/test/ELF/arm-thumb-thunk-empty-pass.s b/lld/test/ELF/arm-thumb-thunk-empty-pass.s index 271d88dcf9d76..35eecc49eda92 100644 --- a/lld/test/ELF/arm-thumb-thunk-empty-pass.s +++ b/lld/test/ELF/arm-thumb-thunk-empty-pass.s @@ -18,13 +18,13 @@ foo: // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 110b4: ff f7 fe ff bl #-4 +// CHECK-NEXT: 200b4: ff f7 fe ff bl #-4 // CHECK: <__Thumbv7ABSLongThunk__start>: -// CHECK-NEXT: 110b8: ff f7 fc bf b.w #-8 <_start> +// CHECK-NEXT: 200b8: ff f7 fc bf b.w #-8 <_start> // CHECK: <__Thumbv7ABSLongThunk__start>: -// CHECK: 10110bc: 41 f2 b5 0c movw r12, #4277 -// CHECK-NEXT: 10110c0: c0 f2 01 0c movt r12, #1 -// CHECK-NEXT: 10110c4: 60 47 bx r12 +// CHECK: 10200bc: 40 f2 b5 0c movw r12, #181 +// CHECK-NEXT: 10200c0: c0 f2 02 0c movt r12, #2 +// CHECK-NEXT: 10200c4: 60 47 bx r12 // CHECK: : -// CHECK-NEXT: 10110c6: ff f7 f9 ff bl #-14 +// CHECK-NEXT: 10200c6: ff f7 f9 ff bl #-14 diff --git a/lld/test/ELF/arm-thumb-thunk-symbols.s b/lld/test/ELF/arm-thumb-thunk-symbols.s index 976b3b2f38a27..e79998c0d0aeb 100644 --- a/lld/test/ELF/arm-thumb-thunk-symbols.s +++ b/lld/test/ELF/arm-thumb-thunk-symbols.s @@ -25,18 +25,18 @@ arm_fn: b thumb_fn // CHECK: Name: __Thumbv7ABSLongThunk_arm_fn -// CHECK-NEXT: Value: 0x13005 +// CHECK-NEXT: Value: 0x22005 // CHECK-NEXT: Size: 10 // CHECK-NEXT: Binding: Local (0x0) // CHECK-NEXT: Type: Function (0x2) // CHECK: Name: __ARMv7ABSLongThunk_thumb_fn -// CHECK-NEXT: Value: 0x13010 +// CHECK-NEXT: Value: 0x22010 // CHECK-NEXT: Size: 12 // CHECK-NEXT: Binding: Local (0x0) // CHECK-NEXT: Type: Function (0x2) // CHECK-PI: Name: __ThumbV7PILongThunk_arm_fn -// CHECK-PI-NEXT: Value: 0x3005 +// CHECK-PI-NEXT: Value: 0x12005 // CHECK-PI-NEXT: Size: 12 // CHECK-PI-NEXT: Binding: Local (0x0) // CHECK-PI-NEXT: Type: Function (0x2) diff --git a/lld/test/ELF/arm-thumb-undefined-weak.s b/lld/test/ELF/arm-thumb-undefined-weak.s index d56480575fdb8..9c9626cfc4a91 100644 --- a/lld/test/ELF/arm-thumb-undefined-weak.s +++ b/lld/test/ELF/arm-thumb-undefined-weak.s @@ -3,9 +3,9 @@ // RUN: ld.lld %t -o %t2 // RUN: llvm-objdump --triple=thumbv7a-none-linux-gnueabi -d %t2 | FileCheck %s -// Check that the ARM ABI rules for undefined weak symbols are applied. -// Branch instructions are resolved to the next instruction. Relative -// relocations are resolved to the place. +/// Check that the ARM ABI rules for undefined weak symbols are applied. +/// Branch instructions are resolved to the next instruction. Relative +/// relocations are resolved to the place. .syntax unified @@ -15,30 +15,30 @@ .text .global _start _start: -// R_ARM_THM_JUMP19 +/// R_ARM_THM_JUMP19 beq.w target -// R_ARM_THM_JUMP24 +/// R_ARM_THM_JUMP24 b.w target -// R_ARM_THM_CALL +/// R_ARM_THM_CALL bl target -// R_ARM_THM_CALL with exchange +/// R_ARM_THM_CALL with exchange blx target -// R_ARM_THM_MOVT_PREL +/// R_ARM_THM_MOVT_PREL movt r0, :upper16:target - . -// R_ARM_THM_MOVW_PREL_NC +/// R_ARM_THM_MOVW_PREL_NC movw r0, :lower16:target - . -// R_ARM_THM_ALU_PREL_11_0 +/// R_ARM_THM_ALU_PREL_11_0 adr r0, target -// R_ARM_THM_PC12 +/// R_ARM_THM_PC12 ldr r0, target // CHECK: Disassembly of section .text: // CHECK-EMPTY: -// CHECK: 110b4: {{.*}} beq.w #0 <_start+0x4> -// CHECK-NEXT: 110b8: {{.*}} b.w #0 <_start+0x8> -// CHECK-NEXT: 110bc: {{.*}} bl #0 -// blx is transformed into bl so we don't change state -// CHECK-NEXT: 110c0: {{.*}} bl #0 -// CHECK-NEXT: 110c4: {{.*}} movt r0, #0 -// CHECK-NEXT: 110c8: {{.*}} movw r0, #0 -// CHECK-NEXT: 110cc: {{.*}} adr.w r0, #-4 -// CHECK-NEXT: 110d0: {{.*}} ldr.w r0, [pc, #-4] +// CHECK: 200b4: {{.*}} beq.w #0 <_start+0x4> +// CHECK-NEXT: 200b8: {{.*}} b.w #0 <_start+0x8> +// CHECK-NEXT: 200bc: {{.*}} bl #0 +/// blx is transformed into bl so we don't change state +// CHECK-NEXT: 200c0: {{.*}} bl #0 +// CHECK-NEXT: 200c4: {{.*}} movt r0, #0 +// CHECK-NEXT: 200c8: {{.*}} movw r0, #0 +// CHECK-NEXT: 200cc: {{.*}} adr.w r0, #-4 +// CHECK-NEXT: 200d0: {{.*}} ldr.w r0, [pc, #-4] diff --git a/lld/test/ELF/arm-thunk-largesection.s b/lld/test/ELF/arm-thunk-largesection.s index 1fc37cf3b4c5a..f51d8dc4187fa 100644 --- a/lld/test/ELF/arm-thunk-largesection.s +++ b/lld/test/ELF/arm-thunk-largesection.s @@ -1,11 +1,11 @@ // REQUIRES: arm // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 -// RUN: llvm-objdump -d --triple=thumbv7a-none-linux-gnueabi --start-address=0x12000 --stop-address=0x12006 %t2 | FileCheck --check-prefix=CHECK1 %s -// RUN: llvm-objdump -d --triple=thumbv7a-none-linux-gnueabi --start-address=0x13004 --stop-address=0x13008 %t2 | FileCheck --check-prefix=CHECK2 %s -// RUN: llvm-objdump -d --triple=thumbv7a-none-linux-gnueabi --start-address=0x1012ff8 --stop-address=0x1012ffc %t2 | FileCheck --check-prefix=CHECK3 %s -// RUN: llvm-objdump -d --triple=thumbv7a-none-linux-gnueabi --start-address=0x2012ff8 --stop-address=0x2012ffc %t2 | FileCheck --check-prefix=CHECK4 %s -// RUN: llvm-objdump -d --triple=thumbv7a-none-linux-gnueabi --start-address=0x3012fec --stop-address=0x3012ff6 %t2 | FileCheck --check-prefix=CHECK5 %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7a-none-linux-gnueabi --start-address=0x21000 --stop-address=0x21006 %t2 | FileCheck --check-prefix=CHECK1 %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7a-none-linux-gnueabi --start-address=0x22004 --stop-address=0x22008 %t2 | FileCheck --check-prefix=CHECK2 %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7a-none-linux-gnueabi --start-address=0x1021ff8 --stop-address=0x1021ffc %t2 | FileCheck --check-prefix=CHECK3 %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7a-none-linux-gnueabi --start-address=0x2012ff8 --stop-address=0x2021ffc %t2 | FileCheck --check-prefix=CHECK4 %s +// RUN: llvm-objdump -d --no-show-raw-insn --triple=thumbv7a-none-linux-gnueabi --start-address=0x3021fec --stop-address=0x3021ff6 %t2 | FileCheck --check-prefix=CHECK5 %s .syntax unified .balign 0x1000 .thumb @@ -15,19 +15,16 @@ _start: bx lr .space 0x1000 -// CHECK1: Disassembly of section .text: -// CHECK1-EMPTY: -// CHECK1-NEXT: <_start>: -// CHECK1-NEXT: 12000: 70 47 bx lr -// CHECK1-EMPTY: -// CHECK1-NEXT: <$d.1>: -// CHECK1-NEXT: 12002: 00 00 00 00 .word 0x00000000 +// CHECK1: <_start>: +// CHECK1-NEXT: 21000: bx lr +// CHECK1: <$d.1>: +// CHECK1-NEXT: 21002: 00 00 00 00 .word 0x00000000 -// CHECK2: <__Thumbv7ABSLongThunk__start>: -// CHECK2-NEXT: 13004: fe f7 fc bf b.w #-4104 <_start> +// CHECK2: <__Thumbv7ABSLongThunk__start>: +// CHECK2-NEXT: 22004: b.w #-4104 <_start> -// Gigantic section where we need a ThunkSection either side of it +/// Gigantic section where we need a ThunkSection either side of it .section .text.large1, "ax", %progbits .balign 4 .space (16 * 1024 * 1024) - 16 @@ -35,10 +32,10 @@ _start: .space (16 * 1024 * 1024) - 4 bl _start .space (16 * 1024 * 1024) - 16 -// CHECK3: 1012ff8: 00 f4 04 d0 bl #-16777208 -// CHECK4: 2012ff8: ff f3 f8 d7 bl #16777200 +// CHECK3: 1021ff8: bl #-16777208 +// CHECK4: 2021ff8: bl #16777200 -// CHECK5: <__Thumbv7ABSLongThunk__start>: -// CHECK5-NEXT: 3012fec: 42 f2 01 0c movw r12, #8193 -// CHECK5-NEXT: 3012ff0: c0 f2 01 0c movt r12, #1 -// CHECK5-NEXT: 3012ff4: 60 47 bx r12 +// CHECK5: <__Thumbv7ABSLongThunk__start>: +// CHECK5-NEXT: 3021fec: movw r12, #4097 +// CHECK5-NEXT: 3021ff0: movt r12, #2 +// CHECK5-NEXT: 3021ff4: bx r12 diff --git a/lld/test/ELF/arm-thunk-multipass-plt.s b/lld/test/ELF/arm-thunk-multipass-plt.s index c39ff5021a44c..328a85d0e07a0 100644 --- a/lld/test/ELF/arm-thunk-multipass-plt.s +++ b/lld/test/ELF/arm-thunk-multipass-plt.s @@ -1,19 +1,19 @@ // REQUIRES: arm // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv5-none-linux-gnueabi %s -o %t // RUN: ld.lld %t -o %t2 --shared -// RUN: llvm-objdump --start-address=7340044 --stop-address=7340048 --triple=armv5-none-linux-gnueabi -d %t2 | FileCheck %s -// RUN: llvm-objdump --start-address=8388620 --stop-address=8388624 --triple=thumbv5-none-linux-gnueabi -d %t2 | FileCheck %s --check-prefix=CHECK-CALL -// RUN: llvm-objdump --start-address=13631520 --stop-address=13631584 --triple=armv5-none-linux-gnueabi -d %t2 | FileCheck %s --check-prefix=CHECK-PLT -// When we create a thunk to a PLT entry the relocation is redirected to the -// Thunk, changing its expression to a non-PLT equivalent. If the thunk -// becomes unusable we need to restore the relocation expression to the PLT -// form so that when we create a new thunk it targets the PLT. +// RUN: llvm-objdump --no-show-raw-insn --start-address=7340044 --stop-address=7340048 --triple=armv5-none-linux-gnueabi -d %t2 | FileCheck %s +// RUN: llvm-objdump --no-show-raw-insn --start-address=8388620 --stop-address=8388624 --triple=thumbv5-none-linux-gnueabi -d %t2 | FileCheck %s --check-prefix=CHECK-CALL +// RUN: llvm-objdump --no-show-raw-insn --start-address=13631520 --stop-address=13631584 --triple=armv5-none-linux-gnueabi -d %t2 | FileCheck %s --check-prefix=CHECK-PLT +/// When we create a thunk to a PLT entry the relocation is redirected to the +/// Thunk, changing its expression to a non-PLT equivalent. If the thunk +/// becomes unusable we need to restore the relocation expression to the PLT +/// form so that when we create a new thunk it targets the PLT. -// Test case that checks the case: -// - Thunk is created on pass 1 to a PLT entry for preemptible -// - Some other Thunk added in the same pass moves the thunk to -// preemptible out of range of its caller. -// - New Thunk is created on pass 2 to PLT entry for preemptible +/// Test case that checks the case: +/// - Thunk is created on pass 1 to a PLT entry for preemptible +/// - Some other Thunk added in the same pass moves the thunk to +/// preemptible out of range of its caller. +/// - New Thunk is created on pass 2 to PLT entry for preemptible .globl preemptible .globl preemptible2 @@ -41,9 +41,9 @@ needsplt: .section .text.07, "ax", %progbits .space (1024 * 1024) -// 0x70000c + 8 + 0x60002c = 0xd00040 = preemptible@plt -// CHECK: 0070000c <__ARMV5PILongThunk_preemptible>: -// CHECK-NEXT: 70000c: 0b 00 18 ea b #6291500 +/// 0x70000c + 8 + 0x60002c = 0xd00040 = preemptible@plt +// CHECK: 0070000c <__ARMV5PILongThunk_preemptible>: +// CHECK-NEXT: 70000c: b #6291500 .section .text.08, "ax", %progbits .space (1024 * 1024) - 4 @@ -52,8 +52,8 @@ needsplt: .balign 2 bl preemptible bl preemptible2 -// 0x80000c + 4 - 100004 = 0x70000c = __ARMv5PILongThunk_preemptible -// CHECK-CALL: 80000c: ff f6 fe ef blx #-1048580 +/// 0x80000c + 4 - 100004 = 0x70000c = __ARMv5PILongThunk_preemptible +// CHECK-CALL: 80000c: blx #-1048580 .balign 2 .globl preemptible .type preemptible, %function @@ -72,24 +72,24 @@ preemptible2: // CHECK-PLT: Disassembly of section .plt: // CHECK-PLT-EMPTY: // CHECK-PLT-NEXT: 00d00020 <$a>: -// CHECK-PLT-NEXT: d00020: 04 e0 2d e5 str lr, [sp, #-4]! -// CHECK-PLT-NEXT: d00024: 00 e6 8f e2 add lr, pc, #0, #12 -// CHECK-PLT-NEXT: d00028: 02 ea 8e e2 add lr, lr, #8192 -// CHECK-PLT-NEXT: d0002c: 94 f0 be e5 ldr pc, [lr, #148]! -// CHECK-PLT: 00d00030 <$d>: -// CHECK-PLT-NEXT: d00030: d4 d4 d4 d4 .word 0xd4d4d4d4 -// CHECK-PLT-NEXT: d00034: d4 d4 d4 d4 .word 0xd4d4d4d4 -// CHECK-PLT-NEXT: d00038: d4 d4 d4 d4 .word 0xd4d4d4d4 -// CHECK-PLT-NEXT: d0003c: d4 d4 d4 d4 .word 0xd4d4d4d4 -// CHECK-PLT: 00d00040 <$a>: -// CHECK-PLT-NEXT: d00040: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK-PLT-NEXT: d00044: 02 ca 8c e2 add r12, r12, #8192 -// CHECK-PLT-NEXT: d00048: 7c f0 bc e5 ldr pc, [r12, #124]! -// CHECK-PLT: 00d0004c <$d>: -// CHECK-PLT-NEXT: d0004c: d4 d4 d4 d4 .word 0xd4d4d4d4 -// CHECK-PLT: 00d00050 <$a>: -// CHECK-PLT-NEXT: d00050: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK-PLT-NEXT: d00054: 02 ca 8c e2 add r12, r12, #8192 -// CHECK-PLT-NEXT: d00058: 70 f0 bc e5 ldr pc, [r12, #112]! -// CHECK-PLT: 00d0005c <$d>: -// CHECK-PLT-NEXT: d0005c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT-NEXT: d00020: str lr, [sp, #-4]! +// CHECK-PLT-NEXT: add lr, pc, #0, #12 +// CHECK-PLT-NEXT: add lr, lr, #32, #20 +// CHECK-PLT-NEXT: ldr pc, [lr, #148]! +// CHECK-PLT: 00d00030 <$d>: +// CHECK-PLT-NEXT: d00030: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT-NEXT: d00034: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT-NEXT: d00038: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT-NEXT: d0003c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT: 00d00040 <$a>: +// CHECK-PLT-NEXT: d00040: add r12, pc, #0, #12 +// CHECK-PLT-NEXT: d00044: add r12, r12, #32, #20 +// CHECK-PLT-NEXT: d00048: ldr pc, [r12, #124]! +// CHECK-PLT: 00d0004c <$d>: +// CHECK-PLT-NEXT: d0004c: d4 d4 d4 d4 .word 0xd4d4d4d4 +// CHECK-PLT: 00d00050 <$a>: +// CHECK-PLT-NEXT: d00050: add r12, pc, #0, #12 +// CHECK-PLT-NEXT: d00054: add r12, r12, #32, #20 +// CHECK-PLT-NEXT: d00058: ldr pc, [r12, #112]! +// CHECK-PLT: 00d0005c <$d>: +// CHECK-PLT-NEXT: d0005c: d4 d4 d4 d4 .word 0xd4d4d4d4 diff --git a/lld/test/ELF/arm-thunk-nosuitable.s b/lld/test/ELF/arm-thunk-nosuitable.s index aea8d7fc431c8..1eed54b4fbc29 100644 --- a/lld/test/ELF/arm-thunk-nosuitable.s +++ b/lld/test/ELF/arm-thunk-nosuitable.s @@ -1,10 +1,10 @@ // REQUIRES: arm // RUN: llvm-mc %s --arm-add-build-attributes --triple=armv7a-linux-gnueabihf --filetype=obj -o %t.o // RUN: ld.lld %t.o -o %t -// RUN: llvm-objdump --triple=thumbv7a -d --start-address=0x2110b4 --stop-address=0x2110be %t | FileCheck %s +// RUN: llvm-objdump --triple=thumbv7a -d --start-address=0x2200b4 --stop-address=0x2200be %t | FileCheck %s - // Create a conditional branch too far away from a precreated thunk - // section. This will need a thunk section created within range. + /// Create a conditional branch too far away from a precreated thunk + /// section. This will need a thunk section created within range. .syntax unified .thumb @@ -13,17 +13,17 @@ .globl _start .type _start, %function _start: - // Range of +/- 1 Megabyte, new ThunkSection will need creating after - // .text.1 + /// Range of +/- 1 Megabyte, new ThunkSection will need creating after + /// .text.1 beq.w target .section .text.1, "ax", %progbits bx lr // CHECK: <_start>: -// CHECK-NEXT: 2110b4: 00 f0 00 80 beq.w #0 +// CHECK-NEXT: 2200b4: 00 f0 00 80 beq.w #0 // CHECK: <__Thumbv7ABSLongThunk_target>: -// CHECK-NEXT: 2110b8: 00 f0 01 90 b.w #12582914 -// CHECK: 2110bc: 70 47 bx lr +// CHECK-NEXT: 2200b8: 00 f0 01 90 b.w #12582914 +// CHECK: 2200bc: 70 47 bx lr .section .text.2, "ax", %progbits .space 12 * 1024 * 1024 diff --git a/lld/test/ELF/arm-thunk-re-add.s b/lld/test/ELF/arm-thunk-re-add.s index 0ba22b158b05b..9d95e916297ba 100644 --- a/lld/test/ELF/arm-thunk-re-add.s +++ b/lld/test/ELF/arm-thunk-re-add.s @@ -7,10 +7,10 @@ // RUN: llvm-objdump -d %t.so --start-address=17825800 --stop-address=17825826 --triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK2 %s // RUN: llvm-objdump -d %t.so --start-address=17825824 --stop-address=17825892 --triple=armv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK3 %s -// A branch to a Thunk that we create on pass N, can drift out of range if -// other Thunks are added in between. In this case we must create a new Thunk -// for the branch that is in range. We also need to make sure that if the -// destination of the Thunk is in the PLT the new Thunk also targets the PLT +/// A branch to a Thunk that we create on pass N, can drift out of range if +/// other Thunks are added in between. In this case we must create a new Thunk +/// for the branch that is in range. We also need to make sure that if the +/// destination of the Thunk is in the PLT the new Thunk also targets the PLT .syntax unified .thumb @@ -64,7 +64,7 @@ tfunc\suff\(): FUNCTION 29 FUNCTION 30 FUNCTION 31 -// Precreated Thunk Pool goes here +/// Precreated Thunk Pool goes here // CHECK1: <__ThumbV7PILongThunk_imported>: // CHECK1-NEXT: 1000004: 40 f2 30 0c movw r12, #48 // CHECK1-NEXT: 1000008: c0 f2 10 0c movt r12, #16 @@ -81,7 +81,7 @@ tfunc\suff\(): .section .text.33, "ax", %progbits .space 0x80000 - 0x14 .section .text.34, "ax", %progbits - // Need a Thunk to the PLT entry, can use precreated ThunkSection + /// Need a Thunk to the PLT entry, can use precreated ThunkSection .globl callers .type callers, %function callers: @@ -103,7 +103,7 @@ callers: // CHECK3-NEXT: <$a>: // CHECK3-NEXT: 1100020: 04 e0 2d e5 str lr, [sp, #-4]! // CHECK3-NEXT: 1100024: 00 e6 8f e2 add lr, pc, #0, #12 -// CHECK3-NEXT: 1100028: 02 ea 8e e2 add lr, lr, #8192 +// CHECK3-NEXT: 1100028: 20 ea 8e e2 add lr, lr, #32 // CHECK3-NEXT: 110002c: 94 f0 be e5 ldr pc, [lr, #148]! // CHECK3: <$d>: // CHECK3-NEXT: 1100030: d4 d4 d4 d4 .word 0xd4d4d4d4 @@ -112,13 +112,13 @@ callers: // CHECK3-NEXT: 110003c: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK3: <$a>: // CHECK3-NEXT: 1100040: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK3-NEXT: 1100044: 02 ca 8c e2 add r12, r12, #8192 +// CHECK3-NEXT: 1100044: 20 ca 8c e2 add r12, r12, #32 // CHECK3-NEXT: 1100048: 7c f0 bc e5 ldr pc, [r12, #124]! // CHECK3: <$d>: // CHECK3-NEXT: 110004c: d4 d4 d4 d4 .word 0xd4d4d4d4 // CHECK3: <$a>: // CHECK3-NEXT: 1100050: 00 c6 8f e2 add r12, pc, #0, #12 -// CHECK3-NEXT: 1100054: 02 ca 8c e2 add r12, r12, #8192 +// CHECK3-NEXT: 1100054: 20 ca 8c e2 add r12, r12, #32 // CHECK3-NEXT: 1100058: 70 f0 bc e5 ldr pc, [r12, #112]! // CHECK3: <$d>: // CHECK3-NEXT: 110005c: d4 d4 d4 d4 .word 0xd4d4d4d4 diff --git a/lld/test/ELF/arm-tls-gd-nonpreemptible.s b/lld/test/ELF/arm-tls-gd-nonpreemptible.s index f629eb6f113fe..489f293db1cb4 100644 --- a/lld/test/ELF/arm-tls-gd-nonpreemptible.s +++ b/lld/test/ELF/arm-tls-gd-nonpreemptible.s @@ -6,9 +6,9 @@ // RUN: ld.lld %t --shared -o %t3.so // RUN: llvm-objdump -s %t3.so | FileCheck --check-prefix=CHECK-SHARED %s -// For an executable, we write the module index 1 and the offset into the TLS -// directly into the GOT. For a shared library we can only write the offset -// into the TLS directly if the symbol is non-preemptible +/// For an executable, we write the module index 1 and the offset into the TLS +/// directly into the GOT. For a shared library we can only write the offset +/// into the TLS directly if the symbol is non-preemptible .text .syntax unified @@ -30,9 +30,9 @@ func: .L3: nop .p2align 2 -// Generate R_ARM_TLS_GD32 relocations -// These can be resolved at static link time for executables as 1 is always the -// module index and the offset into tls is known at static link time +/// Generate R_ARM_TLS_GD32 relocations +/// These can be resolved at static link time for executables as 1 is always the +/// module index and the offset into tls is known at static link time .Lt0: .word x1(TLSGD) + (. - .L0 - 8) .Lt1: .word x2(TLSGD) + (. - .L1 - 8) .Lt2: .word x3(TLSGD) + (. - .L2 - 8) @@ -64,9 +64,9 @@ x4: .space 4 // CHECK: Contents of section .got: -// CHECK-NEXT: 12140 01000000 00000000 01000000 04000000 -// CHECK-NEXT: 12150 01000000 08000000 01000000 0c000000 +// CHECK-NEXT: 30140 01000000 00000000 01000000 04000000 +// CHECK-NEXT: 30150 01000000 08000000 01000000 0c000000 // CHECK-SHARED: Contents of section .got: -// CHECK-SHARED-NEXT: 22a8 00000000 00000000 00000000 04000000 -// CHECK-SHARED-NEXT: 22b8 00000000 00000000 00000000 00000000 +// CHECK-SHARED-NEXT: 202a8 00000000 00000000 00000000 04000000 +// CHECK-SHARED-NEXT: 202b8 00000000 00000000 00000000 00000000 diff --git a/lld/test/ELF/arm-tls-gd32.s b/lld/test/ELF/arm-tls-gd32.s index 07d92584ee34b..55fadad807049 100644 --- a/lld/test/ELF/arm-tls-gd32.s +++ b/lld/test/ELF/arm-tls-gd32.s @@ -4,10 +4,10 @@ // RUN: llvm-readobj -S --dyn-relocations %t.so | FileCheck --check-prefix=SEC %s // RUN: llvm-objdump -d --triple=armv7a-linux-gnueabi %t.so | FileCheck %s -// Test the handling of the global-dynamic TLS model. Dynamic Loader finds -// module index R_ARM_TLS_DTPMOD32 and the offset within the module -// R_ARM_TLS_DTPOFF32. One of the variables is hidden which permits relaxation -// to local dynamic +/// Test the handling of the global-dynamic TLS model. Dynamic Loader finds +/// module index R_ARM_TLS_DTPMOD32 and the offset within the module +/// R_ARM_TLS_DTPOFF32. One of the variables is hidden which permits relaxation +/// to local dynamic .text .syntax unified @@ -23,17 +23,17 @@ func: nop .p2align 2 -// Generate R_ARM_TLS_GD32 relocations -// Allocates a pair of GOT entries dynamically relocated by R_ARM_TLS_DTPMOD32 -// and R_ARM_TLS_DTPOFF32 respectively. The literal contains the offset of the -// first GOT entry from the place +/// Generate R_ARM_TLS_GD32 relocations +/// Allocates a pair of GOT entries dynamically relocated by R_ARM_TLS_DTPMOD32 +/// and R_ARM_TLS_DTPOFF32 respectively. The literal contains the offset of the +/// first GOT entry from the place .Lt0: .word x(TLSGD) + (. - .L0 - 8) .Lt1: .word y(TLSGD) + (. - .L1 - 8) .Lt2: .word z(TLSGD) + (. - .L2 - 8) -// __thread int x = 10 -// __thread int y; -// __thread int z __attribute((visibility("hidden"))) +/// __thread int x = 10 +/// __thread int y; +/// __thread int z __attribute((visibility("hidden"))) .hidden z .globl z @@ -62,7 +62,7 @@ x: // SEC-NEXT: SHF_TLS // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x2210 +// SEC-NEXT: Address: 0x20210 // SEC: Size: 4 // SEC: Name: .tbss // SEC-NEXT: Type: SHT_NOBITS @@ -71,7 +71,7 @@ x: // SEC-NEXT: SHF_TLS // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x2214 +// SEC-NEXT: Address: 0x20214 // SEC: Size: 8 // SEC: Name: .got @@ -80,26 +80,26 @@ x: // SEC-NEXT: SHF_ALLOC // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x2264 +// SEC-NEXT: Address: 0x20264 // SEC: Size: 24 // SEC: Dynamic Relocations { -// SEC-NEXT: 0x2274 R_ARM_TLS_DTPMOD32 - -// SEC-NEXT: 0x2264 R_ARM_TLS_DTPMOD32 x -// SEC-NEXT: 0x2268 R_ARM_TLS_DTPOFF32 x -// SEC-NEXT: 0x226C R_ARM_TLS_DTPMOD32 y -// SEC-NEXT: 0x2270 R_ARM_TLS_DTPOFF32 y +// SEC-NEXT: 0x20274 R_ARM_TLS_DTPMOD32 - +// SEC-NEXT: 0x20264 R_ARM_TLS_DTPMOD32 x +// SEC-NEXT: 0x20268 R_ARM_TLS_DTPOFF32 x +// SEC-NEXT: 0x2026C R_ARM_TLS_DTPMOD32 y +// SEC-NEXT: 0x20270 R_ARM_TLS_DTPOFF32 y -// CHECK-LABEL: 000011f8 : -// CHECK-NEXT: 11f8: 00 f0 20 e3 nop -// CHECK-NEXT: 11fc: 00 f0 20 e3 nop -// CHECK-NEXT: 1200: 00 f0 20 e3 nop +// CHECK-LABEL: 000101f8 : +// CHECK-NEXT: 101f8: 00 f0 20 e3 nop +// CHECK-NEXT: 101fc: 00 f0 20 e3 nop +// CHECK-NEXT: 10200: 00 f0 20 e3 nop -// (0x2264 - 0x1204) + (0x1204 - 0x11f8 - 8) = 0x1064 -// CHECK: 1204: 64 10 00 00 -// (0x226c - 0x1204) + (0x1204 - 0x11fc - 8) = 0x1068 -// CHECK-NEXT: 1208: 68 10 00 00 -// (0x2274 - 0x1204) + (0x1204 - 0x1200 - 8) = 0x106c -// CHECK-NEXT: 120c: 6c 10 00 00 +/// (0x20264 - 0x1204) + (0x10204 - 0x101f8 - 8) = 0x1f064 +// CHECK: 10204: 64 00 01 00 +/// (0x2026c - 0x10204) + (0x10204 - 0x101fc - 8) = 0x10068 +// CHECK-NEXT: 10208: 68 00 01 00 +/// (0x20274 - 0x10204) + (0x10204 - 0x10200 - 8) = 0x1006c +// CHECK-NEXT: 1020c: 6c 00 01 00 diff --git a/lld/test/ELF/arm-tls-ie32.s b/lld/test/ELF/arm-tls-ie32.s index 2a9c8a4b2a31d..37418595ad181 100644 --- a/lld/test/ELF/arm-tls-ie32.s +++ b/lld/test/ELF/arm-tls-ie32.s @@ -4,9 +4,9 @@ // RUN: llvm-readobj -S --dyn-relocations %t.so | FileCheck --check-prefix=SEC %s // RUN: llvm-objdump -d --triple=armv7a-linux-gnueabi %t.so | FileCheck %s -// Test the handling of the initial-exec TLS model. Relative location within -// static TLS is a run-time constant computed by dynamic loader as a result -// of the R_ARM_TLS_TPOFF32 relocation. +/// Test the handling of the initial-exec TLS model. Relative location within +/// static TLS is a run-time constant computed by dynamic loader as a result +/// of the R_ARM_TLS_TPOFF32 relocation. .syntax unified .arm @@ -22,16 +22,16 @@ func: nop .p2align 2 -// Generate R_ARM_TLS_IE32 static relocations -// Allocates a GOT entry dynamically relocated by R_ARM_TLS_TPOFF32 -// literal contains the offset of the GOT entry from the place +/// Generate R_ARM_TLS_IE32 static relocations +/// Allocates a GOT entry dynamically relocated by R_ARM_TLS_TPOFF32 +/// literal contains the offset of the GOT entry from the place .Lt0: .word x(gottpoff) + (. - .L0 - 8) .Lt1: .word y(gottpoff) + (. - .L1 - 8) .Lt2: .word .TLSSTART(gottpoff) + (. - .L2 - 8) -// __thread int x = 10 -// __thread int y; -// __thread int z __attribute((visibility("hidden"))) +/// __thread int x = 10 +/// __thread int y; +/// __thread int z __attribute((visibility("hidden"))) .hidden z .globl z .globl y @@ -73,25 +73,25 @@ x: // SEC-NEXT: SHF_ALLOC // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x2254 +// SEC-NEXT: Address: 0x20254 // SEC: Size: 12 // SEC: Dynamic Relocations { -// SEC: 0x225C R_ARM_TLS_TPOFF32 -// SEC: 0x2254 R_ARM_TLS_TPOFF32 x -// SEC: 0x2258 R_ARM_TLS_TPOFF32 y +// SEC: 0x2025C R_ARM_TLS_TPOFF32 +// SEC: 0x20254 R_ARM_TLS_TPOFF32 x +// SEC: 0x20258 R_ARM_TLS_TPOFF32 y // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: : -// CHECK-NEXT: 11e8: 00 f0 20 e3 nop -// CHECK-NEXT: 11ec: 00 f0 20 e3 nop -// CHECK-NEXT: 11f0: 00 f0 20 e3 nop +// CHECK-NEXT: 101e8: 00 f0 20 e3 nop +// CHECK-NEXT: 101ec: 00 f0 20 e3 nop +// CHECK-NEXT: 101f0: 00 f0 20 e3 nop -// (0x2254 - 0x11f4) + (0x11f4 - 0x11e8 - 8) = 0x1064 -// CHECK: 11f4: 64 10 00 00 -// (0x2258 - 0x11f8) + (0x11f8 - 0x11ec - 8) = 0x1064 -// CHECK-NEXT: 11f8: 64 10 00 00 -// (0x225c - 0x11f8) + (0x11f8 - 0x11f0 - 8) = 0x1064 -// CHECK-NEXT: 11fc: 64 10 00 00 +/// (0x20254 - 0x101f4) + (0x101f4 - 0x101e8 - 8) = 0x10064 +// CHECK: 101f4: 64 00 01 00 +/// (0x20258 - 0x101f8) + (0x101f8 - 0x101ec - 8) = 0x10064 +// CHECK-NEXT: 101f8: 64 00 01 00 +/// (0x2025c - 0x101f8) + (0x101f8 - 0x101f0 - 8) = 0x10064 +// CHECK-NEXT: 101fc: 64 00 01 00 diff --git a/lld/test/ELF/arm-tls-ldm32.s b/lld/test/ELF/arm-tls-ldm32.s index 62be2d49dba3c..b93291431722a 100644 --- a/lld/test/ELF/arm-tls-ldm32.s +++ b/lld/test/ELF/arm-tls-ldm32.s @@ -6,9 +6,9 @@ // RUN: ld.lld %t.o -o %t // RUN: llvm-objdump -d --triple=armv7a-linux-gnueabi %t | FileCheck --check-prefix=CHECK-EXE %s -// Test the handling of the local-dynamic TLS model. Dynamic loader finds -// module index R_ARM_TLS_DTPMOD32. The offset in the next GOT slot is 0 -// The R_ARM_TLS_LDO is the offset of the variable within the TLS block. +/// Test the handling of the local-dynamic TLS model. Dynamic loader finds +/// module index R_ARM_TLS_DTPMOD32. The offset in the next GOT slot is 0 +/// The R_ARM_TLS_LDO is the offset of the variable within the TLS block. .global __tls_get_addr .text .p2align 2 @@ -42,7 +42,7 @@ x: // SEC-NEXT: SHF_TLS // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x21D0 +// SEC-NEXT: Address: 0x201D0 // SEC: Size: 4 // SEC: Name: .tbss // SEC-NEXT: Type: SHT_NOBITS (0x8) @@ -51,24 +51,24 @@ x: // SEC-NEXT: SHF_TLS // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x21D4 +// SEC-NEXT: Address: 0x201D4 // SEC: Size: 4 // SEC: Dynamic Relocations { -// SEC-NEXT: 0x2224 R_ARM_TLS_DTPMOD32 - 0x0 +// SEC-NEXT: 0x20224 R_ARM_TLS_DTPMOD32 - 0x0 // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// CHECK-NEXT: 11c0: 00 f0 20 e3 nop +// CHECK-NEXT: 101c0: 00 f0 20 e3 nop -// (0x2224 - 0x11c4) + (0x11c4 - 0x11c0 - 8) = 0x105c -// CHECK: 11c4: 5c 10 00 00 -// CHECK-NEXT: 11c8: 00 00 00 00 -// CHECK-NEXT: 11cc: 04 00 00 00 +/// (0x20224 - 0x101c4) + (0x101c4 - 0x101c0 - 8) = 0x1005c +// CHECK: 101c4: 5c 00 01 00 +// CHECK-NEXT: 101c8: 00 00 00 00 +// CHECK-NEXT: 101cc: 04 00 00 00 // CHECK-EXE: <_start>: -// CHECK-EXE-NEXT: 11114: 00 f0 20 e3 nop -// CHECK-EXE: 11118: 0c 10 00 00 -// CHECK-EXE-NEXT: 1111c: 00 00 00 00 -// CHECK-EXE-NEXT: 11120: 04 00 00 00 +// CHECK-EXE-NEXT: 20114: 00 f0 20 e3 nop +// CHECK-EXE: 20118: 0c 00 01 00 +// CHECK-EXE-NEXT: 2011c: 00 00 00 00 +// CHECK-EXE-NEXT: 20120: 04 00 00 00 diff --git a/lld/test/ELF/arm-tls-le32.s b/lld/test/ELF/arm-tls-le32.s index 6c572e870bb2e..739752209db44 100644 --- a/lld/test/ELF/arm-tls-le32.s +++ b/lld/test/ELF/arm-tls-le32.s @@ -4,9 +4,9 @@ // RUN: llvm-readobj -S --dyn-relocations %t | FileCheck --check-prefix=SEC %s // RUN: llvm-objdump -d --triple=armv7a-linux-gnueabi %t | FileCheck %s -// Test the handling of the local exec TLS model. TLS can be resolved -// statically for an application. The code sequences assume a thread pointer -// in r9 +/// Test the handling of the local exec TLS model. TLS can be resolved +/// statically for an application. The code sequences assume a thread pointer +/// in r9 .text .syntax unified @@ -15,15 +15,15 @@ .type _start,%function _start: .p2align 2 -// Generate R_ARM_TLS_LE32 relocations. These resolve statically to the offset -// of the variable from the thread pointer +/// Generate R_ARM_TLS_LE32 relocations. These resolve statically to the offset +/// of the variable from the thread pointer .Lt0: .word x(TPOFF) .Lt1: .word y(TPOFF) .Lt2: .word z(TPOFF) -// __thread int x = 10 -// __thread int y; -// __thread int z __attribute((visibility("hidden"))) +/// __thread int x = 10 +/// __thread int y; +/// __thread int z __attribute((visibility("hidden"))) .hidden z .globl z @@ -52,7 +52,7 @@ x: // SEC-NEXT: SHF_TLS // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x12120 +// SEC-NEXT: Address: 0x30120 // SEC: Size: 4 // SEC: Name: .tbss // SEC-NEXT: Type: SHT_NOBITS @@ -61,7 +61,7 @@ x: // SEC-NEXT: SHF_TLS // SEC-NEXT: SHF_WRITE // SEC-NEXT: ] -// SEC-NEXT: Address: 0x12124 +// SEC-NEXT: Address: 0x30124 // SEC: Size: 8 // SEC: Dynamic Relocations { @@ -70,9 +70,9 @@ x: // CHECK: Disassembly of section .text: // CHECK-EMPTY: // CHECK-NEXT: <_start>: -// offset of x from Thread pointer = (TcbSize + 0x0 = 0x8) -// CHECK-NEXT: 11114: 08 00 00 00 -// offset of z from Thread pointer = (TcbSize + 0x8 = 0x10) -// CHECK-NEXT: 11118: 10 00 00 00 -// offset of y from Thread pointer = (TcbSize + 0x4 = 0xc) -// CHECK-NEXT: 1111c: 0c 00 00 00 +/// offset of x from Thread pointer = (TcbSize + 0x0 = 0x8) +// CHECK-NEXT: 20114: 08 00 00 00 +/// offset of z from Thread pointer = (TcbSize + 0x8 = 0x10) +// CHECK-NEXT: 20118: 10 00 00 00 +/// offset of y from Thread pointer = (TcbSize + 0x4 = 0xc) +// CHECK-NEXT: 2011c: 0c 00 00 00 diff --git a/lld/test/ELF/arm-tls-norelax-gd-ie.s b/lld/test/ELF/arm-tls-norelax-gd-ie.s index 261739409a7da..353e34b95ecf4 100644 --- a/lld/test/ELF/arm-tls-norelax-gd-ie.s +++ b/lld/test/ELF/arm-tls-norelax-gd-ie.s @@ -5,11 +5,11 @@ // RUN: ld.lld %t1.so %t.o -o %t // RUN: llvm-readobj -S --dyn-relocations %t | FileCheck %s -// This tls global-dynamic sequence is with respect to a preemptible symbol but -// is in an application so a relaxation to Initial Exec would normally be -// possible. This would result in an assertion failure on ARM as the -// relaxation functions can't be implemented on ARM. Check that the sequence -// is handled as global dynamic +/// This tls global-dynamic sequence is with respect to a preemptible symbol but +/// is in an application so a relaxation to Initial Exec would normally be +/// possible. This would result in an assertion failure on ARM as the +/// relaxation functions can't be implemented on ARM. Check that the sequence +/// is handled as global dynamic .text .syntax unified @@ -25,6 +25,6 @@ func: .Lt0: .word y(TLSGD) + (. - .L0 - 8) // CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x12290 R_ARM_TLS_DTPMOD32 y -// CHECK-NEXT: 0x12294 R_ARM_TLS_DTPOFF32 y -// CHECK-NEXT: 0x132A4 R_ARM_JUMP_SLOT __tls_get_addr +// CHECK-NEXT: 0x30290 R_ARM_TLS_DTPMOD32 y +// CHECK-NEXT: 0x30294 R_ARM_TLS_DTPOFF32 y +// CHECK-NEXT: 0x402A4 R_ARM_JUMP_SLOT __tls_get_addr diff --git a/lld/test/ELF/arm-tls-norelax-gd-le.s b/lld/test/ELF/arm-tls-norelax-gd-le.s index 0cac059cddbdb..1a995f0210d97 100644 --- a/lld/test/ELF/arm-tls-norelax-gd-le.s +++ b/lld/test/ELF/arm-tls-norelax-gd-le.s @@ -5,11 +5,11 @@ // RUN: ld.lld %t1.so %t.o -o %t // RUN: llvm-objdump -s %t | FileCheck %s -// This tls global-dynamic sequence is with respect to a non-preemptible -// symbol in an application so a relaxation to Local Exec would normally be -// possible. This would result in an assertion failure on ARM as the -// relaxation functions can't be implemented on ARM. Check that the sequence -// is handled as global dynamic +/// This tls global-dynamic sequence is with respect to a non-preemptible +/// symbol in an application so a relaxation to Local Exec would normally be +/// possible. This would result in an assertion failure on ARM as the +/// relaxation functions can't be implemented on ARM. Check that the sequence +/// is handled as global dynamic .text .syntax unified @@ -32,10 +32,10 @@ x: .type x, %object // CHECK: Contents of section .got: -// Module index is always 1 for executable -// CHECK-NEXT: 12268 01000000 00000000 +/// Module index is always 1 for executable +// CHECK-NEXT: 30268 01000000 00000000 -// Without any definition of __tls_get_addr we get an error +/// Without any definition of __tls_get_addr we get an error // RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s // ERR: error: undefined symbol: __tls_get_addr diff --git a/lld/test/ELF/arm-tls-norelax-ie-le.s b/lld/test/ELF/arm-tls-norelax-ie-le.s index 90c75afe09141..12a50a16d31d7 100644 --- a/lld/test/ELF/arm-tls-norelax-ie-le.s +++ b/lld/test/ELF/arm-tls-norelax-ie-le.s @@ -5,10 +5,10 @@ // RUN: ld.lld %t1.so %t.o -o %t // RUN: llvm-objdump -s --triple=armv7a-linux-gnueabi %t | FileCheck %s -// This tls Initial Exec sequence is with respect to a non-preemptible symbol -// so a relaxation would normally be possible. This would result in an assertion -// failure on ARM as the relaxation functions can't be implemented on ARM. -// Check that the sequence is handled as initial exec +/// This tls Initial Exec sequence is with respect to a non-preemptible symbol +/// so a relaxation would normally be possible. This would result in an assertion +/// failure on ARM as the relaxation functions can't be implemented on ARM. +/// Check that the sequence is handled as initial exec .text .syntax unified .globl func @@ -37,5 +37,5 @@ x2: .type x2, %object // CHECK: Contents of section .got: -// x1 at offset 8 from TP, x2 at offset 0xc from TP. Offsets include TCB size of 8 -// CHECK-NEXT: 1227c 08000000 0c000000 +/// x1 at offset 8 from TP, x2 at offset 0xc from TP. Offsets include TCB size of 8 +// CHECK-NEXT: 3027c 08000000 0c000000 diff --git a/lld/test/ELF/arm-tls-norelax-ld-le.s b/lld/test/ELF/arm-tls-norelax-ld-le.s index 45c1e86326892..0834846f9ffb4 100644 --- a/lld/test/ELF/arm-tls-norelax-ld-le.s +++ b/lld/test/ELF/arm-tls-norelax-ld-le.s @@ -32,4 +32,4 @@ x: .word 10 // CHECK: Contents of section .got: -// CHECK-NEXT: 1227c 01000000 00000000 +// CHECK-NEXT: 3027c 01000000 00000000 diff --git a/lld/test/ELF/arm-undefined-weak.s b/lld/test/ELF/arm-undefined-weak.s index 727b9a7b07db6..32ab54765947e 100644 --- a/lld/test/ELF/arm-undefined-weak.s +++ b/lld/test/ELF/arm-undefined-weak.s @@ -3,11 +3,11 @@ // RUN: ld.lld --image-base=0x10000000 %t -o %t2 // RUN: llvm-objdump --triple=armv7a-none-linux-gnueabi --no-show-raw-insn -d %t2 | FileCheck %s -// Check that the ARM ABI rules for undefined weak symbols are applied. -// Branch instructions are resolved to the next instruction. Undefined -// Symbols in relative are resolved to the place so S - P + A = A. -// We place the image-base at 0x10000000 to test that a range extensions thunk -// is not generated. +/// Check that the ARM ABI rules for undefined weak symbols are applied. +/// Branch instructions are resolved to the next instruction. Undefined +/// Symbols in relative are resolved to the place so S - P + A = A. +/// We place the image-base at 0x10000000 to test that a range extensions thunk +/// is not generated. .syntax unified @@ -17,25 +17,25 @@ .text .global _start _start: -// R_ARM_JUMP24 +/// R_ARM_JUMP24 b target -// R_ARM_CALL +/// R_ARM_CALL bl target -// R_ARM_CALL with exchange +/// R_ARM_CALL with exchange blx target -// R_ARM_MOVT_PREL +/// R_ARM_MOVT_PREL movt r0, :upper16:target - . -// R_ARM_MOVW_PREL_NC +/// R_ARM_MOVW_PREL_NC movw r0, :lower16:target - . -// R_ARM_REL32 +/// R_ARM_REL32 .word target - . // CHECK: Disassembly of section .text: // CHECK-EMPTY: -// CHECK-NEXT: 100010b4 <_start>: -// CHECK-NEXT: 100010b4: b #-4 -// CHECK-NEXT: 100010b8: bl #-4 -// CHECK-NEXT: 100010bc: bl #-4 -// CHECK-NEXT: 100010c0: movt r0, #0 -// CHECK-NEXT: 100010c4: movw r0, #0 -// CHECK: 100010c8: 00 00 00 00 .word 0x00000000 +// CHECK-NEXT: 100100b4 <_start>: +// CHECK-NEXT: 100100b4: b #-4 +// CHECK-NEXT: 100100b8: bl #-4 +// CHECK-NEXT: 100100bc: bl #-4 +// CHECK-NEXT: 100100c0: movt r0, #0 +// CHECK-NEXT: 100100c4: movw r0, #0 +// CHECK: 100100c8: 00 00 00 00 .word 0x00000000 diff --git a/lld/test/ELF/global-offset-table-position-arm.s b/lld/test/ELF/global-offset-table-position-arm.s index cce8f3e2f8769..f3a7b3c442708 100644 --- a/lld/test/ELF/global-offset-table-position-arm.s +++ b/lld/test/ELF/global-offset-table-position-arm.s @@ -3,7 +3,7 @@ // RUN: ld.lld --hash-style=sysv -shared %t -o %t2 // RUN: llvm-readobj --symbols %t2 | FileCheck %s -// The ARM _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got +/// The ARM _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got .globl a .type a,%object .comm a,4,4 @@ -25,7 +25,7 @@ _start: .data // CHECK: Name: _GLOBAL_OFFSET_TABLE_ -// CHECK-NEXT: Value: 0x2268 +// CHECK-NEXT: Value: 0x20268 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Binding: Local // CHECK-NEXT: Type: None diff --git a/lld/test/ELF/pack-dyn-relocs-arm2.s b/lld/test/ELF/pack-dyn-relocs-arm2.s index bcbde213d453f..dbe6d1aca21ca 100644 --- a/lld/test/ELF/pack-dyn-relocs-arm2.s +++ b/lld/test/ELF/pack-dyn-relocs-arm2.s @@ -8,40 +8,40 @@ // RUN: llvm-readobj -r %t.exe | FileCheck %s // CHECK: Section (5) .relr.dyn { -// CHECK-NEXT: 0x31E0 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31E4 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31E8 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31EC R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31F0 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31F4 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31F8 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x31FC R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3200 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3204 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3208 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x320C R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3210 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3214 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3218 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x321C R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3220 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3224 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3228 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x322C R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3230 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3234 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3238 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x323C R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3240 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3244 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3248 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x324C R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3250 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3254 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3258 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x325C R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3260 R_ARM_RELATIVE - 0x0 -// CHECK-NEXT: 0x3264 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301E0 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301E4 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301E8 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301EC R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301F0 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301F4 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301F8 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x301FC R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30200 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30204 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30208 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x3020C R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30210 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30214 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30218 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x3021C R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30220 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30224 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30228 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x3022C R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30230 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30234 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30238 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x3023C R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30240 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30244 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30248 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x3024C R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30250 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30254 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30258 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x3025C R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30260 R_ARM_RELATIVE - 0x0 +// CHECK-NEXT: 0x30264 R_ARM_RELATIVE - 0x0 // CHECK-NEXT: } // RUN: llvm-readobj -S --dynamic-table %t.exe | FileCheck --check-prefix=HEADER %s diff --git a/lld/test/ELF/pack-dyn-relocs.s b/lld/test/ELF/pack-dyn-relocs.s index 6ecf354f68a2c..6c78a91c9d61c 100644 --- a/lld/test/ELF/pack-dyn-relocs.s +++ b/lld/test/ELF/pack-dyn-relocs.s @@ -6,44 +6,44 @@ // RUN: ld.lld -pie --pack-dyn-relocs=none %t.a32.o %t.a32.so -o %t2.a32 // RUN: llvm-readobj -r %t2.a32 | FileCheck --check-prefix=UNPACKED32 %s -// Unpacked should have the relative relocations in their natural order. -// UNPACKED32: Section ({{.+}}) .rel.dyn { -// UNPACKED32-NEXT: 0x331C R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3320 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3324 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3328 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x332C R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3330 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3334 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3338 R_ARM_RELATIVE - 0x0 - -// UNPACKED32-NEXT: 0x3340 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3344 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3348 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x334C R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3350 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3354 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3358 R_ARM_RELATIVE - 0x0 - -// UNPACKED32-NEXT: 0x3364 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3368 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x336C R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3370 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3374 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3378 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x337C R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3380 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3384 R_ARM_RELATIVE - 0x0 -// UNPACKED32-NEXT: 0x3389 R_ARM_RELATIVE - 0x0 - -// UNPACKED32-NEXT: 0x333C R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x3360 R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x338D R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x3391 R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x3395 R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x3399 R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x339D R_ARM_ABS32 bar2 0x0 -// UNPACKED32-NEXT: 0x335C R_ARM_ABS32 zed2 0x0 +/// Unpacked should have the relative relocations in their natural order. +/// UNPACKED32: Section ({{.+}}) .rel.dyn { +// UNPACKED32-NEXT: 0x3031C R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30320 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30324 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30328 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x3032C R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30330 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30334 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30338 R_ARM_RELATIVE - 0x0 + +// UNPACKED32-NEXT: 0x30340 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30344 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30348 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x3034C R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30350 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30354 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30358 R_ARM_RELATIVE - 0x0 + +// UNPACKED32-NEXT: 0x30364 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30368 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x3036C R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30370 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30374 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30378 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x3037C R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30380 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30384 R_ARM_RELATIVE - 0x0 +// UNPACKED32-NEXT: 0x30389 R_ARM_RELATIVE - 0x0 + +// UNPACKED32-NEXT: 0x3033C R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x30360 R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x3038D R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x30391 R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x30395 R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x30399 R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x3039D R_ARM_ABS32 bar2 0x0 +// UNPACKED32-NEXT: 0x3035C R_ARM_ABS32 zed2 0x0 // UNPACKED32-NEXT: } // RUN: ld.lld -pie --pack-dyn-relocs=android %t.a32.o %t.a32.so -o %t3.a32 @@ -69,46 +69,46 @@ // ANDROID32-HEADERS: 0x6000000F ANDROID_REL [[ADDR]] // ANDROID32-HEADERS: 0x60000010 ANDROID_RELSZ [[SIZE]] -// Packed should have the groups of non-relative relocations first, followed -// by the larger groups of relative relocations (i.e. the 8 and 9 followed -// by the 7.) +/// Packed should have the groups of non-relative relocations first, followed +/// by the larger groups of relative relocations (i.e. the 8 and 9 followed +/// by the 7.) // ANDROID32: Section ({{.+}}) .rel.dyn { -// ANDROID32-NEXT: 0x324C R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3250 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3254 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3258 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x325C R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3260 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3264 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3268 R_ARM_RELATIVE - 0 - -// ANDROID32-NEXT: 0x3294 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3298 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x329C R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32A0 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32A4 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32A8 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32AC R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32B0 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32B4 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3270 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3274 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3278 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x327C R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3280 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3284 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x3288 R_ARM_RELATIVE - 0 -// ANDROID32-NEXT: 0x32B9 R_ARM_RELATIVE - 0 - -// ANDROID32-NEXT: 0x326C R_ARM_ABS32 bar2 0 -// ANDROID32-NEXT: 0x3290 R_ARM_ABS32 bar2 0 -// ANDROID32-NEXT: 0x32BD R_ARM_ABS32 bar2 0 -// ANDROID32-NEXT: 0x32C1 R_ARM_ABS32 bar2 0 -// ANDROID32-NEXT: 0x32C5 R_ARM_ABS32 bar2 0 -// ANDROID32-NEXT: 0x32C9 R_ARM_ABS32 bar2 0 -// ANDROID32-NEXT: 0x32CD R_ARM_ABS32 bar2 0 - -// ANDROID32-NEXT: 0x328C R_ARM_ABS32 zed2 0 +// ANDROID32-NEXT: 0x3024C R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30250 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30254 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30258 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x3025C R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30260 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30264 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30268 R_ARM_RELATIVE - 0 + +// ANDROID32-NEXT: 0x30294 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30298 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x3029C R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302A0 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302A4 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302A8 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302AC R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302B0 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302B4 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30270 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30274 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30278 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x3027C R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30280 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30284 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x30288 R_ARM_RELATIVE - 0 +// ANDROID32-NEXT: 0x302B9 R_ARM_RELATIVE - 0 + +// ANDROID32-NEXT: 0x3026C R_ARM_ABS32 bar2 0 +// ANDROID32-NEXT: 0x30290 R_ARM_ABS32 bar2 0 +// ANDROID32-NEXT: 0x302BD R_ARM_ABS32 bar2 0 +// ANDROID32-NEXT: 0x302C1 R_ARM_ABS32 bar2 0 +// ANDROID32-NEXT: 0x302C5 R_ARM_ABS32 bar2 0 +// ANDROID32-NEXT: 0x302C9 R_ARM_ABS32 bar2 0 +// ANDROID32-NEXT: 0x302CD R_ARM_ABS32 bar2 0 + +// ANDROID32-NEXT: 0x3028C R_ARM_ABS32 zed2 0 // ANDROID32-NEXT: } // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a32.o %t.a32.so -o %t4.a32 @@ -136,54 +136,54 @@ // RELR32-HEADERS: 0x00000023 RELRSZ 0x8 // RELR32-HEADERS: 0x00000025 RELRENT 0x4 -// SHT_RELR section contains address/bitmap entries -// encoding the offsets for relative relocation. +/// SHT_RELR section contains address/bitmap entries +/// encoding the offsets for relative relocation. // RAW-RELR32: Section ({{.+}}) .relr.dyn { -// RAW-RELR32-NEXT: 0x327C +// RAW-RELR32-NEXT: 0x3027C // RAW-RELR32-NEXT: 0x7FCFEFF // RAW-RELR32-NEXT: } -// Decoded SHT_RELR section is same as UNPACKED, -// but contains only the relative relocations. -// Any relative relocations with odd offset stay in SHT_REL. +/// Decoded SHT_RELR section is same as UNPACKED, +/// but contains only the relative relocations. +/// Any relative relocations with odd offset stay in SHT_REL. // RELR32: Section ({{.+}}) .rel.dyn { -// RELR32-NEXT: 0x32E9 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x329C R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32C0 R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32ED R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32F1 R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32F5 R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32F9 R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32FD R_ARM_ABS32 bar2 0x0 -// RELR32-NEXT: 0x32BC R_ARM_ABS32 zed2 0x0 +// RELR32-NEXT: 0x302E9 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x3029C R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302C0 R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302ED R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302F1 R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302F5 R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302F9 R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302FD R_ARM_ABS32 bar2 0x0 +// RELR32-NEXT: 0x302BC R_ARM_ABS32 zed2 0x0 // RELR32-NEXT: } // RELR32-NEXT: Section ({{.+}}) .relr.dyn { -// RELR32-NEXT: 0x327C R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x3280 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x3284 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x3288 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x328C R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x3290 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x3294 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x3298 R_ARM_RELATIVE - 0x0 - -// RELR32-NEXT: 0x32A0 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32A4 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32A8 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32AC R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32B0 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32B4 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32B8 R_ARM_RELATIVE - 0x0 - -// RELR32-NEXT: 0x32C4 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32C8 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32CC R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32D0 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32D4 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32D8 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32DC R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32E0 R_ARM_RELATIVE - 0x0 -// RELR32-NEXT: 0x32E4 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x3027C R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x30280 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x30284 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x30288 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x3028C R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x30290 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x30294 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x30298 R_ARM_RELATIVE - 0x0 + +// RELR32-NEXT: 0x302A0 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302A4 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302A8 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302AC R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302B0 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302B4 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302B8 R_ARM_RELATIVE - 0x0 + +// RELR32-NEXT: 0x302C4 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302C8 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302CC R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302D0 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302D4 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302D8 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302DC R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302E0 R_ARM_RELATIVE - 0x0 +// RELR32-NEXT: 0x302E4 R_ARM_RELATIVE - 0x0 // RELR32-NEXT: } // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/shared2.s -o %t.a64.so.o @@ -318,16 +318,16 @@ // RELR64-HEADERS: 0x0000000000000023 RELRSZ 0x10 // RELR64-HEADERS: 0x0000000000000025 RELRENT 0x8 -// SHT_RELR section contains address/bitmap entries -// encoding the offsets for relative relocation. +/// SHT_RELR section contains address/bitmap entries +/// encoding the offsets for relative relocation. // RAW-RELR64: Section ({{.+}}) .relr.dyn { // RAW-RELR64-NEXT: 0x30480 // RAW-RELR64-NEXT: 0x7FCFEFF // RAW-RELR64-NEXT: } -// Decoded SHT_RELR section is same as UNPACKED, -// but contains only the relative relocations. -// Any relative relocations with odd offset stay in SHT_RELA. +/// Decoded SHT_RELR section is same as UNPACKED, +/// but contains only the relative relocations. +/// Any relative relocations with odd offset stay in SHT_RELA. // RELR64: Section ({{.+}}) .rela.dyn { // RELR64-NEXT: 0x30559 R_AARCH64_RELATIVE - 0xA // RELR64-NEXT: 0x304C0 R_AARCH64_ABS64 bar2 0x1 From 5eb8d45ab5b85cb3a2edfe995cbf1d4b1beae462 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Fri, 17 Apr 2020 16:43:35 -0400 Subject: [PATCH 50/56] [libc++] Use proper shell escaping in the executors This was originally committed as f8452ddfcc33 and reverted in 7cb1aa9d9368. The issue was that shell builtins were being escaped too, and apparently Bash won't execute a builtin when it is quoted e.g. '!'. Instead, it thinks it's a command and it can't find it. Re-committing the change with that issue fixed. --- .../{sh.cpp => }/remote-substitutions.sh.cpp | 0 .../selftest/newformat/shell-escape.sh.cpp | 18 ++++++++++++++++++ libcxx/utils/run.py | 8 ++++---- libcxx/utils/ssh.py | 3 ++- 4 files changed, 24 insertions(+), 5 deletions(-) rename libcxx/test/libcxx/selftest/newformat/{sh.cpp => }/remote-substitutions.sh.cpp (100%) create mode 100644 libcxx/test/libcxx/selftest/newformat/shell-escape.sh.cpp diff --git a/libcxx/test/libcxx/selftest/newformat/sh.cpp/remote-substitutions.sh.cpp b/libcxx/test/libcxx/selftest/newformat/remote-substitutions.sh.cpp similarity index 100% rename from libcxx/test/libcxx/selftest/newformat/sh.cpp/remote-substitutions.sh.cpp rename to libcxx/test/libcxx/selftest/newformat/remote-substitutions.sh.cpp diff --git a/libcxx/test/libcxx/selftest/newformat/shell-escape.sh.cpp b/libcxx/test/libcxx/selftest/newformat/shell-escape.sh.cpp new file mode 100644 index 0000000000000..c942df0133b4a --- /dev/null +++ b/libcxx/test/libcxx/selftest/newformat/shell-escape.sh.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// Make sure that arguments of the %{exec} substitution are shell-escaped +// properly. If that wasn't the case, the command would fail because the +// shell would look for a matching `"`. + +// RUN: %{exec} echo '"' + +// Also make sure that we don't escape Shell builtins like `!`, because the +// shell otherwise thinks it's a command and it can't find it. + +// RUN: ! false diff --git a/libcxx/utils/run.py b/libcxx/utils/run.py index 7cdf65264ec0b..0453e4a1f0184 100644 --- a/libcxx/utils/run.py +++ b/libcxx/utils/run.py @@ -30,11 +30,11 @@ def main(): if len(remaining) < 2: sys.stderr.write('Missing actual commands to run') exit(1) - remaining = remaining[1:] # Skip the '--' + commandLine = remaining[1:] # Skip the '--' # Do any necessary codesigning. if args.codesign_identity: - exe = remaining[0] + exe = commandLine[0] rc = subprocess.call(['xcrun', 'codesign', '-f', '-s', args.codesign_identity, exe], env={}) if rc != 0: sys.stderr.write('Failed to codesign: ' + exe) @@ -57,8 +57,8 @@ def main(): else: shutil.copy2(dep, args.execdir) - # Run the executable with the given environment in the execution directory. - return subprocess.call(' '.join(remaining), cwd=args.execdir, env=env, shell=True) + # Run the command line with the given environment in the execution directory. + return subprocess.call(subprocess.list2cmdline(commandLine), cwd=args.execdir, env=env, shell=True) finally: shutil.rmtree(args.execdir) diff --git a/libcxx/utils/ssh.py b/libcxx/utils/ssh.py index c7d8c97a14078..4bb983e5d2cbb 100644 --- a/libcxx/utils/ssh.py +++ b/libcxx/utils/ssh.py @@ -97,10 +97,11 @@ def main(): # host by transforming the path of test-executables to their path in the # temporary directory, where we know they have been copied when we handled # test dependencies above. + commandLine = (pathOnRemote(x) if isTestExe(x) else x for x in commandLine) remoteCommands += [ 'cd {}'.format(tmp), 'export {}'.format(' '.join(args.env)), - ' '.join(pathOnRemote(x) if isTestExe(x) else x for x in commandLine) + subprocess.list2cmdline(commandLine) ] # Finally, SSH to the remote host and execute all the commands. From cacf1b5093279ae2aaa695d3eb5f0c116d0746ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20B=C3=B6ck?= Date: Sat, 18 Apr 2020 08:23:37 -0700 Subject: [PATCH 51/56] [llvm-objdump] Demangle C++ Symbols in branch and call targets Currently C++ symbols are demangled in the symbol table as well as in the disassembly and relocations. This patch adds demangling of C++ symbols in targets of calls and branches making it easier to decipher control flow in disassembly. This also matches up with GNUobjdump's behavior Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D77957 --- llvm/test/tools/llvm-objdump/X86/demangle.s | 2 +- llvm/tools/llvm-objdump/llvm-objdump.cpp | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/test/tools/llvm-objdump/X86/demangle.s b/llvm/test/tools/llvm-objdump/X86/demangle.s index f6523f2e931bb..c2caae865a5ad 100644 --- a/llvm/test/tools/llvm-objdump/X86/demangle.s +++ b/llvm/test/tools/llvm-objdump/X86/demangle.s @@ -11,7 +11,7 @@ ## Check the case when relocations are inlined into disassembly. # RUN: llvm-objdump -d -r --demangle %t | FileCheck %s --check-prefix=INLINE # INLINE: : -# INLINE-NEXT: 0: {{.*}} callq 0x5 <_Z3foov+0x5> +# INLINE-NEXT: 0: {{.*}} callq 0x5 # INLINE-NEXT: 0000000000000001: R_X86_64_PLT32 foo()-0x4 .text diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp index c264ea6461bc2..0eeb337c1b7be 100644 --- a/llvm/tools/llvm-objdump/llvm-objdump.cpp +++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp @@ -1556,7 +1556,10 @@ static void disassembleObject(const Target *TheTarget, const ObjectFile *Obj, if (TargetSym != TargetSectionSymbols->begin()) { --TargetSym; uint64_t TargetAddress = TargetSym->Addr; - StringRef TargetName = TargetSym->Name; + std::string TargetName = TargetSym->Name.str(); + if (Demangle) + TargetName = demangle(TargetName); + outs() << " <" << TargetName; uint64_t Disp = Target - TargetAddress; if (Disp) From f043677f6dd6e5392509b59139999918b421699d Mon Sep 17 00:00:00 2001 From: Uday Bondhugula Date: Sat, 18 Apr 2020 19:07:19 +0530 Subject: [PATCH 52/56] [MLIR] Make isPerfectlyNested check more efficient Make mlir::isPerfectlyNested more efficient; use O(1) check instead of O(N) size() method. Differential Revision: https://reviews.llvm.org/D78428 --- mlir/lib/Transforms/Utils/LoopUtils.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/mlir/lib/Transforms/Utils/LoopUtils.cpp b/mlir/lib/Transforms/Utils/LoopUtils.cpp index c03cf6cfc2820..2175e6709f650 100644 --- a/mlir/lib/Transforms/Utils/LoopUtils.cpp +++ b/mlir/lib/Transforms/Utils/LoopUtils.cpp @@ -705,17 +705,25 @@ bool mlir::isValidLoopInterchangePermutation(ArrayRef loops, return checkLoopInterchangeDependences(depCompsVec, loops, loopPermMap); } -/// Return true if `loops` is a perfect nest. +/// Returns true if `loops` is a perfectly nested loop nest, where loops appear +/// in it from outermost to innermost. static bool LLVM_ATTRIBUTE_UNUSED isPerfectlyNested(ArrayRef loops) { - auto outerLoop = loops.front(); + assert(!loops.empty() && "no loops provided"); + + // We already know that the block can't be empty. + auto hasTwoElements = [](Block *block) { + auto secondOpIt = std::next(block->begin()); + return secondOpIt != block->end() && &*secondOpIt == &block->back(); + }; + + auto enclosingLoop = loops.front(); for (auto loop : loops.drop_front()) { auto parentForOp = dyn_cast(loop.getParentOp()); // parentForOp's body should be just this loop and the terminator. - if (parentForOp != outerLoop || - parentForOp.getBody()->getOperations().size() != 2) + if (parentForOp != enclosingLoop || !hasTwoElements(parentForOp.getBody())) return false; - outerLoop = loop; + enclosingLoop = loop; } return true; } From 46853b95ca550ccd6e2700df85f2a5f558134bb3 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Sat, 18 Apr 2020 19:44:54 +0100 Subject: [PATCH 53/56] [SCCP] Drop unused early exit from visitStoreInst (NFC). There are no lattice values associated with store instructions directly. They will never get marked as overdefined. --- llvm/lib/Transforms/Scalar/SCCP.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index 6bb19383964cb..187f26f7ca523 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -1061,11 +1061,6 @@ void SCCPSolver::visitStoreInst(StoreInst &SI) { if (TrackedGlobals.empty() || !isa(SI.getOperand(1))) return; - // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would - // discover a concrete value later. - if (isOverdefined(ValueState[&SI])) - return (void)markOverdefined(&SI); - GlobalVariable *GV = cast(SI.getOperand(1)); auto I = TrackedGlobals.find(GV); if (I == TrackedGlobals.end()) From ec73ae11a37e65c984a88d05ad401d28e78e96f8 Mon Sep 17 00:00:00 2001 From: Mircea Trofin Date: Fri, 17 Apr 2020 19:35:05 -0700 Subject: [PATCH 54/56] [llvm][NFC][CallSite] Remove CallSite from ProfileSummary Summary: Depends on D78395. Reviewers: craig.topper, dblaikie, wmi, davidxl Subscribers: eraman, hiraditya, haicheng, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D78414 --- llvm/include/llvm/Analysis/ProfileSummaryInfo.h | 10 +++++----- llvm/lib/Analysis/InlineCost.cpp | 5 ++--- llvm/lib/Analysis/ProfileSummaryInfo.cpp | 11 ++++++----- llvm/unittests/Analysis/ProfileSummaryInfoTest.cpp | 11 +++++------ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/llvm/include/llvm/Analysis/ProfileSummaryInfo.h b/llvm/include/llvm/Analysis/ProfileSummaryInfo.h index accc78b62b9ee..50057a26d9064 100644 --- a/llvm/include/llvm/Analysis/ProfileSummaryInfo.h +++ b/llvm/include/llvm/Analysis/ProfileSummaryInfo.h @@ -24,7 +24,7 @@ namespace llvm { class BasicBlock; class BlockFrequencyInfo; -class CallSite; +class CallBase; class Instruction; class ProfileSummary; /// Analysis providing profile information. @@ -144,10 +144,10 @@ class ProfileSummaryInfo { /// cold percentile cutoff value. bool isColdBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB, BlockFrequencyInfo *BFI); - /// Returns true if CallSite \p CS is considered hot. - bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); - /// Returns true if Callsite \p CS is considered cold. - bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI); + /// Returns true if the call site \p CB is considered hot. + bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI); + /// Returns true if call site \p CB is considered cold. + bool isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI); /// Returns HotCountThreshold if set. Recompute HotCountThreshold /// if not set. uint64_t getOrCompHotCountThreshold(); diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp index b9f0699ab6f7a..548def45eccb5 100644 --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -1173,7 +1173,7 @@ bool InlineCostCallAnalyzer::isColdCallSite(CallBase &Call, // If global profile summary is available, then callsite's coldness is // determined based on that. if (PSI && PSI->hasProfileSummary()) - return PSI->isColdCallSite(CallSite(&Call), CallerBFI); + return PSI->isColdCallSite(Call, CallerBFI); // Otherwise we need BFI to be available. if (!CallerBFI) @@ -1197,8 +1197,7 @@ InlineCostCallAnalyzer::getHotCallSiteThreshold(CallBase &Call, // If global profile summary is available, then callsite's hotness is // determined based on that. - if (PSI && PSI->hasProfileSummary() && - PSI->isHotCallSite(CallSite(&Call), CallerBFI)) + if (PSI && PSI->hasProfileSummary() && PSI->isHotCallSite(Call, CallerBFI)) return Params.HotCallSiteThreshold; // Otherwise we need BFI to be available and to have a locally hot callsite diff --git a/llvm/lib/Analysis/ProfileSummaryInfo.cpp b/llvm/lib/Analysis/ProfileSummaryInfo.cpp index 678d66f632a8a..919cda7cf1af6 100644 --- a/llvm/lib/Analysis/ProfileSummaryInfo.cpp +++ b/llvm/lib/Analysis/ProfileSummaryInfo.cpp @@ -101,6 +101,7 @@ bool ProfileSummaryInfo::computeSummary() { return true; } +// FIXME(CallSite): the parameter should be a CallBase. Optional ProfileSummaryInfo::getProfileCount(const Instruction *Inst, BlockFrequencyInfo *BFI, @@ -385,21 +386,21 @@ bool ProfileSummaryInfo::isColdBlockNthPercentile(int PercentileCutoff, return isHotOrColdBlockNthPercentile(PercentileCutoff, BB, BFI); } -bool ProfileSummaryInfo::isHotCallSite(const CallSite &CS, +bool ProfileSummaryInfo::isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) { - auto C = getProfileCount(CS.getInstruction(), BFI); + auto C = getProfileCount(&CB, BFI); return C && isHotCount(*C); } -bool ProfileSummaryInfo::isColdCallSite(const CallSite &CS, +bool ProfileSummaryInfo::isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) { - auto C = getProfileCount(CS.getInstruction(), BFI); + auto C = getProfileCount(&CB, BFI); if (C) return isColdCount(*C); // In SamplePGO, if the caller has been sampled, and there is no profile // annotated on the callsite, we consider the callsite as cold. - return hasSampleProfile() && CS.getCaller()->hasProfileData(); + return hasSampleProfile() && CB.getCaller()->hasProfileData(); } INITIALIZE_PASS(ProfileSummaryInfoWrapperPass, "profile-summary-info", diff --git a/llvm/unittests/Analysis/ProfileSummaryInfoTest.cpp b/llvm/unittests/Analysis/ProfileSummaryInfoTest.cpp index ea354a9ede38a..e3f2446fc3957 100644 --- a/llvm/unittests/Analysis/ProfileSummaryInfoTest.cpp +++ b/llvm/unittests/Analysis/ProfileSummaryInfoTest.cpp @@ -12,7 +12,6 @@ #include "llvm/Analysis/LoopInfo.h" #include "llvm/AsmParser/Parser.h" #include "llvm/IR/BasicBlock.h" -#include "llvm/IR/CallSite.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" @@ -134,7 +133,7 @@ TEST_F(ProfileSummaryInfoTest, TestNoProfile) { EXPECT_FALSE(PSI.isHotBlock(&BB0, &BFI)); EXPECT_FALSE(PSI.isColdBlock(&BB0, &BFI)); - CallSite CS1(BB1->getFirstNonPHI()); + CallBase &CS1 = *cast(BB1->getFirstNonPHI()); EXPECT_FALSE(PSI.isHotCallSite(CS1, &BFI)); EXPECT_FALSE(PSI.isColdCallSite(CS1, &BFI)); } @@ -228,9 +227,9 @@ TEST_F(ProfileSummaryInfoTest, InstrProf) { EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB2, &BFI)); EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB3, &BFI)); - CallSite CS1(BB1->getFirstNonPHI()); + CallBase &CS1 = *cast(BB1->getFirstNonPHI()); auto *CI2 = BB2->getFirstNonPHI(); - CallSite CS2(CI2); + CallBase &CS2 = *cast(CI2); EXPECT_TRUE(PSI.isHotCallSite(CS1, &BFI)); EXPECT_FALSE(PSI.isHotCallSite(CS2, &BFI)); @@ -323,14 +322,14 @@ TEST_F(ProfileSummaryInfoTest, SampleProf) { EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB2, &BFI)); EXPECT_TRUE(PSI.isColdBlockNthPercentile(10000, BB3, &BFI)); - CallSite CS1(BB1->getFirstNonPHI()); + CallBase &CS1 = *cast(BB1->getFirstNonPHI()); auto *CI2 = BB2->getFirstNonPHI(); // Manually attach branch weights metadata to the call instruction. SmallVector Weights; Weights.push_back(1000); MDBuilder MDB(M->getContext()); CI2->setMetadata(LLVMContext::MD_prof, MDB.createBranchWeights(Weights)); - CallSite CS2(CI2); + CallBase &CS2 = *cast(CI2); EXPECT_FALSE(PSI.isHotCallSite(CS1, &BFI)); EXPECT_TRUE(PSI.isHotCallSite(CS2, &BFI)); From ecddafd84a7aa74fb8c4087926db16eb1c459028 Mon Sep 17 00:00:00 2001 From: Uday Bondhugula Date: Sat, 18 Apr 2020 16:21:07 +0530 Subject: [PATCH 55/56] [MLIR] NFC affine for op tiling cleanup / utility rename Rename mlir::tileCodeGen -> mlir::tilePerfectlyNested to be consistent. NFC clean up tiling utility code, drop dead code, better comments. Expose isPerfectlyNested and reuse. Differential Revision: https://reviews.llvm.org/D78423 --- mlir/include/mlir/Transforms/LoopUtils.h | 12 +++- .../Dialect/Affine/Transforms/LoopTiling.cpp | 66 +++++++++---------- mlir/lib/Transforms/Utils/LoopUtils.cpp | 4 +- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/mlir/include/mlir/Transforms/LoopUtils.h b/mlir/include/mlir/Transforms/LoopUtils.h index 1d0e8d39bd619..30f024e9f1b18 100644 --- a/mlir/include/mlir/Transforms/LoopUtils.h +++ b/mlir/include/mlir/Transforms/LoopUtils.h @@ -45,6 +45,10 @@ LogicalResult loopUnrollByFactor(AffineForOp forOp, uint64_t unrollFactor); /// whichever is lower. LogicalResult loopUnrollUpToFactor(AffineForOp forOp, uint64_t unrollFactor); +/// Returns true if `loops` is a perfectly nested loop nest, where loops appear +/// in it from outermost to innermost. +bool LLVM_ATTRIBUTE_UNUSED isPerfectlyNested(ArrayRef loops); + /// Get perfectly nested sequence of loops starting at root of loop nest /// (the first op being another AffineFor, and the second op - a terminator). /// A loop is perfectly nested iff: the first op in the loop's body is another @@ -84,10 +88,12 @@ LogicalResult affineForOpBodySkew(AffineForOp forOp, ArrayRef shifts, /// Tiles the specified band of perfectly nested loops creating tile-space loops /// and intra-tile loops. A band is a contiguous set of loops. `tiledNest` when /// non-null is set to the loops of the tiled nest from outermost to innermost. +/// Loops in `input` are erased when the tiling is successful. LLVM_NODISCARD -LogicalResult tileCodeGen(MutableArrayRef band, - ArrayRef tileSizes, - SmallVectorImpl *tiledNest = nullptr); +LogicalResult +tilePerfectlyNested(MutableArrayRef input, + ArrayRef tileSizes, + SmallVectorImpl *tiledNest = nullptr); /// Performs loop interchange on 'forOpA' and 'forOpB'. Requires that 'forOpA' /// and 'forOpB' are part of a perfectly nested sequence of loops. diff --git a/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp b/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp index f6d1a5494be21..ce692e405ae1f 100644 --- a/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp +++ b/mlir/lib/Dialect/Affine/Transforms/LoopTiling.cpp @@ -93,10 +93,8 @@ constructTiledIndexSetHyperRect(MutableArrayRef origLoops, // Bounds for tile space loops. for (unsigned i = 0; i < width; i++) { - auto lbOperands = origLoops[i].getLowerBoundOperands(); - auto ubOperands = origLoops[i].getUpperBoundOperands(); - SmallVector newLbOperands(lbOperands); - SmallVector newUbOperands(ubOperands); + OperandRange newLbOperands = origLoops[i].getLowerBoundOperands(); + OperandRange newUbOperands = origLoops[i].getUpperBoundOperands(); newLoops[i].setLowerBound(newLbOperands, origLoops[i].getLowerBoundMap()); newLoops[i].setUpperBound(newUbOperands, origLoops[i].getUpperBoundMap()); newLoops[i].setStep(tileSizes[i]); @@ -111,8 +109,7 @@ constructTiledIndexSetHyperRect(MutableArrayRef origLoops, /*operands=*/newLoops[i].getInductionVar(), lbMap); // Set the upper bound. - if (mayBeConstantCount.hasValue() && - mayBeConstantCount.getValue() < tileSizes[i]) { + if (mayBeConstantCount && mayBeConstantCount.getValue() < tileSizes[i]) { // Trip count is less than tile size; upper bound is the trip count. auto ubMap = b.getConstantAffineMap(mayBeConstantCount.getValue()); newLoops[width + i].setUpperBoundMap(ubMap); @@ -121,20 +118,22 @@ constructTiledIndexSetHyperRect(MutableArrayRef origLoops, // Construct the upper bound map; the operands are the original operands // with 'i' (tile-space loop) appended to it. The new upper bound map is // the original one with an additional expression i + tileSize appended. - auto ub = origLoops[i].getUpperBound(); + + // Add dim operands from original upper bound. SmallVector ubOperands; + auto ub = origLoops[i].getUpperBound(); ubOperands.reserve(ub.getNumOperands() + 1); auto origUbMap = ub.getMap(); - // Add dim operands from original upper bound. - for (unsigned j = 0, e = origUbMap.getNumDims(); j < e; ++j) { + for (unsigned j = 0, e = origUbMap.getNumDims(); j < e; ++j) ubOperands.push_back(ub.getOperand(j)); - } + // Add dim operand for new loop upper bound. ubOperands.push_back(newLoops[i].getInductionVar()); + // Add symbol operands from original upper bound. - for (unsigned j = 0, e = origUbMap.getNumSymbols(); j < e; ++j) { + for (unsigned j = 0, e = origUbMap.getNumSymbols(); j < e; ++j) ubOperands.push_back(ub.getOperand(origUbMap.getNumDims() + j)); - } + SmallVector boundExprs; boundExprs.reserve(1 + origUbMap.getNumResults()); auto dim = b.getAffineDimExpr(origUbMap.getNumDims()); @@ -159,22 +158,22 @@ constructTiledIndexSetHyperRect(MutableArrayRef origLoops, /// Tiles the specified band of perfectly nested loops creating tile-space loops /// and intra-tile loops. A band is a contiguous set of loops. // TODO(bondhugula): handle non hyper-rectangular spaces. -LogicalResult mlir::tileCodeGen(MutableArrayRef band, - ArrayRef tileSizes, - SmallVectorImpl *tiledNest) { +LogicalResult +mlir::tilePerfectlyNested(MutableArrayRef input, + ArrayRef tileSizes, + SmallVectorImpl *tiledNest) { // Check if the supplied for op's are all successively nested. - assert(!band.empty() && "no loops in band"); - assert(band.size() == tileSizes.size() && "Too few/many tile sizes"); + assert(!input.empty() && "no loops in input band"); + assert(input.size() == tileSizes.size() && "Too few/many tile sizes"); - for (unsigned i = 1, e = band.size(); i < e; i++) - assert(band[i].getParentOp() == band[i - 1] && "not a perfect nest / band"); + assert(isPerfectlyNested(input) && "input loops not perfectly nested"); - auto origLoops = band; + auto origLoops = input; AffineForOp rootAffineForOp = origLoops[0]; auto loc = rootAffineForOp.getLoc(); // Note that width is at least one since band isn't empty. - unsigned width = band.size(); + unsigned width = input.size(); SmallVector tiledLoops(2 * width); @@ -209,14 +208,13 @@ LogicalResult mlir::tileCodeGen(MutableArrayRef band, } // Move the loop body of the original nest to the new one. - moveLoopBody(origLoops[origLoops.size() - 1], innermostPointLoop); + moveLoopBody(origLoops.back(), innermostPointLoop); SmallVector origLoopIVs; - extractForInductionVars(band, &origLoopIVs); - SmallVector, 6> ids(origLoopIVs.begin(), origLoopIVs.end()); - FlatAffineConstraints cst; - getIndexSet(band, &cst); + extractForInductionVars(input, &origLoopIVs); + FlatAffineConstraints cst; + getIndexSet(input, &cst); if (!cst.isHyperRectangular(0, width)) { llvm::dbgs() << "tiled code generation unimplemented for the " "non-hyperrectangular case, op:" @@ -258,15 +256,15 @@ static void getTileableBands(FuncOp f, getMaximalPerfectLoopNest(forOp); } -// Reduce each tile size to the largest divisor of the corresponding trip count -// (if the trip count is known). +/// Reduces each tile size to the largest divisor of the corresponding trip +/// count (if the trip count is known). static void adjustToDivisorsOfTripCounts(ArrayRef band, SmallVectorImpl *tileSizes) { assert(band.size() == tileSizes->size() && "invalid tile size count"); for (unsigned i = 0, e = band.size(); i < e; i++) { unsigned &tSizeAdjusted = (*tileSizes)[i]; auto mayConst = getConstantTripCount(band[i]); - if (!mayConst.hasValue()) + if (!mayConst) continue; // Adjust the tile size to largest factor of the trip count less than // tSize. @@ -289,8 +287,8 @@ void LoopTiling::getTileSizes(ArrayRef band, if (band.empty()) return; - // Use tileSize for all loops if specified. - if (tileSize.hasValue()) { + // Use command-line tileSize for all loops if specified. + if (tileSize) { tileSizes->assign(band.size(), tileSize); return; } @@ -312,7 +310,7 @@ void LoopTiling::getTileSizes(ArrayRef band, // footprint increases with the tile size linearly in that dimension (i.e., // assumes one-to-one access function). auto fp = getMemoryFootprintBytes(band[0], 0); - if (!fp.hasValue()) { + if (!fp) { // Fill with default tile sizes if footprint is unknown. std::fill(tileSizes->begin(), tileSizes->end(), LoopTiling::kDefaultTileSize); @@ -339,7 +337,7 @@ void LoopTiling::getTileSizes(ArrayRef band, // one possible approach. Or compute a polynomial in tile sizes and solve for // it. - // For an n-d tileable band, compute n^th root of the excess. + // For an n-d tileable band, compute the n^th root of the excess. unsigned tSize = static_cast(floorl(std::pow(excessFactor, 1.0 / band.size()))); // We'll keep a running product to determine the last tile size better. @@ -375,7 +373,7 @@ void LoopTiling::runOnFunction() { diag << "]\n"; } SmallVector tiledNest; - if (failed(tileCodeGen(band, tileSizes, &tiledNest))) + if (failed(tilePerfectlyNested(band, tileSizes, &tiledNest))) return signalPassFailure(); // Separate full and partial tiles. diff --git a/mlir/lib/Transforms/Utils/LoopUtils.cpp b/mlir/lib/Transforms/Utils/LoopUtils.cpp index 2175e6709f650..0161fbef621e7 100644 --- a/mlir/lib/Transforms/Utils/LoopUtils.cpp +++ b/mlir/lib/Transforms/Utils/LoopUtils.cpp @@ -707,8 +707,8 @@ bool mlir::isValidLoopInterchangePermutation(ArrayRef loops, /// Returns true if `loops` is a perfectly nested loop nest, where loops appear /// in it from outermost to innermost. -static bool LLVM_ATTRIBUTE_UNUSED -isPerfectlyNested(ArrayRef loops) { +bool LLVM_ATTRIBUTE_UNUSED +mlir::isPerfectlyNested(ArrayRef loops) { assert(!loops.empty() && "no loops provided"); // We already know that the block can't be empty. From aad3d578da0ddf6d0d3d95e5e09a32e47f6dfeb8 Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 18 Apr 2020 11:31:38 -0700 Subject: [PATCH 56/56] [DebugInfo] Change DIEnumerator payload type from int64_t to APInt This allows the representation of arbitrarily large enumeration values. See https://lists.llvm.org/pipermail/llvm-dev/2017-December/119475.html for context. Reviewed By: andrewrk, aprantl, MaskRay Differential Revision: https://reviews.llvm.org/D62475 --- llvm/include/llvm/Bitcode/BitcodeReader.h | 2 + llvm/include/llvm/IR/DebugInfoMetadata.h | 26 +++++++--- llvm/lib/AsmParser/LLParser.cpp | 48 ++++++++---------- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 2 +- llvm/lib/Bitcode/Reader/MetadataLoader.cpp | 16 ++++-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 41 ++++++++------- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 3 +- llvm/lib/IR/AsmWriter.cpp | 20 +++++--- llvm/lib/IR/DIBuilder.cpp | 3 +- llvm/lib/IR/DebugInfoMetadata.cpp | 2 +- llvm/lib/IR/LLVMContextImpl.h | 11 ++-- llvm/lib/Target/BPF/BTFDebug.cpp | 7 ++- llvm/test/Assembler/DIEnumeratorBig.ll | 13 +++++ llvm/test/Bitcode/DIEnumerator-10.0.ll | 10 ++++ llvm/test/Bitcode/DIEnumerator-10.0.ll.bc | Bin 0 -> 1056 bytes llvm/unittests/IR/MetadataTest.cpp | 11 +++- 17 files changed, 145 insertions(+), 72 deletions(-) create mode 100644 llvm/test/Assembler/DIEnumeratorBig.ll create mode 100644 llvm/test/Bitcode/DIEnumerator-10.0.ll create mode 100644 llvm/test/Bitcode/DIEnumerator-10.0.ll.bc diff --git a/llvm/include/llvm/Bitcode/BitcodeReader.h b/llvm/include/llvm/Bitcode/BitcodeReader.h index ba61da733bea9..c6f2378ec1311 100644 --- a/llvm/include/llvm/Bitcode/BitcodeReader.h +++ b/llvm/include/llvm/Bitcode/BitcodeReader.h @@ -255,6 +255,8 @@ class Module; return false; } + APInt readWideAPInt(ArrayRef Vals, unsigned TypeBits); + const std::error_category &BitcodeErrorCategory(); enum class BitcodeError { CorruptedBitcode = 1 }; inline std::error_code make_error_code(BitcodeError E) { diff --git a/llvm/include/llvm/IR/DebugInfoMetadata.h b/llvm/include/llvm/IR/DebugInfoMetadata.h index 3eaed3270602c..718ecea5afebe 100644 --- a/llvm/include/llvm/IR/DebugInfoMetadata.h +++ b/llvm/include/llvm/IR/DebugInfoMetadata.h @@ -348,22 +348,26 @@ class DIEnumerator : public DINode { friend class LLVMContextImpl; friend class MDNode; - int64_t Value; - DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + APInt Value; + DIEnumerator(LLVMContext &C, StorageType Storage, APInt Value, bool IsUnsigned, ArrayRef Ops) : DINode(C, DIEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), Value(Value) { SubclassData32 = IsUnsigned; } + DIEnumerator(LLVMContext &C, StorageType Storage, int64_t Value, + bool IsUnsigned, ArrayRef Ops) + : DIEnumerator(C, Storage, APInt(64, Value, !IsUnsigned), IsUnsigned, + Ops) {} ~DIEnumerator() = default; - static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + static DIEnumerator *getImpl(LLVMContext &Context, APInt Value, bool IsUnsigned, StringRef Name, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Value, IsUnsigned, getCanonicalMDString(Context, Name), Storage, ShouldCreate); } - static DIEnumerator *getImpl(LLVMContext &Context, int64_t Value, + static DIEnumerator *getImpl(LLVMContext &Context, APInt Value, bool IsUnsigned, MDString *Name, StorageType Storage, bool ShouldCreate = true); @@ -372,14 +376,22 @@ class DIEnumerator : public DINode { } public: - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, StringRef Name), + DEFINE_MDNODE_GET(DIEnumerator, + (int64_t Value, bool IsUnsigned, StringRef Name), + (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) + DEFINE_MDNODE_GET(DIEnumerator, + (int64_t Value, bool IsUnsigned, MDString *Name), + (APInt(64, Value, !IsUnsigned), IsUnsigned, Name)) + DEFINE_MDNODE_GET(DIEnumerator, + (APInt Value, bool IsUnsigned, StringRef Name), (Value, IsUnsigned, Name)) - DEFINE_MDNODE_GET(DIEnumerator, (int64_t Value, bool IsUnsigned, MDString *Name), + DEFINE_MDNODE_GET(DIEnumerator, + (APInt Value, bool IsUnsigned, MDString *Name), (Value, IsUnsigned, Name)) TempDIEnumerator clone() const { return cloneImpl(); } - int64_t getValue() const { return Value; } + const APInt &getValue() const { return Value; } bool isUnsigned() const { return SubclassData32; } StringRef getName() const { return getStringOperand(0); } diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 2e446abec1dc5..e2d0180eb3c60 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -3872,6 +3872,10 @@ struct DISPFlagField : public MDFieldImpl { DISPFlagField() : MDFieldImpl(DISubprogram::SPFlagZero) {} }; +struct MDAPSIntField : public MDFieldImpl { + MDAPSIntField() : ImplTy(APSInt()) {} +}; + struct MDSignedField : public MDFieldImpl { int64_t Min; int64_t Max; @@ -3950,6 +3954,16 @@ struct MDSignedOrUnsignedField namespace llvm { +template <> +bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDAPSIntField &Result) { + if (Lex.getKind() != lltok::APSInt) + return TokError("expected integer"); + + Result.assign(Lex.getAPSIntVal()); + Lex.Lex(); + return false; +} + template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDUnsignedField &Result) { @@ -4281,27 +4295,6 @@ bool LLParser::ParseMDField(LocTy Loc, StringRef Name, return true; } -template <> -bool LLParser::ParseMDField(LocTy Loc, StringRef Name, - MDSignedOrUnsignedField &Result) { - if (Lex.getKind() != lltok::APSInt) - return false; - - if (Lex.getAPSIntVal().isSigned()) { - MDSignedField Res = Result.A; - if (ParseMDField(Loc, Name, Res)) - return true; - Result.assign(Res); - return false; - } - - MDUnsignedField Res = Result.B; - if (ParseMDField(Loc, Name, Res)) - return true; - Result.assign(Res); - return false; -} - template <> bool LLParser::ParseMDField(LocTy Loc, StringRef Name, MDStringField &Result) { LocTy ValueLoc = Lex.getLoc(); @@ -4475,17 +4468,20 @@ bool LLParser::ParseDISubrange(MDNode *&Result, bool IsDistinct) { bool LLParser::ParseDIEnumerator(MDNode *&Result, bool IsDistinct) { #define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \ REQUIRED(name, MDStringField, ); \ - REQUIRED(value, MDSignedOrUnsignedField, ); \ + REQUIRED(value, MDAPSIntField, ); \ OPTIONAL(isUnsigned, MDBoolField, (false)); PARSE_MD_FIELDS(); #undef VISIT_MD_FIELDS - if (isUnsigned.Val && value.isMDSignedField()) + if (isUnsigned.Val && value.Val.isNegative()) return TokError("unsigned enumerator with negative value"); - int64_t Value = value.isMDSignedField() - ? value.getMDSignedValue() - : static_cast(value.getMDUnsignedValue()); + APSInt Value(value.Val); + // Add a leading zero so that unsigned values with the msb set are not + // mistaken for negative values when used for signed enumerators. + if (!isUnsigned.Val && value.Val.isUnsigned() && value.Val.isSignBitSet()) + Value = Value.zext(Value.getBitWidth() + 1); + Result = GET_OR_DISTINCT(DIEnumerator, (Context, Value, isUnsigned.Val, name.Val)); diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 8f7f980c517cb..4b8b0ec8a24da 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -2317,7 +2317,7 @@ Error BitcodeReader::resolveGlobalAndIndirectSymbolInits() { return Error::success(); } -static APInt readWideAPInt(ArrayRef Vals, unsigned TypeBits) { +APInt llvm::readWideAPInt(ArrayRef Vals, unsigned TypeBits) { SmallVector Words(Vals.size()); transform(Vals, Words.begin(), BitcodeReader::decodeSignRotatedValue); diff --git a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp index c1fa91d0672dd..6ec4416f4b43c 100644 --- a/llvm/lib/Bitcode/Reader/MetadataLoader.cpp +++ b/llvm/lib/Bitcode/Reader/MetadataLoader.cpp @@ -1277,14 +1277,24 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata( break; } case bitc::METADATA_ENUMERATOR: { - if (Record.size() != 3) + if (Record.size() < 3) return error("Invalid record"); IsDistinct = Record[0] & 1; bool IsUnsigned = Record[0] & 2; + bool IsBigInt = Record[0] & 4; + APInt Value; + + if (IsBigInt) { + const uint64_t BitWidth = Record[1]; + const size_t NumWords = Record.size() - 3; + Value = readWideAPInt(makeArrayRef(&Record[3], NumWords), BitWidth); + } else + Value = APInt(64, unrotateSign(Record[1]), !IsUnsigned); + MetadataList.assignValue( - GET_OR_DISTINCT(DIEnumerator, (Context, unrotateSign(Record[1]), - IsUnsigned, getMDString(Record[2]))), + GET_OR_DISTINCT(DIEnumerator, + (Context, Value, IsUnsigned, getMDString(Record[2]))), NextMetadataNo); NextMetadataNo++; break; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 1de3ea898e538..f6d0e40aa639d 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1529,12 +1529,32 @@ void ModuleBitcodeWriter::writeDISubrange(const DISubrange *N, Record.clear(); } +static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { + if ((int64_t)V >= 0) + Vals.push_back(V << 1); + else + Vals.push_back((-V << 1) | 1); +} + +static void emitWideAPInt(SmallVectorImpl &Vals, const APInt &A) { + // We have an arbitrary precision integer value to write whose + // bit width is > 64. However, in canonical unsigned integer + // format it is likely that the high bits are going to be zero. + // So, we only write the number of active words. + unsigned NumWords = A.getActiveWords(); + const uint64_t *RawData = A.getRawData(); + for (unsigned i = 0; i < NumWords; i++) + emitSignedInt64(Vals, RawData[i]); +} + void ModuleBitcodeWriter::writeDIEnumerator(const DIEnumerator *N, SmallVectorImpl &Record, unsigned Abbrev) { - Record.push_back((N->isUnsigned() << 1) | N->isDistinct()); - Record.push_back(rotateSign(N->getValue())); + const uint64_t IsBigInt = 1 << 2; + Record.push_back(IsBigInt | (N->isUnsigned() << 1) | N->isDistinct()); + Record.push_back(N->getValue().getBitWidth()); Record.push_back(VE.getMetadataOrNullID(N->getRawName())); + emitWideAPInt(Record, N->getValue()); Stream.EmitRecord(bitc::METADATA_ENUMERATOR, Record, Abbrev); Record.clear(); @@ -2269,13 +2289,6 @@ void ModuleBitcodeWriter::writeSyncScopeNames() { Stream.ExitBlock(); } -static void emitSignedInt64(SmallVectorImpl &Vals, uint64_t V) { - if ((int64_t)V >= 0) - Vals.push_back(V << 1); - else - Vals.push_back((-V << 1) | 1); -} - void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, bool isGlobal) { if (FirstVal == LastVal) return; @@ -2362,15 +2375,7 @@ void ModuleBitcodeWriter::writeConstants(unsigned FirstVal, unsigned LastVal, Code = bitc::CST_CODE_INTEGER; AbbrevToUse = CONSTANTS_INTEGER_ABBREV; } else { // Wide integers, > 64 bits in size. - // We have an arbitrary precision integer value to write whose - // bit width is > 64. However, in canonical unsigned integer - // format it is likely that the high bits are going to be zero. - // So, we only write the number of active words. - unsigned NWords = IV->getValue().getActiveWords(); - const uint64_t *RawWords = IV->getValue().getRawData(); - for (unsigned i = 0; i != NWords; ++i) { - emitSignedInt64(Record, RawWords[i]); - } + emitWideAPInt(Record, IV->getValue()); Code = bitc::CST_CODE_WIDE_INTEGER; } } else if (const ConstantFP *CFP = dyn_cast(C)) { diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 7c2673a2d99a9..cd182c77f41ed 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -2080,7 +2080,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) { // order, which is what MSVC does. if (auto *Enumerator = dyn_cast_or_null(Element)) { EnumeratorRecord ER(MemberAccess::Public, - APSInt::getUnsigned(Enumerator->getValue()), + APSInt(Enumerator->getValue(), true), Enumerator->getName()); ContinuationBuilder.writeMemberType(ER); EnumeratorCount++; diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 91362644da218..ecf4a78f3be65 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1449,8 +1449,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) { DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer); StringRef Name = Enum->getName(); addString(Enumerator, dwarf::DW_AT_name, Name); - auto Value = static_cast(Enum->getValue()); - addConstantValue(Enumerator, IsUnsigned, Value); + addConstantValue(Enumerator, Enum->getValue(), IsUnsigned); if (IndexEnumerators) addGlobalName(Name, Enumerator, Context); } diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp index ca01fe4462839..5c04881d1af77 100644 --- a/llvm/lib/IR/AsmWriter.cpp +++ b/llvm/lib/IR/AsmWriter.cpp @@ -1647,6 +1647,8 @@ struct MDFieldPrinter { bool ShouldSkipNull = true); template void printInt(StringRef Name, IntTy Int, bool ShouldSkipZero = true); + void printAPInt(StringRef Name, APInt Int, bool IsUnsigned, + bool ShouldSkipZero); void printBool(StringRef Name, bool Value, Optional Default = None); void printDIFlags(StringRef Name, DINode::DIFlags Flags); void printDISPFlags(StringRef Name, DISubprogram::DISPFlags Flags); @@ -1722,6 +1724,15 @@ void MDFieldPrinter::printInt(StringRef Name, IntTy Int, bool ShouldSkipZero) { Out << FS << Name << ": " << Int; } +void MDFieldPrinter::printAPInt(StringRef Name, APInt Int, bool IsUnsigned, + bool ShouldSkipZero) { + if (ShouldSkipZero && Int.isNullValue()) + return; + + Out << FS << Name << ": "; + Int.print(Out, !IsUnsigned); +} + void MDFieldPrinter::printBool(StringRef Name, bool Value, Optional Default) { if (Default && Value == *Default) @@ -1851,13 +1862,10 @@ static void writeDIEnumerator(raw_ostream &Out, const DIEnumerator *N, Out << "!DIEnumerator("; MDFieldPrinter Printer(Out); Printer.printString("name", N->getName(), /* ShouldSkipEmpty */ false); - if (N->isUnsigned()) { - auto Value = static_cast(N->getValue()); - Printer.printInt("value", Value, /* ShouldSkipZero */ false); + Printer.printAPInt("value", N->getValue(), N->isUnsigned(), + /*ShouldSkipZero=*/false); + if (N->isUnsigned()) Printer.printBool("isUnsigned", true); - } else { - Printer.printInt("value", N->getValue(), /* ShouldSkipZero */ false); - } Out << ")"; } diff --git a/llvm/lib/IR/DIBuilder.cpp b/llvm/lib/IR/DIBuilder.cpp index b6446f47e03e3..6ed621c407ec7 100644 --- a/llvm/lib/IR/DIBuilder.cpp +++ b/llvm/lib/IR/DIBuilder.cpp @@ -246,7 +246,8 @@ DIMacroFile *DIBuilder::createTempMacroFile(DIMacroFile *Parent, DIEnumerator *DIBuilder::createEnumerator(StringRef Name, int64_t Val, bool IsUnsigned) { assert(!Name.empty() && "Unable to create enumerator without name"); - return DIEnumerator::get(VMContext, Val, IsUnsigned, Name); + return DIEnumerator::get(VMContext, APInt(64, Val, !IsUnsigned), IsUnsigned, + Name); } DIBasicType *DIBuilder::createUnspecifiedType(StringRef Name) { diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp index cb4fab0088fbd..db92c126ad749 100644 --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -347,7 +347,7 @@ DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode, DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops); } -DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value, +DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, APInt Value, bool IsUnsigned, MDString *Name, StorageType Storage, bool ShouldCreate) { assert(isCanonical(Name) && "Expected canonical MDString"); diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index e136bd54dd90e..26e08d2656055 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -355,19 +355,22 @@ template <> struct MDNodeKeyImpl { }; template <> struct MDNodeKeyImpl { - int64_t Value; + APInt Value; MDString *Name; bool IsUnsigned; - MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name) + MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name) : Value(Value), Name(Name), IsUnsigned(IsUnsigned) {} + MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name) + : Value(APInt(64, Value, !IsUnsigned)), Name(Name), + IsUnsigned(IsUnsigned) {} MDNodeKeyImpl(const DIEnumerator *N) : Value(N->getValue()), Name(N->getRawName()), IsUnsigned(N->isUnsigned()) {} bool isKeyOf(const DIEnumerator *RHS) const { - return Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() && - Name == RHS->getRawName(); + return APInt::isSameValue(Value, RHS->getValue()) && + IsUnsigned == RHS->isUnsigned() && Name == RHS->getRawName(); } unsigned getHashValue() const { return hash_combine(Value, Name); } diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index e9ca8dad6e24c..8df2273b59956 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -171,7 +171,12 @@ void BTFTypeEnum::completeType(BTFDebug &BDebug) { struct BTF::BTFEnum BTFEnum; BTFEnum.NameOff = BDebug.addString(Enum->getName()); // BTF enum value is 32bit, enforce it. - BTFEnum.Val = static_cast(Enum->getValue()); + uint32_t Value; + if (Enum->isUnsigned()) + Value = static_cast(Enum->getValue().getZExtValue()); + else + Value = static_cast(Enum->getValue().getSExtValue()); + BTFEnum.Val = Value; EnumValues.push_back(BTFEnum); } } diff --git a/llvm/test/Assembler/DIEnumeratorBig.ll b/llvm/test/Assembler/DIEnumeratorBig.ll new file mode 100644 index 0000000000000..0e4742fd6735a --- /dev/null +++ b/llvm/test/Assembler/DIEnumeratorBig.ll @@ -0,0 +1,13 @@ +;; Round-trip test for enumeration members using more than 64 bits. + +; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s + +!named = !{!0, !1, !2} + +; CHECK: !DIEnumerator(name: "D0", value: -170141183460469231731687303715884105728) +; CHECK: !DIEnumerator(name: "D1", value: 170141183460469231731687303715884105727) +!0 = !DIEnumerator(name: "D0", value: -170141183460469231731687303715884105728) +!1 = !DIEnumerator(name: "D1", value: 170141183460469231731687303715884105727) + +; CHECK: !DIEnumerator(name: "D1", value: 2722258935367507707706996859454145691648, isUnsigned: true) +!2 = !DIEnumerator(name: "D1", value: 2722258935367507707706996859454145691648, isUnsigned: true) diff --git a/llvm/test/Bitcode/DIEnumerator-10.0.ll b/llvm/test/Bitcode/DIEnumerator-10.0.ll new file mode 100644 index 0000000000000..b0372d078453d --- /dev/null +++ b/llvm/test/Bitcode/DIEnumerator-10.0.ll @@ -0,0 +1,10 @@ +;; DIEnumerator-10.0.ll.bc was generated by llvm-as 10.0.0 +; RUN: llvm-dis < %s.bc | FileCheck %s +; RUN: verify-uselistorder < %s.bc + +!named = !{!0, !1} + +; CHECK: !DIEnumerator(name: "A0", value: 9223372036854775807) +!0 = !DIEnumerator(name: "A0", value: 9223372036854775807) +; CHECK: !DIEnumerator(name: "B0", value: -9223372036854775808) +!1 = !DIEnumerator(name: "B0", value: -9223372036854775808) diff --git a/llvm/test/Bitcode/DIEnumerator-10.0.ll.bc b/llvm/test/Bitcode/DIEnumerator-10.0.ll.bc new file mode 100644 index 0000000000000000000000000000000000000000..93b77a5d60855abb8867526dafcdc279dcb5fa97 GIT binary patch literal 1056 zcmXw2acCP=7=P)dxwOgN-C~%Dy*uvK3Sp?briw`~874PJbakfa9~CAhrG!qTT(Z!n zol4SVT&6+Ou7Bi@{?Xw65fn1$9|MOpxj17vMmL63Eg>OkHzg~<)iH1|Uo!WO_kHhs z_ult@-}n7Kueect%?v;<0ASL{554`tkD+(|U4Pdw9v{=7JE*CRj^yO|T;iquHr%hle>Px?$0jRzs+p(M zuG|Syn;cb6(3?TsuUXMq5uLfNyrwu-L`NDER+QuD(Z`Fz9ZV=F#-Gp0(u5q5lF?~A z7LcPBIl3lWZ@x$D1LAK#Y-VBO4WiD%7K(zk(K|(^6ooW0mCR55C{lS2;nCv@HawC`oNbV>wE=hi@Bu$qyzOC{_2;+ibQJ;cS%pH< zy`CIMDUOWjR2A2?qO+o)7+tDwJ*>wOsxV66glzre25be0`!!vgC3bmYmn9zh;S32I zJVfS$n(ogUZ2I9NUabGl(R+ESt?42Up1Sj!;y}eJD95+OQB@pGi=!y&E%5}HXP^^odky%>0b#jfgO}U2c-mkLUH#Sla77_P6yq9kn<4>NA=Q1PU+4{-X z=w{z$>E-Xf&wOI`SkQ6sEs}?kHuOhqhzt0_gp?EAsH6qaxuq=bQ8)63?s+;?-Q(z| zIX?1gBLMIEQR#?gr+~y=KRoF8x| gwaD&_4^e-2?wGKZL&N+l=yRQqPMw=M(ftd+e;vVirT_o{ literal 0 HcmV?d00001 diff --git a/llvm/unittests/IR/MetadataTest.cpp b/llvm/unittests/IR/MetadataTest.cpp index e886c77ebb6f1..b60bcac550130 100644 --- a/llvm/unittests/IR/MetadataTest.cpp +++ b/llvm/unittests/IR/MetadataTest.cpp @@ -1186,7 +1186,7 @@ typedef MetadataTest DIEnumeratorTest; TEST_F(DIEnumeratorTest, get) { auto *N = DIEnumerator::get(Context, 7, false, "name"); EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag()); - EXPECT_EQ(7, N->getValue()); + EXPECT_EQ(7, N->getValue().getSExtValue()); EXPECT_FALSE(N->isUnsigned()); EXPECT_EQ("name", N->getName()); EXPECT_EQ(N, DIEnumerator::get(Context, 7, false, "name")); @@ -1199,6 +1199,15 @@ TEST_F(DIEnumeratorTest, get) { EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); } +TEST_F(DIEnumeratorTest, getWithLargeValues) { + auto *N = DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val"); + EXPECT_EQ(128U, N->getValue().countPopulation()); + EXPECT_EQ(N, + DIEnumerator::get(Context, APInt::getMaxValue(128), false, "val")); + EXPECT_NE(N, + DIEnumerator::get(Context, APInt::getMinValue(128), false, "val")); +} + typedef MetadataTest DIBasicTypeTest; TEST_F(DIBasicTypeTest, get) {