mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 12:43:36 +01:00
Clarify that llvm.used can contain aliases.
Also add a check for llvm.used in the verifier and simplify clients now that they can assume they have a ConstantArray. llvm-svn: 180019
This commit is contained in:
parent
8fa9d9a193
commit
88a7961c64
@ -2868,9 +2868,9 @@ All globals of this sort should have a section specified as
|
||||
The '``llvm.used``' Global Variable
|
||||
-----------------------------------
|
||||
|
||||
The ``@llvm.used`` global is an array with i8\* element type which has
|
||||
:ref:`appending linkage <linkage_appending>`. This array contains a list of
|
||||
pointers to global variables and functions which may optionally have a
|
||||
The ``@llvm.used`` global is an array which has
|
||||
:ref:`appending linkage <linkage_appending>`. This array contains a list of
|
||||
pointers to global variables, functions and aliases which may optionally have a
|
||||
pointer cast formed of bitcast or getelementptr. For example, a legal
|
||||
use of it is:
|
||||
|
||||
@ -2884,13 +2884,13 @@ use of it is:
|
||||
i8* bitcast (i32* @Y to i8*)
|
||||
], section "llvm.metadata"
|
||||
|
||||
If a global variable appears in the ``@llvm.used`` list, then the
|
||||
compiler, assembler, and linker are required to treat the symbol as if
|
||||
there is a reference to the global that it cannot see. For example, if a
|
||||
variable has internal linkage and no references other than that from the
|
||||
``@llvm.used`` list, it cannot be deleted. This is commonly used to
|
||||
represent references from inline asms and other things the compiler
|
||||
cannot "see", and corresponds to "``attribute((used))``" in GNU C.
|
||||
If a symbol appears in the ``@llvm.used`` list, then the compiler, assembler,
|
||||
and linker are required to treat the symbol as if there is a reference to the
|
||||
symbol that it cannot see. For example, if a variable has internal linkage and
|
||||
no references other than that from the ``@llvm.used`` list, it cannot be
|
||||
deleted. This is commonly used to represent references from inline asms and
|
||||
other things the compiler cannot "see", and corresponds to
|
||||
"``attribute((used))``" in GNU C.
|
||||
|
||||
On some targets, the code generator must emit a directive to the
|
||||
assembler or object file to prevent the assembler and linker from
|
||||
|
@ -25,6 +25,7 @@ namespace llvm {
|
||||
class BlockAddress;
|
||||
class GCStrategy;
|
||||
class Constant;
|
||||
class ConstantArray;
|
||||
class GCMetadataPrinter;
|
||||
class GlobalValue;
|
||||
class GlobalVariable;
|
||||
@ -480,7 +481,7 @@ namespace llvm {
|
||||
void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI,
|
||||
const MachineBasicBlock *MBB,
|
||||
unsigned uid) const;
|
||||
void EmitLLVMUsedList(const Constant *List);
|
||||
void EmitLLVMUsedList(const ConstantArray *InitList);
|
||||
void EmitXXStructorList(const Constant *List, bool isCtor);
|
||||
GCMetadataPrinter *GetOrCreateGCPrinter(GCStrategy *C);
|
||||
};
|
||||
|
@ -1213,7 +1213,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI,
|
||||
bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
|
||||
if (GV->getName() == "llvm.used") {
|
||||
if (MAI->hasNoDeadStrip()) // No need to emit this at all.
|
||||
EmitLLVMUsedList(GV->getInitializer());
|
||||
EmitLLVMUsedList(cast<ConstantArray>(GV->getInitializer()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1256,11 +1256,8 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
|
||||
/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each
|
||||
/// global in the specified llvm.used list for which emitUsedDirectiveFor
|
||||
/// is true, as being used with this directive.
|
||||
void AsmPrinter::EmitLLVMUsedList(const Constant *List) {
|
||||
void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) {
|
||||
// Should be an array of 'i8*'.
|
||||
const ConstantArray *InitList = dyn_cast<ConstantArray>(List);
|
||||
if (InitList == 0) return;
|
||||
|
||||
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
|
||||
const GlobalValue *GV =
|
||||
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
|
||||
|
@ -326,8 +326,7 @@ void MachineModuleInfo::AnalyzeModule(const Module &M) {
|
||||
if (!GV || !GV->hasInitializer()) return;
|
||||
|
||||
// Should be an array of 'i8*'.
|
||||
const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
|
||||
if (InitList == 0) return;
|
||||
const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer());
|
||||
|
||||
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
|
||||
if (const Function *F =
|
||||
|
@ -449,6 +449,29 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
|
||||
}
|
||||
}
|
||||
|
||||
if (GV.hasName() && (GV.getName() == "llvm.used")) {
|
||||
Assert1(!GV.hasInitializer() || GV.hasAppendingLinkage(),
|
||||
"invalid linkage for intrinsic global variable", &GV);
|
||||
Type *GVType = GV.getType()->getElementType();
|
||||
if (ArrayType *ATy = dyn_cast<ArrayType>(GVType)) {
|
||||
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
|
||||
Assert1(PTy, "wrong type for intrinsic global variable", &GV);
|
||||
if (GV.hasInitializer()) {
|
||||
Constant *Init = GV.getInitializer();
|
||||
ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
|
||||
Assert1(InitArray, "wrong initalizer for intrinsic global variable",
|
||||
Init);
|
||||
for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) {
|
||||
Value *V = Init->getOperand(i)->stripPointerCasts();
|
||||
// stripPointerCasts strips aliases, so we only need to check for
|
||||
// variables and functions.
|
||||
Assert1(isa<GlobalVariable>(V) || isa<Function>(V),
|
||||
"invalid llvm.used member", V);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
visitGlobalValue(GV);
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,8 @@ ModulePass *llvm::createConstantMergePass() { return new ConstantMerge(); }
|
||||
static void FindUsedValues(GlobalVariable *LLVMUsed,
|
||||
SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
|
||||
if (LLVMUsed == 0) return;
|
||||
ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
|
||||
if (Inits == 0) return;
|
||||
|
||||
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
|
||||
|
||||
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
|
||||
if (GlobalValue *GV =
|
||||
dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
|
||||
|
@ -195,10 +195,9 @@ static void findUsedValues(GlobalVariable *LLVMUsed,
|
||||
SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
|
||||
if (LLVMUsed == 0) return;
|
||||
UsedValues.insert(LLVMUsed);
|
||||
|
||||
ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
|
||||
if (Inits == 0) return;
|
||||
|
||||
|
||||
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
|
||||
|
||||
for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
|
||||
if (GlobalValue *GV =
|
||||
dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
|
||||
|
@ -200,9 +200,8 @@ void GlobalMerge::collectUsedGlobalVariables(Module &M) {
|
||||
if (!GV || !GV->hasInitializer()) return;
|
||||
|
||||
// Should be an array of 'i8*'.
|
||||
const ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
|
||||
if (InitList == 0) return;
|
||||
|
||||
const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer());
|
||||
|
||||
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
|
||||
if (const GlobalVariable *G =
|
||||
dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts()))
|
||||
|
@ -2,6 +2,8 @@
|
||||
; RUN: llvm-as %t1.ll -o - | llvm-dis > %t2.ll
|
||||
; RUN: diff %t1.ll %t2.ll
|
||||
|
||||
@llvm.used = appending global [1 x i8*] [i8* bitcast (i32* @foo1 to i8*)], section "llvm.metadata"
|
||||
|
||||
@bar = external global i32
|
||||
@foo1 = alias i32* @bar
|
||||
@foo2 = alias i32* @bar
|
||||
|
6
test/Verifier/llvm.used-invalid-init.ll
Normal file
6
test/Verifier/llvm.used-invalid-init.ll
Normal file
@ -0,0 +1,6 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
@llvm.used = appending global [1 x i8*] zeroinitializer, section "llvm.metadata"
|
||||
|
||||
; CHECK: wrong initalizer for intrinsic global variable
|
||||
; CHECK-NEXT: [1 x i8*] zeroinitializer
|
7
test/Verifier/llvm.used-invalid-init2.ll
Normal file
7
test/Verifier/llvm.used-invalid-init2.ll
Normal file
@ -0,0 +1,7 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
@a = global i8 42
|
||||
@llvm.used = appending global [2 x i8*] [i8* @a, i8* null], section "llvm.metadata"
|
||||
|
||||
; CHECK: invalid llvm.used member
|
||||
; CHECK-NEXT: i8* null
|
6
test/Verifier/llvm.used-invalid-type.ll
Normal file
6
test/Verifier/llvm.used-invalid-type.ll
Normal file
@ -0,0 +1,6 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
|
||||
@llvm.used = appending global [1 x i32] [i32 0], section "llvm.metadata"
|
||||
|
||||
; CHECK: wrong type for intrinsic global variable
|
||||
; CHECK-NEXT: [1 x i32]* @llvm.used
|
5
test/Verifier/llvm.used-invalid-type2.ll
Normal file
5
test/Verifier/llvm.used-invalid-type2.ll
Normal file
@ -0,0 +1,5 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
|
||||
@llvm.used = appending global i32 0, section "llvm.metadata"
|
||||
|
||||
; CHECK: Only global arrays can have appending linkage!
|
||||
; CHEKC-NEXT: i32* @llvm.used
|
4
test/Verifier/llvm.used-ptr-type.ll
Normal file
4
test/Verifier/llvm.used-ptr-type.ll
Normal file
@ -0,0 +1,4 @@
|
||||
; RUN: llvm-as < %s -o /dev/null
|
||||
|
||||
@a = global i32 42
|
||||
@llvm.used = appending global [1 x i32*] [i32* @a], section "llvm.metadata"
|
Loading…
Reference in New Issue
Block a user