Skip to content

Commit d97a634

Browse files
committed
Re-commit: [mips] Implement .ent, .end, .frame, .mask and .fmask.
Patch by Matheus Almeida and Toma Tabacu The lld test failure on the previous attempt to commit was caused by the addition of the .pdr section causing the offsets it was checking to change. This has been fixed by removing the .ent/.end directives from that test since they weren't really needed. llvm-svn: 215535
1 parent df153c1 commit d97a634

File tree

5 files changed

+369
-22
lines changed

5 files changed

+369
-22
lines changed

llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp

Lines changed: 196 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class MipsAsmParser : public MCTargetAsmParser {
8282
MCSubtargetInfo &STI;
8383
MCAsmParser &Parser;
8484
MipsAssemblerOptions Options;
85+
MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a
86+
// nullptr, which indicates that no function is currently
87+
// selected. This usually happens after an '.end func'
88+
// directive.
8589

8690
#define GET_ASSEMBLER_HEADER
8791
#include "MipsGenAsmMatcher.inc"
@@ -285,6 +289,8 @@ class MipsAsmParser : public MCTargetAsmParser {
285289

286290
if (!isABI_O32() && !useOddSPReg() != 0)
287291
report_fatal_error("-mno-odd-spreg requires the O32 ABI");
292+
293+
CurrentFn = nullptr;
288294
}
289295

290296
MCAsmParser &getParser() const { return Parser; }
@@ -3055,38 +3061,213 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
30553061
parseDataDirective(8, DirectiveID.getLoc());
30563062
return false;
30573063
}
3058-
30593064
if (IDVal == ".ent") {
3060-
// Ignore this directive for now.
3061-
Parser.Lex();
3065+
StringRef SymbolName;
3066+
3067+
if (Parser.parseIdentifier(SymbolName)) {
3068+
reportParseError("expected identifier after .ent");
3069+
return false;
3070+
}
3071+
3072+
// There's an undocumented extension that allows an integer to
3073+
// follow the name of the procedure which AFAICS is ignored by GAS.
3074+
// Example: .ent foo,2
3075+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
3076+
if (getLexer().isNot(AsmToken::Comma)) {
3077+
// Even though we accept this undocumented extension for compatibility
3078+
// reasons, the additional integer argument does not actually change
3079+
// the behaviour of the '.ent' directive, so we would like to discourage
3080+
// its use. We do this by not referring to the extended version in
3081+
// error messages which are not directly related to its use.
3082+
reportParseError("unexpected token, expected end of statement");
3083+
return false;
3084+
}
3085+
Parser.Lex(); // Eat the comma.
3086+
const MCExpr *DummyNumber;
3087+
int64_t DummyNumberVal;
3088+
// If the user was explicitly trying to use the extended version,
3089+
// we still give helpful extension-related error messages.
3090+
if (Parser.parseExpression(DummyNumber)) {
3091+
reportParseError("expected number after comma");
3092+
return false;
3093+
}
3094+
if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) {
3095+
reportParseError("expected an absolute expression after comma");
3096+
return false;
3097+
}
3098+
}
3099+
3100+
// If this is not the end of the statement, report an error.
3101+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
3102+
reportParseError("unexpected token, expected end of statement");
3103+
return false;
3104+
}
3105+
3106+
MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName);
3107+
3108+
getTargetStreamer().emitDirectiveEnt(*Sym);
3109+
CurrentFn = Sym;
30623110
return false;
30633111
}
30643112

30653113
if (IDVal == ".end") {
3066-
// Ignore this directive for now.
3067-
Parser.Lex();
3114+
StringRef SymbolName;
3115+
3116+
if (Parser.parseIdentifier(SymbolName)) {
3117+
reportParseError("expected identifier after .end");
3118+
return false;
3119+
}
3120+
3121+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
3122+
reportParseError("unexpected token, expected end of statement");
3123+
return false;
3124+
}
3125+
3126+
if (CurrentFn == nullptr) {
3127+
reportParseError(".end used without .ent");
3128+
return false;
3129+
}
3130+
3131+
if ((SymbolName != CurrentFn->getName())) {
3132+
reportParseError(".end symbol does not match .ent symbol");
3133+
return false;
3134+
}
3135+
3136+
getTargetStreamer().emitDirectiveEnd(SymbolName);
3137+
CurrentFn = nullptr;
30683138
return false;
30693139
}
30703140

30713141
if (IDVal == ".frame") {
3072-
// Ignore this directive for now.
3073-
Parser.eatToEndOfStatement();
3142+
// .frame $stack_reg, frame_size_in_bytes, $return_reg
3143+
SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> TmpReg;
3144+
OperandMatchResultTy ResTy = ParseAnyRegister(TmpReg);
3145+
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3146+
reportParseError("expected stack register");
3147+
return false;
3148+
}
3149+
3150+
MipsOperand &StackRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3151+
if (!StackRegOpnd.isGPRAsmReg()) {
3152+
reportParseError(StackRegOpnd.getStartLoc(),
3153+
"expected general purpose register");
3154+
return false;
3155+
}
3156+
unsigned StackReg = StackRegOpnd.getGPR32Reg();
3157+
3158+
if (Parser.getTok().is(AsmToken::Comma))
3159+
Parser.Lex();
3160+
else {
3161+
reportParseError("unexpected token, expected comma");
3162+
return false;
3163+
}
3164+
3165+
// Parse the frame size.
3166+
const MCExpr *FrameSize;
3167+
int64_t FrameSizeVal;
3168+
3169+
if (Parser.parseExpression(FrameSize)) {
3170+
reportParseError("expected frame size value");
3171+
return false;
3172+
}
3173+
3174+
if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) {
3175+
reportParseError("frame size not an absolute expression");
3176+
return false;
3177+
}
3178+
3179+
if (Parser.getTok().is(AsmToken::Comma))
3180+
Parser.Lex();
3181+
else {
3182+
reportParseError("unexpected token, expected comma");
3183+
return false;
3184+
}
3185+
3186+
// Parse the return register.
3187+
TmpReg.clear();
3188+
ResTy = ParseAnyRegister(TmpReg);
3189+
if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
3190+
reportParseError("expected return register");
3191+
return false;
3192+
}
3193+
3194+
MipsOperand &ReturnRegOpnd = static_cast<MipsOperand &>(*TmpReg[0]);
3195+
if (!ReturnRegOpnd.isGPRAsmReg()) {
3196+
reportParseError(ReturnRegOpnd.getStartLoc(),
3197+
"expected general purpose register");
3198+
return false;
3199+
}
3200+
3201+
// If this is not the end of the statement, report an error.
3202+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
3203+
reportParseError("unexpected token, expected end of statement");
3204+
return false;
3205+
}
3206+
3207+
getTargetStreamer().emitFrame(StackReg, FrameSizeVal,
3208+
ReturnRegOpnd.getGPR32Reg());
30743209
return false;
30753210
}
30763211

30773212
if (IDVal == ".set") {
30783213
return parseDirectiveSet();
30793214
}
30803215

3081-
if (IDVal == ".fmask") {
3082-
// Ignore this directive for now.
3083-
Parser.eatToEndOfStatement();
3084-
return false;
3085-
}
3216+
if (IDVal == ".mask" || IDVal == ".fmask") {
3217+
// .mask bitmask, frame_offset
3218+
// bitmask: One bit for each register used.
3219+
// frame_offset: Offset from Canonical Frame Address ($sp on entry) where
3220+
// first register is expected to be saved.
3221+
// Examples:
3222+
// .mask 0x80000000, -4
3223+
// .fmask 0x80000000, -4
3224+
//
30863225

3087-
if (IDVal == ".mask") {
3088-
// Ignore this directive for now.
3089-
Parser.eatToEndOfStatement();
3226+
// Parse the bitmask
3227+
const MCExpr *BitMask;
3228+
int64_t BitMaskVal;
3229+
3230+
if (Parser.parseExpression(BitMask)) {
3231+
reportParseError("expected bitmask value");
3232+
return false;
3233+
}
3234+
3235+
if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) {
3236+
reportParseError("bitmask not an absolute expression");
3237+
return false;
3238+
}
3239+
3240+
if (Parser.getTok().is(AsmToken::Comma))
3241+
Parser.Lex();
3242+
else {
3243+
reportParseError("unexpected token, expected comma");
3244+
return false;
3245+
}
3246+
3247+
// Parse the frame_offset
3248+
const MCExpr *FrameOffset;
3249+
int64_t FrameOffsetVal;
3250+
3251+
if (Parser.parseExpression(FrameOffset)) {
3252+
reportParseError("expected frame offset value");
3253+
return false;
3254+
}
3255+
3256+
if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) {
3257+
reportParseError("frame offset not an absolute expression");
3258+
return false;
3259+
}
3260+
3261+
// If this is not the end of the statement, report an error.
3262+
if (getLexer().isNot(AsmToken::EndOfStatement)) {
3263+
reportParseError("unexpected token, expected end of statement");
3264+
return false;
3265+
}
3266+
3267+
if (IDVal == ".mask")
3268+
getTargetStreamer().emitMask(BitMaskVal, FrameOffsetVal);
3269+
else
3270+
getTargetStreamer().emitFMask(BitMaskVal, FrameOffsetVal);
30903271
return false;
30913272
}
30923273

llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@
2929
using namespace llvm;
3030

3131
MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
32-
: MCTargetStreamer(S), canHaveModuleDirective(true) {}
32+
: MCTargetStreamer(S), canHaveModuleDirective(true) {
33+
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
34+
}
3335
void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
3436
void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}
3537
void MipsTargetStreamer::emitDirectiveSetMips16() {}
@@ -492,11 +494,45 @@ void MipsTargetELFStreamer::emitDirectiveSetNoAt() {
492494
}
493495

494496
void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
495-
// FIXME: implement.
497+
MCAssembler &MCA = getStreamer().getAssembler();
498+
MCContext &Context = MCA.getContext();
499+
MCStreamer &OS = getStreamer();
500+
501+
const MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS,
502+
ELF::SHF_ALLOC | ELF::SHT_REL,
503+
SectionKind::getMetadata());
504+
505+
const MCSymbolRefExpr *ExprRef =
506+
MCSymbolRefExpr::Create(Name, MCSymbolRefExpr::VK_None, Context);
507+
508+
MCSectionData &SecData = MCA.getOrCreateSectionData(*Sec);
509+
SecData.setAlignment(4);
510+
511+
OS.PushSection();
512+
513+
OS.SwitchSection(Sec);
514+
515+
OS.EmitValueImpl(ExprRef, 4);
516+
517+
OS.EmitIntValue(GPRInfoSet ? GPRBitMask : 0, 4); // reg_mask
518+
OS.EmitIntValue(GPRInfoSet ? GPROffset : 0, 4); // reg_offset
519+
520+
OS.EmitIntValue(FPRInfoSet ? FPRBitMask : 0, 4); // fpreg_mask
521+
OS.EmitIntValue(FPRInfoSet ? FPROffset : 0, 4); // fpreg_offset
522+
523+
OS.EmitIntValue(FrameInfoSet ? FrameOffset : 0, 4); // frame_offset
524+
OS.EmitIntValue(FrameInfoSet ? FrameReg : 0, 4); // frame_reg
525+
OS.EmitIntValue(FrameInfoSet ? ReturnReg : 0, 4); // return_reg
526+
527+
// The .end directive marks the end of a procedure. Invalidate
528+
// the information gathered up until this point.
529+
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
530+
531+
OS.PopSection();
496532
}
497533

498534
void MipsTargetELFStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
499-
// FIXME: implement.
535+
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
500536
}
501537

502538
void MipsTargetELFStreamer::emitDirectiveAbiCalls() {
@@ -542,18 +578,28 @@ void MipsTargetELFStreamer::emitDirectiveOptionPic2() {
542578
}
543579

544580
void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize,
545-
unsigned ReturnReg) {
546-
// FIXME: implement.
581+
unsigned ReturnReg_) {
582+
MCContext &Context = getStreamer().getAssembler().getContext();
583+
const MCRegisterInfo *RegInfo = Context.getRegisterInfo();
584+
585+
FrameInfoSet = true;
586+
FrameReg = RegInfo->getEncodingValue(StackReg);
587+
FrameOffset = StackSize;
588+
ReturnReg = RegInfo->getEncodingValue(ReturnReg_);
547589
}
548590

549591
void MipsTargetELFStreamer::emitMask(unsigned CPUBitmask,
550592
int CPUTopSavedRegOff) {
551-
// FIXME: implement.
593+
GPRInfoSet = true;
594+
GPRBitMask = CPUBitmask;
595+
GPROffset = CPUTopSavedRegOff;
552596
}
553597

554598
void MipsTargetELFStreamer::emitFMask(unsigned FPUBitmask,
555599
int FPUTopSavedRegOff) {
556-
// FIXME: implement.
600+
FPRInfoSet = true;
601+
FPRBitMask = FPUBitmask;
602+
FPROffset = FPUTopSavedRegOff;
557603
}
558604

559605
void MipsTargetELFStreamer::emitDirectiveSetMips1() {

llvm/lib/Target/Mips/MipsTargetStreamer.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#define MIPSTARGETSTREAMER_H
1212

1313
#include "llvm/MC/MCELFStreamer.h"
14+
#include "llvm/MC/MCRegisterInfo.h"
1415
#include "llvm/MC/MCStreamer.h"
1516
#include "MCTargetDesc/MipsABIFlagsSection.h"
1617

@@ -97,6 +98,19 @@ class MipsTargetStreamer : public MCTargetStreamer {
9798
protected:
9899
MipsABIFlagsSection ABIFlagsSection;
99100

101+
bool GPRInfoSet;
102+
unsigned GPRBitMask;
103+
int GPROffset;
104+
105+
bool FPRInfoSet;
106+
unsigned FPRBitMask;
107+
int FPROffset;
108+
109+
bool FrameInfoSet;
110+
int FrameOffset;
111+
unsigned FrameReg;
112+
unsigned ReturnReg;
113+
100114
private:
101115
bool canHaveModuleDirective;
102116
};

0 commit comments

Comments
 (0)