diff --git a/bolt/test/X86/Inputs/indirect_goto.c b/bolt/test/X86/Inputs/indirect_goto.c new file mode 100644 index 000000000000..b781e9e03b6d --- /dev/null +++ b/bolt/test/X86/Inputs/indirect_goto.c @@ -0,0 +1,18 @@ +int main(int argc, char *argv[]) { + static const void *T1[] = { &&L1, &&L2 }; + static const void *T2[] = { &&L2, &&L3 }; + + const void **T = (argc > 1) ? T1 : T2; + + int i = 0; + +L0: + goto *T[argc]; +L1: + ++i; +L2: + i++; +L3: + i++; + return i; +} diff --git a/bolt/test/X86/Inputs/inlined.cpp b/bolt/test/X86/Inputs/inlined.cpp new file mode 100644 index 000000000000..a6ff9e262a4b --- /dev/null +++ b/bolt/test/X86/Inputs/inlined.cpp @@ -0,0 +1,23 @@ +extern "C" int printf(const char*, ...); +extern const char* question(); + +inline int answer() __attribute__((always_inline)); +inline int answer() { return 42; } + +int main(int argc, char *argv[]) { + int ans; + if (argc == 1) { + ans = 0; + } else { + ans = argc; + } + printf("%s\n", question()); + for (int i = 0; i < 10; ++i) { + int x = answer(); + int y = answer(); + ans += x - y; + } + // padding to make sure question() is inlineable + asm("nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;nop;"); + return ans; +} diff --git a/bolt/test/X86/Inputs/inlinee.cpp b/bolt/test/X86/Inputs/inlinee.cpp new file mode 100644 index 000000000000..edb7ab145798 --- /dev/null +++ b/bolt/test/X86/Inputs/inlinee.cpp @@ -0,0 +1,3 @@ +const char* question() { + return "What do you get if you multiply six by nine?"; +} diff --git a/bolt/test/X86/indirect_goto.test b/bolt/test/X86/indirect_goto.test new file mode 100644 index 000000000000..55674e5390fe --- /dev/null +++ b/bolt/test/X86/indirect_goto.test @@ -0,0 +1,8 @@ +# Check llvm-bolt processes binaries compiled from sources that use indirect goto. +RUN: %clang %cflags %S/Inputs/indirect_goto.c -Wl,-q -o %t +RUN: llvm-bolt %t -o /dev/null -relocs=1 -print-cfg -print-only=main -strict \ +RUN: |& FileCheck %s + +# Check that all possible destinations are included as successors. +CHECK: jmpq *%rax # UNKNOWN CONTROL FLOW +CHECK: Successors: .Ltmp0, .Ltmp1, .Ltmp2 diff --git a/bolt/test/X86/inlined_function_mixed.test b/bolt/test/X86/inlined_function_mixed.test new file mode 100644 index 000000000000..1b17c1932c1d --- /dev/null +++ b/bolt/test/X86/inlined_function_mixed.test @@ -0,0 +1,11 @@ +# Make sure inlining from a unit with debug info into unit without +# debug info does not cause a crash. + +RUN: %clangxx %S/Inputs/inlined.cpp -c -o %T/inlined.o +RUN: %clangxx %S/Inputs/inlinee.cpp -c -o %T/inlinee.o -g +RUN: %clangxx %T/inlined.o %T/inlinee.o -o %t + +RUN: llvm-bolt %t -o %t.bolt -update-debug-sections -reorder-blocks=reverse \ +RUN: -inline-small-functions -force-inline=main | FileCheck %s + +CHECK-NOT: BOLT: 0 out of {{.*}} functions were overwritten diff --git a/bolt/test/runtime/X86/Inputs/indirect_goto.c b/bolt/test/runtime/X86/Inputs/indirect_goto.c new file mode 100644 index 000000000000..b781e9e03b6d --- /dev/null +++ b/bolt/test/runtime/X86/Inputs/indirect_goto.c @@ -0,0 +1,18 @@ +int main(int argc, char *argv[]) { + static const void *T1[] = { &&L1, &&L2 }; + static const void *T2[] = { &&L2, &&L3 }; + + const void **T = (argc > 1) ? T1 : T2; + + int i = 0; + +L0: + goto *T[argc]; +L1: + ++i; +L2: + i++; +L3: + i++; + return i; +} diff --git a/bolt/test/runtime/X86/indirect_goto_pie.test b/bolt/test/runtime/X86/indirect_goto_pie.test new file mode 100644 index 000000000000..0280f88478db --- /dev/null +++ b/bolt/test/runtime/X86/indirect_goto_pie.test @@ -0,0 +1,10 @@ +# Check llvm-bolt processes binaries compiled from sources that use indirect goto. +REQUIRES: x86_64-linux + +RUN: %clang %S/Inputs/indirect_goto.c -o %t -fpic -pie -Wl,-q +RUN: llvm-bolt %t -o %t.bolt -relocs=1 -print-cfg -print-only=main \ +RUN: |& FileCheck %s +# The test fails as we don't update corresponding dynamic relocations. +RUN: not %t.bolt + +CHECK: jmpq *%rax # UNKNOWN CONTROL FLOW