Index: llvm/trunk/include/llvm/MC/MCELFStreamer.h =================================================================== --- llvm/trunk/include/llvm/MC/MCELFStreamer.h +++ llvm/trunk/include/llvm/MC/MCELFStreamer.h @@ -42,6 +42,7 @@ void InitSections(bool NoExecStack) override; void ChangeSection(MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override; Index: llvm/trunk/include/llvm/MC/MCObjectStreamer.h =================================================================== --- llvm/trunk/include/llvm/MC/MCObjectStreamer.h +++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h @@ -90,6 +90,7 @@ /// @{ void EmitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override; + virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F); void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc = SMLoc()) override; Index: llvm/trunk/lib/MC/MCELFStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCELFStreamer.cpp +++ llvm/trunk/lib/MC/MCELFStreamer.cpp @@ -103,6 +103,16 @@ Symbol->setType(ELF::STT_TLS); } +void MCELFStreamer::EmitLabel(MCSymbol *S, SMLoc Loc, MCFragment *F) { + auto *Symbol = cast(S); + MCObjectStreamer::EmitLabel(Symbol, Loc, F); + + const MCSectionELF &Section = + static_cast(*getCurrentSectionOnly()); + if (Section.getFlags() & ELF::SHF_TLS) + Symbol->setType(ELF::STT_TLS); +} + void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { // Let the target do whatever target specific stuff it needs to do. getAssembler().getBackend().handleAssemblerFlag(Flag); Index: llvm/trunk/lib/MC/MCObjectStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCObjectStreamer.cpp +++ llvm/trunk/lib/MC/MCObjectStreamer.cpp @@ -171,6 +171,16 @@ } } +void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) { + MCStreamer::EmitLabel(Symbol, Loc); + getAssembler().registerSymbol(*Symbol); + auto *DF = dyn_cast_or_null(F); + if (DF) + Symbol->setFragment(F); + else + PendingLabels.push_back(Symbol); +} + void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { int64_t IntValue; if (Value->evaluateAsAbsolute(IntValue, getAssembler())) { @@ -491,8 +501,8 @@ MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_GPRel_4)); + DF->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 4, 0); } @@ -501,8 +511,8 @@ MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - DF->getFixups().push_back(MCFixup::create(DF->getContents().size(), - Value, FK_GPRel_4)); + DF->getFixups().push_back( + MCFixup::create(DF->getContents().size(), Value, FK_GPRel_4)); DF->getContents().resize(DF->getContents().size() + 8, 0); } Index: llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp +++ llvm/trunk/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp @@ -464,13 +464,14 @@ void emitUnwindRaw(int64_t Offset, const SmallVectorImpl &Opcodes); void ChangeSection(MCSection *Section, const MCExpr *Subsection) override { - // We have to keep track of the mapping symbol state of any sections we - // use. Each one should start off as EMS_None, which is provided as the - // default constructor by DenseMap::lookup. - LastMappingSymbols[getPreviousSection().first] = LastEMS; - LastEMS = LastMappingSymbols.lookup(Section); - + LastMappingSymbols[getPreviousSection().first] = std::move(LastEMSInfo); MCELFStreamer::ChangeSection(Section, Subsection); + auto LastMappingSymbol = LastMappingSymbols.find(Section); + if (LastMappingSymbol != LastMappingSymbols.end()) { + LastEMSInfo = std::move(LastMappingSymbol->second); + return; + } + LastEMSInfo.reset(new ElfMappingSymbolInfo(SMLoc(), nullptr, 0)); } /// This function is the one used to emit instruction data into the ELF @@ -532,15 +533,25 @@ MCELFStreamer::EmitBytes(Data); } + void FlushPendingMappingSymbol() { + if (!LastEMSInfo->hasInfo()) + return; + ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); + EmitMappingSymbol("$d", EMS->Loc, EMS->F, EMS->Offset); + EMS->resetInfo(); + } + /// This is one of the functions used to emit data into an ELF section, so the /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if /// necessary. void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { - if (const MCSymbolRefExpr *SRE = dyn_cast_or_null(Value)) + if (const MCSymbolRefExpr *SRE = dyn_cast_or_null(Value)) { if (SRE->getKind() == MCSymbolRefExpr::VK_ARM_SBREL && !(Size == 4)) { getContext().reportError(Loc, "relocated expression must be 32-bit"); return; } + getOrCreateDataFragment(); + } EmitDataMappingSymbol(); MCELFStreamer::EmitValueImpl(Value, Size, Loc); @@ -573,22 +584,54 @@ EMS_Data }; + struct ElfMappingSymbolInfo { + explicit ElfMappingSymbolInfo(SMLoc Loc, MCFragment *F, uint64_t O) + : Loc(Loc), F(F), Offset(O), State(EMS_None) {} + void resetInfo() { + F = nullptr; + Offset = 0; + } + bool hasInfo() { return F != nullptr; } + SMLoc Loc; + MCFragment *F; + uint64_t Offset; + ElfMappingSymbol State; + }; + void EmitDataMappingSymbol() { - if (LastEMS == EMS_Data) return; + if (LastEMSInfo->State == EMS_Data) + return; + else if (LastEMSInfo->State == EMS_None) { + // This is a tentative symbol, it won't really be emitted until it's + // actually needed. + ElfMappingSymbolInfo *EMS = LastEMSInfo.get(); + auto *DF = dyn_cast_or_null(getCurrentFragment()); + if (!DF) + return; + EMS->Loc = SMLoc(); + EMS->F = getCurrentFragment(); + EMS->Offset = DF->getContents().size(); + LastEMSInfo->State = EMS_Data; + return; + } EmitMappingSymbol("$d"); - LastEMS = EMS_Data; + LastEMSInfo->State = EMS_Data; } void EmitThumbMappingSymbol() { - if (LastEMS == EMS_Thumb) return; + if (LastEMSInfo->State == EMS_Thumb) + return; + FlushPendingMappingSymbol(); EmitMappingSymbol("$t"); - LastEMS = EMS_Thumb; + LastEMSInfo->State = EMS_Thumb; } void EmitARMMappingSymbol() { - if (LastEMS == EMS_ARM) return; + if (LastEMSInfo->State == EMS_ARM) + return; + FlushPendingMappingSymbol(); EmitMappingSymbol("$a"); - LastEMS = EMS_ARM; + LastEMSInfo->State = EMS_ARM; } void EmitMappingSymbol(StringRef Name) { @@ -601,6 +644,17 @@ Symbol->setExternal(false); } + void EmitMappingSymbol(StringRef Name, SMLoc Loc, MCFragment *F, + uint64_t Offset) { + auto *Symbol = cast(getContext().getOrCreateSymbol( + Name + "." + Twine(MappingSymbolCounter++))); + EmitLabel(Symbol, Loc, F); + Symbol->setType(ELF::STT_NOTYPE); + Symbol->setBinding(ELF::STB_LOCAL); + Symbol->setExternal(false); + Symbol->setOffset(Offset); + } + void EmitThumbFunc(MCSymbol *Func) override { getAssembler().setIsThumbFunc(Func); EmitSymbolAttribute(Func, MCSA_ELF_TypeFunction); @@ -626,8 +680,10 @@ bool IsThumb; int64_t MappingSymbolCounter = 0; - DenseMap LastMappingSymbols; - ElfMappingSymbol LastEMS = EMS_None; + DenseMap> + LastMappingSymbols; + + std::unique_ptr LastEMSInfo; // ARM Exception Handling Frame Information MCSymbol *ExTab; Index: llvm/trunk/test/MC/ARM/Inputs/1.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/1.s +++ llvm/trunk/test/MC/ARM/Inputs/1.s @@ -0,0 +1,3 @@ + .section .foobar,"ax",%progbits + nop + .word 32 Index: llvm/trunk/test/MC/ARM/Inputs/2.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/2.s +++ llvm/trunk/test/MC/ARM/Inputs/2.s @@ -0,0 +1,3 @@ + .section .foobar,"",%progbits + nop + .word 32 Index: llvm/trunk/test/MC/ARM/Inputs/3.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/3.s +++ llvm/trunk/test/MC/ARM/Inputs/3.s @@ -0,0 +1,3 @@ + .section .foobar,"aw",%progbits + nop + .word 32 Index: llvm/trunk/test/MC/ARM/Inputs/4.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/4.s +++ llvm/trunk/test/MC/ARM/Inputs/4.s @@ -0,0 +1,2 @@ + .section .foobar,"",%progbits + .word 32 Index: llvm/trunk/test/MC/ARM/Inputs/5.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/5.s +++ llvm/trunk/test/MC/ARM/Inputs/5.s @@ -0,0 +1,2 @@ + .section .foobar,"aw",%progbits + .word 32 Index: llvm/trunk/test/MC/ARM/Inputs/6.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/6.s +++ llvm/trunk/test/MC/ARM/Inputs/6.s @@ -0,0 +1,12 @@ + .section .foo + .word 30 + .word 31 + .word 32 + .word 33 + nop + .word 34 + .word 35 + .word 36 + .word 37 + .word 38 + nop Index: llvm/trunk/test/MC/ARM/Inputs/7.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/7.s +++ llvm/trunk/test/MC/ARM/Inputs/7.s @@ -0,0 +1,3 @@ + .section .foobar,"aw",%progbits + .word 32 + nop Index: llvm/trunk/test/MC/ARM/Inputs/attr.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/attr.s +++ llvm/trunk/test/MC/ARM/Inputs/attr.s @@ -0,0 +1,5 @@ + .text + .syntax unified + .eabi_attribute 67, "2.09" @ Tag_conformance + .cpu arm7tdmi + .eabi_attribute 6, 2 @ Tag_CPU_arch Index: llvm/trunk/test/MC/ARM/Inputs/ident.s =================================================================== --- llvm/trunk/test/MC/ARM/Inputs/ident.s +++ llvm/trunk/test/MC/ARM/Inputs/ident.s @@ -0,0 +1 @@ + .ident "LLVM ARM Compiler" Index: llvm/trunk/test/MC/ARM/data-in-code.ll =================================================================== --- llvm/trunk/test/MC/ARM/data-in-code.ll +++ llvm/trunk/test/MC/ARM/data-in-code.ll @@ -60,23 +60,6 @@ ;; ARM-NEXT: Other: ;; ARM-NEXT: Section: [[MIXED_SECT]] -;; ARM: Symbol { -;; ARM: Name: $d -;; ARM-NEXT: Value: 0x0 -;; ARM-NEXT: Size: 0 -;; ARM-NEXT: Binding: Local (0x0) -;; ARM-NEXT: Type: None (0x0) -;; ARM-NEXT: Other: 0 -;; ARM-NEXT: Section: .ARM.exidx -;; ARM-NEXT: } - -;; ARM: Symbol { -;; ARM: Name: $d -;; ARM-NEXT: Value: 0 -;; ARM-NEXT: Size: 0 -;; ARM-NEXT: Binding: Local -;; ARM-NEXT: Type: None - ;; ARM-NOT: ${{[atd]}} ;; TMB: Symbol { Index: llvm/trunk/test/MC/ARM/mappingsymbols.s =================================================================== --- llvm/trunk/test/MC/ARM/mappingsymbols.s +++ llvm/trunk/test/MC/ARM/mappingsymbols.s @@ -0,0 +1,48 @@ +# Check section containing code and data with permission executable for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/1.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +# Check section containing code and data with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/2.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +# Check section containing code and data with read/write permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/3.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +# Check section containing data with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/4.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing only data with read/write permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/5.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing the ident string with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/ident.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing the attributes with no permissions for the section. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/attr.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MAPPINGSYMBOLS + +# Check section containing code and data with no permissions for the section. +# data comes before code. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/6.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s -check-prefix=MIX + +# Check section containing code and data with no permissions for the section. +# data comes before code. +@ RUN: llvm-mc -triple armv7-none-linux -filetype=obj -o %t.o %p/Inputs/7.s +@ RUN: llvm-readobj -elf-output-style=GNU -symbols %t.o | FileCheck %s + +#CHECK: $a +#CHECK: $d + +#MIX: $a +#MIX: $a +#MIX: $d +#MIX: $d + +#MAPPINGSYMBOLS-NOT: $a +#MAPPINGSYMBOLS-NOT: $d Index: llvm/trunk/test/MC/ARM/multi-section-mapping.s =================================================================== --- llvm/trunk/test/MC/ARM/multi-section-mapping.s +++ llvm/trunk/test/MC/ARM/multi-section-mapping.s @@ -29,7 +29,6 @@ @ CHECK: 00000000 .text 00000000 $a @ CHECK-NEXT: 00000000 .wibble 00000000 $a -@ CHECK-NEXT: 00000000 .starts_data 00000000 $d @ CHECK-NEXT: 00000000 .starts_thumb 00000000 $t @ CHECK-NOT: ${{[adt]}} Index: llvm/trunk/test/Object/ARM/nm-mapping-symbol.s =================================================================== --- llvm/trunk/test/Object/ARM/nm-mapping-symbol.s +++ llvm/trunk/test/Object/ARM/nm-mapping-symbol.s @@ -9,3 +9,4 @@ .section .foobar,"",%progbits .asciz "foo" + nop