llvm.org GIT mirror llvm / 3e96531
Refactor data-in-code annotations. Use a dedicated MachO load command to annotate data-in-code regions. This is the same format the linker produces for final executable images, allowing consistency of representation and use of introspection tools for both object and executable files. Data-in-code regions are annotated via ".data_region"/".end_data_region" directive pairs, with an optional region type. data_region_directive := ".data_region" { region_type } region_type := "jt8" | "jt16" | "jt32" | "jta32" end_data_region_directive := ".end_data_region" The previous handling of ARM-style "$d.*" labels was broken and has been removed. Specifically, it didn't handle ARM vs. Thumb mode when marking the end of the section. rdar://11459456 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157062 91177308-0d34-0410-b5e6-96231b3b80d8 Jim Grosbach 8 years ago
28 changed file(s) with 411 addition(s) and 215 deletion(s). Raw diff Collapse all Expand all
146146 // FIXME: Make this a more general encoding setting?
147147 bool AllowUTF8;
148148
149 /// UseDataRegionDirectives - This is true if data region markers should
150 /// be printed as ".data_region/.end_data_region" directives. If false,
151 /// use "$d/$a" labels instead.
152 bool UseDataRegionDirectives;
153
149154 //===--- Data Emission Directives -------------------------------------===//
150155
151156 /// ZeroDirective - this should be set to the directive used to get some
171176 const char *Data32bitsDirective; // Defaults to "\t.long\t"
172177 const char *Data64bitsDirective; // Defaults to "\t.quad\t"
173178
174 /// [Data|Code]Begin - These magic labels are used to marked a region as
175 /// data or code, and are used to provide additional information for
176 /// correct disassembly on targets that like to mix data and code within
177 /// a segment. These labels will be implicitly suffixed by the streamer
178 /// to give them unique names.
179 const char *DataBegin; // Defaults to "$d."
180 const char *CodeBegin; // Defaults to "$a."
181 const char *JT8Begin; // Defaults to "$a."
182 const char *JT16Begin; // Defaults to "$a."
183 const char *JT32Begin; // Defaults to "$a."
184 bool SupportsDataRegions;
185
186179 /// GPRel64Directive - if non-null, a directive that is used to emit a word
187180 /// which should be relocated as a 64-bit GP-relative offset, e.g. .gpdword
188181 /// on Mips.
383376 const char *getGPRel64Directive() const { return GPRel64Directive; }
384377 const char *getGPRel32Directive() const { return GPRel32Directive; }
385378
386 /// [Code|Data]Begin label name accessors.
387 const char *getCodeBeginLabelName() const { return CodeBegin; }
388 const char *getDataBeginLabelName() const { return DataBegin; }
389 const char *getJumpTable8BeginLabelName() const { return JT8Begin; }
390 const char *getJumpTable16BeginLabelName() const { return JT16Begin; }
391 const char *getJumpTable32BeginLabelName() const { return JT32Begin; }
392 bool getSupportsDataRegions() const { return SupportsDataRegions; }
393
394379 /// getNonexecutableStackSection - Targets can implement this method to
395380 /// specify a section to switch to if the translation unit doesn't have any
396381 /// trampolines that require an executable stack.
487472 bool doesAllowUTF8() const {
488473 return AllowUTF8;
489474 }
475 bool doesSupportDataRegionDirectives() const {
476 return UseDataRegionDirectives;
477 }
490478 const char *getZeroDirective() const {
491479 return ZeroDirective;
492480 }
650650 MCSectionData *SectionData;
651651 };
652652
653 // FIXME: Ditto this. Purely so the Streamer and the ObjectWriter can talk
654 // to one another.
655 struct DataRegionData {
656 // This enum should be kept in sync w/ the mach-o definition in
657 // llvm/Object/MachOFormat.h.
658 enum KindTy { Data = 1, JumpTable8, JumpTable16, JumpTable32 } Kind;
659 MCSymbol *Start;
660 MCSymbol *End;
661 };
662
653663 class MCAssembler {
654664 friend class MCAsmLayout;
655665
666676 typedef std::vector::const_iterator
667677 const_indirect_symbol_iterator;
668678 typedef std::vector::iterator indirect_symbol_iterator;
679
680 typedef std::vector::const_iterator
681 const_data_region_iterator;
682 typedef std::vector::iterator data_region_iterator;
669683
670684 private:
671685 MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
697711
698712 std::vector IndirectSymbols;
699713
714 std::vector DataRegions;
700715 /// The set of function symbols for which a .thumb_func directive has
701716 /// been seen.
702717 //
883898 size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
884899
885900 /// @}
901 /// @name Data Region List Access
902 /// @{
903
904 // FIXME: This is a total hack, this should not be here. Once things are
905 // factored so that the streamer has direct access to the .o writer, it can
906 // disappear.
907 std::vector &getDataRegions() {
908 return DataRegions;
909 }
910
911 data_region_iterator data_region_begin() {
912 return DataRegions.begin();
913 }
914 const_data_region_iterator data_region_begin() const {
915 return DataRegions.begin();
916 }
917
918 data_region_iterator data_region_end() {
919 return DataRegions.end();
920 }
921 const_data_region_iterator data_region_end() const {
922 return DataRegions.end();
923 }
924
925 size_t data_region_size() const { return DataRegions.size(); }
926
927 /// @}
886928 /// @name Backend Data Access
887929 /// @{
888930
159159 /// CreateTempSymbol - Create and return a new assembler temporary symbol
160160 /// with a unique but unspecified name.
161161 MCSymbol *CreateTempSymbol();
162
163 /// getUniqueSymbolID() - Return a unique identifier for use in constructing
164 /// symbol names.
165 unsigned getUniqueSymbolID() { return NextUniqueID++; }
162166
163167 /// CreateDirectionalLocalSymbol - Create the definition of a directional
164168 /// local symbol for numbered label (used for "1:" definitions).
5151 MCAF_Code64 ///< .code64 (X86)
5252 };
5353
54 enum MCDataRegionType {
55 MCDR_DataRegion, ///< .data_region
56 MCDR_DataRegionJT8, ///< .data_region jt8
57 MCDR_DataRegionJT16, ///< .data_region jt16
58 MCDR_DataRegionJT32, ///< .data_region jt32
59 MCDR_DataRegionEnd ///< .end_data_region
60 };
61
5462 } // end namespace llvm
5563
5664 #endif
177177 uint32_t NumIndirectSymbols);
178178
179179 void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout);
180
181 void WriteLinkeditLoadCommand(uint32_t Type, uint32_t DataOffset,
182 uint32_t DataSize);
180183
181184 // FIXME: We really need to improve the relocation validation. Basically, we
182185 // want to implement a separate computation which evaluates the relocation
6868 SmallVector
6969 const MCSection *>, 4> SectionStack;
7070
71 unsigned UniqueCodeBeginSuffix;
72 unsigned UniqueDataBeginSuffix;
73
7471 protected:
75 /// Indicator of whether the previous data-or-code indicator was for
76 /// code or not. Used to determine when we need to emit a new indicator.
77 enum DataType {
78 Data,
79 Code,
80 JumpTable8,
81 JumpTable16,
82 JumpTable32
83 };
84 DataType RegionIndicator;
85
86
8772 MCStreamer(MCContext &Ctx);
8873
8974 const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A,
240225 /// used in an assignment.
241226 virtual void EmitLabel(MCSymbol *Symbol);
242227
243 /// EmitDataRegion - Emit a label that marks the beginning of a data
244 /// region.
245 /// On ELF targets, this corresponds to an assembler statement such as:
246 /// $d.1:
247 virtual void EmitDataRegion();
248
249 /// EmitJumpTable8Region - Emit a label that marks the beginning of a
250 /// jump table composed of 8-bit offsets.
251 /// On ELF targets, this corresponds to an assembler statement such as:
252 /// $d.1:
253 virtual void EmitJumpTable8Region();
254
255 /// EmitJumpTable16Region - Emit a label that marks the beginning of a
256 /// jump table composed of 16-bit offsets.
257 /// On ELF targets, this corresponds to an assembler statement such as:
258 /// $d.1:
259 virtual void EmitJumpTable16Region();
260
261 /// EmitJumpTable32Region - Emit a label that marks the beginning of a
262 /// jump table composed of 32-bit offsets.
263 /// On ELF targets, this corresponds to an assembler statement such as:
264 /// $d.1:
265 virtual void EmitJumpTable32Region();
266
267 /// EmitCodeRegion - Emit a label that marks the beginning of a code
268 /// region.
269 /// On ELF targets, this corresponds to an assembler statement such as:
270 /// $a.1:
271 virtual void EmitCodeRegion();
272
273 /// ForceCodeRegion - Forcibly sets the current region mode to code. Used
274 /// at function entry points.
275 void ForceCodeRegion() { RegionIndicator = Code; }
276
277
278228 virtual void EmitEHSymAttributes(const MCSymbol *Symbol,
279229 MCSymbol *EHSymbol);
280230
281 /// EmitAssemblerFlag - Note in the output the specified @p Flag
231 /// EmitAssemblerFlag - Note in the output the specified @p Flag.
282232 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) = 0;
233
234 /// EmitDataRegion - Note in the output the specified region @p Kind.
235 virtual void EmitDataRegion(MCDataRegionType Kind) {}
283236
284237 /// EmitThumbFunc - Note in the output that the specified @p Func is
285238 /// a Thumb mode function (ARM target only).
9696 DysymtabLoadCommandSize = 80,
9797 Nlist32Size = 12,
9898 Nlist64Size = 16,
99 RelocationInfoSize = 8
99 RelocationInfoSize = 8,
100 LinkeditLoadCommandSize = 16
100101 };
101102
102103 /// \brief Constants for header magic field.
139140 LCT_UUID = 0x1b,
140141 LCT_CodeSignature = 0x1d,
141142 LCT_SegmentSplitInfo = 0x1e,
142 LCT_FunctionStarts = 0x26
143 LCT_FunctionStarts = 0x26,
144 LCT_DataInCode = 0x29
143145 };
144146
145147 /// \brief Load command structure.
276278 uint8_t SectionIndex;
277279 uint16_t Flags;
278280 uint64_t Value;
281 };
282
283 /// @}
284 /// @name Data-in-code Table Entry
285 /// @{
286
287 // See .
288 enum DataRegionType { Data = 1, JumpTable8, JumpTable16, JumpTable32 };
289 struct DataInCodeTableEntry {
290 uint32_t Offset; /* from mach_header to start of data region */
291 uint16_t Length; /* number of bytes in data region */
292 uint16_t Kind; /* a DataRegionType value */
279293 };
280294
281295 /// @}
173173 void ReadSymbol64TableEntry(
174174 uint64_t SymbolTableOffset, unsigned Index,
175175 InMemoryStruct &Res) const;
176 void ReadDataInCodeTableEntry(
177 uint64_t TableOffset, unsigned Index,
178 InMemoryStruct &Res) const;
176179 void ReadULEB128s(uint64_t Index, SmallVectorImpl &Out) const;
177180
178181 /// @}
474474 void AsmPrinter::EmitFunctionEntryLabel() {
475475 // The function label could have already been emitted if two symbols end up
476476 // conflicting due to asm renaming. Detect this and emit an error.
477 if (CurrentFnSym->isUndefined()) {
478 OutStreamer.ForceCodeRegion();
477 if (CurrentFnSym->isUndefined())
479478 return OutStreamer.EmitLabel(CurrentFnSym);
480 }
481479
482480 report_fatal_error("'" + Twine(CurrentFnSym->getName()) +
483481 "' label emitted multiple times to assembly file");
10831081 }
10841082
10851083 EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getTargetData())));
1086
1087 // If we know the form of the jump table, go ahead and tag it as such.
1088 if (!JTInDiffSection) {
1089 if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32) {
1090 OutStreamer.EmitJumpTable32Region();
1091 } else {
1092 OutStreamer.EmitDataRegion();
1093 }
1094 }
10951084
10961085 for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
10971086 const std::vector &JTBBs = JT[JTI].MBBs;
4949 AllowNameToStartWithDigit = false;
5050 AllowPeriodsInName = true;
5151 AllowUTF8 = true;
52 UseDataRegionDirectives = false;
5253 ZeroDirective = "\t.zero\t";
5354 AsciiDirective = "\t.ascii\t";
5455 AscizDirective = "\t.asciz\t";
5657 Data16bitsDirective = "\t.short\t";
5758 Data32bitsDirective = "\t.long\t";
5859 Data64bitsDirective = "\t.quad\t";
59 DataBegin = "$d.";
60 CodeBegin = "$a.";
61 JT8Begin = "$d.";
62 JT16Begin = "$d.";
63 JT32Begin = "$d.";
64 SupportsDataRegions = false;
6560 SunStyleELFSectionSwitchSyntax = false;
6661 UsesELFSectionDirectiveForBSS = false;
6762 AlignDirective = "\t.align\t";
3535 SupportsDebugInformation = true;
3636 DwarfSectionOffsetDirective = "\t.secrel32\t";
3737 HasMicrosoftFastStdCallMangling = true;
38
39 SupportsDataRegions = false;
4038 }
4139
4240 void MCAsmInfoMicrosoft::anchor() { }
4242 HasMachoTBSSDirective = true; // Uses .tbss
4343 HasStaticCtorDtorReferenceInStaticMode = true;
4444
45 CodeBegin = "L$start$code$";
46 DataBegin = "L$start$data$";
47 JT8Begin = "L$start$jt8$";
48 JT16Begin = "L$start$jt16$";
49 JT32Begin = "L$start$jt32$";
50 SupportsDataRegions = true;
51
5245 // FIXME: Darwin 10 and newer don't need this.
5346 LinkerRequiresNonEmptyDwarfLines = true;
5447
137137 virtual void EmitEHSymAttributes(const MCSymbol *Symbol,
138138 MCSymbol *EHSymbol);
139139 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
140 virtual void EmitDataRegion(MCDataRegionType Kind);
140141 virtual void EmitThumbFunc(MCSymbol *Func);
141142
142143 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
347348 case MCAF_Code16: OS << '\t'<< MAI.getCode16Directive(); break;
348349 case MCAF_Code32: OS << '\t'<< MAI.getCode32Directive(); break;
349350 case MCAF_Code64: OS << '\t'<< MAI.getCode64Directive(); break;
351 }
352 EmitEOL();
353 }
354
355 void MCAsmStreamer::EmitDataRegion(MCDataRegionType Kind) {
356 MCContext &Ctx = getContext();
357 const MCAsmInfo &MAI = Ctx.getAsmInfo();
358 if (!MAI.doesSupportDataRegionDirectives())
359 return;
360 switch (Kind) {
361 case MCDR_DataRegion: OS << "\t.data_region"; break;
362 case MCDR_DataRegionJT8: OS << "\t.data_region jt8"; break;
363 case MCDR_DataRegionJT16: OS << "\t.data_region jt16"; break;
364 case MCDR_DataRegionJT32: OS << "\t.data_region jt32"; break;
365 case MCDR_DataRegionEnd: OS << "\t.end_data_region"; break;
350366 }
351367 EmitEOL();
352368 }
1212
1313 #include "MCELF.h"
1414 #include "llvm/ADT/SmallPtrSet.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include "llvm/ADT/Twine.h"
1517 #include "llvm/MC/MCAssembler.h"
1618 #include "llvm/MC/MCCodeEmitter.h"
1719 #include "llvm/MC/MCContext.h"
None //===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===//
1 //
21 // The LLVM Compiler Infrastructure
32 //
3231 private:
3332 virtual void EmitInstToData(const MCInst &Inst);
3433
34 void EmitDataRegion(DataRegionData::KindTy Kind);
35 void EmitDataRegionEnd();
3536 public:
3637 MCMachOStreamer(MCContext &Context, MCAsmBackend &MAB,
3738 raw_ostream &OS, MCCodeEmitter *Emitter)
4546 virtual void EmitEHSymAttributes(const MCSymbol *Symbol,
4647 MCSymbol *EHSymbol);
4748 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag);
49 virtual void EmitDataRegion(MCDataRegionType Kind);
4850 virtual void EmitThumbFunc(MCSymbol *Func);
4951 virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value);
5052 virtual void EmitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute);
135137 // FIXME: Cleanup this code, these bits should be emitted based on semantic
136138 // properties, not on the order of definition, etc.
137139 SD.setFlags(SD.getFlags() & ~SF_ReferenceTypeMask);
140 }
141
142 void MCMachOStreamer::EmitDataRegion(DataRegionData::KindTy Kind) {
143 // Create a temporary label to mark the start of the data region.
144 MCSymbol *Start = getContext().CreateTempSymbol();
145 EmitLabel(Start);
146 // Record the region for the object writer to use.
147 DataRegionData Data = { Kind, Start, NULL };
148 std::vector &Regions = getAssembler().getDataRegions();
149 Regions.push_back(Data);
150 }
151
152 void MCMachOStreamer::EmitDataRegionEnd() {
153 std::vector &Regions = getAssembler().getDataRegions();
154 assert(Regions.size() && "Mismatched .end_data_region!");
155 DataRegionData &Data = Regions.back();
156 assert(Data.End == NULL && "Mismatched .end_data_region!");
157 // Create a temporary label to mark the end of the data region.
158 Data.End = getContext().CreateTempSymbol();
159 EmitLabel(Data.End);
138160 }
139161
140162 void MCMachOStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
148170 case MCAF_Code64: return; // Change parsing mode; no-op here.
149171 case MCAF_SubsectionsViaSymbols:
150172 getAssembler().setSubsectionsViaSymbols(true);
173 return;
174 }
175 }
176
177 void MCMachOStreamer::EmitDataRegion(MCDataRegionType Kind) {
178 switch (Kind) {
179 case MCDR_DataRegion:
180 EmitDataRegion(DataRegionData::Data);
181 return;
182 case MCDR_DataRegionJT8:
183 EmitDataRegion(DataRegionData::JumpTable8);
184 return;
185 case MCDR_DataRegionJT16:
186 EmitDataRegion(DataRegionData::JumpTable16);
187 return;
188 case MCDR_DataRegionJT32:
189 EmitDataRegion(DataRegionData::JumpTable32);
190 return;
191 case MCDR_DataRegionEnd:
192 EmitDataRegionEnd();
151193 return;
152194 }
153195 }
1313 #include "llvm/MC/MCSymbol.h"
1414 #include "llvm/MC/MCParser/MCAsmLexer.h"
1515 #include "llvm/MC/MCParser/MCAsmParser.h"
16 #include "llvm/ADT/StringSwitch.h"
1617 #include "llvm/ADT/StringRef.h"
1718 #include "llvm/ADT/Twine.h"
1819 #include "llvm/Support/MemoryBuffer.h"
5455 ".secure_log_reset");
5556 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveTBSS>(".tbss");
5657 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveZerofill>(".zerofill");
58
59 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegion>(".data_region");
60 AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDataRegionEnd>(".end_data_region");
5761
5862 // Special section directives.
5963 AddDirectiveHandler<&DarwinAsmParser::ParseSectionDirectiveConst>(".const");
112116 bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc);
113117 bool ParseDirectiveTBSS(StringRef, SMLoc);
114118 bool ParseDirectiveZerofill(StringRef, SMLoc);
119 bool ParseDirectiveDataRegion(StringRef, SMLoc);
120 bool ParseDirectiveDataRegionEnd(StringRef, SMLoc);
115121
116122 // Named Section Directive
117123 bool ParseSectionDirectiveConst(StringRef, SMLoc) {
658664 return false;
659665 }
660666
667 /// ParseDirectiveDataRegion
668 /// ::= .data_region [ ( jt8 | jt16 | jt32 ) ]
669 bool DarwinAsmParser::ParseDirectiveDataRegion(StringRef, SMLoc) {
670 if (getLexer().is(AsmToken::EndOfStatement)) {
671 Lex();
672 getStreamer().EmitDataRegion(MCDR_DataRegion);
673 return false;
674 }
675 StringRef RegionType;
676 SMLoc Loc = getParser().getTok().getLoc();
677 if (getParser().ParseIdentifier(RegionType))
678 return TokError("expected region type after '.data_region' directive");
679 int Kind = StringSwitch(RegionType)
680 .Case("jt8", MCDR_DataRegionJT8)
681 .Case("jt16", MCDR_DataRegionJT16)
682 .Case("jt32", MCDR_DataRegionJT32)
683 .Default(-1);
684 if (Kind == -1)
685 return Error(Loc, "unknown region type in '.data_region' directive");
686 Lex();
687
688 getStreamer().EmitDataRegion((MCDataRegionType)Kind);
689 return false;
690 }
691
692 /// ParseDirectiveDataRegionEnd
693 /// ::= .end_data_region
694 bool DarwinAsmParser::ParseDirectiveDataRegionEnd(StringRef, SMLoc) {
695 if (getLexer().isNot(AsmToken::EndOfStatement))
696 return TokError("unexpected token in '.end_data_region' directive");
697
698 Lex();
699 getStreamer().EmitDataRegion(MCDR_DataRegionEnd);
700 return false;
701 }
702
661703 namespace llvm {
662704
663705 MCAsmParserExtension *createDarwinAsmParser() {
1919 #include
2020 using namespace llvm;
2121
22 MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true),
23 EmitDebugFrame(false),
24 CurrentW64UnwindInfo(0),
25 LastSymbol(0),
26 UniqueCodeBeginSuffix(0),
27 UniqueDataBeginSuffix(0) {
22 MCStreamer::MCStreamer(MCContext &Ctx)
23 : Context(Ctx), EmitEHFrame(true), EmitDebugFrame(false),
24 CurrentW64UnwindInfo(0), LastSymbol(0) {
2825 const MCSection *section = NULL;
2926 SectionStack.push_back(std::make_pair(section, section));
3027 }
182179 LastSymbol = Symbol;
183180 }
184181
185 void MCStreamer::EmitDataRegion() {
186 if (RegionIndicator == Data) return;
187
188 MCContext &Context = getContext();
189 const MCAsmInfo &MAI = Context.getAsmInfo();
190 if (!MAI.getSupportsDataRegions()) return;
191
192 // Generate a unique symbol name.
193 MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getDataBeginLabelName() +
194 Twine(UniqueDataBeginSuffix++));
195 EmitLabel(NewSym);
196
197 RegionIndicator = Data;
198 }
199
200 void MCStreamer::EmitCodeRegion() {
201 if (RegionIndicator == Code) return;
202
203 MCContext &Context = getContext();
204 const MCAsmInfo &MAI = Context.getAsmInfo();
205 if (!MAI.getSupportsDataRegions()) return;
206
207 // Generate a unique symbol name.
208 MCSymbol *NewSym = Context.GetOrCreateSymbol(MAI.getCodeBeginLabelName() +
209 Twine(UniqueCodeBeginSuffix++));
210 EmitLabel(NewSym);
211
212 RegionIndicator = Code;
213 }
214
215 void MCStreamer::EmitJumpTable8Region() {
216 if (RegionIndicator == JumpTable8) return;
217
218 MCContext &Context = getContext();
219 const MCAsmInfo &MAI = Context.getAsmInfo();
220 if (!MAI.getSupportsDataRegions()) return;
221
222 // Generate a unique symbol name.
223 MCSymbol *NewSym =
224 Context.GetOrCreateSymbol(MAI.getJumpTable8BeginLabelName() +
225 Twine(UniqueDataBeginSuffix++));
226 EmitLabel(NewSym);
227
228 RegionIndicator = JumpTable8;
229 }
230
231 void MCStreamer::EmitJumpTable16Region() {
232 if (RegionIndicator == JumpTable16) return;
233
234 MCContext &Context = getContext();
235 const MCAsmInfo &MAI = Context.getAsmInfo();
236 if (!MAI.getSupportsDataRegions()) return;
237
238 // Generate a unique symbol name.
239 MCSymbol *NewSym =
240 Context.GetOrCreateSymbol(MAI.getJumpTable16BeginLabelName() +
241 Twine(UniqueDataBeginSuffix++));
242 EmitLabel(NewSym);
243
244 RegionIndicator = JumpTable16;
245 }
246
247
248 void MCStreamer::EmitJumpTable32Region() {
249 if (RegionIndicator == JumpTable32) return;
250
251 MCContext &Context = getContext();
252 const MCAsmInfo &MAI = Context.getAsmInfo();
253 if (!MAI.getSupportsDataRegions()) return;
254
255 // Generate a unique symbol name.
256 MCSymbol *NewSym =
257 Context.GetOrCreateSymbol(MAI.getJumpTable32BeginLabelName() +
258 Twine(UniqueDataBeginSuffix++));
259 EmitLabel(NewSym);
260
261 RegionIndicator = JumpTable32;
262 }
263
264182 void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) {
265183 EnsureValidFrame();
266184 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo();
282200 EmitCFIStartProcImpl(Frame);
283201
284202 FrameInfos.push_back(Frame);
285 RegionIndicator = Code;
286203 }
287204
288205 void MCStreamer::EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) {
2020 #include "llvm/MC/MCMachOSymbolFlags.h"
2121 #include "llvm/MC/MCValue.h"
2222 #include "llvm/Object/MachOFormat.h"
23 #include "llvm/Support/Debug.h"
2324 #include "llvm/Support/ErrorHandling.h"
2425
2526 #include
350351 Write32(Address);
351352 }
352353
354 void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type,
355 uint32_t DataOffset,
356 uint32_t DataSize) {
357 uint64_t Start = OS.tell();
358 (void) Start;
359
360 Write32(Type);
361 Write32(macho::LinkeditLoadCommandSize);
362 Write32(DataOffset);
363 Write32(DataSize);
364
365 assert(OS.tell() - Start == macho::LinkeditLoadCommandSize);
366 }
367
368
353369 void MachObjectWriter::RecordRelocation(const MCAssembler &Asm,
354370 const MCAsmLayout &Layout,
355371 const MCFragment *Fragment,
653669 macho::DysymtabLoadCommandSize);
654670 }
655671
672 // Add the data-in-code load command size, if used.
673 unsigned NumDataRegions = Asm.getDataRegions().size();
674 if (NumDataRegions) {
675 ++NumLoadCommands;
676 LoadCommandsSize += macho::LinkeditLoadCommandSize;
677 }
678
656679 // Compute the total size of the section data, as well as its file size and vm
657680 // size.
658681 uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
700723 RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
701724 }
702725
726 // Write the data-in-code load command, if used.
727 uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
728 if (NumDataRegions) {
729 uint64_t DataRegionsOffset = RelocTableEnd;
730 uint64_t DataRegionsSize = NumDataRegions * 8;
731 WriteLinkeditLoadCommand(macho::LCT_DataInCode, DataRegionsOffset,
732 DataRegionsSize);
733 }
734
703735 // Write the symbol table load command, if used.
704736 if (NumSymbols) {
705737 unsigned FirstLocalSymbol = 0;
716748
717749 // If used, the indirect symbols are written after the section data.
718750 if (NumIndirectSymbols)
719 IndirectSymbolOffset = RelocTableEnd;
751 IndirectSymbolOffset = DataInCodeTableEnd;
720752
721753 // The symbol table is written after the indirect symbol data.
722 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
754 uint64_t SymbolTableOffset = DataInCodeTableEnd + IndirectSymbolSize;
723755
724756 // The string table is written after symbol table.
725757 uint64_t StringTableOffset =
757789 Write32(Relocs[e - i - 1].Word0);
758790 Write32(Relocs[e - i - 1].Word1);
759791 }
792 }
793
794 // Write out the data-in-code region payload, if there is one.
795 for (MCAssembler::const_data_region_iterator
796 it = Asm.data_region_begin(), ie = Asm.data_region_end();
797 it != ie; ++it) {
798 const DataRegionData *Data = &(*it);
799 uint64_t Start = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->Start), Layout);
800 uint64_t End = getSymbolAddress(&Layout.getAssembler().getSymbolData(*Data->End), Layout);
801 DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
802 << " start: " << Start << "(" << Data->Start->getName() << ")"
803 << " end: " << End << "(" << Data->End->getName() << ")"
804 << " size: " << End - Start
805 << "\n");
806 Write32(Start);
807 Write16(End - Start);
808 Write16(Data->Kind);
760809 }
761810
762811 // Write the symbol table data, if used.
356356 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
357357 }
358358
359 template<>
360 void SwapStruct(macho::DataInCodeTableEntry &Value) {
361 SwapValue(Value.Offset);
362 SwapValue(Value.Length);
363 SwapValue(Value.Kind);
364 }
365 void MachOObject::ReadDataInCodeTableEntry(uint64_t TableOffset,
366 unsigned Index,
367 InMemoryStruct &Res) const {
368 uint64_t Offset = (TableOffset +
369 Index * sizeof(macho::DataInCodeTableEntry));
370 ReadInMemoryStruct(*this, Buffer->getBuffer(), Offset, Res);
371 }
359372
360373 void MachOObject::ReadULEB128s(uint64_t Index,
361374 SmallVectorImpl &Out) const {
282282 }
283283 }
284284
285 void ARMAsmPrinter::EmitFunctionBodyEnd() {
286 // Make sure to terminate any constant pools that were at the end
287 // of the function.
288 if (!InConstantPool)
289 return;
290 InConstantPool = false;
291 OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
292 }
293
285294 void ARMAsmPrinter::EmitFunctionEntryLabel() {
286 OutStreamer.ForceCodeRegion();
287
288295 if (AFI->isThumbFunction()) {
289296 OutStreamer.EmitAssemblerFlag(MCAF_Code16);
290297 OutStreamer.EmitThumbFunc(CurrentFnSym);
933940 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
934941 unsigned JTI = MO1.getIndex();
935942
936 // Tag the jump table appropriately for precise disassembly.
937 OutStreamer.EmitJumpTable32Region();
938
939943 // Emit a label for the jump table.
940944 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
941945 OutStreamer.EmitLabel(JTISymbol);
946
947 // Mark the jump table as data-in-code.
948 OutStreamer.EmitDataRegion(MCDR_DataRegionJT32);
942949
943950 // Emit each entry of the table.
944951 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
968975 OutContext);
969976 OutStreamer.EmitValue(Expr, 4);
970977 }
978 // Mark the end of jump table data-in-code region.
979 OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
971980 }
972981
973982 void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
977986 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
978987 unsigned JTI = MO1.getIndex();
979988
980 // Emit a label for the jump table.
981 if (MI->getOpcode() == ARM::t2TBB_JT) {
982 OutStreamer.EmitJumpTable8Region();
983 } else if (MI->getOpcode() == ARM::t2TBH_JT) {
984 OutStreamer.EmitJumpTable16Region();
985 } else {
986 OutStreamer.EmitJumpTable32Region();
987 }
988
989989 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
990990 OutStreamer.EmitLabel(JTISymbol);
991991
994994 const std::vector &JT = MJTI->getJumpTables();
995995 const std::vector &JTBBs = JT[JTI].MBBs;
996996 unsigned OffsetWidth = 4;
997 if (MI->getOpcode() == ARM::t2TBB_JT)
997 if (MI->getOpcode() == ARM::t2TBB_JT) {
998998 OffsetWidth = 1;
999 else if (MI->getOpcode() == ARM::t2TBH_JT)
999 // Mark the jump table as data-in-code.
1000 OutStreamer.EmitDataRegion(MCDR_DataRegionJT8);
1001 } else if (MI->getOpcode() == ARM::t2TBH_JT) {
10001002 OffsetWidth = 2;
1003 // Mark the jump table as data-in-code.
1004 OutStreamer.EmitDataRegion(MCDR_DataRegionJT16);
1005 }
10011006
10021007 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
10031008 MachineBasicBlock *MBB = JTBBs[i];
10301035 OutContext);
10311036 OutStreamer.EmitValue(Expr, OffsetWidth);
10321037 }
1038 // Mark the end of jump table data-in-code region.
1039 OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
10331040 }
10341041
10351042 void ARMAsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
12071214 #include "ARMGenMCPseudoLowering.inc"
12081215
12091216 void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1210 if (MI->getOpcode() != ARM::CONSTPOOL_ENTRY)
1211 OutStreamer.EmitCodeRegion();
1217 // If we just ended a constant pool, mark it as such.
1218 if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1219 OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
1220 InConstantPool = false;
1221 }
12121222
12131223 // Emit unwinding stuff for frame-related instructions
12141224 if (EnableARMEHABI && MI->getFlag(MachineInstr::FrameSetup))
15641574 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
15651575 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
15661576
1567 // Mark the constant pool entry as data if we're not already in a data
1568 // region.
1569 OutStreamer.EmitDataRegion();
1577 // If this is the first entry of the pool, mark it.
1578 if (!InConstantPool) {
1579 OutStreamer.EmitDataRegion(MCDR_DataRegion);
1580 InConstantPool = true;
1581 }
1582
15701583 OutStreamer.EmitLabel(GetCPISymbol(LabelId));
15711584
15721585 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
4343 /// MachineFunction.
4444 const MachineConstantPool *MCP;
4545
46 /// InConstantPool - Maintain state when emitting a sequence of constant
47 /// pool entries so we can properly mark them as data regions.
48 bool InConstantPool;
4649 public:
4750 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
48 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
51 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL), InConstantPool(false) {
4952 Subtarget = &TM.getSubtarget();
5053 }
5154
6972 bool runOnMachineFunction(MachineFunction &F);
7073
7174 virtual void EmitConstantPool() {} // we emit constant pools customly!
75 virtual void EmitFunctionBodyEnd();
7276 virtual void EmitFunctionEntryLabel();
7377 void EmitStartOfAsmFile(Module &M);
7478 void EmitEndOfAsmFile(Module &M);
2828 CommentString = "@";
2929 Code16Directive = ".code\t16";
3030 Code32Directive = ".code\t32";
31 UseDataRegionDirectives = true;
3132
3233 SupportsDebugInformation = true;
3334
609609 }
610610
611611 void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
612 OutStreamer.EmitCodeRegion();
613
614612 X86MCInstLower MCInstLowering(Mang, *MF, *this);
615613 switch (MI->getOpcode()) {
616614 case TargetOpcode::DBG_VALUE:
0 ; RUN: llc < %s -mtriple=armv7-apple-darwin | FileCheck %s
1
2 define double @f1() nounwind {
3 ; CHECK: f1:
4 ; CHECK: .data_region
5 ; CHECK: .long 1413754129
6 ; CHECK: .long 1074340347
7 ; CHECK: .end_data_region
8 ret double 0x400921FB54442D11
9 }
10
11
12 define i32 @f2() {
13 ; CHECK: f2:
14 ; CHECK: .data_region jt32
15 ; CHECK: .end_data_region
16
17 entry:
18 switch i32 undef, label %return [
19 i32 1, label %sw.bb
20 i32 2, label %sw.bb6
21 i32 3, label %sw.bb13
22 i32 4, label %sw.bb20
23 ]
24
25 sw.bb: ; preds = %entry
26 br label %return
27
28 sw.bb6: ; preds = %entry
29 br label %return
30
31 sw.bb13: ; preds = %entry
32 br label %return
33
34 sw.bb20: ; preds = %entry
35 %div = sdiv i32 undef, undef
36 br label %return
37
38 return: ; preds = %sw.bb20, %sw.bb13, %sw.bb6, %sw.bb, %entry
39 %retval.0 = phi i32 [ %div, %sw.bb20 ], [ undef, %sw.bb13 ], [ undef, %sw.bb6 ], [ undef, %sw.bb ], [ 0, %entry ]
40 ret i32 %retval.0
41 }
44 entry:
55 ; CHECK: bar:
66 ; CHECK: tbb
7 ; CHECK: .align 1
7 ; CHECK: .data_region jt8
8 ; CHECK: .end_data_region
9 ; CHECK-NEXT: .align 1
810
911 switch i32 %n.u, label %bb12 [i32 1, label %bb i32 2, label %bb6 i32 4, label %bb7 i32 5, label %bb8 i32 6, label %bb10 i32 7, label %bb1 i32 8, label %bb3 i32 9, label %bb4 i32 10, label %bb9 i32 11, label %bb2 i32 12, label %bb5 i32 13, label %bb11 ]
1012 bb:
6060 declare void @exit(i32) noreturn nounwind
6161
6262 ;; OBJ: Relocation 1
63 ;; OBJ-NEXT: 'r_offset',
63 ;; OBJ-NEXT: 'r_offset',
6464 ;; OBJ-NEXT: 'r_sym', 0x000002
6565 ;; OBJ-NEXT: 'r_type', 0x2b
6666
0 @ RUN: llvm-mc -triple armv7-apple-darwin10 -filetype=obj -o - < %s | macho-dump | FileCheck %s
1 .text
2 _foo:
3 @ CHECK: # DICE 0
4 @ CHECK: ('offset', 0)
5 @ CHECK: ('length', 4)
6 @ CHECK: ('kind', 1)
7 @ CHECK: # DICE 1
8 @ CHECK: ('offset', 4)
9 @ CHECK: ('length', 4)
10 @ CHECK: ('kind', 4)
11 @ CHECK: # DICE 2
12 @ CHECK: ('offset', 8)
13 @ CHECK: ('length', 2)
14 @ CHECK: ('kind', 3)
15 @ CHECK: # DICE 3
16 @ CHECK: ('offset', 10)
17 @ CHECK: ('length', 1)
18 @ CHECK: ('kind', 2)
19
20 .data_region
21 .long 10
22 .end_data_region
23 .data_region jt32
24 .long 1
25 .end_data_region
26 .data_region jt16
27 .short 2
28 .end_data_region
29 .data_region jt8
30 .byte 3
31 .end_data_region
32
331331 return 0;
332332 }
333333
334 static int DumpDataInCodeDataCommand(MachOObject &Obj,
335 const MachOObject::LoadCommandInfo &LCI) {
336 InMemoryStruct LLC;
337 Obj.ReadLinkeditDataLoadCommand(LCI, LLC);
338 if (!LLC)
339 return Error("unable to read segment load command");
340
341 outs() << " ('dataoff', " << LLC->DataOffset << ")\n"
342 << " ('datasize', " << LLC->DataSize << ")\n"
343 << " ('_data_regions', [\n";
344
345
346 unsigned NumRegions = LLC->DataSize / 8;
347 for (unsigned i = 0; i < NumRegions; ++i) {
348 InMemoryStruct DICE;
349 Obj.ReadDataInCodeTableEntry(LLC->DataOffset, i, DICE);
350 if (!DICE)
351 return Error("unable to read DataInCodeTableEntry");
352 outs() << " # DICE " << i << "\n"
353 << " ('offset', " << DICE->Offset << ")\n"
354 << " ('length', " << DICE->Length << ")\n"
355 << " ('kind', " << DICE->Kind << ")\n";
356 }
357
358 outs() <<" ])\n";
359
360 return 0;
361 }
362
334363
335364 static int DumpLoadCommand(MachOObject &Obj, unsigned Index) {
336365 const MachOObject::LoadCommandInfo &LCI = Obj.getLoadCommandInfo(Index);
357386 case macho::LCT_FunctionStarts:
358387 Res = DumpLinkeditDataCommand(Obj, LCI);
359388 break;
389 case macho::LCT_DataInCode:
390 Res = DumpDataInCodeDataCommand(Obj, LCI);
391 break;
360392 default:
361393 Warning("unknown load command: " + Twine(LCI.Command.Type));
362394 break;