Skip to content

Commit

Permalink
[mips][ias] Support .dtprel[d]word and .tprel[d]word directives
Browse files Browse the repository at this point in the history
Assembler directives .dtprelword, .dtpreldword, .tprelword, and
.tpreldword generates relocations R_MIPS_TLS_DTPREL32, R_MIPS_TLS_DTPREL64,
R_MIPS_TLS_TPREL32, and R_MIPS_TLS_TPREL64 respectively.

The main motivation for this patch is to be able to write test cases
for checking correctness of the LLD linker's behaviour.

Differential Revision: https://reviews.llvm.org/D23669

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@279439 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
atanasyan committed Aug 22, 2016
1 parent 5c13456 commit b469a38
Show file tree
Hide file tree
Showing 13 changed files with 267 additions and 8 deletions.
12 changes: 12 additions & 0 deletions include/llvm/MC/MCAsmInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ class MCAsmInfo {
/// on Alpha. Defaults to NULL.
const char *GPRel32Directive;

/// If non-null, directives that are used to emit a word/dword which should
/// be relocated as a 32/64-bit DTP/TP-relative offset, e.g. .dtprelword/
/// .dtpreldword/.tprelword/.tpreldword on Mips.
const char *DTPRel32Directive = nullptr;
const char *DTPRel64Directive = nullptr;
const char *TPRel32Directive = nullptr;
const char *TPRel64Directive = nullptr;

/// This is true if this target uses "Sun Style" syntax for section switching
/// ("#alloc,#write" etc) instead of the normal ELF syntax (,"a,w") in
/// .section directives. Defaults to false.
Expand Down Expand Up @@ -396,6 +404,10 @@ class MCAsmInfo {
const char *getData64bitsDirective() const { return Data64bitsDirective; }
const char *getGPRel64Directive() const { return GPRel64Directive; }
const char *getGPRel32Directive() const { return GPRel32Directive; }
const char *getDTPRel64Directive() const { return DTPRel64Directive; }
const char *getDTPRel32Directive() const { return DTPRel32Directive; }
const char *getTPRel64Directive() const { return TPRel64Directive; }
const char *getTPRel32Directive() const { return TPRel32Directive; }

/// Targets can implement this method to specify a section to switch to if the
/// translation unit doesn't have any trampolines that require an executable
Expand Down
4 changes: 4 additions & 0 deletions include/llvm/MC/MCFixup.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ enum MCFixupKind {
FK_GPRel_2, ///< A two-byte gp relative fixup.
FK_GPRel_4, ///< A four-byte gp relative fixup.
FK_GPRel_8, ///< A eight-byte gp relative fixup.
FK_DTPRel_4, ///< A four-byte dtp relative fixup.
FK_DTPRel_8, ///< A eight-byte dtp relative fixup.
FK_TPRel_4, ///< A four-byte tp relative fixup.
FK_TPRel_8, ///< A eight-byte tp relative fixup.
FK_SecRel_1, ///< A one-byte section relative fixup.
FK_SecRel_2, ///< A two-byte section relative fixup.
FK_SecRel_4, ///< A four-byte section relative fixup.
Expand Down
4 changes: 4 additions & 0 deletions include/llvm/MC/MCObjectStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ class MCObjectStreamer : public MCStreamer {
StringRef FixedSizePortion) override;
void EmitCVStringTableDirective() override;
void EmitCVFileChecksumsDirective() override;
void EmitDTPRel32Value(const MCExpr *Value) override;
void EmitDTPRel64Value(const MCExpr *Value) override;
void EmitTPRel32Value(const MCExpr *Value) override;
void EmitTPRel64Value(const MCExpr *Value) override;
void EmitGPRel32Value(const MCExpr *Value) override;
void EmitGPRel64Value(const MCExpr *Value) override;
bool EmitRelocDirective(const MCExpr &Offset, StringRef Name,
Expand Down
28 changes: 28 additions & 0 deletions include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,34 @@ class MCStreamer {
void EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
bool IsSectionRelative = false);

/// \brief Emit the expression \p Value into the output as a dtprel
/// (64-bit DTP relative) value.
///
/// This is used to implement assembler directives such as .dtpreldword on
/// targets that support them.
virtual void EmitDTPRel64Value(const MCExpr *Value);

/// \brief Emit the expression \p Value into the output as a dtprel
/// (32-bit DTP relative) value.
///
/// This is used to implement assembler directives such as .dtprelword on
/// targets that support them.
virtual void EmitDTPRel32Value(const MCExpr *Value);

/// \brief Emit the expression \p Value into the output as a tprel
/// (64-bit TP relative) value.
///
/// This is used to implement assembler directives such as .tpreldword on
/// targets that support them.
virtual void EmitTPRel64Value(const MCExpr *Value);

/// \brief Emit the expression \p Value into the output as a tprel
/// (32-bit TP relative) value.
///
/// This is used to implement assembler directives such as .tprelword on
/// targets that support them.
virtual void EmitTPRel32Value(const MCExpr *Value);

/// \brief Emit the expression \p Value into the output as a gprel64 (64-bit
/// GP relative) value.
///
Expand Down
4 changes: 4 additions & 0 deletions lib/MC/MCAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ const MCFixupKindInfo &MCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
{"FK_GPRel_2", 0, 16, 0},
{"FK_GPRel_4", 0, 32, 0},
{"FK_GPRel_8", 0, 64, 0},
{"FK_DTPRel_4", 0, 32, 0},
{"FK_DTPRel_8", 0, 64, 0},
{"FK_TPRel_4", 0, 32, 0},
{"FK_TPRel_8", 0, 64, 0},
{"FK_SecRel_1", 0, 8, 0},
{"FK_SecRel_2", 0, 16, 0},
{"FK_SecRel_4", 0, 32, 0},
Expand Down
33 changes: 33 additions & 0 deletions lib/MC/MCAsmStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ class MCAsmStreamer final : public MCStreamer {

void EmitSLEB128Value(const MCExpr *Value) override;

void EmitDTPRel32Value(const MCExpr *Value) override;
void EmitDTPRel64Value(const MCExpr *Value) override;
void EmitTPRel32Value(const MCExpr *Value) override;
void EmitTPRel64Value(const MCExpr *Value) override;

void EmitGPRel64Value(const MCExpr *Value) override;

void EmitGPRel32Value(const MCExpr *Value) override;
Expand Down Expand Up @@ -856,6 +861,34 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) {
EmitEOL();
}

void MCAsmStreamer::EmitDTPRel64Value(const MCExpr *Value) {
assert(MAI->getDTPRel64Directive() != nullptr);
OS << MAI->getDTPRel64Directive();
Value->print(OS, MAI);
EmitEOL();
}

void MCAsmStreamer::EmitDTPRel32Value(const MCExpr *Value) {
assert(MAI->getDTPRel32Directive() != nullptr);
OS << MAI->getDTPRel32Directive();
Value->print(OS, MAI);
EmitEOL();
}

void MCAsmStreamer::EmitTPRel64Value(const MCExpr *Value) {
assert(MAI->getTPRel64Directive() != nullptr);
OS << MAI->getTPRel64Directive();
Value->print(OS, MAI);
EmitEOL();
}

void MCAsmStreamer::EmitTPRel32Value(const MCExpr *Value) {
assert(MAI->getTPRel32Directive() != nullptr);
OS << MAI->getTPRel32Directive();
Value->print(OS, MAI);
EmitEOL();
}

void MCAsmStreamer::EmitGPRel64Value(const MCExpr *Value) {
assert(MAI->getGPRel64Directive() != nullptr);
OS << MAI->getGPRel64Directive();
Expand Down
42 changes: 41 additions & 1 deletion lib/MC/MCObjectStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,46 @@ void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset,
insert(new MCOrgFragment(*Offset, Value));
}

// Associate DTPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitDTPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());

DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
Value, FK_DTPRel_4));
DF->getContents().resize(DF->getContents().size() + 4, 0);
}

// Associate DTPRel64 fixup with data and resize data area
void MCObjectStreamer::EmitDTPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());

DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
Value, FK_DTPRel_8));
DF->getContents().resize(DF->getContents().size() + 8, 0);
}

// Associate TPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitTPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());

DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
Value, FK_TPRel_4));
DF->getContents().resize(DF->getContents().size() + 4, 0);
}

// Associate TPRel64 fixup with data and resize data area
void MCObjectStreamer::EmitTPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());

DF->getFixups().push_back(MCFixup::create(DF->getContents().size(),
Value, FK_TPRel_8));
DF->getContents().resize(DF->getContents().size() + 8, 0);
}

// Associate GPRel32 fixup with data and resize data area
void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
Expand All @@ -455,7 +495,7 @@ void MCObjectStreamer::EmitGPRel32Value(const MCExpr *Value) {
DF->getContents().resize(DF->getContents().size() + 4, 0);
}

// Associate GPRel32 fixup with data and resize data area
// Associate GPRel64 fixup with data and resize data area
void MCObjectStreamer::EmitGPRel64Value(const MCExpr *Value) {
MCDataFragment *DF = getOrCreateDataFragment();
flushPendingLabels(DF, DF->getContents().size());
Expand Down
16 changes: 16 additions & 0 deletions lib/MC/MCStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
EmitCOFFSecRel32(Sym);
}

void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::EmitDTPRel32Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::EmitTPRel64Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::EmitTPRel32Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}

void MCStreamer::EmitGPRel64Value(const MCExpr *Value) {
report_fatal_error("unsupported directive in streamer");
}
Expand Down
98 changes: 97 additions & 1 deletion lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,10 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseDataDirective(unsigned Size, SMLoc L);
bool parseDirectiveGpWord();
bool parseDirectiveGpDWord();
bool parseDirectiveDtpRelWord();
bool parseDirectiveDtpRelDWord();
bool parseDirectiveTpRelWord();
bool parseDirectiveTpRelDWord();
bool parseDirectiveModule();
bool parseDirectiveModuleFP();
bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
Expand Down Expand Up @@ -5749,7 +5753,79 @@ bool MipsAsmParser::parseDirectiveGpDWord() {
getParser().getStreamer().EmitGPRel64Value(Value);

if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
}

/// parseDirectiveDtpRelWord
/// ::= .dtprelword tls_sym
bool MipsAsmParser::parseDirectiveDtpRelWord() {
MCAsmParser &Parser = getParser();
const MCExpr *Value;
// EmitDTPRel32Value requires an expression, so we are using base class
// method to evaluate the expression.
if (getParser().parseExpression(Value))
return true;
getParser().getStreamer().EmitDTPRel32Value(Value);

if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
}

/// parseDirectiveDtpRelDWord
/// ::= .dtpreldword tls_sym
bool MipsAsmParser::parseDirectiveDtpRelDWord() {
MCAsmParser &Parser = getParser();
const MCExpr *Value;
// EmitDTPRel64Value requires an expression, so we are using base class
// method to evaluate the expression.
if (getParser().parseExpression(Value))
return true;
getParser().getStreamer().EmitDTPRel64Value(Value);

if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
}

/// parseDirectiveTpRelWord
/// ::= .tprelword tls_sym
bool MipsAsmParser::parseDirectiveTpRelWord() {
MCAsmParser &Parser = getParser();
const MCExpr *Value;
// EmitTPRel32Value requires an expression, so we are using base class
// method to evaluate the expression.
if (getParser().parseExpression(Value))
return true;
getParser().getStreamer().EmitTPRel32Value(Value);

if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
}

/// parseDirectiveTpRelDWord
/// ::= .tpreldword tls_sym
bool MipsAsmParser::parseDirectiveTpRelDWord() {
MCAsmParser &Parser = getParser();
const MCExpr *Value;
// EmitTPRel64Value requires an expression, so we are using base class
// method to evaluate the expression.
if (getParser().parseExpression(Value))
return true;
getParser().getStreamer().EmitTPRel64Value(Value);

if (getLexer().isNot(AsmToken::EndOfStatement))
return Error(getLexer().getLoc(),
"unexpected token, expected end of statement");
Parser.Lex(); // Eat EndOfStatement token.
return false;
Expand Down Expand Up @@ -6304,6 +6380,26 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}

if (IDVal == ".dtprelword") {
parseDirectiveDtpRelWord();
return false;
}

if (IDVal == ".dtpreldword") {
parseDirectiveDtpRelDWord();
return false;
}

if (IDVal == ".tprelword") {
parseDirectiveTpRelWord();
return false;
}

if (IDVal == ".tpreldword") {
parseDirectiveTpRelDWord();
return false;
}

if (IDVal == ".word") {
parseDataDirective(4, DirectiveID.getLoc());
return false;
Expand Down
4 changes: 4 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case Mips::fixup_MIPS_PCLO16:
Value &= 0xffff;
break;
case FK_DTPRel_4:
case FK_DTPRel_8:
case FK_TPRel_4:
case FK_TPRel_8:
case FK_GPRel_4:
case FK_Data_4:
case FK_Data_8:
Expand Down
8 changes: 8 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
case Mips::fixup_Mips_64:
case FK_Data_8:
return ELF::R_MIPS_64;
case FK_DTPRel_4:
return ELF::R_MIPS_TLS_DTPREL32;
case FK_DTPRel_8:
return ELF::R_MIPS_TLS_DTPREL64;
case FK_TPRel_4:
return ELF::R_MIPS_TLS_TPREL32;
case FK_TPRel_8:
return ELF::R_MIPS_TLS_TPREL64;
case FK_GPRel_4:
if (isN64()) {
unsigned Type = (unsigned)ELF::R_MIPS_NONE;
Expand Down
4 changes: 4 additions & 0 deletions lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) {
ZeroDirective = "\t.space\t";
GPRel32Directive = "\t.gpword\t";
GPRel64Directive = "\t.gpdword\t";
DTPRel32Directive = "\t.dtprelword\t";
DTPRel64Directive = "\t.dtpreldword\t";
TPRel32Directive = "\t.tprelword\t";
TPRel64Directive = "\t.tpreldword\t";
UseAssignmentForEHBegin = true;
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
Expand Down
Loading

0 comments on commit b469a38

Please sign in to comment.