LTO: Decide upfront whether to use opaque/non-opaque pointer types

LTO code may end up mixing bitcode files from various sources varying in
their use of opaque pointer types. The current strategy to decide
between opaque / typed pointers upon the first bitcode file loaded does
not work here, since we could be loading a non-opaque bitcode file first
and would then be unable to load any files with opaque pointer types
later.

So for LTO this:
- Adds an `lto::Config::OpaquePointer` option and enforces an upfront
  decision between the two modes.
- Adds `-opaque-pointers`/`-no-opaque-pointers` options to the gold
  plugin; disabled by default.
- `--opaque-pointers`/`--no-opaque-pointers` options with
  `-plugin-opt=-opaque-pointers`/`-plugin-opt=-no-opaque-pointers`
  aliases to lld; disabled by default.
- Adds an `-lto-opaque-pointers` option to the `llvm-lto2` tool.
- Changes the clang driver to pass `-plugin-opt=-opaque-pointers` to
  the linker in LTO modes when clang was configured with opaque
  pointers enabled by default.

This fixes https://github.com/llvm/llvm-project/issues/55377

Differential Revision: https://reviews.llvm.org/D125847
This commit is contained in:
Matthias Braun 2022-05-17 20:33:22 -07:00
parent a92ed167f2
commit 850d53a197
46 changed files with 171 additions and 106 deletions

View File

@ -559,6 +559,9 @@ void tools::addLTOOptions(const ToolChain &ToolChain, const ArgList &Args,
CmdArgs.push_back( CmdArgs.push_back(
Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism))); Args.MakeArgString("-plugin-opt=jobs=" + Twine(Parallelism)));
if (!CLANG_ENABLE_OPAQUE_POINTERS_INTERNAL)
CmdArgs.push_back(Args.MakeArgString("-plugin-opt=no-opaque-pointers"));
// If an explicit debugger tuning argument appeared, pass it along. // If an explicit debugger tuning argument appeared, pass it along.
if (Arg *A = Args.getLastArg(options::OPT_gTune_Group, if (Arg *A = Args.getLastArg(options::OPT_gTune_Group,
options::OPT_ggdbN_Group)) { options::OPT_ggdbN_Group)) {

View File

@ -5,7 +5,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -flto=thin -emit-llvm-bc %t/b.c -o %t/b.bc // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -flto=thin -emit-llvm-bc %t/b.c -o %t/b.bc
// RUN: llvm-nm %t/a.bc | FileCheck %s --check-prefix=NM // RUN: llvm-nm %t/a.bc | FileCheck %s --check-prefix=NM
// RUN: llvm-lto2 run %t/a.bc %t/b.bc -o %t/out -save-temps -r=%t/a.bc,ref,plx -r=%t/b.bc,ff_h264_cabac_tables,pl // RUN: llvm-lto2 run -lto-opaque-pointers %t/a.bc %t/b.bc -o %t/out -save-temps -r=%t/a.bc,ref,plx -r=%t/b.bc,ff_h264_cabac_tables,pl
// RUN: llvm-dis < %t/out.2.2.internalize.bc | FileCheck %s // RUN: llvm-dis < %t/out.2.2.internalize.bc | FileCheck %s
//--- a.c //--- a.c

View File

@ -2,9 +2,9 @@
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -S -o - -emit-llvm -DCALL_LIB -DDEFINE_LIB | FileCheck %s // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -S -o - -emit-llvm -DCALL_LIB -DDEFINE_LIB | FileCheck %s
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.call_full.bc -DCALL_LIB // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=full -c -o %t.call_full.bc -DCALL_LIB
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=full -c -o %t.define_full.bc -DDEFINE_LIB // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=full -c -o %t.define_full.bc -DDEFINE_LIB
// RUN: llvm-lto2 run -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \ // RUN: llvm-lto2 run -lto-opaque-pointers -o %t.lto_full -save-temps %t.call_full.bc %t.define_full.bc \
// RUN: -r %t.call_full.bc,fn,px \ // RUN: -r %t.call_full.bc,fn,px \
// RUN: -r %t.call_full.bc,fwrite,l \ // RUN: -r %t.call_full.bc,fwrite,l \
// RUN: -r %t.call_full.bc,putchar,l \ // RUN: -r %t.call_full.bc,putchar,l \
@ -14,9 +14,9 @@
// RUN: -r %t.define_full.bc,otherfn,px // RUN: -r %t.define_full.bc,otherfn,px
// RUN: llvm-dis %t.lto_full.0.4.opt.bc -o - | FileCheck %s // RUN: llvm-dis %t.lto_full.0.4.opt.bc -o - | FileCheck %s
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.call_thin.bc -DCALL_LIB // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=thin -c -o %t.call_thin.bc -DCALL_LIB
// RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB // RUN: %clang --target=arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=hard -O1 %s -Xclang -opaque-pointers -flto=thin -c -o %t.define_thin.bc -DDEFINE_LIB
// RUN: llvm-lto2 run -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \ // RUN: llvm-lto2 run -lto-opaque-pointers -o %t.lto_thin -save-temps %t.call_thin.bc %t.define_thin.bc \
// RUN: -r %t.call_thin.bc,fn,px \ // RUN: -r %t.call_thin.bc,fn,px \
// RUN: -r %t.call_thin.bc,fwrite,l \ // RUN: -r %t.call_thin.bc,fwrite,l \
// RUN: -r %t.call_thin.bc,putchar,l \ // RUN: -r %t.call_thin.bc,putchar,l \

View File

@ -0,0 +1,5 @@
// UNSUPPORTED: enable-opaque-pointers
// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 2> %t
// RUN: FileCheck %s < %t
// CHECK: -plugin-opt=no-opaque-pointers

View File

@ -0,0 +1,5 @@
// REQUIRES: enable-opaque-pointers
// RUN: %clang --target=x86_64-unknown-linux -### %s -flto 2> %t
// RUN: FileCheck %s < %t
// CHECK-NOT: -plugin-opt=no-opaque-pointers

View File

@ -8,9 +8,9 @@
// RUN: %clang -O1 -target aarch64-unknown-linux -mllvm -stack-safety-print %s -S -o - 2>&1 | FileCheck %s // RUN: %clang -O1 -target aarch64-unknown-linux -mllvm -stack-safety-print %s -S -o - 2>&1 | FileCheck %s
// Full LTO // Full LTO
// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -flto=full -o %t.ltonewpm1.bc // RUN: %clang -O1 -target aarch64-unknown-linux -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc
// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -flto=full -o %t.ltonewpm2.bc // RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc
// RUN: llvm-lto2 run -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
// RUN: -r %t.ltonewpm1.bc,fn,plx \ // RUN: -r %t.ltonewpm1.bc,fn,plx \
// RUN: -r %t.ltonewpm1.bc,use,lx \ // RUN: -r %t.ltonewpm1.bc,use,lx \
// RUN: -r %t.ltonewpm1.bc,use_local,plx \ // RUN: -r %t.ltonewpm1.bc,use_local,plx \
@ -19,9 +19,9 @@
// RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s --allow-empty // RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s --allow-empty
// Thin LTO, new PM // Thin LTO, new PM
// RUN: %clang -O1 -target aarch64-unknown-linux -c %s -flto=thin -o %t.thinltonewpm1.bc // RUN: %clang -O1 -target aarch64-unknown-linux -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc
// RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -flto=thin -o %t.thinltonewpm2.bc // RUN: %clang -O1 -target aarch64-unknown-linux -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc
// RUN: llvm-lto2 run -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
// RUN: -r %t.thinltonewpm1.bc,fn,plx \ // RUN: -r %t.thinltonewpm1.bc,fn,plx \
// RUN: -r %t.thinltonewpm1.bc,use,lx \ // RUN: -r %t.thinltonewpm1.bc,use,lx \
// RUN: -r %t.thinltonewpm1.bc,use_local,plx \ // RUN: -r %t.thinltonewpm1.bc,use_local,plx \
@ -39,9 +39,9 @@
// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print %s -S -o /dev/null 2>&1 | FileCheck %s -check-prefixes=SSI,XUNSAFE,YSAFE // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -mllvm -stack-safety-print %s -S -o /dev/null 2>&1 | FileCheck %s -check-prefixes=SSI,XUNSAFE,YSAFE
// Full LTO: both are safe. // Full LTO: both are safe.
// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=full -o %t.ltonewpm1.bc // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm1.bc
// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -flto=full -o %t.ltonewpm2.bc // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=full -o %t.ltonewpm2.bc
// RUN: llvm-lto2 run -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: llvm-lto2 run -lto-opaque-pointers -o %t.ltonewpm %t.ltonewpm1.bc %t.ltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
// RUN: -r %t.ltonewpm1.bc,fn,plx \ // RUN: -r %t.ltonewpm1.bc,fn,plx \
// RUN: -r %t.ltonewpm1.bc,use,lx \ // RUN: -r %t.ltonewpm1.bc,use,lx \
// RUN: -r %t.ltonewpm1.bc,use_local,plx \ // RUN: -r %t.ltonewpm1.bc,use_local,plx \
@ -50,9 +50,9 @@
// RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s -check-prefixes=SSI,XSAFE,YSAFE // RUN: -r %t.ltonewpm2.bc,z, 2>&1 | FileCheck %s -check-prefixes=SSI,XSAFE,YSAFE
// Thin LTO: both are safe. // Thin LTO: both are safe.
// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -flto=thin -o %t.thinltonewpm1.bc // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm1.bc
// RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -flto=thin -o %t.thinltonewpm2.bc // RUN: %clang -O1 -target aarch64-unknown-linux -march=armv8+memtag -fsanitize=memtag -c -DBUILD2 %s -Xclang -opaque-pointers -flto=thin -o %t.thinltonewpm2.bc
// RUN: llvm-lto2 run -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \ // RUN: llvm-lto2 run -lto-opaque-pointers -o %t.thinltonewpm %t.thinltonewpm1.bc %t.thinltonewpm2.bc -save-temps -stack-safety-print -thinlto-threads 1 -O1 \
// RUN: -r %t.thinltonewpm1.bc,fn,plx \ // RUN: -r %t.thinltonewpm1.bc,fn,plx \
// RUN: -r %t.thinltonewpm1.bc,use,lx \ // RUN: -r %t.thinltonewpm1.bc,use,lx \
// RUN: -r %t.thinltonewpm1.bc,use_local,plx \ // RUN: -r %t.thinltonewpm1.bc,use_local,plx \

View File

@ -198,6 +198,7 @@ struct Configuration {
bool nostdlib; bool nostdlib;
bool oFormatBinary; bool oFormatBinary;
bool omagic; bool omagic;
bool opaquePointers;
bool optEB = false; bool optEB = false;
bool optEL = false; bool optEL = false;
bool optimizeBBJumps; bool optimizeBBJumps;

View File

@ -1126,6 +1126,8 @@ static void readConfigs(opt::InputArgList &args) {
config->nostdlib = args.hasArg(OPT_nostdlib); config->nostdlib = args.hasArg(OPT_nostdlib);
config->oFormatBinary = isOutputFormatBinary(args); config->oFormatBinary = isOutputFormatBinary(args);
config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false); config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
config->opaquePointers = args.hasFlag(
OPT_plugin_opt_opaque_pointers, OPT_plugin_opt_no_opaque_pointers, true);
config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename); config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
config->optStatsFilename = args.getLastArgValue(OPT_plugin_opt_stats_file); config->optStatsFilename = args.getLastArgValue(OPT_plugin_opt_stats_file);

View File

@ -164,6 +164,8 @@ static lto::Config createConfig() {
c.RunCSIRInstr = config->ltoCSProfileGenerate; c.RunCSIRInstr = config->ltoCSProfileGenerate;
c.PGOWarnMismatch = config->ltoPGOWarnMismatch; c.PGOWarnMismatch = config->ltoPGOWarnMismatch;
c.OpaquePointers = config->opaquePointers;
if (config->emitLLVM) { if (config->emitLLVM) {
c.PostInternalizeModuleHook = [](size_t task, const Module &m) { c.PostInternalizeModuleHook = [](size_t task, const Module &m) {
if (std::unique_ptr<raw_fd_ostream> os = if (std::unique_ptr<raw_fd_ostream> os =

View File

@ -626,6 +626,10 @@ def: J<"plugin-opt=cs-profile-path=">,
def: J<"plugin-opt=obj-path=">, def: J<"plugin-opt=obj-path=">,
Alias<lto_obj_path_eq>, Alias<lto_obj_path_eq>,
HelpText<"Alias for --lto-obj-path=">; HelpText<"Alias for --lto-obj-path=">;
def plugin_opt_opaque_pointers: F<"plugin-opt=opaque-pointers">,
HelpText<"Use opaque pointers in IR during LTO (default)">;
def plugin_opt_no_opaque_pointers: F<"plugin-opt=no-opaque-pointers">,
HelpText<"Use typed pointers in IR during LTO">;
def: J<"plugin-opt=opt-remarks-filename=">, def: J<"plugin-opt=opt-remarks-filename=">,
Alias<opt_remarks_filename>, Alias<opt_remarks_filename>,
HelpText<"Alias for --opt-remarks-filename">; HelpText<"Alias for --opt-remarks-filename">;

View File

@ -7,7 +7,7 @@
; CHECK: @GlobalValueName ; CHECK: @GlobalValueName
; CHECK: @foo(i32 %in) ; CHECK: @foo(i32 %in)
; CHECK: somelabel: ; CHECK: somelabel:
; CHECK: %GV = load i32, i32* @GlobalValueName ; CHECK: %GV = load i32, ptr @GlobalValueName
; CHECK: %add = add i32 %in, %GV ; CHECK: %add = add i32 %in, %GV
; CHECK: ret i32 %add ; CHECK: ret i32 %add

View File

@ -12,6 +12,6 @@ define void @ctor() {
} }
; `@ctor` doesn't do anything and so the optimizer should kill it, leaving no ctors ; `@ctor` doesn't do anything and so the optimizer should kill it, leaving no ctors
; CHECK: @llvm.global_ctors = appending global [0 x { i32, void ()*, i8* }] zeroinitializer ; CHECK: @llvm.global_ctors = appending global [0 x { i32, ptr, ptr }] zeroinitializer
; MLLVM: Pass Arguments: ; MLLVM: Pass Arguments:

View File

@ -14,13 +14,13 @@ define void @foo() {
declare void @bar(i8*) declare void @bar(i8*)
; CHECK: define void @foo() { ; CHECK: define void @foo() {
; CHECK-NEXT: call void @bar(i8* null) ; CHECK-NEXT: call void @bar(ptr null)
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
; CHECK: declare void @bar(i8*) ; CHECK: declare void @bar(ptr)
; CHECK: define void @zed() { ; CHECK: define void @zed() {
; CHECK-NEXT: call void bitcast (void (i8*)* @bar to void ()*)() ; CHECK-NEXT: call void @bar()
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }

View File

@ -14,15 +14,12 @@ define void @foo() {
} }
declare void @bar(%zed*) declare void @bar(%zed*)
; CHECK: %zed = type { i8 }
; CHECK-NEXT: %zed.0 = type { i16 }
; CHECK: define void @foo() { ; CHECK: define void @foo() {
; CHECK-NEXT: call void bitcast (void (%zed.0*)* @bar to void (%zed*)*)(%zed* null) ; CHECK-NEXT: call void @bar(ptr null)
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }
; CHECK: define void @bar(%zed.0* %this) { ; CHECK: define void @bar(ptr %this) {
; CHECK-NEXT: store %zed.0* %this, %zed.0** null ; CHECK-NEXT: store ptr %this, ptr null
; CHECK-NEXT: ret void ; CHECK-NEXT: ret void
; CHECK-NEXT: } ; CHECK-NEXT: }

View File

@ -28,8 +28,9 @@
# RUN: llvm-mc -triple x86_64-elf -filetype=obj -o %t/malloc.o %t/malloc.s # RUN: llvm-mc -triple x86_64-elf -filetype=obj -o %t/malloc.o %t/malloc.s
# RUN: ld.lld -shared -o %t/libmalloc.so -soname libmalloc.so %t/malloc.o # RUN: ld.lld -shared -o %t/libmalloc.so -soname libmalloc.so %t/malloc.o
# RUN: llvm-mc -triple x86_64-elf -filetype=obj -o %t/emutls.o %t/emutls.s # RUN: llvm-mc -triple x86_64-elf -filetype=obj -o %t/emutls.o %t/emutls.s
# RUN: llvm-as -o %t/usetls.bc %t/usetls.ll # RUN: llvm-as -opaque-pointers=1 -o %t/usetls.bc %t/usetls.ll
# RUN: ld.lld -shared -o %t/libusetls.so %t/usetls.bc %t/libmalloc.so \ # RUN: ld.lld --plugin-opt=opaque-pointers -shared -o %t/libusetls.so \
# RUN: %t/usetls.bc %t/libmalloc.so \
# RUN: --start-lib %t/emutls.o -mllvm -emulated-tls --wrap malloc # RUN: --start-lib %t/emutls.o -mllvm -emulated-tls --wrap malloc
# RUN: llvm-objdump --dynamic-reloc --disassemble %t/libusetls.so | \ # RUN: llvm-objdump --dynamic-reloc --disassemble %t/libusetls.so | \
# RUN: FileCheck --check-prefix=USETLS-DISASM %s # RUN: FileCheck --check-prefix=USETLS-DISASM %s

View File

@ -205,6 +205,9 @@ For users of the clang cc1 interface, ``-no-opaque-pointers`` can be passed.
Note that the ``CLANG_ENABLE_OPAQUE_POINTERS`` cmake option has no effect on Note that the ``CLANG_ENABLE_OPAQUE_POINTERS`` cmake option has no effect on
the cc1 interface. the cc1 interface.
Usage for LTO can be disabled by passing ``-Wl,-plugin-opt=no-opaque-pointers``
to the clang driver.
The next steps for the opaque pointer migration are: The next steps for the opaque pointer migration are:
* Migrate Clang/LLVM tests to use opaque pointers. * Migrate Clang/LLVM tests to use opaque pointers.

View File

@ -177,6 +177,10 @@ struct Config {
/// Add FSAFDO discriminators. /// Add FSAFDO discriminators.
bool AddFSDiscriminator = false; bool AddFSDiscriminator = false;
/// Use opaque pointer types. Used to call LLVMContext::setOpaquePointers
/// unless already set by the `-opaque-pointers` commandline option.
bool OpaquePointers = true;
/// If this field is set, LTO will write input file paths and symbol /// If this field is set, LTO will write input file paths and symbol
/// resolutions here in llvm-lto2 command line flag format. This can be /// resolutions here in llvm-lto2 command line flag format. This can be
/// used for testing and for running the LTO pipeline outside of the linker /// used for testing and for running the LTO pipeline outside of the linker
@ -288,6 +292,8 @@ struct LTOLLVMContext : LLVMContext {
enableDebugTypeODRUniquing(); enableDebugTypeODRUniquing();
setDiagnosticHandler( setDiagnosticHandler(
std::make_unique<LTOLLVMDiagnosticHandler>(&DiagHandler), true); std::make_unique<LTOLLVMDiagnosticHandler>(&DiagHandler), true);
if (!hasSetOpaquePointersValue())
setOpaquePointers(C.OpaquePointers);
} }
DiagnosticHandlerFunction DiagHandler; DiagnosticHandlerFunction DiagHandler;
}; };

View File

@ -33,7 +33,7 @@
; RUN: -r %t.summ1.bc,PreemptableAliasWrite1,px \ ; RUN: -r %t.summ1.bc,PreemptableAliasWrite1,px \
; RUN: -r %t.summ1.bc,Write1,px ; RUN: -r %t.summ1.bc,Write1,px
; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \ ; RUN: llvm-lto2 run -opaque-pointers=0 %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
; RUN: $(cat %t.res.txt) \ ; RUN: $(cat %t.res.txt) \
; RUN: 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO ; RUN: 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO

View File

@ -83,7 +83,7 @@
; RUN: -r %t.summ1.bc,Write8,px \ ; RUN: -r %t.summ1.bc,Write8,px \
; RUN: -r %t.summ1.bc,WriteAndReturn8,px ; RUN: -r %t.summ1.bc,WriteAndReturn8,px
; RUN: llvm-lto2 run %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \ ; RUN: llvm-lto2 run -opaque-pointers=0 %t.summ0.bc %t.summ1.bc -o %t.lto -stack-safety-print -stack-safety-run -save-temps -thinlto-threads 1 -O0 \
; RUN: $(cat %t.res.txt) \ ; RUN: $(cat %t.res.txt) \
; RUN: 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO ; RUN: 2>&1 | FileCheck %s --check-prefixes=CHECK,GLOBAL,LTO

View File

@ -6,10 +6,10 @@
; CHECK-NOT: alias ; CHECK-NOT: alias
; CHECK: @c = global i32 1 ; CHECK: @c = global i32 1
; CHECK-NEXT: @d = global i32* @a ; CHECK-NEXT: @d = global ptr @a
; CHECK-EMPTY: ; CHECK-EMPTY:
; CHECK-NEXT: @a = weak alias i32, i32* @b ; CHECK-NEXT: @a = weak alias i32, ptr @b
; CHECK-NEXT: @b = internal alias i32, i32* @c ; CHECK-NEXT: @b = internal alias i32, ptr @c
; RES: 1.o{{$}} ; RES: 1.o{{$}}
; RES-NEXT: {{^}}-r={{.*}}1.o,c,p{{$}} ; RES-NEXT: {{^}}-r={{.*}}1.o,c,p{{$}}

View File

@ -50,36 +50,36 @@ bb11:
; CHECK-DAG: @v1 = weak_odr global i32 42, comdat($c1) ; CHECK-DAG: @v1 = weak_odr global i32 42, comdat($c1)
; CHECK-DAG: @r11 = global i32* @v1{{$}} ; CHECK-DAG: @r11 = global ptr @v1{{$}}
; CHECK-DAG: @r12 = global i32 (i8*)* @f1{{$}} ; CHECK-DAG: @r12 = global ptr @f1{{$}}
; CHECK-DAG: @r21 = global i32* @v1{{$}} ; CHECK-DAG: @r21 = global ptr @v1{{$}}
; CHECK-DAG: @r22 = global i32 (i8*)* @f1{{$}} ; CHECK-DAG: @r22 = global ptr @f1{{$}}
; CHECK-DAG: @v1.1 = internal global i32 41, comdat($c2) ; CHECK-DAG: @v1.1 = internal global i32 41, comdat($c2)
; CHECK-DAG: @a11 = alias i32, i32* @v1{{$}} ; CHECK-DAG: @a11 = alias i32, ptr @v1{{$}}
; CHECK-DAG: @a12 = alias i16, bitcast (i32* @v1 to i16*) ; CHECK-DAG: @a12 = alias i16, ptr @v1{{$}}
; CHECK-DAG: @a13 = alias i32 (i8*), i32 (i8*)* @f1{{$}} ; CHECK-DAG: @a13 = alias i32 (ptr), ptr @f1{{$}}
; CHECK-DAG: @a14 = alias i16, bitcast (i32 (i8*)* @f1 to i16*) ; CHECK-DAG: @a14 = alias i16, ptr @f1{{$}}
; CHECK-DAG: @a21 = alias i32, i32* @v1.1{{$}} ; CHECK-DAG: @a21 = alias i32, ptr @v1.1{{$}}
; CHECK-DAG: @a22 = alias i16, bitcast (i32* @v1.1 to i16*) ; CHECK-DAG: @a22 = alias i16, ptr @v1.1{{$}}
; CHECK-DAG: @a23 = alias i32 (i8*), i32 (i8*)* @f1.2{{$}} ; CHECK-DAG: @a23 = alias i32 (ptr), ptr @f1.2{{$}}
; CHECK-DAG: @a24 = alias i16, bitcast (i32 (i8*)* @f1.2 to i16*) ; CHECK-DAG: @a24 = alias i16, ptr @f1.2{{$}}
; CHECK: define weak_odr dso_local i32 @f1(i8* %0) comdat($c1) { ; CHECK: define weak_odr dso_local i32 @f1(ptr %0) comdat($c1) {
; CHECK-NEXT: bb10: ; CHECK-NEXT: bb10:
; CHECK-NEXT: br label %bb11{{$}} ; CHECK-NEXT: br label %bb11{{$}}
; CHECK: bb11: ; CHECK: bb11:
; CHECK-NEXT: ret i32 42 ; CHECK-NEXT: ret i32 42
; CHECK-NEXT: } ; CHECK-NEXT: }
; CHECK: define internal i32 @f1.2(i8* %this) comdat($c2) { ; CHECK: define internal i32 @f1.2(ptr %this) comdat($c2) {
; CHECK-NEXT: bb20: ; CHECK-NEXT: bb20:
; CHECK-NEXT: store i8* %this, i8** null ; CHECK-NEXT: store ptr %this, ptr null
; CHECK-NEXT: br label %bb21 ; CHECK-NEXT: br label %bb21
; CHECK: bb21: ; CHECK: bb21:
; CHECK-NEXT: ret i32 41 ; CHECK-NEXT: ret i32 41

View File

@ -6,14 +6,14 @@
target datalayout = "e-p:64:64" target datalayout = "e-p:64:64"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
; CHECK: @foo = ifunc i32 (), i32 ()* ()* @foo_resolver.2 ; CHECK: @foo = ifunc i32 (), ptr @foo_resolver.2
@foo = ifunc i32 (), i32 ()* ()* @foo_resolver @foo = ifunc i32 (), i32 ()* ()* @foo_resolver
; CHECK: define internal i32 ()* @foo_resolver.2() { ; CHECK: define internal ptr @foo_resolver.2() {
; CHECK-NEXT: ret i32 ()* inttoptr (i32 1 to i32 ()*) ; CHECK-NEXT: ret ptr inttoptr (i32 1 to ptr)
define weak i32 ()* @foo_resolver() { define weak i32 ()* @foo_resolver() {
ret i32 ()* inttoptr (i32 1 to i32 ()*) ret i32 ()* inttoptr (i32 1 to i32 ()*)
} }
; CHECK: define i32 ()* @foo_resolver() { ; CHECK: define ptr @foo_resolver() {
; CHECK-NEXT: ret i32 ()* inttoptr (i32 2 to i32 ()*) ; CHECK-NEXT: ret ptr inttoptr (i32 2 to ptr)

View File

@ -13,7 +13,7 @@ target triple = "x86_64-unknown-linux-gnu"
$g = comdat any $g = comdat any
@g = global i8 42, comdat, !type !0 @g = global i8 42, comdat, !type !0
; CHECK: define available_externally dllimport i8* @f() ; CHECK: define available_externally dllimport ptr @f()
define available_externally dllimport i8* @f() { define available_externally dllimport i8* @f() {
ret i8* @g ret i8* @g
} }

View File

@ -0,0 +1,7 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define i64 @foo(ptr %p) {
%t = load i64, ptr %p
ret i64 %t
}

View File

@ -46,7 +46,7 @@
; CHECK-THIN-OD: jmp {{.*}} <a.cfi_jt ; CHECK-THIN-OD: jmp {{.*}} <a.cfi_jt
; CHECK-THIN-OD-NEXT: R_X86_64_PLT32 a ; CHECK-THIN-OD-NEXT: R_X86_64_PLT32 a
; CHECK-USED: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @a.cfi_jt to i8*), i8* bitcast (void ()* @b.cfi_jt to i8*), i8* bitcast (void ()* @c.cfi_jt to i8*)], section "llvm.metadata" ; CHECK-USED: @llvm.used = appending global [3 x ptr] [ptr @a.cfi_jt, ptr @b.cfi_jt, ptr @c.cfi_jt], section "llvm.metadata"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -0,0 +1,19 @@
; RUN: llvm-as -opaque-pointers=0 %s -o %t-typed.bc
; RUN: llvm-as -opaque-pointers=1 %S/Inputs/opaque-pointers.ll -o %t-opaque.bc
; RUN: llvm-lto2 run -o %t-lto.bc %t-typed.bc %t-opaque.bc -save-temps \
; RUN: -lto-opaque-pointers \
; RUN: -r %t-typed.bc,call_foo,px -r %t-typed.bc,foo,l \
; RUN: -r %t-opaque.bc,foo,px
; RUN: opt -S -o - %t-lto.bc.0.4.opt.bc | FileCheck %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
declare i64 @foo(i64* %p);
define i64 @call_foo(i64* %p) {
; CHECK-LABEL: define i64 @call_foo(ptr nocapture readonly %p) local_unnamed_addr #0 {
; CHECK-NEXT: %t.i = load i64, ptr %p, align 8
%t = call i64 @foo(i64* %p)
ret i64 %t
}

View File

@ -13,26 +13,25 @@
; Stage1 and stage2 are described in type-mapping-bug4_1.ll. ; Stage1 and stage2 are described in type-mapping-bug4_1.ll.
; Stage3 is described in this file. ; Stage3 is described in this file.
; CHECK: %class.CCSM = type opaque ; CHECK: %class.CB.1 = type { %"class.std::unique_ptr_base.2" }
; CHECK: %class.CB = type { %"class.std::unique_ptr_base.1" } ; CHECK: %"class.std::unique_ptr_base.2" = type { ptr }
; CHECK: %"class.std::unique_ptr_base.1" = type { %class.CCSM* }
; CHECK: define void @j() { ; CHECK: define void @j() {
; CHECK: call void @h(%class.CCSM* undef) ; CHECK: call void @h(ptr undef)
; CHECK: ret void ; CHECK: ret void
; CHECK: } ; CHECK: }
; CHECK: declare void @h(%class.CCSM*) ; CHECK: declare void @h(ptr)
; CHECK: define void @a() { ; CHECK: define void @a() {
; CHECK: call void @llvm.dbg.value(metadata %class.CB* undef, metadata !10, metadata !DIExpression()) ; CHECK: call void @llvm.dbg.value(metadata ptr undef, metadata !10, metadata !DIExpression())
; CHECK: ret void ; CHECK: ret void
; CHECK: } ; CHECK: }
; CHECK: declare void @llvm.dbg.value(metadata, metadata, metadata) #0 ; CHECK: declare void @llvm.dbg.value(metadata, metadata, metadata) #0
; CHECK: define void @d(%class.CB* %0) { ; CHECK: define void @d(ptr %0) {
; CHECK: %2 = getelementptr inbounds %class.CB, %class.CB* undef, i64 0, i32 0, i32 0 ; CHECK: %2 = getelementptr inbounds %class.CB.1, ptr undef, i64 0, i32 0, i32 0
; CHECK: ret void ; CHECK: ret void
; CHECK: } ; CHECK: }

View File

@ -10,6 +10,6 @@ target triple = "x86_64-unknown-linux-gnu"
define dso_local nonnull %struct.S* @_Z6getObjv() local_unnamed_addr { define dso_local nonnull %struct.S* @_Z6getObjv() local_unnamed_addr {
entry: entry:
store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0), align 8 store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 1, i32 0), align 8
ret %struct.S* @_ZL3Obj ret %struct.S* @_ZL3Obj
} }

View File

@ -94,7 +94,7 @@ cont2:
; CHECK-IR: br i1 {{.*}}, label %trap, label %cont2 ; CHECK-IR: br i1 {{.*}}, label %trap, label %cont2
; We still have to call it as virtual. ; We still have to call it as virtual.
; CHECK-IR: %call3 = tail call i32 %7 ; CHECK-IR: %call3 = tail call i32 %5
%call3 = tail call i32 %8(%struct.A* nonnull %obj, i32 %call) %call3 = tail call i32 %8(%struct.A* nonnull %obj, i32 %call)
ret i32 %call3 ret i32 %call3
} }

View File

@ -59,14 +59,12 @@ cont:
; CHECK-IR0: define weak_odr i32 @test ; CHECK-IR0: define weak_odr i32 @test
; CHECK-IR0-NEXT: entry: ; CHECK-IR0-NEXT: entry:
; CHECK-IR0-NEXT: %0 = bitcast
; CHECK-IR0-NEXT: %vtable5 = ; CHECK-IR0-NEXT: %vtable5 =
; CHECK-IR0-NEXT: tail call void @llvm.trap() ; CHECK-IR0-NEXT: tail call void @llvm.trap()
; CHECK-IR0-NEXT: unreachable ; CHECK-IR0-NEXT: unreachable
; CHECK-IR0-NEXT: } ; CHECK-IR0-NEXT: }
; CHECK-IR0: define weak_odr i32 @testb ; CHECK-IR0: define weak_odr i32 @testb
; CHECK-IR0-NEXT: entry: ; CHECK-IR0-NEXT: entry:
; CHECK-IR0-NEXT: %0 = bitcast
; CHECK-IR0-NEXT: %vtable5 = ; CHECK-IR0-NEXT: %vtable5 =
; CHECK-IR0-NEXT: tail call void @llvm.trap() ; CHECK-IR0-NEXT: tail call void @llvm.trap()
; CHECK-IR0-NEXT: unreachable ; CHECK-IR0-NEXT: unreachable

View File

@ -100,7 +100,7 @@ if.true.direct_targ: ; preds = %entry
%8 = load i32 (%class.B*)*, i32 (%class.B*)** %vfn.i, align 8 %8 = load i32 (%class.B*)*, i32 (%class.B*)** %vfn.i, align 8
; Call to bar() can be devirtualized to call to B::bar(), since it was ; Call to bar() can be devirtualized to call to B::bar(), since it was
; inlined from B::foo() after ICP introduced the guarded promotion. ; inlined from B::foo() after ICP introduced the guarded promotion.
; CHECK-IR: %call.i = tail call i32 @_ZN1B3barEv(%class.B* %3) ; CHECK-IR: %call.i = tail call i32 @_ZN1B3barEv(ptr nonnull %a)
%call.i = tail call i32 %8(%class.B* %5) %call.i = tail call i32 %8(%class.B* %5)
br label %if.end.icp br label %if.end.icp

View File

@ -180,7 +180,7 @@ entry:
; Check that the call was devirtualized. Ignore extra character before ; Check that the call was devirtualized. Ignore extra character before
; symbol name which would happen if it was promoted during module ; symbol name which would happen if it was promoted during module
; splitting for hybrid WPD. ; splitting for hybrid WPD.
; CHECK-IR1: %call = tail call i32 bitcast (void ()* @{{.*}}_ZN1A1nEi ; CHECK-IR1: %call = tail call i32 @_ZN1A1nEi
%call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a) %call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a)
%3 = bitcast i8** %vtable to i32 (%struct.A*, i32)** %3 = bitcast i8** %vtable to i32 (%struct.A*, i32)**

View File

@ -54,20 +54,20 @@ entry:
; Check that the call was devirtualized, but preceeded by a check guarding ; Check that the call was devirtualized, but preceeded by a check guarding
; a trap if the function pointer doesn't match. ; a trap if the function pointer doesn't match.
; TRAP: %.not = icmp eq i32 (%struct.A*, i32)* %fptr1, @_ZN1A1nEi ; TRAP: %.not = icmp eq ptr %fptr1, @_ZN1A1nEi
; Ensure !prof and !callees metadata for indirect call promotion removed. ; Ensure !prof and !callees metadata for indirect call promotion removed.
; TRAP-NOT: prof ; TRAP-NOT: prof
; TRAP-NOT: callees ; TRAP-NOT: callees
; TRAP: br i1 %.not, label %3, label %2 ; TRAP: br i1 %.not, label %1, label %0
; TRAP: 2: ; TRAP: 0:
; TRAP: tail call void @llvm.debugtrap() ; TRAP: tail call void @llvm.debugtrap()
; TRAP: br label %3 ; TRAP: br label %1
; TRAP: 3: ; TRAP: 1:
; TRAP: tail call i32 @_ZN1A1nEi ; TRAP: tail call i32 @_ZN1A1nEi
; Check that the call was devirtualized, but preceeded by a check guarding ; Check that the call was devirtualized, but preceeded by a check guarding
; a fallback if the function pointer doesn't match. ; a fallback if the function pointer doesn't match.
; FALLBACK: %2 = icmp eq i32 (%struct.A*, i32)* %fptr1, @_ZN1A1nEi ; FALLBACK: %0 = icmp eq ptr %fptr1, @_ZN1A1nEi
; FALLBACK: br i1 %2, label %if.true.direct_targ, label %if.false.orig_indirect ; FALLBACK: br i1 %0, label %if.true.direct_targ, label %if.false.orig_indirect
; FALLBACK: if.true.direct_targ: ; FALLBACK: if.true.direct_targ:
; FALLBACK: tail call i32 @_ZN1A1nEi ; FALLBACK: tail call i32 @_ZN1A1nEi
; Ensure !prof and !callees metadata for indirect call promotion removed. ; Ensure !prof and !callees metadata for indirect call promotion removed.

View File

@ -58,7 +58,7 @@ entry:
%fptr1 = load i32 (%struct.A*, i32)*, i32 (%struct.A*, i32)** %2, align 8 %fptr1 = load i32 (%struct.A*, i32)*, i32 (%struct.A*, i32)** %2, align 8
; Check that the call was devirtualized. ; Check that the call was devirtualized.
; CHECK-IR1: %call = tail call i32 bitcast (void ()* @_ZN1A1nEi ; CHECK-IR1: %call = tail call i32 @_ZN1A1nEi
%call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a) %call = tail call i32 %fptr1(%struct.A* nonnull %obj, i32 %a)
ret i32 %call ret i32 %call

View File

@ -24,7 +24,7 @@
; REMARK-COUNT-3: single-impl: devirtualized a call to _ZNK1A1fEv ; REMARK-COUNT-3: single-impl: devirtualized a call to _ZNK1A1fEv
; IMPORT: define available_externally hidden i32 @_ZNK1A1fEv(%struct.A* %this) ; IMPORT: define available_externally hidden i32 @_ZNK1A1fEv(ptr %this)
; IMPORT-NEXT: entry: ; IMPORT-NEXT: entry:
; IMPORT-NEXT: ret i32 3 ; IMPORT-NEXT: ret i32 3

View File

@ -8,14 +8,14 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"
; CHECK-NOT: ; Function Attrs: ; CHECK-NOT: ; Function Attrs:
; CHECK: define i32 @indirect(i32 ()* nocapture %0) { ; CHECK: define i32 @indirect(ptr nocapture %0) {
define i32 @indirect(i32 ()* nocapture) { define i32 @indirect(i32 ()* nocapture) {
%2 = tail call i32 %0() %2 = tail call i32 %0()
ret i32 %2 ret i32 %2
} }
; CHECK-NOT: ; Function Attrs: ; CHECK-NOT: ; Function Attrs:
; CHECK: define i8* @inlineasm() { ; CHECK: define ptr @inlineasm() {
define i8* @inlineasm() { define i8* @inlineasm() {
entry: entry:
%0 = tail call i8* asm sideeffect "lea ff_h264_cabac_tables(%rip), $0", "=&r,~{dirflag},~{fpsr},~{flags}"() %0 = tail call i8* asm sideeffect "lea ff_h264_cabac_tables(%rip), $0", "=&r,~{dirflag},~{fpsr},~{flags}"()

View File

@ -6,9 +6,9 @@
; Verify that we haven't imported GV containing blockaddress ; Verify that we haven't imported GV containing blockaddress
; CHECK: @label_addr.llvm.0 = external hidden constant ; CHECK: @label_addr.llvm.0 = external hidden constant
; Verify that bar is not imported since it has address-taken block that is target of indirect branch ; Verify that bar is not imported since it has address-taken block that is target of indirect branch
; CHECK: declare [1 x i8*]* @bar() ; CHECK: declare ptr @bar()
; Verify that foo is imported ; Verify that foo is imported
; CHECK: available_externally [1 x i8*]* @foo ; CHECK: available_externally ptr @foo
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -25,18 +25,18 @@
; RUN: llvm-dis %t-out-norefs.1.3.import.bc -o - | FileCheck %s --check-prefix=NOREFS ; RUN: llvm-dis %t-out-norefs.1.3.import.bc -o - | FileCheck %s --check-prefix=NOREFS
; Check that variable has been promoted in the source module ; Check that variable has been promoted in the source module
; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, i32* @val } ; PROMOTE: @_ZL3Obj.llvm.{{.*}} = hidden constant %struct.S { i32 4, i32 8, ptr @val }
; @outer is a write-only variable, so it's been converted to zeroinitializer. ; @outer is a write-only variable, so it's been converted to zeroinitializer.
; IMPORT: @val = available_externally global i32 42 ; IMPORT: @val = available_externally global i32 42
; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, i32* @val } ; IMPORT-NEXT: @_ZL3Obj.llvm.{{.*}} = available_externally hidden constant %struct.S { i32 4, i32 8, ptr @val }
; IMPORT-NEXT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer ; IMPORT-NEXT: @outer = internal local_unnamed_addr global %struct.Q zeroinitializer
; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer ; OPT: @outer = internal unnamed_addr global %struct.Q zeroinitializer
; OPT: define dso_local i32 @main() ; OPT: define dso_local i32 @main()
; OPT-NEXT: entry: ; OPT-NEXT: entry:
; OPT-NEXT: store %struct.S* null, %struct.S** getelementptr inbounds (%struct.Q, %struct.Q* @outer, i64 0, i32 0) ; OPT-NEXT: store ptr null, ptr getelementptr inbounds (%struct.Q, ptr @outer, i64 1, i32 0)
; OPT-NEXT: ret i32 12 ; OPT-NEXT: ret i32 12
; NOREFS: @_ZL3Obj.llvm.{{.*}} = external hidden constant %struct.S ; NOREFS: @_ZL3Obj.llvm.{{.*}} = external hidden constant %struct.S

View File

@ -21,21 +21,21 @@
; RUN: llvm-dis %t2.1.3.import.bc -o - | FileCheck %s --check-prefixes=DEST,DEST2 ; RUN: llvm-dis %t2.1.3.import.bc -o - | FileCheck %s --check-prefixes=DEST,DEST2
; DEST: @a = available_externally global i32 42, align 4 ; DEST: @a = available_externally global i32 42, align 4
; DEST-NEXT: @b = external global i32*, align 8 ; DEST-NEXT: @b = external global ptr, align 8
; DEST: declare void @linkonce() ; DEST: declare void @linkonce()
; DEST: declare void @weak() ; DEST: declare void @weak()
; DEST: define dso_local i32 @main() ; DEST: define dso_local i32 @main()
; DEST: define available_externally void @extern() ; DEST: define available_externally void @extern()
; DEST1: declare i32 @extern_aux(i32*, i32**) ; DEST1: declare i32 @extern_aux(ptr, ptr)
; DEST1: declare i32 @linkonceodr_aux(i32*, i32**) ; DEST1: declare i32 @linkonceodr_aux(ptr, ptr)
; DEST2: define available_externally i32 @extern_aux(i32* %a, i32** %b) ; DEST2: define available_externally i32 @extern_aux(ptr %a, ptr %b)
; DEST2: define available_externally i32 @linkonceodr_aux(i32* %a, i32** %b) ; DEST2: define available_externally i32 @linkonceodr_aux(ptr %a, ptr %b)
; DEST: define available_externally void @weakodr() ; DEST: define available_externally void @weakodr()
; DEST1: declare i32 @weakodr_aux(i32*, i32**) ; DEST1: declare i32 @weakodr_aux(ptr, ptr)
; DEST2: define available_externally i32 @weakodr_aux(i32* %a, i32** %b) ; DEST2: define available_externally i32 @weakodr_aux(ptr %a, ptr %b)
;--- a.ll ;--- a.ll
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -6,7 +6,7 @@
; RUN: llvm-dis %t3.2.3.import.bc -o - | FileCheck %s --check-prefix=DEST ; RUN: llvm-dis %t3.2.3.import.bc -o - | FileCheck %s --check-prefix=DEST
;; For PIE, keep dso_local for declarations to enable direct access. ;; For PIE, keep dso_local for declarations to enable direct access.
; DEST: @b = external dso_local global i32* ; DEST: @b = external dso_local global ptr
; DEST-NEXT: @a = available_externally dso_local global i32 42, align 4 ; DEST-NEXT: @a = available_externally dso_local global i32 42, align 4
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"

View File

@ -12,13 +12,13 @@
; RUN: llvm-dis %t4.2.3.import.bc -o - | FileCheck %s --check-prefix=DEST_DSO ; RUN: llvm-dis %t4.2.3.import.bc -o - | FileCheck %s --check-prefix=DEST_DSO
; No variable in the source module should have been internalized ; No variable in the source module should have been internalized
; SRC: @b = dso_local global i32* @a ; SRC: @b = dso_local global ptr @a
; SRC-NEXT: @a = dso_local global i32 42 ; SRC-NEXT: @a = dso_local global i32 42
; We can't internalize globals referenced by other live globals ; We can't internalize globals referenced by other live globals
; DEST: @b = external dso_local global i32* ; DEST: @b = external dso_local global ptr
; DEST-NEXT: @a = available_externally dso_local global i32 42, align 4 ; DEST-NEXT: @a = available_externally dso_local global i32 42, align 4
; DEST_DSO: @b = external global i32* ; DEST_DSO: @b = external global ptr
; DEST_DSO-NEXT: @a = available_externally global i32 42, align 4 ; DEST_DSO-NEXT: @a = available_externally global i32 42, align 4
;; Test old API. ;; Test old API.

View File

@ -9,7 +9,7 @@
; - common linkage ; - common linkage
; - available_externally linkage ; - available_externally linkage
; - reference from @llvm.used ; - reference from @llvm.used
; CHECK: @llvm.used = appending global [1 x i32*] [i32* @g2] ; CHECK: @llvm.used = appending global [1 x ptr] [ptr @g2]
; CHECK-NEXT: @g1 = external global i32, align 4 ; CHECK-NEXT: @g1 = external global i32, align 4
; CHECK-NEXT: @g2 = available_externally global i32 42, align 4 ; CHECK-NEXT: @g2 = available_externally global i32 42, align 4
; CHECK-NEXT: @g3 = available_externally global i32 42, align 4 ; CHECK-NEXT: @g3 = available_externally global i32 42, align 4

View File

@ -22,7 +22,7 @@ target triple = "x86_64-apple-macosx10.11.0"
; We want foo to be imported in the main module! ; We want foo to be imported in the main module!
; RUN: llvm-dis < %t.o.2.3.import.bc | FileCheck %s --check-prefix=IMPORT ; RUN: llvm-dis < %t.o.2.3.import.bc | FileCheck %s --check-prefix=IMPORT
; IMPORT: define available_externally dso_local i8** @foo() ; IMPORT: define available_externally dso_local ptr @foo()
define i8 **@foo() { define i8 **@foo() {
ret i8 **@b ret i8 **@b
} }

View File

@ -10,9 +10,9 @@
; RUN: llvm-dis %t.out.1.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE ; RUN: llvm-dis %t.out.1.2.internalize.bc -o - | FileCheck %s --check-prefix=INTERNALIZE
; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE8instance = available_externally dso_local global %struct.S zeroinitializer ; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE8instance = available_externally dso_local global %struct.S zeroinitializer
; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE13instance_weak = available_externally dso_local global %struct.S* null, align 8 ; CHECK: @_ZZN9SingletonI1SE11getInstanceEvE13instance_weak = available_externally dso_local global ptr null, align 8
; CHECK: define linkonce_odr dso_local dereferenceable(16) %struct.S* @_ZN9SingletonI1SE11getInstanceEv() comdat ; CHECK: define linkonce_odr dso_local dereferenceable(16) ptr @_ZN9SingletonI1SE11getInstanceEv() comdat
; INTERNALIZE: define internal dereferenceable(16) %struct.S* @_ZN9SingletonI1SE11getInstanceEv() ; INTERNALIZE: define internal dereferenceable(16) ptr @_ZN9SingletonI1SE11getInstanceEv()
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu" target triple = "x86_64-unknown-linux-gnu"

View File

@ -208,6 +208,8 @@ namespace options {
static std::string stats_file; static std::string stats_file;
// Asserts that LTO link has whole program visibility // Asserts that LTO link has whole program visibility
static bool whole_program_visibility = false; static bool whole_program_visibility = false;
// Use opaque pointer types.
static bool opaque_pointers = true;
// Optimization remarks filename, accepted passes and hotness options // Optimization remarks filename, accepted passes and hotness options
static std::string RemarksFilename; static std::string RemarksFilename;
@ -308,6 +310,10 @@ namespace options {
RemarksFormat = std::string(opt); RemarksFormat = std::string(opt);
} else if (opt.consume_front("stats-file=")) { } else if (opt.consume_front("stats-file=")) {
stats_file = std::string(opt); stats_file = std::string(opt);
} else if (opt == "opaque-pointers") {
opaque_pointers = true;
} else if (opt == "no-opaque-pointers") {
opaque_pointers = false;
} else { } else {
// Save this option to pass to the code generator. // Save this option to pass to the code generator.
// ParseCommandLineOptions() expects argv[0] to be program name. Lazily // ParseCommandLineOptions() expects argv[0] to be program name. Lazily
@ -957,6 +963,8 @@ static std::unique_ptr<LTO> createLTO(IndexWriteCallback OnIndexWrite,
Conf.HasWholeProgramVisibility = options::whole_program_visibility; Conf.HasWholeProgramVisibility = options::whole_program_visibility;
Conf.OpaquePointers = options.opaque_pointers;
Conf.StatsFile = options::stats_file; Conf.StatsFile = options::stats_file;
return std::make_unique<LTO>(std::move(Conf), Backend, return std::make_unique<LTO>(std::move(Conf), Backend,
options::ParallelCodeGenParallelismLevel); options::ParallelCodeGenParallelismLevel);

View File

@ -143,6 +143,10 @@ static cl::opt<bool>
cl::desc("Run PGO context sensitive IR instrumentation"), cl::desc("Run PGO context sensitive IR instrumentation"),
cl::init(false), cl::Hidden); cl::init(false), cl::Hidden);
static cl::opt<bool> LtoOpaquePointers("lto-opaque-pointers",
cl::desc("Enable opaque pointer types"),
cl::init(true), cl::Hidden);
static cl::opt<bool> static cl::opt<bool>
DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden, DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
cl::desc("Print pass management debugging information")); cl::desc("Print pass management debugging information"));
@ -291,6 +295,7 @@ static int run(int argc, char **argv) {
Conf.StatsFile = StatsFile; Conf.StatsFile = StatsFile;
Conf.PTO.LoopVectorization = Conf.OptLevel > 1; Conf.PTO.LoopVectorization = Conf.OptLevel > 1;
Conf.PTO.SLPVectorization = Conf.OptLevel > 1; Conf.PTO.SLPVectorization = Conf.OptLevel > 1;
Conf.OpaquePointers = LtoOpaquePointers;
ThinBackend Backend; ThinBackend Backend;
if (ThinLTODistributedIndexes) if (ThinLTODistributedIndexes)