llvm.org GIT mirror llvm / 6816d66
[mips] Add MipsOptionRecord abstraction and use it to implement .reginfo/.MIPS.options This abstraction allows us to support the various records that can be placed in the .MIPS.options section in the future. We currently use it to record register usage information (the ODK_REGINFO record in our ELF64 spec). Each .MIPS.options record should subclass MipsOptionRecord and provide an implementation of EmitMipsOptionRecord. Patch by Matheus Almeida and Toma Tabacu git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213522 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 6 years ago
10 changed file(s) with 320 addition(s) and 46 deletion(s). Raw diff Collapse all Expand all
77 MipsMCExpr.cpp
88 MipsMCTargetDesc.cpp
99 MipsNaClELFStreamer.cpp
10 MipsOptionRecord.cpp
1011 MipsTargetStreamer.cpp
1112 )
77 //===----------------------------------------------------------------------===//
88
99 #include "MipsELFStreamer.h"
10 #include "llvm/MC/MCInst.h"
11
12 void MipsELFStreamer::EmitInstruction(const MCInst &Inst,
13 const MCSubtargetInfo &STI) {
14 MCELFStreamer::EmitInstruction(Inst, STI);
15
16 MCContext &Context = getContext();
17 const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo();
18
19 for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) {
20 const MCOperand &Op = Inst.getOperand(OpIndex);
21
22 if (!Op.isReg())
23 continue;
24
25 unsigned Reg = Op.getReg();
26 RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo);
27 }
28 }
29
30 void MipsELFStreamer::EmitMipsOptionRecords() {
31 for (const auto &I : MipsOptionRecords)
32 I->EmitMipsOptionRecord();
33 }
1034
1135 namespace llvm {
1236 MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB,
1414 #ifndef MIPSELFSTREAMER_H
1515 #define MIPSELFSTREAMER_H
1616
17 #include "MipsOptionRecord.h"
18 #include "llvm/ADT/SmallVector.h"
1719 #include "llvm/MC/MCELFStreamer.h"
18 #include "llvm/Support/raw_ostream.h"
20 #include
1921
2022 namespace llvm {
2123 class MCAsmBackend;
2426 class MCSubtargetInfo;
2527
2628 class MipsELFStreamer : public MCELFStreamer {
29 SmallVector, 8> MipsOptionRecords;
30 MipsRegInfoRecord *RegInfoRecord;
2731
2832 public:
2933 MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS,
3034 MCCodeEmitter *Emitter, const MCSubtargetInfo &STI)
31 : MCELFStreamer(Context, MAB, OS, Emitter) {}
35 : MCELFStreamer(Context, MAB, OS, Emitter) {
3236
33 virtual ~MipsELFStreamer() {}
37 RegInfoRecord = new MipsRegInfoRecord(this, Context, STI);
38 MipsOptionRecords.push_back(
39 std::unique_ptr(RegInfoRecord));
40 }
41
42 /// Overriding this function allows us to add arbitrary behaviour before the
43 /// \p Inst is actually emitted. For example, we can inspect the operands and
44 /// gather sufficient information that allows us to reason about the register
45 /// usage for the translation unit.
46 void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override;
47
48 /// Emits all the option records stored up until the point it's called.
49 void EmitMipsOptionRecords();
3450 };
3551
3652 MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB,
0 //===-- MipsOptionRecord.cpp - Abstraction for storing information --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "MipsOptionRecord.h"
10 #include "MipsELFStreamer.h"
11 #include "llvm/MC/MCSectionELF.h"
12
13 using namespace llvm;
14
15 void MipsRegInfoRecord::EmitMipsOptionRecord() {
16 MCAssembler &MCA = Streamer->getAssembler();
17 Triple T(STI.getTargetTriple());
18 uint64_t Features = STI.getFeatureBits();
19
20 Streamer->PushSection();
21
22 // We need to distinguish between N64 and the rest because at the moment
23 // we don't emit .Mips.options for other ELFs other than N64.
24 // Since .reginfo has the same information as .Mips.options (ODK_REGINFO),
25 // we can use the same abstraction (MipsRegInfoRecord class) to handle both.
26 if (Features & Mips::FeatureN64) {
27 // The EntrySize value of 1 seems strange since the records are neither
28 // 1-byte long nor fixed length but it matches the value GAS emits.
29 const MCSectionELF *Sec =
30 Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS,
31 ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP,
32 SectionKind::getMetadata(), 1, "");
33 MCA.getOrCreateSectionData(*Sec).setAlignment(8);
34 Streamer->SwitchSection(Sec);
35
36 Streamer->EmitIntValue(1, 1); // kind
37 Streamer->EmitIntValue(40, 1); // size
38 Streamer->EmitIntValue(0, 2); // section
39 Streamer->EmitIntValue(0, 4); // info
40 Streamer->EmitIntValue(ri_gprmask, 4);
41 Streamer->EmitIntValue(0, 4); // pad
42 Streamer->EmitIntValue(ri_cprmask[0], 4);
43 Streamer->EmitIntValue(ri_cprmask[1], 4);
44 Streamer->EmitIntValue(ri_cprmask[2], 4);
45 Streamer->EmitIntValue(ri_cprmask[3], 4);
46 Streamer->EmitIntValue(ri_gp_value, 8);
47 } else {
48 const MCSectionELF *Sec =
49 Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC,
50 SectionKind::getMetadata(), 24, "");
51 MCA.getOrCreateSectionData(*Sec)
52 .setAlignment(Features & Mips::FeatureN32 ? 8 : 4);
53 Streamer->SwitchSection(Sec);
54
55 Streamer->EmitIntValue(ri_gprmask, 4);
56 Streamer->EmitIntValue(ri_cprmask[0], 4);
57 Streamer->EmitIntValue(ri_cprmask[1], 4);
58 Streamer->EmitIntValue(ri_cprmask[2], 4);
59 Streamer->EmitIntValue(ri_cprmask[3], 4);
60 assert((ri_gp_value & 0xffffffff) == ri_gp_value);
61 Streamer->EmitIntValue(ri_gp_value, 4);
62 }
63
64 Streamer->PopSection();
65 }
66
67 void MipsRegInfoRecord::SetPhysRegUsed(unsigned Reg,
68 const MCRegisterInfo *MCRegInfo) {
69 unsigned Value = 0;
70
71 for (MCSubRegIterator SubRegIt(Reg, MCRegInfo, true); SubRegIt.isValid();
72 ++SubRegIt) {
73 unsigned CurrentSubReg = *SubRegIt;
74
75 unsigned EncVal = MCRegInfo->getEncodingValue(CurrentSubReg);
76 Value |= 1 << EncVal;
77
78 if (GPR32RegClass->contains(CurrentSubReg) ||
79 GPR64RegClass->contains(CurrentSubReg))
80 ri_gprmask |= Value;
81 else if (FGR32RegClass->contains(CurrentSubReg) ||
82 FGR64RegClass->contains(CurrentSubReg) ||
83 AFGR64RegClass->contains(CurrentSubReg) ||
84 MSA128BRegClass->contains(CurrentSubReg))
85 ri_cprmask[1] |= Value;
86 else if (COP2RegClass->contains(CurrentSubReg))
87 ri_cprmask[2] |= Value;
88 else if (COP3RegClass->contains(CurrentSubReg))
89 ri_cprmask[3] |= Value;
90 }
91 }
1111 //===----------------------------------------------------------------------===//
1212
1313 #include "InstPrinter/MipsInstPrinter.h"
14 #include "MipsELFStreamer.h"
1415 #include "MipsMCTargetDesc.h"
1516 #include "MipsTargetObjectFile.h"
1617 #include "MipsTargetStreamer.h"
322323
323324 void MipsTargetELFStreamer::finish() {
324325 MCAssembler &MCA = getStreamer().getAssembler();
325 MCContext &Context = MCA.getContext();
326 MCStreamer &OS = getStreamer();
327 const MCObjectFileInfo &OFI = *Context.getObjectFileInfo();
328 Triple T(STI.getTargetTriple());
329 uint64_t Features = STI.getFeatureBits();
326 const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo();
330327
331328 // .bss, .text and .data are always at least 16-byte aligned.
332329 MCSectionData &TextSectionData =
340337 DataSectionData.setAlignment(std::max(16u, DataSectionData.getAlignment()));
341338 BSSSectionData.setAlignment(std::max(16u, BSSSectionData.getAlignment()));
342339
343 if (T.isArch64Bit() && (Features & Mips::FeatureN64)) {
344 // The EntrySize value of 1 seems strange since the records are neither
345 // 1-byte long nor fixed length but it matches the value GAS emits.
346 const MCSectionELF *Sec =
347 Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS,
348 ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP,
349 SectionKind::getMetadata(), 1, "");
350 MCA.getOrCreateSectionData(*Sec).setAlignment(8);
351 OS.SwitchSection(Sec);
352
353 OS.EmitIntValue(1, 1); // kind
354 OS.EmitIntValue(40, 1); // size
355 OS.EmitIntValue(0, 2); // section
356 OS.EmitIntValue(0, 4); // info
357 OS.EmitIntValue(0, 4); // ri_gprmask
358 OS.EmitIntValue(0, 4); // pad
359 OS.EmitIntValue(0, 4); // ri_cpr[0]mask
360 OS.EmitIntValue(0, 4); // ri_cpr[1]mask
361 OS.EmitIntValue(0, 4); // ri_cpr[2]mask
362 OS.EmitIntValue(0, 4); // ri_cpr[3]mask
363 OS.EmitIntValue(0, 8); // ri_gp_value
364 } else {
365 const MCSectionELF *Sec =
366 Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC,
367 SectionKind::getMetadata(), 24, "");
368 MCA.getOrCreateSectionData(*Sec)
369 .setAlignment(Features & Mips::FeatureN32 ? 8 : 4);
370 OS.SwitchSection(Sec);
371
372 OS.EmitIntValue(0, 4); // ri_gprmask
373 OS.EmitIntValue(0, 4); // ri_cpr[0]mask
374 OS.EmitIntValue(0, 4); // ri_cpr[1]mask
375 OS.EmitIntValue(0, 4); // ri_cpr[2]mask
376 OS.EmitIntValue(0, 4); // ri_cpr[3]mask
377 OS.EmitIntValue(0, 4); // ri_gp_value
378 }
340 // Emit all the option records.
341 // At the moment we are only emitting .Mips.options (ODK_REGINFO) and
342 // .reginfo.
343 MipsELFStreamer &MEF = static_cast(Streamer);
344 MEF.EmitMipsOptionRecords();
345
379346 emitMipsAbiFlags();
380347 }
381348
0 //===-- MipsOptionRecord.h - Abstraction for storing information ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // MipsOptionRecord - Abstraction for storing arbitrary information in
10 // ELF files. Arbitrary information (e.g. register usage) can be stored in Mips
11 // specific ELF sections like .Mips.options. Specific records should subclass
12 // MipsOptionRecord and provide an implementation to EmitMipsOptionRecord which
13 // basically just dumps the information into an ELF section. More information
14 // about .Mips.option can be found in the SysV ABI and the 64-bit ELF Object
15 // specification.
16 //
17 //===----------------------------------------------------------------------===//
18
19 #ifndef MIPSOPTIONRECORD_H
20 #define MIPSOPTIONRECORD_H
21
22 #include "MipsMCTargetDesc.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25
26 using namespace llvm;
27
28 namespace llvm {
29 class MipsELFStreamer;
30 class MCSubtargetInfo;
31 }
32
33 class MipsOptionRecord {
34 public:
35 virtual ~MipsOptionRecord(){};
36 virtual void EmitMipsOptionRecord() = 0;
37 };
38
39 class MipsRegInfoRecord : public MipsOptionRecord {
40 public:
41 MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context,
42 const MCSubtargetInfo &STI)
43 : Streamer(S), Context(Context), STI(STI) {
44 ri_gprmask = 0;
45 ri_cprmask[0] = ri_cprmask[1] = ri_cprmask[2] = ri_cprmask[3] = 0;
46 ri_gp_value = 0;
47
48 const MCRegisterInfo *TRI = Context.getRegisterInfo();
49 GPR32RegClass = &(TRI->getRegClass(Mips::GPR32RegClassID));
50 GPR64RegClass = &(TRI->getRegClass(Mips::GPR64RegClassID));
51 FGR32RegClass = &(TRI->getRegClass(Mips::FGR32RegClassID));
52 FGR64RegClass = &(TRI->getRegClass(Mips::FGR64RegClassID));
53 AFGR64RegClass = &(TRI->getRegClass(Mips::AFGR64RegClassID));
54 MSA128BRegClass = &(TRI->getRegClass(Mips::MSA128BRegClassID));
55 COP2RegClass = &(TRI->getRegClass(Mips::COP2RegClassID));
56 COP3RegClass = &(TRI->getRegClass(Mips::COP3RegClassID));
57 }
58 ~MipsRegInfoRecord() {}
59
60 void EmitMipsOptionRecord();
61 void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo);
62
63 private:
64 MipsELFStreamer *Streamer;
65 MCContext &Context;
66 const MCSubtargetInfo &STI;
67 const MCRegisterClass *GPR32RegClass;
68 const MCRegisterClass *GPR64RegClass;
69 const MCRegisterClass *FGR32RegClass;
70 const MCRegisterClass *FGR64RegClass;
71 const MCRegisterClass *AFGR64RegClass;
72 const MCRegisterClass *MSA128BRegClass;
73 const MCRegisterClass *COP2RegClass;
74 const MCRegisterClass *COP3RegClass;
75 uint32_t ri_gprmask;
76 uint32_t ri_cprmask[4];
77 int64_t ri_gp_value;
78 };
79 #endif
0 # RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -filetype=obj -o - | \
1 # RUN: llvm-readobj -s -section-data | \
2 # RUN: FileCheck %s
3
4 # CHECK: Section {
5 # CHECK: Index:
6 # CHECK: Name: .reginfo
7 # CHECK: Type: SHT_MIPS_REGINFO (0x70000006)
8 # CHECK: Flags [ (0x2)
9 # CHECK: SHF_ALLOC (0x2)
10 # CHECK: ]
11 # CHECK: Size: 24
12 # CHECK: SectionData (
13 # CHECK: 0000: 01010101 00000000 C0007535 00000000
14 # CHECK: 0010: 00000000 00000000
15 # CHECK: )
16 # CHECK: }
17
18 .text
19 add $0,$0,$0
20 add $8,$0,$0
21 add $16,$0,$0
22 add $24,$0,$0
23
24 # abs.s - Reads and writes from/to $f0.
25 abs.s $f0,$f0
26 # round.w.d - Reads $f4 and $f5 and writes to $f2.
27 round.w.d $f2,$f4
28 # ceil.w.s - Reads $f8 and writes to $f10.
29 ceil.w.s $f10, $f8
30 # cvt.s.d - Reads from $f12 and $f13 and writes to $f14
31 cvt.s.d $f14, $f12
32 # abs.d - Reads from $f30 and $f31 and writes to $f30 and $f31.
33 abs.d $f30,$f30
0 # RUN: llvm-mc %s -arch=mips -mcpu=mips32r2 -mattr=+msa,+fp64 -filetype=obj -o - | \
1 # RUN: llvm-readobj -s -section-data | \
2 # RUN: FileCheck %s -check-prefix=ELF32
3
4 # RUN: llvm-mc %s -arch=mips64 -mcpu=mips64r2 -mattr=+msa,+fp64,-n64,+n32 -filetype=obj -o - | \
5 # RUN: llvm-readobj -s -section-data | \
6 # RUN: FileCheck %s -check-prefix=ELF32
7
8 # RUN: llvm-mc %s -arch=mips64 -mcpu=mips64r2 -mattr=+msa,+fp64,+n64 -filetype=obj -o - | \
9 # RUN: llvm-readobj -s -section-data | \
10 # RUN: FileCheck %s -check-prefix=ELF64
11
12 # ELF32: Section {
13 # ELF32: Name: .reginfo
14 # ELF32: Type: SHT_MIPS_REGINFO (0x70000006)
15 # ELF32: Flags [ (0x2)
16 # ELF32: SHF_ALLOC (0x2)
17 # ELF32: ]
18 # ELF32: Size: 24
19 # ELF32: SectionData (
20 # ELF32: 0000: 01010101 00000000 4C005515 00000000
21 # ELF32: 0010: 00000000 00000000
22 # ELF32: )
23 # ELF32: }
24
25 # ELF64: Section {
26 # ELF64: Name: .MIPS.options
27 # ELF64: Type: SHT_MIPS_OPTIONS (0x7000000D)
28 # ELF64: Flags [ (0x8000002)
29 # ELF64: SHF_ALLOC (0x2)
30 # ELF64: SHF_MIPS_NOSTRIP (0x8000000)
31 # ELF64: ]
32 # ELF64: Size: 40
33 # ELF64: SectionData (
34 # ELF64: 0000: 01280000 00000000 01010101 00000000
35 # ELF64: 0010: 00000000 4C005515 00000000 00000000
36 # ELF64: 0020: 00000000 00000000
37 # ELF64: )
38 # ELF64: }
39
40 .text
41 add $0,$0,$0
42 add $8,$0,$0
43 add $16,$0,$0
44 add $24,$0,$0
45
46 # abs.s - Reads and writes from/to $f0.
47 abs.s $f0,$f0
48 # round.w.d - Reads $f4 and writes to $f2.
49 round.w.d $f2,$f4
50 # ceil.w.s - Reads $f8 and writes to $f10.
51 ceil.w.s $f10, $f8
52 # cvt.s.d - Reads from $f12 and writes to $f14.
53 cvt.s.d $f14, $f12
54 # abs.d - Reads from $f30 and writes to $f30.
55 abs.d $f30,$f30
56
57 # Read and write from/to $f26 and $f27
58 add_a.b $w26,$w26,$w26
59 add_a.b $w27,$w27,$w27
99 # Checking if the Mips.abiflags were correctly emitted.
1010 # CHECK-OBJ: Section {
1111 # CHECK-OBJ: Index: 5
12 # CHECK-OBJ-LABEL: Name: .MIPS.abiflags (12)
12 # CHECK-OBJ-LABEL: Name: .MIPS.abiflags
1313 # CHECK-OBJ: Type: SHT_MIPS_ABIFLAGS (0x7000002A)
1414 # CHECK-OBJ: Flags [ (0x2)
1515 # CHECK-OBJ: SHF_ALLOC (0x2)
99 # Checking if the Mips.abiflags were correctly emitted.
1010 # CHECK-OBJ: Section {
1111 # CHECK-OBJ: Index: 5
12 # CHECK-OBJ-LABEL: Name: .MIPS.abiflags (12)
12 # CHECK-OBJ-LABEL: Name: .MIPS.abiflags
1313 # CHECK-OBJ: Type: SHT_MIPS_ABIFLAGS (0x7000002A)
1414 # CHECK-OBJ: Flags [ (0x2)
1515 # CHECK-OBJ: SHF_ALLOC (0x2)