mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-19 16:35:10 +00:00
Use a scheme closer to that of GNU as when deciding the type of a
symbol with multiple .type declarations. Differential Revision: http://llvm-reviews.chandlerc.com/D607 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179184 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b08c6df678
commit
01a7b5c43e
@ -13,6 +13,7 @@
|
||||
|
||||
#include "llvm/MC/MCELFStreamer.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
@ -126,6 +127,26 @@ void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) {
|
||||
Alias->setVariableValue(Value);
|
||||
}
|
||||
|
||||
// When GNU as encounters more than one .type declaration for an object it seems
|
||||
// to use a mechanism similar to the one below to decide which type is actually
|
||||
// used in the object file. The greater of T1 and T2 is selected based on the
|
||||
// following ordering:
|
||||
// STT_NOTYPE < STT_OBJECT < STT_FUNC < STT_GNU_IFUNC < STT_TLS < anything else
|
||||
// If neither T1 < T2 nor T2 < T1 according to this ordering, use T2 (the user
|
||||
// provided type).
|
||||
static unsigned CombineSymbolTypes(unsigned T1, unsigned T2) {
|
||||
unsigned TypeOrdering[] = {ELF::STT_NOTYPE, ELF::STT_OBJECT, ELF::STT_FUNC,
|
||||
ELF::STT_GNU_IFUNC, ELF::STT_TLS};
|
||||
for (unsigned i = 0; i != array_lengthof(TypeOrdering); ++i) {
|
||||
if (T1 == TypeOrdering[i])
|
||||
return T2;
|
||||
if (T2 == TypeOrdering[i])
|
||||
return T1;
|
||||
}
|
||||
|
||||
return T2;
|
||||
}
|
||||
|
||||
void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
||||
MCSymbolAttr Attribute) {
|
||||
// Indirect symbols are handled differently, to match how 'as' handles
|
||||
@ -187,27 +208,34 @@ void MCELFStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeFunction:
|
||||
MCELF::SetType(SD, ELF::STT_FUNC);
|
||||
MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD),
|
||||
ELF::STT_FUNC));
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeIndFunction:
|
||||
MCELF::SetType(SD, ELF::STT_GNU_IFUNC);
|
||||
MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD),
|
||||
ELF::STT_GNU_IFUNC));
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeObject:
|
||||
MCELF::SetType(SD, ELF::STT_OBJECT);
|
||||
MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD),
|
||||
ELF::STT_OBJECT));
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeTLS:
|
||||
MCELF::SetType(SD, ELF::STT_TLS);
|
||||
MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD),
|
||||
ELF::STT_TLS));
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeCommon:
|
||||
MCELF::SetType(SD, ELF::STT_COMMON);
|
||||
// TODO: Emit these as a common symbol.
|
||||
MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD),
|
||||
ELF::STT_OBJECT));
|
||||
break;
|
||||
|
||||
case MCSA_ELF_TypeNoType:
|
||||
MCELF::SetType(SD, ELF::STT_NOTYPE);
|
||||
MCELF::SetType(SD, CombineSymbolTypes(MCELF::GetType(SD),
|
||||
ELF::STT_NOTYPE));
|
||||
break;
|
||||
|
||||
case MCSA_Protected:
|
||||
|
@ -12,35 +12,70 @@ bar:
|
||||
// Test that gnu_unique_object is accepted.
|
||||
.type zed,@gnu_unique_object
|
||||
|
||||
obj:
|
||||
.global obj
|
||||
.type obj,@object
|
||||
.type obj,@notype
|
||||
|
||||
func:
|
||||
.global func
|
||||
.type func,@function
|
||||
.type func,@object
|
||||
|
||||
ifunc:
|
||||
.global ifunc
|
||||
.type ifunc,@gnu_indirect_function
|
||||
.type ifunc,@function
|
||||
|
||||
// CHECK: # Symbol 4
|
||||
// CHECK-NEXT: (('st_name', 0x00000005) # 'bar'
|
||||
tls:
|
||||
.global tls
|
||||
.type tls,@tls_object
|
||||
.type tls,@gnu_indirect_function
|
||||
|
||||
// CHECK: (('st_name', {{.*}}) # 'bar'
|
||||
// CHECK-NEXT: ('st_bind', 0x1)
|
||||
// CHECK-NEXT: ('st_type', 0x1)
|
||||
// CHECK-NEXT: ('st_other', 0x00)
|
||||
// CHECK-NEXT: ('st_shndx', 0x0001)
|
||||
// CHECK-NEXT: ('st_value', 0x0000000000000000)
|
||||
// CHECK-NEXT: ('st_size', 0x0000000000000000)
|
||||
// CHECK-NEXT: ),
|
||||
// CHECK-NEXT: # Symbol 5
|
||||
// CHECK-NEXT: (('st_name', 0x00000001) # 'foo'
|
||||
|
||||
// CHECK: (('st_name', {{.*}}) # 'foo'
|
||||
// CHECK-NEXT: ('st_bind', 0x1)
|
||||
// CHECK-NEXT: ('st_type', 0x2)
|
||||
// CHECK-NEXT: ('st_other', 0x00)
|
||||
// CHECK-NEXT: ('st_shndx', 0x0001)
|
||||
// CHECK-NEXT: ('st_value', 0x0000000000000000)
|
||||
// CHECK-NEXT: ('st_size', 0x0000000000000000)
|
||||
// CHECK-NEXT: ),
|
||||
// CHECK-NEXT: # Symbol 6
|
||||
// CHECK-NEXT: (('st_name', 0x00000009) # 'ifunc'
|
||||
|
||||
// CHECK: (('st_name', {{.*}}) # 'func'
|
||||
// CHECK-NEXT: ('st_bind', 0x1)
|
||||
// CHECK-NEXT: ('st_type', 0x2)
|
||||
// CHECK-NEXT: ('st_other', 0x00)
|
||||
// CHECK-NEXT: ('st_shndx', 0x0001)
|
||||
// CHECK-NEXT: ('st_value', 0x0000000000000000)
|
||||
// CHECK-NEXT: ('st_size', 0x0000000000000000)
|
||||
|
||||
// CHECK: (('st_name', {{.*}}) # 'ifunc'
|
||||
// CHECK-NEXT: ('st_bind', 0x1)
|
||||
// CHECK-NEXT: ('st_type', 0xa)
|
||||
// CHECK-NEXT: ('st_other', 0x00)
|
||||
// CHECK-NEXT: ('st_shndx', 0x0001)
|
||||
// CHECK-NEXT: ('st_value', 0x0000000000000000)
|
||||
// CHECK-NEXT: ('st_size', 0x0000000000000000)
|
||||
// CHECK-NEXT: ),
|
||||
|
||||
// CHECK: (('st_name', {{.*}}) # 'obj'
|
||||
// CHECK-NEXT: ('st_bind', 0x1)
|
||||
// CHECK-NEXT: ('st_type', 0x1)
|
||||
// CHECK-NEXT: ('st_other', 0x00)
|
||||
// CHECK-NEXT: ('st_shndx', 0x0001)
|
||||
// CHECK-NEXT: ('st_value', 0x0000000000000000)
|
||||
// CHECK-NEXT: ('st_size', 0x0000000000000000)
|
||||
|
||||
// CHECK: (('st_name', {{.*}}) # 'tls'
|
||||
// CHECK-NEXT: ('st_bind', 0x1)
|
||||
// CHECK-NEXT: ('st_type', 0x6)
|
||||
// CHECK-NEXT: ('st_other', 0x00)
|
||||
// CHECK-NEXT: ('st_shndx', 0x0001)
|
||||
// CHECK-NEXT: ('st_value', 0x0000000000000000)
|
||||
// CHECK-NEXT: ('st_size', 0x0000000000000000)
|
||||
|
Loading…
x
Reference in New Issue
Block a user