mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[WebAssembly] Add new relocation type for TLS data symbols
These relocations represent offsets from the __tls_base symbol. Previously we were just using normal MEMORY_ADDR relocations and relying on the linker to select a segment-offset rather and absolute value in Symbol::getVirtualAddress(). Using an explicit relocation type allows allow us to clearly distinguish absolute from relative relocations based on the relocation information alone. One place this is useful is being able to reject absolute relocation in the PIC case, but still accept TLS relocations. Differential Revision: https://reviews.llvm.org/D91276
This commit is contained in:
parent
5020d4daa4
commit
258639659d
@ -23,3 +23,4 @@ WASM_RELOC(R_WASM_MEMORY_ADDR_REL_SLEB64, 17)
|
||||
WASM_RELOC(R_WASM_TABLE_INDEX_SLEB64, 18)
|
||||
WASM_RELOC(R_WASM_TABLE_INDEX_I64, 19)
|
||||
WASM_RELOC(R_WASM_TABLE_NUMBER_LEB, 20)
|
||||
WASM_RELOC(R_WASM_MEMORY_ADDR_TLS_SLEB, 21)
|
||||
|
@ -321,8 +321,9 @@ public:
|
||||
VK_Hexagon_IE_GOT,
|
||||
|
||||
VK_WASM_TYPEINDEX, // Reference to a symbol's type (signature)
|
||||
VK_WASM_MBREL, // Memory address relative to memory base
|
||||
VK_WASM_TBREL, // Table index relative to table bare
|
||||
VK_WASM_TLSREL, // Memory address relative to __tls_base
|
||||
VK_WASM_MBREL, // Memory address relative to __memory_base
|
||||
VK_WASM_TBREL, // Table index relative to __table_base
|
||||
|
||||
VK_AMDGPU_GOTPCREL32_LO, // symbol@gotpcrel32@lo
|
||||
VK_AMDGPU_GOTPCREL32_HI, // symbol@gotpcrel32@hi
|
||||
|
@ -48,6 +48,7 @@ bool llvm::wasm::relocTypeHasAddend(uint32_t Type) {
|
||||
case R_WASM_MEMORY_ADDR_REL_SLEB64:
|
||||
case R_WASM_MEMORY_ADDR_I32:
|
||||
case R_WASM_MEMORY_ADDR_I64:
|
||||
case R_WASM_MEMORY_ADDR_TLS_SLEB:
|
||||
case R_WASM_FUNCTION_OFFSET_I32:
|
||||
case R_WASM_SECTION_OFFSET_I32:
|
||||
return true;
|
||||
|
@ -350,6 +350,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
|
||||
case VK_Hexagon_IE_GOT: return "IEGOT";
|
||||
case VK_WASM_TYPEINDEX: return "TYPEINDEX";
|
||||
case VK_WASM_MBREL: return "MBREL";
|
||||
case VK_WASM_TLSREL: return "TLSREL";
|
||||
case VK_WASM_TBREL: return "TBREL";
|
||||
case VK_AMDGPU_GOTPCREL32_LO: return "gotpcrel32@lo";
|
||||
case VK_AMDGPU_GOTPCREL32_HI: return "gotpcrel32@hi";
|
||||
@ -490,6 +491,7 @@ MCSymbolRefExpr::getVariantKindForName(StringRef Name) {
|
||||
.Case("typeindex", VK_WASM_TYPEINDEX)
|
||||
.Case("tbrel", VK_WASM_TBREL)
|
||||
.Case("mbrel", VK_WASM_MBREL)
|
||||
.Case("tlsrel", VK_WASM_TLSREL)
|
||||
.Case("gotpcrel32@lo", VK_AMDGPU_GOTPCREL32_LO)
|
||||
.Case("gotpcrel32@hi", VK_AMDGPU_GOTPCREL32_HI)
|
||||
.Case("rel32@lo", VK_AMDGPU_REL32_LO)
|
||||
|
@ -576,7 +576,8 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry,
|
||||
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
|
||||
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB64:
|
||||
case wasm::R_WASM_MEMORY_ADDR_I32:
|
||||
case wasm::R_WASM_MEMORY_ADDR_I64: {
|
||||
case wasm::R_WASM_MEMORY_ADDR_I64:
|
||||
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB: {
|
||||
// Provisional value is address of the global plus the offset
|
||||
const MCSymbolWasm *Base =
|
||||
cast<MCSymbolWasm>(Layout.getBaseSymbol(*RelEntry.Symbol));
|
||||
@ -685,6 +686,7 @@ void WasmObjectWriter::applyRelocations(
|
||||
case wasm::R_WASM_TABLE_INDEX_REL_SLEB:
|
||||
case wasm::R_WASM_MEMORY_ADDR_SLEB:
|
||||
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
|
||||
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
|
||||
writePatchableSLEB<5>(Stream, Value, Offset);
|
||||
break;
|
||||
case wasm::R_WASM_TABLE_INDEX_SLEB64:
|
||||
|
@ -855,6 +855,7 @@ Error WasmObjectFile::parseRelocSection(StringRef Name, ReadContext &Ctx) {
|
||||
case wasm::R_WASM_MEMORY_ADDR_SLEB:
|
||||
case wasm::R_WASM_MEMORY_ADDR_I32:
|
||||
case wasm::R_WASM_MEMORY_ADDR_REL_SLEB:
|
||||
case wasm::R_WASM_MEMORY_ADDR_TLS_SLEB:
|
||||
if (!isValidDataSymbol(Reloc.Index))
|
||||
return make_error<GenericBinaryError>("Bad relocation data index",
|
||||
object_error::parse_failed);
|
||||
|
@ -100,6 +100,11 @@ enum TOF {
|
||||
// Only applicable to data symbols.
|
||||
MO_MEMORY_BASE_REL,
|
||||
|
||||
// On a symbol operand this indicates that the immediate is the symbol
|
||||
// address relative the __tls_base wasm global.
|
||||
// Only applicable to data symbols.
|
||||
MO_TLS_BASE_REL,
|
||||
|
||||
// On a symbol operand this indicates that the immediate is the symbol
|
||||
// address relative the __table_base wasm global.
|
||||
// Only applicable to function symbols.
|
||||
|
@ -76,6 +76,8 @@ unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target,
|
||||
case MCSymbolRefExpr::VK_WASM_TBREL:
|
||||
assert(SymA.isFunction());
|
||||
return wasm::R_WASM_TABLE_INDEX_REL_SLEB;
|
||||
case MCSymbolRefExpr::VK_WASM_TLSREL:
|
||||
return wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;
|
||||
case MCSymbolRefExpr::VK_WASM_MBREL:
|
||||
assert(SymA.isData());
|
||||
return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64
|
||||
|
@ -149,7 +149,8 @@ void WebAssemblyDAGToDAGISel::Select(SDNode *Node) {
|
||||
|
||||
SDValue TLSBaseSym = CurDAG->getTargetExternalSymbol("__tls_base", PtrVT);
|
||||
SDValue TLSOffsetSym = CurDAG->getTargetGlobalAddress(
|
||||
GA->getGlobal(), DL, PtrVT, GA->getOffset(), 0);
|
||||
GA->getGlobal(), DL, PtrVT, GA->getOffset(),
|
||||
WebAssemblyII::MO_TLS_BASE_REL);
|
||||
|
||||
MachineSDNode *TLSBase =
|
||||
CurDAG->getMachineNode(GlobalGetIns, DL, PtrVT, TLSBaseSym);
|
||||
|
@ -106,6 +106,7 @@ private:
|
||||
SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerJumpTable(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
@ -139,6 +139,9 @@ MCOperand WebAssemblyMCInstLower::lowerSymbolOperand(const MachineOperand &MO,
|
||||
case WebAssemblyII::MO_MEMORY_BASE_REL:
|
||||
Kind = MCSymbolRefExpr::VK_WASM_MBREL;
|
||||
break;
|
||||
case WebAssemblyII::MO_TLS_BASE_REL:
|
||||
Kind = MCSymbolRefExpr::VK_WASM_TLSREL;
|
||||
break;
|
||||
case WebAssemblyII::MO_TABLE_BASE_REL:
|
||||
Kind = MCSymbolRefExpr::VK_WASM_TBREL;
|
||||
break;
|
||||
|
@ -277,10 +277,9 @@ private:
|
||||
bool stripThreadLocals(Module &M) {
|
||||
bool Stripped = false;
|
||||
for (auto &GV : M.globals()) {
|
||||
if (GV.getThreadLocalMode() !=
|
||||
GlobalValue::ThreadLocalMode::NotThreadLocal) {
|
||||
if (GV.isThreadLocal()) {
|
||||
Stripped = true;
|
||||
GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal);
|
||||
GV.setThreadLocal(false);
|
||||
}
|
||||
}
|
||||
return Stripped;
|
||||
|
@ -12,7 +12,7 @@ target triple = "wasm32-unknown-unknown"
|
||||
; CHECK-NEXT: .functype address_of_tls () -> (i32)
|
||||
define i32 @address_of_tls() {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: return
|
||||
|
||||
@ -25,7 +25,7 @@ define i32 @address_of_tls() {
|
||||
; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
|
||||
define i32* @ptr_to_tls() {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: return
|
||||
|
||||
@ -38,7 +38,7 @@ define i32* @ptr_to_tls() {
|
||||
; CHECK-NEXT: .functype tls_load () -> (i32)
|
||||
define i32 @tls_load() {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: i32.load 0
|
||||
; TLS-NEXT: return
|
||||
@ -54,7 +54,7 @@ define i32 @tls_load() {
|
||||
; CHECK-NEXT: .functype tls_store (i32) -> ()
|
||||
define void @tls_store(i32 %x) {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: i32.store 0
|
||||
; TLS-NEXT: return
|
||||
|
@ -8,7 +8,7 @@ target triple = "wasm32-unknown-unknown"
|
||||
; CHECK-NEXT: .functype address_of_tls () -> (i32)
|
||||
define i32 @address_of_tls() {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: return
|
||||
|
||||
@ -21,7 +21,7 @@ define i32 @address_of_tls() {
|
||||
; CHECK-NEXT: .functype ptr_to_tls () -> (i32)
|
||||
define i32* @ptr_to_tls() {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: return
|
||||
|
||||
@ -34,7 +34,7 @@ define i32* @ptr_to_tls() {
|
||||
; CHECK-NEXT: .functype tls_load () -> (i32)
|
||||
define i32 @tls_load() {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: i32.load 0
|
||||
; TLS-NEXT: return
|
||||
@ -50,7 +50,7 @@ define i32 @tls_load() {
|
||||
; CHECK-NEXT: .functype tls_store (i32) -> ()
|
||||
define void @tls_store(i32 %x) {
|
||||
; TLS-DAG: global.get __tls_base
|
||||
; TLS-DAG: i32.const tls
|
||||
; TLS-DAG: i32.const tls@TLSREL
|
||||
; TLS-NEXT: i32.add
|
||||
; TLS-NEXT: i32.store 0
|
||||
; TLS-NEXT: return
|
||||
|
43
test/MC/WebAssembly/tls.s
Normal file
43
test/MC/WebAssembly/tls.s
Normal file
@ -0,0 +1,43 @@
|
||||
# RUN: llvm-mc -triple=wasm32-unknown-unknown < %s | FileCheck %s
|
||||
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o < %s
|
||||
# RUN: obj2yaml %t.o | FileCheck %s --check-prefix=CHECK-OBJ
|
||||
|
||||
tls_store:
|
||||
.functype tls_store (i32) -> ()
|
||||
# CHECK: global.get __tls_base
|
||||
# CHECK-NEXT: i32.const tls@TLSREL
|
||||
# CHECK-NEXT: i32.add
|
||||
# CHECK-NEXT: i32.store 0
|
||||
global.get __tls_base
|
||||
i32.const tls@TLSREL
|
||||
i32.add
|
||||
i32.store 0
|
||||
end_function
|
||||
|
||||
|
||||
# CHECK-OBJ: - Type: CODE
|
||||
# CHECK-OBJ-NEXT: Relocations:
|
||||
# CHECK-OBJ-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
|
||||
# CHECK-OBJ-NEXT: Index: 1
|
||||
# CHECK-OBJ-NEXT: Offset: 0x00000004
|
||||
# CHECK-OBJ-NEXT: - Type: R_WASM_MEMORY_ADDR_TLS_SLEB
|
||||
# CHECK-OBJ-NEXT: Index: 2
|
||||
# CHECK-OBJ-NEXT: Offset: 0x0000000A
|
||||
|
||||
# CHECK-OBJ: - Type: CUSTOM
|
||||
# CHECK-OBJ-NEXT: Name: linking
|
||||
# CHECK-OBJ-NEXT: Version: 2
|
||||
# CHECK-OBJ-NEXT: SymbolTable:
|
||||
# CHECK-OBJ-NEXT: - Index: 0
|
||||
# CHECK-OBJ-NEXT: Kind: FUNCTION
|
||||
# CHECK-OBJ-NEXT: Name: tls_store
|
||||
# CHECK-OBJ-NEXT: Flags: [ BINDING_LOCAL ]
|
||||
# CHECK-OBJ-NEXT: Function: 0
|
||||
# CHECK-OBJ-NEXT: - Index: 1
|
||||
# CHECK-OBJ-NEXT: Kind: DATA
|
||||
# CHECK-OBJ-NEXT: Name: __tls_base
|
||||
# CHECK-OBJ-NEXT: Flags: [ UNDEFINED ]
|
||||
# CHECK-OBJ-NEXT: - Index: 2
|
||||
# CHECK-OBJ-NEXT: Kind: DATA
|
||||
# CHECK-OBJ-NEXT: Name: tls
|
||||
# CHECK-OBJ-NEXT: Flags: [ UNDEFINED ]
|
Loading…
Reference in New Issue
Block a user