[lld] 3041b16 - [WebAssembly] Add TLS data segment flag: WASM_SEG_FLAG_TLS
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Wed May 12 13:31:11 PDT 2021
Author: Sam Clegg
Date: 2021-05-12T13:31:02-07:00
New Revision: 3041b16f7322a0392810e4a14b13cacac1929ad8
URL: https://github.com/llvm/llvm-project/commit/3041b16f7322a0392810e4a14b13cacac1929ad8
DIFF: https://github.com/llvm/llvm-project/commit/3041b16f7322a0392810e4a14b13cacac1929ad8.diff
LOG: [WebAssembly] Add TLS data segment flag: WASM_SEG_FLAG_TLS
Previously the linker was relying solely on the name of the segment
to imply TLS.
Differential Revision: https://reviews.llvm.org/D102202
Added:
Modified:
lld/test/wasm/tls.s
lld/wasm/InputChunks.h
lld/wasm/Writer.cpp
llvm/include/llvm/BinaryFormat/Wasm.h
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/lib/MC/MCParser/WasmAsmParser.cpp
llvm/lib/MC/MCSectionWasm.cpp
llvm/lib/ObjectYAML/WasmYAML.cpp
llvm/test/CodeGen/WebAssembly/target-features-tls.ll
llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
llvm/test/CodeGen/WebAssembly/tls-local-exec.ll
llvm/test/MC/WebAssembly/tls.s
Removed:
################################################################################
diff --git a/lld/test/wasm/tls.s b/lld/test/wasm/tls.s
index 878498bc2e483..9675b7839aa9b 100644
--- a/lld/test/wasm/tls.s
+++ b/lld/test/wasm/tls.s
@@ -40,6 +40,8 @@ no_tls:
.int32 0
.size no_tls, 4
+// Older versions of LLVM did not use the "T" flag so we need to support
+// infering TLS from the name alone.
.section .tdata.tls1,"",@
.globl tls1
.p2align 2
@@ -47,14 +49,14 @@ tls1:
.int32 1
.size tls1, 4
-.section .tdata.tls2,"",@
+.section sec_tls2,"T",@
.globl tls2
.p2align 2
tls2:
.int32 1
.size tls2, 4
-.section .tbss.tls3,"",@
+.section sec_tls3,"T",@
.globl tls3
.p2align 2
tls3:
diff --git a/lld/wasm/InputChunks.h b/lld/wasm/InputChunks.h
index 161e7435090b7..d0195b5f8ceeb 100644
--- a/lld/wasm/InputChunks.h
+++ b/lld/wasm/InputChunks.h
@@ -137,8 +137,11 @@ class InputSegment : public InputChunk {
uint64_t getVA(uint64_t offset = 0) const;
- bool isTLS() {
- return getName().startswith(".tdata") || getName().startswith(".tbss");
+ bool isTLS() const {
+ // Older object files don't include WASM_SEG_FLAG_TLS and instead
+ // relied on the naming convention.
+ return flags & llvm::wasm::WASM_SEG_FLAG_TLS ||
+ getName().startswith(".tdata") || getName().startswith(".tbss");
}
const OutputSegment *outputSeg = nullptr;
diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp
index 14a68ebdf907f..08149bc605a24 100644
--- a/lld/wasm/Writer.cpp
+++ b/lld/wasm/Writer.cpp
@@ -461,9 +461,7 @@ void Writer::populateTargetFeatures() {
// Find TLS data segments
auto isTLS = [](InputSegment *segment) {
- StringRef name = segment->getName();
- return segment->live &&
- (name.startswith(".tdata") || name.startswith(".tbss"));
+ return segment->live && segment->isTLS();
};
tlsUsed = tlsUsed ||
std::any_of(file->segments.begin(), file->segments.end(), isTLS);
@@ -818,12 +816,12 @@ void Writer::assignIndexes() {
out.tableSec->assignIndexes();
}
-static StringRef getOutputDataSegmentName(StringRef name) {
- // We only support one thread-local segment, so we must merge the segments
- // despite --no-merge-data-segments.
- // We also need to merge .tbss into .tdata so they share the same offsets.
- if (name.startswith(".tdata") || name.startswith(".tbss"))
+static StringRef getOutputDataSegmentName(const InputSegment &seg) {
+ // We always merge .tbss and .tdata into a single TLS segment so all TLS
+ // symbols are be relative to single __tls_base.
+ if (seg.isTLS())
return ".tdata";
+ StringRef name = seg.getName();
if (!config->mergeDataSegments)
return name;
if (name.startswith(".text."))
@@ -857,7 +855,7 @@ void Writer::createOutputSegments() {
for (InputSegment *segment : file->segments) {
if (!segment->live)
continue;
- StringRef name = getOutputDataSegmentName(segment->getName());
+ StringRef name = getOutputDataSegmentName(*segment);
OutputSegment *s = nullptr;
// When running in relocatable mode we can't merge segments that are part
// of comdat groups since the ultimate linker needs to be able exclude or
diff --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 077913d7fa59d..999f4a2578130 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -359,6 +359,7 @@ enum WasmSymbolType : unsigned {
enum WasmSegmentFlag : unsigned {
WASM_SEG_FLAG_STRINGS = 0x1,
+ WASM_SEG_FLAG_TLS = 0x2,
};
// Kinds of event attributes.
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
index 54d65ccac50d9..31122295fa37c 100644
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -2009,11 +2009,14 @@ static const Comdat *getWasmComdat(const GlobalValue *GV) {
static unsigned getWasmSectionFlags(SectionKind K) {
unsigned Flags = 0;
- // TODO(sbc): Add suport for K.isMergeableConst()
+ if (K.isThreadLocal())
+ Flags |= wasm::WASM_SEG_FLAG_TLS;
if (K.isMergeableCString())
Flags |= wasm::WASM_SEG_FLAG_STRINGS;
+ // TODO(sbc): Add suport for K.isMergeableConst()
+
return Flags;
}
diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
index fdf8c45ba5c6a..833530bef3bf3 100644
--- a/llvm/lib/MC/MCParser/WasmAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp
@@ -100,6 +100,9 @@ class WasmAsmParser : public MCAsmParserExtension {
case 'G':
Group = true;
break;
+ case 'T':
+ flags |= wasm::WASM_SEG_FLAG_TLS;
+ break;
case 'S':
flags |= wasm::WASM_SEG_FLAG_STRINGS;
break;
diff --git a/llvm/lib/MC/MCSectionWasm.cpp b/llvm/lib/MC/MCSectionWasm.cpp
index 9faa4caad64f9..459913263268b 100644
--- a/llvm/lib/MC/MCSectionWasm.cpp
+++ b/llvm/lib/MC/MCSectionWasm.cpp
@@ -69,6 +69,8 @@ void MCSectionWasm::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
OS << 'G';
if (SegmentFlags & wasm::WASM_SEG_FLAG_STRINGS)
OS << 'S';
+ if (SegmentFlags & wasm::WASM_SEG_FLAG_TLS)
+ OS << 'T';
OS << '"';
diff --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index 0017e7e609a9d..6b7357c4d1d8e 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -544,6 +544,7 @@ void ScalarBitSetTraits<WasmYAML::SegmentFlags>::bitset(
IO &IO, WasmYAML::SegmentFlags &Value) {
#define BCase(X) IO.bitSetCase(Value, #X, wasm::WASM_SEG_FLAG_##X)
BCase(STRINGS);
+ BCase(TLS);
#undef BCase
}
diff --git a/llvm/test/CodeGen/WebAssembly/target-features-tls.ll b/llvm/test/CodeGen/WebAssembly/target-features-tls.ll
index e146bdae5f54e..f5ec6842de71f 100644
--- a/llvm/test/CodeGen/WebAssembly/target-features-tls.ll
+++ b/llvm/test/CodeGen/WebAssembly/target-features-tls.ll
@@ -23,4 +23,4 @@ target triple = "wasm32-unknown-unknown"
; BULK-MEM-NEXT: .int8 43
; BULK-MEM-NEXT: .int8 11
; BULK-MEM-NEXT: .ascii "bulk-memory"
-; BULK-MEM-NEXT: .tbss.foo,"",@
+; BULK-MEM-NEXT: .tbss.foo,"T",@
diff --git a/llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll b/llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
index 16a312bd6bada..cb20066e14c57 100644
--- a/llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
+++ b/llvm/test/CodeGen/WebAssembly/tls-general-dynamic.ll
@@ -105,7 +105,7 @@ define void @tls_base_write(i8** %output) {
}
; CHECK: .type tls, at object
-; TLS-NEXT: .section .tbss.tls,"",@
+; TLS-NEXT: .section .tbss.tls,"T",@
; NO-TLS-NEXT: .section .bss.tls,"",@
; CHECK-NEXT: .p2align 2
; CHECK-NEXT: tls:
diff --git a/llvm/test/CodeGen/WebAssembly/tls-local-exec.ll b/llvm/test/CodeGen/WebAssembly/tls-local-exec.ll
index 7cc043a13ac0d..c6ae34b7fc81b 100644
--- a/llvm/test/CodeGen/WebAssembly/tls-local-exec.ll
+++ b/llvm/test/CodeGen/WebAssembly/tls-local-exec.ll
@@ -72,7 +72,7 @@ define i32 @tls_size() {
}
; CHECK: .type tls, at object
-; TLS-NEXT: .section .tbss.tls,"",@
+; TLS-NEXT: .section .tbss.tls,"T",@
; NO-TLS-NEXT: .section .bss.tls,"",@
; CHECK-NEXT: .p2align 2
; CHECK-NEXT: tls:
diff --git a/llvm/test/MC/WebAssembly/tls.s b/llvm/test/MC/WebAssembly/tls.s
index f1dba82994460..2df245ff9385a 100644
--- a/llvm/test/MC/WebAssembly/tls.s
+++ b/llvm/test/MC/WebAssembly/tls.s
@@ -5,15 +5,26 @@
tls_store:
.functype tls_store (i32) -> ()
# CHECK: global.get __tls_base
- # CHECK-NEXT: i32.const tls at TLSREL
+ # CHECK-NEXT: i32.const tls1 at TLSREL
# CHECK-NEXT: i32.add
# CHECK-NEXT: i32.store 0
global.get __tls_base
- i32.const tls at TLSREL
+ i32.const tls1 at TLSREL
i32.add
i32.store 0
end_function
+.section .tls.foo,"T",@
+# CHECK: .tls.foo,"T",@
+tls1:
+ .int32 42
+ .size tls1, 4
+
+.section custom_tls,"T",@
+# CHECK: custom_tls,"T",@
+tls2:
+ .int32 43
+ .size tls2, 4
# CHECK-OBJ: - Type: CODE
# CHECK-OBJ-NEXT: Relocations:
@@ -39,5 +50,22 @@ tls_store:
# 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 ]
+# CHECK-OBJ-NEXT: Name: tls1
+# CHECK-OBJ-NEXT: Flags: [ BINDING_LOCAL ]
+# CHECK-OBJ-NEXT: Segment: 0
+# CHECK-OBJ-NEXT: Size: 4
+# CHECK-OBJ-NEXT: - Index: 3
+# CHECK-OBJ-NEXT: Kind: DATA
+# CHECK-OBJ-NEXT: Name: tls2
+# CHECK-OBJ-NEXT: Flags: [ BINDING_LOCAL ]
+# CHECK-OBJ-NEXT: Segment: 1
+# CHECK-OBJ-NEXT: Size: 4
+# CHECK-OBJ-NEXT: SegmentInfo:
+# CHECK-OBJ-NEXT: - Index: 0
+# CHECK-OBJ-NEXT: Name: .tls.foo
+# CHECK-OBJ-NEXT: Alignment: 0
+# CHECK-OBJ-NEXT: Flags: [ TLS ]
+# CHECK-OBJ-NEXT: - Index: 1
+# CHECK-OBJ-NEXT: Name: custom_tls
+# CHECK-OBJ-NEXT: Alignment: 0
+# CHECK-OBJ-NEXT: Flags: [ TLS ]
More information about the llvm-commits
mailing list