From 5a719fcb5ea91ec4e7af6fc2e48ec31774a859dd Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Tue, 23 Oct 2012 17:43:43 +0000 Subject: [PATCH] [ms-inline asm] Add an implementation of the offset operator. This is a follow on patch to r166433. rdar://12470317 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166488 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCParser/MCAsmParser.h | 2 +- include/llvm/MC/MCParser/MCParsedAsmOperand.h | 3 ++ lib/MC/MCParser/AsmParser.cpp | 57 ++++++++++++++++++--------- lib/Target/X86/AsmParser/X86AsmParser.cpp | 32 +++++++++------ 4 files changed, 62 insertions(+), 32 deletions(-) diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index fe7bda08db9..8a5f37cb0c8 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -90,7 +90,7 @@ public: /// ParseMSInlineAsm - Parse ms-style inline assembly. virtual bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl &OpDecls, + SmallVectorImpl > &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index 35f47c0b9c8..89b0a1f47b6 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -69,6 +69,9 @@ public: /// inline assembly. virtual bool isOffsetOf() const { return false; } + /// getOffsetOfLoc - Get the location of the offset operator. + virtual SMLoc getOffsetOfLoc() const { return SMLoc(); } + /// needSizeDirective - Do we need to emit a sizing directive for this /// operand? Only valid when parsing MS-style inline assembly. virtual bool needSizeDirective() const { return false; } diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 9d3d4e3bdcb..b87a239a554 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -207,7 +207,7 @@ public: bool ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl &OpDecls, + SmallVectorImpl > &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, @@ -3589,7 +3589,8 @@ enum AsmRewriteKind { AOK_Input, AOK_Output, AOK_SizeDirective, - AOK_Emit + AOK_Emit, + AOK_Skip }; struct AsmRewrite { @@ -3621,14 +3622,16 @@ bool AsmParser::ParseDirectiveEmit(SMLoc IDLoc, ParseStatementInfo &Info) { bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl &OpDecls, + SmallVectorImpl > &OpDecls, SmallVectorImpl &Constraints, SmallVectorImpl &Clobbers, const MCInstrInfo *MII, const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) { - SmallVector InputDecls; - SmallVector OutputDecls; + SmallVector InputDecls; + SmallVector OutputDecls; + SmallVector InputDeclsOffsetOf; + SmallVector OutputDeclsOffsetOf; SmallVector InputConstraints; SmallVector OutputConstraints; std::set ClobberRegs; @@ -3656,8 +3659,8 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, // Immediate. if (Operand->isImm()) { AsmStrRewrites.push_back(AsmRewrite(AOK_Imm, - Operand->getStartLoc(), - Operand->getNameLen())); + Operand->getStartLoc(), + Operand->getNameLen())); continue; } @@ -3680,26 +3683,33 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, Size); if (OpDecl) { bool isOutput = (i == 1) && Desc.mayStore(); - if (Operand->needSizeDirective()) + if (Operand->needSizeDirective() && !Operand->isOffsetOf()) AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective, - Operand->getStartLoc(), 0, - Operand->getMemSize())); - + Operand->getStartLoc(), 0, + Operand->getMemSize())); + + // Don't emit the offset directive. + if (Operand->isOffsetOf()) + AsmStrRewrites.push_back(AsmRewrite(AOK_Skip, + Operand->getOffsetOfLoc(), 7)); + if (isOutput) { std::string Constraint = "="; ++InputIdx; OutputDecls.push_back(OpDecl); + OutputDeclsOffsetOf.push_back(Operand->isOffsetOf()); Constraint += Operand->getConstraint().str(); OutputConstraints.push_back(Constraint); AsmStrRewrites.push_back(AsmRewrite(AOK_Output, - Operand->getStartLoc(), - Operand->getNameLen())); + Operand->getStartLoc(), + Operand->getNameLen())); } else { InputDecls.push_back(OpDecl); + InputDeclsOffsetOf.push_back(Operand->isOffsetOf()); InputConstraints.push_back(Operand->getConstraint().str()); AsmStrRewrites.push_back(AsmRewrite(AOK_Input, - Operand->getStartLoc(), - Operand->getNameLen())); + Operand->getStartLoc(), + Operand->getNameLen())); } } } @@ -3720,13 +3730,15 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, unsigned NumExprs = NumOutputs + NumInputs; OpDecls.resize(NumExprs); Constraints.resize(NumExprs); + // FIXME: Constraints are hard coded to 'm', but we need an 'r' + // constraint for offsetof. This needs to be cleaned up! for (unsigned i = 0; i < NumOutputs; ++i) { - OpDecls[i] = OutputDecls[i]; - Constraints[i] = OutputConstraints[i]; + OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsOffsetOf[i]); + Constraints[i] = OutputDeclsOffsetOf[i] ? "=r" : OutputConstraints[i]; } for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { - OpDecls[j] = InputDecls[i]; - Constraints[j] = InputConstraints[i]; + OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsOffsetOf[i]); + Constraints[j] = InputDeclsOffsetOf[i] ? "r" : InputConstraints[i]; } } @@ -3747,8 +3759,15 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, OS << StringRef(Start, Loc - Start); PrevKind = Kind; + // Skip the original expression. + if (Kind == AOK_Skip) { + Start = Loc + (*I).Len; + continue; + } + // Rewrite expressions in $N notation. switch (Kind) { + default: break; case AOK_Imm: OS << Twine("$$") + StringRef(Loc, (*I).Len); break; diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 9689180afdb..ab3bdfa03a5 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -159,6 +159,7 @@ struct X86Operand : public MCParsedAsmOperand { } Kind; SMLoc StartLoc, EndLoc; + SMLoc OffsetOfLoc; union { struct { @@ -196,6 +197,8 @@ struct X86Operand : public MCParsedAsmOperand { /// getLocRange - Get the range between the first and last token of this /// operand. SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } + /// getOffsetOfLoc - Get the location of the offset operator. + SMLoc getOffsetOfLoc() const { return OffsetOfLoc; } virtual void print(raw_ostream &OS) const {} @@ -469,8 +472,9 @@ struct X86Operand : public MCParsedAsmOperand { /// Create an absolute memory operand. static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc, - SMLoc EndLoc, unsigned Size = 0, - bool OffsetOf = false, bool NeedSizeDir = false){ + SMLoc EndLoc, SMLoc OffsetOfLoc = SMLoc(), + unsigned Size = 0, bool OffsetOf = false, + bool NeedSizeDir = false){ X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc); Res->Mem.SegReg = 0; Res->Mem.Disp = Disp; @@ -479,6 +483,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.Scale = 1; Res->Mem.Size = Size; Res->Mem.OffsetOf = OffsetOf; + Res->OffsetOfLoc = OffsetOfLoc; Res->Mem.NeedSizeDir = NeedSizeDir; return Res; } @@ -487,8 +492,8 @@ struct X86Operand : public MCParsedAsmOperand { static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc, - unsigned Size = 0, bool OffsetOf = false, - bool NeedSizeDir = false) { + SMLoc OffsetOfLoc = SMLoc(), unsigned Size = 0, + bool OffsetOf = false, bool NeedSizeDir = false){ // We should never just have a displacement, that should be parsed as an // absolute memory operand. assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); @@ -504,6 +509,7 @@ struct X86Operand : public MCParsedAsmOperand { Res->Mem.Scale = Scale; Res->Mem.Size = Size; Res->Mem.OffsetOf = OffsetOf; + Res->OffsetOfLoc = OffsetOfLoc; Res->Mem.NeedSizeDir = NeedSizeDir; return Res; } @@ -661,7 +667,7 @@ static unsigned getIntelMemOperandSize(StringRef OpStr) { X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, unsigned Size) { unsigned BaseReg = 0, IndexReg = 0, Scale = 1; - SMLoc Start = Parser.getTok().getLoc(), End; + SMLoc Start = Parser.getTok().getLoc(), End, OffsetOfLoc; const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext()); // Parse [ BaseReg + Scale*IndexReg + Disp ] or [ symbol ] @@ -679,7 +685,7 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, if (getLexer().isNot(AsmToken::RBrac)) return ErrorOperand(Start, "Expected ']' token!"); Parser.Lex(); - return X86Operand::CreateMem(Disp, Start, End, Size); + return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size); } } else if (getLexer().is(AsmToken::Integer)) { int64_t Val = Parser.getTok().getIntVal(); @@ -691,8 +697,8 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, const MCExpr *Disp = MCConstantExpr::Create(Val, getContext()); if (SegReg) return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale, - Start, End, Size); - return X86Operand::CreateMem(Disp, Start, End, Size); + Start, End, OffsetOfLoc, Size); + return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size); } else if (getLexer().is(AsmToken::Star)) { // Handle '[' Scale*IndexReg ']' Parser.Lex(); @@ -742,16 +748,16 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, // handle [-42] if (!BaseReg && !IndexReg) - return X86Operand::CreateMem(Disp, Start, End, Size); + return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size); return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, - Start, End, Size); + Start, End, OffsetOfLoc, Size); } /// ParseIntelMemOperand - Parse intel style memory operand. X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) { const AsmToken &Tok = Parser.getTok(); - SMLoc End; + SMLoc End, OffsetOfLoc; unsigned Size = getIntelMemOperandSize(Tok.getString()); if (Size) { @@ -767,6 +773,7 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) { if(isParsingInlineAsm() && (Tok.getString() == "offset" || Tok.getString() == "OFFSET")) { OffsetOf = true; + OffsetOfLoc = Parser.getTok().getLoc(); Parser.Lex(); // Eat offset. } @@ -801,7 +808,8 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) { NeedSizeDir = Size > 0; } } - return X86Operand::CreateMem(Disp, Start, End, Size, OffsetOf, NeedSizeDir); + return X86Operand::CreateMem(Disp, Start, End, OffsetOfLoc, Size, OffsetOf, + NeedSizeDir); } X86Operand *X86AsmParser::ParseIntelOperand() { -- 2.11.0