llvm.org GIT mirror llvm / 0074173
[mips][ias] Fix all the hacks related to MIPS-specific unary operators (%hi/%lo/%gp_rel/etc.). Summary: They are now lexed as a single token on targets where MCAsmInfo::HasMipsExpressions is true and then parsed in a similar way to the '~' operator as part of MCExpr::parseExpression. As a result: * expressions and immediates no longer have different parsing rules. The difference is now solely down to whether evaluateAsAbsolute() succeeds. * %hi(%neg(%gp_rel(x))) are no longer parsed as a single operator and decomposed into the three MipsMCExpr nodes. They are parsed directly as three MipsMCExpr nodes. * parseMemOperand no longer needs to eat all the surrounding parenthesis to get at the outermost operator to make this work * %hi(%neg(%gp_rel(x))) and %lo(%neg(%gp_rel(x))) are no longer the only 3-in-1 relocs that parse for N64. They're still the only combinations that are permitted in relocatable expressions though. Fixing that should be a later patch. * We no longer need to list all the tokens that can occur as the first token of an expression or immediate. test/MC/Mips/expr1.s: This change also prevents the incorrect lowering of %lo(2*4)+foo to %lo(8+foo) which is not an equivalent expression (the difference is whether foo is truncated to 16-bit or not) and the test has been updated to account for the macro expansion the correct expression requires. Reviewers: sdardis Subscribers: dsanders, sdardis, llvm-commits Differential Revision: https://reviews.llvm.org/D23110 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@277988 91177308-0d34-0410-b5e6-96231b3b80d8 Daniel Sanders 3 years ago
14 changed file(s) with 290 addition(s) and 188 deletion(s). Raw diff Collapse all Expand all
362362 // X86_64 ELF.
363363 bool RelaxELFRelocations = true;
364364
365 // If true, then the lexer and expression parser will support %neg(),
366 // %hi(), and similar unary operators.
367 bool HasMipsExpressions = false;
368
365369 public:
366370 explicit MCAsmInfo();
367371 virtual ~MCAsmInfo();
581585
582586 bool canRelaxRelocations() const { return RelaxELFRelocations; }
583587 void setRelaxELFRelocations(bool V) { RelaxELFRelocations = V; }
588 bool hasMipsExpressions() const { return HasMipsExpressions; }
584589 };
585590 }
586591
5454 Pipe, PipePipe, Caret,
5555 Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash,
5656 Less, LessEqual, LessLess, LessGreater,
57 Greater, GreaterEqual, GreaterGreater, At
57 Greater, GreaterEqual, GreaterGreater, At,
58
59 // MIPS unary expression operators such as %neg.
60 PercentCall16, PercentCall_Hi, PercentCall_Lo, PercentDtprel_Hi,
61 PercentDtprel_Lo, PercentGot, PercentGot_Disp, PercentGot_Hi, PercentGot_Lo,
62 PercentGot_Ofst, PercentGot_Page, PercentGottprel, PercentGp_Rel, PercentHi,
63 PercentHigher, PercentHighest, PercentLo, PercentNeg, PercentPcrel_Hi,
64 PercentPcrel_Lo, PercentTlsgd, PercentTlsldm, PercentTprel_Hi,
65 PercentTprel_Lo
5866 };
5967
6068 private:
227227 /// Ensure that all previously parsed instructions have been emitted to the
228228 /// output streamer, if the target does not emit them immediately.
229229 virtual void flushPendingInstructions(MCStreamer &Out) { }
230
231 virtual const MCExpr *createTargetUnaryExpr(const MCExpr *E,
232 AsmToken::TokenKind OperatorToken,
233 MCContext &Ctx) {
234 return nullptr;
235 }
230236 };
231237
232238 } // End llvm namespace
1010 //
1111 //===----------------------------------------------------------------------===//
1212
13 #include "llvm/ADT/StringSwitch.h"
1314 #include "llvm/MC/MCParser/AsmLexer.h"
1415 #include "llvm/MC/MCAsmInfo.h"
1516 #include "llvm/Support/MemoryBuffer.h"
599600 return AsmToken(AsmToken::ExclaimEqual, StringRef(TokStart, 2));
600601 }
601602 return AsmToken(AsmToken::Exclaim, StringRef(TokStart, 1));
602 case '%': return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
603 case '%':
604 if (MAI.hasMipsExpressions()) {
605 AsmToken::TokenKind Operator;
606 unsigned OperatorLength;
607
608 std::tie(Operator, OperatorLength) =
609 StringSwitch>(
610 StringRef(CurPtr))
611 .StartsWith("call16", {AsmToken::PercentCall16, 7})
612 .StartsWith("call_hi", {AsmToken::PercentCall_Hi, 8})
613 .StartsWith("call_lo", {AsmToken::PercentCall_Lo, 8})
614 .StartsWith("dtprel_hi", {AsmToken::PercentDtprel_Hi, 10})
615 .StartsWith("dtprel_lo", {AsmToken::PercentDtprel_Lo, 10})
616 .StartsWith("got_disp", {AsmToken::PercentGot_Disp, 9})
617 .StartsWith("got_hi", {AsmToken::PercentGot_Hi, 7})
618 .StartsWith("got_lo", {AsmToken::PercentGot_Lo, 7})
619 .StartsWith("got_ofst", {AsmToken::PercentGot_Ofst, 9})
620 .StartsWith("got_page", {AsmToken::PercentGot_Page, 9})
621 .StartsWith("gottprel", {AsmToken::PercentGottprel, 9})
622 .StartsWith("got", {AsmToken::PercentGot, 4})
623 .StartsWith("gp_rel", {AsmToken::PercentGp_Rel, 7})
624 .StartsWith("higher", {AsmToken::PercentHigher, 7})
625 .StartsWith("highest", {AsmToken::PercentHighest, 8})
626 .StartsWith("hi", {AsmToken::PercentHi, 3})
627 .StartsWith("lo", {AsmToken::PercentLo, 3})
628 .StartsWith("neg", {AsmToken::PercentNeg, 4})
629 .StartsWith("pcrel_hi", {AsmToken::PercentPcrel_Hi, 9})
630 .StartsWith("pcrel_lo", {AsmToken::PercentPcrel_Lo, 9})
631 .StartsWith("tlsgd", {AsmToken::PercentTlsgd, 6})
632 .StartsWith("tlsldm", {AsmToken::PercentTlsldm, 7})
633 .StartsWith("tprel_hi", {AsmToken::PercentTprel_Hi, 9})
634 .StartsWith("tprel_lo", {AsmToken::PercentTprel_Lo, 9})
635 .Default({AsmToken::Percent, 1});
636
637 if (Operator != AsmToken::Percent) {
638 CurPtr += OperatorLength - 1;
639 return AsmToken(Operator, StringRef(TokStart, OperatorLength));
640 }
641 }
642 return AsmToken(AsmToken::Percent, StringRef(TokStart, 1));
603643 case '/':
604644 IsAtStartOfStatement = OldIsAtStartOfStatement;
605645 return LexSlash();
10631063 return true;
10641064 Res = MCUnaryExpr::createNot(Res, getContext());
10651065 return false;
1066 // MIPS unary expression operators. The lexer won't generate these tokens if
1067 // MCAsmInfo::HasMipsExpressions is false for the target.
1068 case AsmToken::PercentCall16:
1069 case AsmToken::PercentCall_Hi:
1070 case AsmToken::PercentCall_Lo:
1071 case AsmToken::PercentDtprel_Hi:
1072 case AsmToken::PercentDtprel_Lo:
1073 case AsmToken::PercentGot:
1074 case AsmToken::PercentGot_Disp:
1075 case AsmToken::PercentGot_Hi:
1076 case AsmToken::PercentGot_Lo:
1077 case AsmToken::PercentGot_Ofst:
1078 case AsmToken::PercentGot_Page:
1079 case AsmToken::PercentGottprel:
1080 case AsmToken::PercentGp_Rel:
1081 case AsmToken::PercentHi:
1082 case AsmToken::PercentHigher:
1083 case AsmToken::PercentHighest:
1084 case AsmToken::PercentLo:
1085 case AsmToken::PercentNeg:
1086 case AsmToken::PercentPcrel_Hi:
1087 case AsmToken::PercentPcrel_Lo:
1088 case AsmToken::PercentTlsgd:
1089 case AsmToken::PercentTlsldm:
1090 case AsmToken::PercentTprel_Hi:
1091 case AsmToken::PercentTprel_Lo:
1092 Lex(); // Eat the operator.
1093 if (Lexer.isNot(AsmToken::LParen))
1094 return TokError("expected '(' after operator");
1095 Lex(); // Eat the operator.
1096 if (parseExpression(Res, EndLoc))
1097 return true;
1098 if (Lexer.isNot(AsmToken::RParen))
1099 return TokError("expected ')'");
1100 Lex(); // Eat the operator.
1101 Res = getTargetParser().createTargetUnaryExpr(Res, FirstTokenKind, Ctx);
1102 return !Res;
10661103 }
10671104 }
10681105
251251 bool reportParseError(SMLoc Loc, Twine ErrorMsg);
252252
253253 bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
254 bool parseRelocOperand(const MCExpr *&Res);
255
256 const MCExpr *evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
257254
258255 bool isEvaluated(const MCExpr *Expr);
259256 bool parseSetMips0Directive();
551548 void warnIfNoMacro(SMLoc Loc);
552549
553550 bool isLittle() const { return IsLittleEndian; }
551
552 const MCExpr *createTargetUnaryExpr(const MCExpr *E,
553 AsmToken::TokenKind OperatorToken,
554 MCContext &Ctx) override {
555 switch(OperatorToken) {
556 default:
557 llvm_unreachable("Unknown token");
558 return nullptr;
559 case AsmToken::PercentCall16:
560 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, E, Ctx);
561 case AsmToken::PercentCall_Hi:
562 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_HI16, E, Ctx);
563 case AsmToken::PercentCall_Lo:
564 return MipsMCExpr::create(MipsMCExpr::MEK_CALL_LO16, E, Ctx);
565 case AsmToken::PercentDtprel_Hi:
566 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_HI, E, Ctx);
567 case AsmToken::PercentDtprel_Lo:
568 return MipsMCExpr::create(MipsMCExpr::MEK_DTPREL_LO, E, Ctx);
569 case AsmToken::PercentGot:
570 return MipsMCExpr::create(MipsMCExpr::MEK_GOT, E, Ctx);
571 case AsmToken::PercentGot_Disp:
572 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, E, Ctx);
573 case AsmToken::PercentGot_Hi:
574 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_HI16, E, Ctx);
575 case AsmToken::PercentGot_Lo:
576 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_LO16, E, Ctx);
577 case AsmToken::PercentGot_Ofst:
578 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_OFST, E, Ctx);
579 case AsmToken::PercentGot_Page:
580 return MipsMCExpr::create(MipsMCExpr::MEK_GOT_PAGE, E, Ctx);
581 case AsmToken::PercentGottprel:
582 return MipsMCExpr::create(MipsMCExpr::MEK_GOTTPREL, E, Ctx);
583 case AsmToken::PercentGp_Rel:
584 return MipsMCExpr::create(MipsMCExpr::MEK_GPREL, E, Ctx);
585 case AsmToken::PercentHi:
586 return MipsMCExpr::create(MipsMCExpr::MEK_HI, E, Ctx);
587 case AsmToken::PercentHigher:
588 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, E, Ctx);
589 case AsmToken::PercentHighest:
590 return MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, E, Ctx);
591 case AsmToken::PercentLo:
592 return MipsMCExpr::create(MipsMCExpr::MEK_LO, E, Ctx);
593 case AsmToken::PercentNeg:
594 return MipsMCExpr::create(MipsMCExpr::MEK_NEG, E, Ctx);
595 case AsmToken::PercentPcrel_Hi:
596 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_HI16, E, Ctx);
597 case AsmToken::PercentPcrel_Lo:
598 return MipsMCExpr::create(MipsMCExpr::MEK_PCREL_LO16, E, Ctx);
599 case AsmToken::PercentTlsgd:
600 return MipsMCExpr::create(MipsMCExpr::MEK_TLSGD, E, Ctx);
601 case AsmToken::PercentTlsldm:
602 return MipsMCExpr::create(MipsMCExpr::MEK_TLSLDM, E, Ctx);
603 case AsmToken::PercentTprel_Hi:
604 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_HI, E, Ctx);
605 case AsmToken::PercentTprel_Lo:
606 return MipsMCExpr::create(MipsMCExpr::MEK_TPREL_LO, E, Ctx);
607 }
608 }
554609 };
555610 }
556611
41864241 DEBUG(dbgs() << ".. Generic Parser\n");
41874242
41884243 switch (getLexer().getKind()) {
4189 default:
4190 Error(Parser.getTok().getLoc(), "unexpected token in operand");
4191 return true;
41924244 case AsmToken::Dollar: {
41934245 // Parse the register.
41944246 SMLoc S = Parser.getTok().getLoc();
42154267 Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this));
42164268 return false;
42174269 }
4218 // Else drop to expression parsing.
4219 case AsmToken::LParen:
4220 case AsmToken::Minus:
4221 case AsmToken::Plus:
4222 case AsmToken::Integer:
4223 case AsmToken::Tilde:
4224 case AsmToken::String: {
4225 DEBUG(dbgs() << ".. generic integer\n");
4226 OperandMatchResultTy ResTy = parseImm(Operands);
4227 return ResTy != MatchOperand_Success;
4228 }
4229 case AsmToken::Percent: {
4230 // It is a symbol reference or constant expression.
4231 const MCExpr *IdVal;
4270 default: {
4271 DEBUG(dbgs() << ".. generic integer expression\n");
4272
4273 const MCExpr *Expr;
42324274 SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
4233 if (parseRelocOperand(IdVal))
4275 if (getParser().parseExpression(Expr))
42344276 return true;
42354277
42364278 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
42374279
4238 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4239 return false;
4240 } // case AsmToken::Percent
4280 Operands.push_back(MipsOperand::CreateImm(Expr, S, E, *this));
4281 return false;
4282 }
42414283 } // switch(getLexer().getKind())
42424284 return true;
4243 }
4244
4245 const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
4246 StringRef RelocStr) {
4247 if (RelocStr == "hi(%neg(%gp_rel")
4248 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
4249 else if (RelocStr == "lo(%neg(%gp_rel")
4250 return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
4251
4252 MipsMCExpr::MipsExprKind Kind =
4253 StringSwitch(RelocStr)
4254 .Case("call16", MipsMCExpr::MEK_GOT_CALL)
4255 .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
4256 .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
4257 .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
4258 .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
4259 .Case("got", MipsMCExpr::MEK_GOT)
4260 .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
4261 .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
4262 .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
4263 .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
4264 .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
4265 .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
4266 .Case("gp_rel", MipsMCExpr::MEK_GPREL)
4267 .Case("hi", MipsMCExpr::MEK_HI)
4268 .Case("higher", MipsMCExpr::MEK_HIGHER)
4269 .Case("highest", MipsMCExpr::MEK_HIGHEST)
4270 .Case("lo", MipsMCExpr::MEK_LO)
4271 .Case("neg", MipsMCExpr::MEK_NEG)
4272 .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
4273 .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
4274 .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
4275 .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
4276 .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
4277 .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
4278 .Default(MipsMCExpr::MEK_None);
4279
4280 assert(Kind != MipsMCExpr::MEK_None);
4281 return MipsMCExpr::create(Kind, Expr, getContext());
42824285 }
42834286
42844287 bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
43024305 return false;
43034306 }
43044307
4305 bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
4306 MCAsmParser &Parser = getParser();
4307 Parser.Lex(); // Eat the % token.
4308 const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
4309 if (Tok.isNot(AsmToken::Identifier))
4310 return true;
4311
4312 std::string Str = Tok.getIdentifier();
4313
4314 Parser.Lex(); // Eat the identifier.
4315 // Now make an expression from the rest of the operand.
4316 const MCExpr *IdVal;
4317 SMLoc EndLoc;
4318
4319 if (getLexer().getKind() == AsmToken::LParen) {
4320 while (1) {
4321 Parser.Lex(); // Eat the '(' token.
4322 if (getLexer().getKind() == AsmToken::Percent) {
4323 Parser.Lex(); // Eat the % token.
4324 const AsmToken &nextTok = Parser.getTok();
4325 if (nextTok.isNot(AsmToken::Identifier))
4326 return true;
4327 Str += "(%";
4328 Str += nextTok.getIdentifier();
4329 Parser.Lex(); // Eat the identifier.
4330 if (getLexer().getKind() != AsmToken::LParen)
4331 return true;
4332 } else
4333 break;
4334 }
4335 if (getParser().parseParenExpression(IdVal, EndLoc))
4336 return true;
4337
4338 while (getLexer().getKind() == AsmToken::RParen)
4339 Parser.Lex(); // Eat the ')' token.
4340
4341 } else
4342 return true; // Parenthesis must follow the relocation operand.
4343
4344 Res = evaluateRelocExpr(IdVal, Str);
4345 return false;
4346 }
4347
43484308 bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
43494309 SMLoc &EndLoc) {
43504310 SmallVector, 1> Operands;
43724332 }
43734333
43744334 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
4375 MCAsmParser &Parser = getParser();
43764335 SMLoc S;
4377 bool Result = true;
4378 unsigned NumOfLParen = 0;
4379
4380 while (getLexer().getKind() == AsmToken::LParen) {
4381 Parser.Lex();
4382 ++NumOfLParen;
4383 }
4384
4385 switch (getLexer().getKind()) {
4386 default:
4387 return true;
4388 case AsmToken::Identifier:
4389 case AsmToken::LParen:
4390 case AsmToken::Integer:
4391 case AsmToken::Minus:
4392 case AsmToken::Plus:
4393 if (isParenExpr)
4394 Result = getParser().parseParenExprOfDepth(NumOfLParen, Res, S);
4395 else
4396 Result = (getParser().parseExpression(Res));
4397 while (getLexer().getKind() == AsmToken::RParen)
4398 Parser.Lex();
4399 break;
4400 case AsmToken::Percent:
4401 Result = parseRelocOperand(Res);
4402 }
4403 return Result;
4336
4337 if (isParenExpr)
4338 return getParser().parseParenExprOfDepth(0, Res, S);
4339 return getParser().parseExpression(Res);
44044340 }
44054341
44064342 MipsAsmParser::OperandMatchResultTy
46314567 }
46324568
46334569 MipsAsmParser::OperandMatchResultTy
4634 MipsAsmParser::parseImm(OperandVector &Operands) {
4635 MCAsmParser &Parser = getParser();
4636 switch (getLexer().getKind()) {
4637 default:
4638 return MatchOperand_NoMatch;
4639 case AsmToken::LParen:
4640 case AsmToken::Minus:
4641 case AsmToken::Plus:
4642 case AsmToken::Integer:
4643 case AsmToken::Tilde:
4644 case AsmToken::String:
4645 break;
4646 }
4647
4648 const MCExpr *IdVal;
4649 SMLoc S = Parser.getTok().getLoc();
4650 if (getParser().parseExpression(IdVal))
4651 return MatchOperand_ParseFail;
4652
4653 SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4654 Operands.push_back(MipsOperand::CreateImm(IdVal, S, E, *this));
4655 return MatchOperand_Success;
4656 }
4657
4658 MipsAsmParser::OperandMatchResultTy
46594570 MipsAsmParser::parseJumpTarget(OperandVector &Operands) {
46604571 MCAsmParser &Parser = getParser();
46614572 DEBUG(dbgs() << "parseJumpTarget\n");
46624573
46634574 SMLoc S = getLexer().getLoc();
46644575
4665 // Integers and expressions are acceptable
4666 OperandMatchResultTy ResTy = parseImm(Operands);
4576 // Registers are a valid target and have priority over symbols.
4577 OperandMatchResultTy ResTy = parseAnyRegister(Operands);
46674578 if (ResTy != MatchOperand_NoMatch)
46684579 return ResTy;
46694580
4670 // Registers are a valid target and have priority over symbols.
4671 ResTy = parseAnyRegister(Operands);
4672 if (ResTy != MatchOperand_NoMatch)
4673 return ResTy;
4674
4581 // Integers and expressions are acceptable
46754582 const MCExpr *Expr = nullptr;
46764583 if (Parser.parseExpression(Expr)) {
46774584 // We have no way of knowing if a symbol was consumed so we must ParseFail
6161 case FK_GPRel_4:
6262 case FK_Data_4:
6363 case FK_Data_8:
64 case Mips::fixup_Mips_SUB:
65 case Mips::fixup_MICROMIPS_SUB:
6466 break;
6567 case Mips::fixup_Mips_PC16:
6668 // The displacement is then divided by 4 to give us an 18 bit
360362 { "fixup_MICROMIPS_TLS_DTPREL_HI16", 0, 16, 0 },
361363 { "fixup_MICROMIPS_TLS_DTPREL_LO16", 0, 16, 0 },
362364 { "fixup_MICROMIPS_TLS_TPREL_HI16", 0, 16, 0 },
363 { "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 }
365 { "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 },
366 { "fixup_Mips_SUB", 0, 64, 0 },
367 { "fixup_MICROMIPS_SUB", 0, 64, 0 }
364368 };
365369
366370 const static MCFixupKindInfo BigEndianInfos[Mips::NumTargetFixupKinds] = {
429433 { "fixup_MICROMIPS_TLS_DTPREL_HI16", 16, 16, 0 },
430434 { "fixup_MICROMIPS_TLS_DTPREL_LO16", 16, 16, 0 },
431435 { "fixup_MICROMIPS_TLS_TPREL_HI16", 16, 16, 0 },
432 { "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 }
436 { "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 },
437 { "fixup_Mips_SUB", 0, 64, 0 },
438 { "fixup_MICROMIPS_SUB", 0, 64, 0 }
433439 };
434440
435441 if (Kind < FirstTargetFixupKind)
328328 return ELF::R_MIPS_HIGHER;
329329 case Mips::fixup_Mips_HIGHEST:
330330 return ELF::R_MIPS_HIGHEST;
331 case Mips::fixup_Mips_SUB:
332 return ELF::R_MIPS_SUB;
331333 case Mips::fixup_Mips_GOT_HI16:
332334 return ELF::R_MIPS_GOT_HI16;
333335 case Mips::fixup_Mips_GOT_LO16:
364366 return ELF::R_MICROMIPS_TLS_TPREL_HI16;
365367 case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
366368 return ELF::R_MICROMIPS_TLS_TPREL_LO16;
369 case Mips::fixup_MICROMIPS_SUB:
370 return ELF::R_MICROMIPS_SUB;
367371 }
368372
369373 llvm_unreachable("invalid fixup kind!");
208208 // resulting in - R_MICROMIPS_TLS_TPREL_LO16
209209 fixup_MICROMIPS_TLS_TPREL_LO16,
210210
211 // resulting in - R_MIPS_SUB/R_MICROMIPS_SUB
212 fixup_Mips_SUB,
213 fixup_MICROMIPS_SUB,
214
211215 // Marker
212216 LastTargetFixupKind,
213217 NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
4848 SupportsDebugInformation = true;
4949 ExceptionsType = ExceptionHandling::DwarfCFI;
5050 DwarfRegNumForCFI = true;
51 HasMipsExpressions = true;
5152
5253 // Enable IAS by default for O32.
5354 if (TheTriple.getArch() == Triple::mips ||
636636
637637 Mips::Fixups FixupKind = Mips::Fixups(0);
638638 switch (MipsExpr->getKind()) {
639 case MipsMCExpr::MEK_NEG:
640639 case MipsMCExpr::MEK_None:
641640 case MipsMCExpr::MEK_Special:
642641 llvm_unreachable("Unhandled fixup kind!");
733732 case MipsMCExpr::MEK_TPREL_LO:
734733 FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
735734 : Mips::fixup_Mips_TPREL_LO;
735 break;
736 case MipsMCExpr::MEK_NEG:
737 FixupKind =
738 isMicroMips(STI) ? Mips::fixup_MICROMIPS_SUB : Mips::fixup_Mips_SUB;
736739 break;
737740 }
738741 Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
99 # 32R2-EL: lw $4, %lo(foo)($4) # encoding: [A,A,0x84,0x8c]
1010 # 32R2-EL: # fixup A - offset: 0, value: %lo(foo), kind: fixup_Mips_LO16
1111 # 32R2-EL: lw $4, 56($4) # encoding: [0x38,0x00,0x84,0x8c]
12 # 32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [A,A,0x84,0x8c]
13 # 32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16
14 # 32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [A,A,0x84,0x8c]
15 # 32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16
16 # 32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [A,A,0x84,0x8c]
17 # 32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_Mips_LO16
12 # 32R2-EL: lui $1, %hi(foo+(%lo(8))) # encoding: [A,A,0x01,0x3c]
13 # 32R2-EL: # fixup A - offset: 0, value: %hi(foo+(%lo(8))), kind: fixup_Mips_HI16
14 # 32R2-EL: addu $1, $1, $4 # encoding: [0x21,0x08,0x24,0x00]
15 # 32R2-EL: lw $4, %lo(foo+(%lo(8)))($1) # encoding: [A,A,0x24,0x8c]
16 # 32R2-EL: # fixup A - offset: 0, value: %lo(foo+(%lo(8))), kind: fixup_Mips_LO16
17 # 32R2-EL: lw $4, %lo(12+foo)($4) # encoding: [A,A,0x84,0x8c]
18 # 32R2-EL: # fixup A - offset: 0, value: %lo(12+foo), kind: fixup_Mips_LO16
19 # 32R2-EL: lw $4, %lo(16+foo)($4) # encoding: [A,A,0x84,0x8c]
20 # 32R2-EL: # fixup A - offset: 0, value: %lo(16+foo), kind: fixup_Mips_LO16
1821 # 32R2-EL: lw $4, 10($4) # encoding: [0x0a,0x00,0x84,0x8c]
1922 # 32R2-EL: lw $4, 15($4) # encoding: [0x0f,0x00,0x84,0x8c]
2023 # 32R2-EL: lw $4, 21($4) # encoding: [0x15,0x00,0x84,0x8c]
2124 # 32R2-EL: lw $4, 28($4) # encoding: [0x1c,0x00,0x84,0x8c]
22 # 32R2-EL: lw $4, %lo(65542)($4) # encoding: [0x06,0x00,0x84,0x8c]
25 # 32R2-EL: lw $4, 6($4) # encoding: [0x06,0x00,0x84,0x8c]
2326 # 32R2-EL: .space 64
2427
2528 # MM-32R2-EL: .text
2831 # MM-32R2-EL: lw $4, %lo(foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
2932 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(foo), kind: fixup_MICROMIPS_LO16
3033 # MM-32R2-EL: lw $4, 56($4) # encoding: [0x84,0xfc,0x38,0x00]
31 # MM-32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
32 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16
33 # MM-32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
34 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16
35 # MM-32R2-EL: lw $4, %lo(8+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
36 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(8+foo), kind: fixup_MICROMIPS_LO16
34 # MM-32R2-EL: lui $1, %hi(foo+(%lo(8))) # encoding: [0xa1'A',0x41'A',0x00,0x00]
35 # MM-32R2-EL: # fixup A - offset: 0, value: %hi(foo+(%lo(8))), kind: fixup_MICROMIPS_HI16
36 # MM-32R2-EL: addu $1, $1, $4 # encoding: [0x81,0x00,0x50,0x09]
37 # MM-32R2-EL: lw $4, %lo(foo+(%lo(8)))($1) # encoding: [0x81'A',0xfc'A',0x00,0x00]
38 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(foo+(%lo(8))), kind: fixup_MICROMIPS_LO16
39 # MM-32R2-EL: lw $4, %lo(12+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
40 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(12+foo), kind: fixup_MICROMIPS_LO16
41 # MM-32R2-EL: lw $4, %lo(16+foo)($4) # encoding: [0x84'A',0xfc'A',0x00,0x00]
42 # MM-32R2-EL: # fixup A - offset: 0, value: %lo(16+foo), kind: fixup_MICROMIPS_LO16
3743 # MM-32R2-EL: lw $4, 10($4) # encoding: [0x84,0xfc,0x0a,0x00]
3844 # MM-32R2-EL: lw $4, 15($4) # encoding: [0x84,0xfc,0x0f,0x00]
3945 # MM-32R2-EL: lw $4, 21($4) # encoding: [0x84,0xfc,0x15,0x00]
4046 # MM-32R2-EL: lw $4, 28($4) # encoding: [0x84,0xfc,0x1c,0x00]
41 # MM-32R2-EL: lw $4, %lo(65542)($4) # encoding: [0x84,0xfc,0x06,0x00]
47 # MM-32R2-EL: lw $4, 6($4) # encoding: [0x84,0xfc,0x06,0x00]
4248 # MM-32R2-EL: .space 64
4349
4450 .globl foo
4753 lw $4,%lo(foo)($4)
4854 lw $4,((10 + 4) * 4)($4)
4955 lw $4,%lo (2 * 4) + foo($4)
50 lw $4,%lo((2 * 4) + foo)($4)
51 lw $4,(((%lo ((2 * 4) + foo))))($4)
56 lw $4,%lo((3 * 4) + foo)($4)
57 lw $4,(((%lo ((4 * 4) + foo))))($4)
5258 lw $4, (((1+2)+3)+4)($4)
5359 lw $4, ((((1+2)+3)+4)+5)($4)
5460 lw $4, (((((1+2)+3)+4)+5)+6)($4)
152152 // ENCLE: addiu $2, $3, %got_lo(foo) # encoding: [A,A,0x62,0x24]
153153 // FIXUP: # fixup A - offset: 0, value: %got_lo(foo), kind: fixup_Mips_GOT_LO16
154154
155 // addiu $2, $3, %neg(foo) // FIXME: R_MIPS_SUB foo
155 // It turns out that %neg() isn't actually usable for anything. It's
156 // not supported in .quad and it doesn't make sense to use a 64-bit
157 // reloc on a 32-bit instruction.
158 // .quad %neg(foo) // ?????: R_MIPS_SUB foo
156159 // ?????: R_MIPS_INSERT_A
157160 // ?????: R_MIPS_INSERT_B
158161 // ?????: R_MIPS_DELETE
313313 case AsmToken::Slash: OS << "Slash"; break;
314314 case AsmToken::Star: OS << "Star"; break;
315315 case AsmToken::Tilde: OS << "Tilde"; break;
316 case AsmToken::PercentCall16:
317 OS << "PercentCall16";
318 break;
319 case AsmToken::PercentCall_Hi:
320 OS << "PercentCall_Hi";
321 break;
322 case AsmToken::PercentCall_Lo:
323 OS << "PercentCall_Lo";
324 break;
325 case AsmToken::PercentDtprel_Hi:
326 OS << "PercentDtprel_Hi";
327 break;
328 case AsmToken::PercentDtprel_Lo:
329 OS << "PercentDtprel_Lo";
330 break;
331 case AsmToken::PercentGot:
332 OS << "PercentGot";
333 break;
334 case AsmToken::PercentGot_Disp:
335 OS << "PercentGot_Disp";
336 break;
337 case AsmToken::PercentGot_Hi:
338 OS << "PercentGot_Hi";
339 break;
340 case AsmToken::PercentGot_Lo:
341 OS << "PercentGot_Lo";
342 break;
343 case AsmToken::PercentGot_Ofst:
344 OS << "PercentGot_Ofst";
345 break;
346 case AsmToken::PercentGot_Page:
347 OS << "PercentGot_Page";
348 break;
349 case AsmToken::PercentGottprel:
350 OS << "PercentGottprel";
351 break;
352 case AsmToken::PercentGp_Rel:
353 OS << "PercentGp_Rel";
354 break;
355 case AsmToken::PercentHi:
356 OS << "PercentHi";
357 break;
358 case AsmToken::PercentHigher:
359 OS << "PercentHigher";
360 break;
361 case AsmToken::PercentHighest:
362 OS << "PercentHighest";
363 break;
364 case AsmToken::PercentLo:
365 OS << "PercentLo";
366 break;
367 case AsmToken::PercentNeg:
368 OS << "PercentNeg";
369 break;
370 case AsmToken::PercentPcrel_Hi:
371 OS << "PercentPcrel_Hi";
372 break;
373 case AsmToken::PercentPcrel_Lo:
374 OS << "PercentPcrel_Lo";
375 break;
376 case AsmToken::PercentTlsgd:
377 OS << "PercentTlsgd";
378 break;
379 case AsmToken::PercentTlsldm:
380 OS << "PercentTlsldm";
381 break;
382 case AsmToken::PercentTprel_Hi:
383 OS << "PercentTprel_Hi";
384 break;
385 case AsmToken::PercentTprel_Lo:
386 OS << "PercentTprel_Lo";
387 break;
316388 }
317389
318390 // Print the token string.