diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 05a1d0027ea..8c4c06bf4d4 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -36,7 +36,7 @@ class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc, - unsigned &Size) = 0; + unsigned &Size, bool &IsVarDecl) = 0; virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) = 0; }; diff --git a/include/llvm/MC/MCParser/MCParsedAsmOperand.h b/include/llvm/MC/MCParser/MCParsedAsmOperand.h index e03974c1908..c78cd976f2a 100644 --- a/include/llvm/MC/MCParser/MCParsedAsmOperand.h +++ b/include/llvm/MC/MCParser/MCParsedAsmOperand.h @@ -70,6 +70,10 @@ public: /// care of the rewrites. Only valid when parsing MS-style inline assembly. virtual bool needAsmRewrite() const { return true; } + /// needAddressOf - Do we need to emit code to get the address of the + /// variable/label? Only valid when parsing MS-style inline assembly. + virtual bool needAddressOf() const { return false; } + /// isOffsetOf - Do we need to emit code to get the offset of the variable, /// rather then the value of the variable? Only valid when parsing MS-style /// inline assembly. diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 7c3fea56400..64a08857741 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -3777,8 +3777,8 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, MCAsmParserSemaCallback &SI) { SmallVector InputDecls; SmallVector OutputDecls; - SmallVector InputDeclsOffsetOf; - SmallVector OutputDeclsOffsetOf; + SmallVector InputDeclsAddressOf; + SmallVector OutputDeclsAddressOf; SmallVector InputConstraints; SmallVector OutputConstraints; std::set ClobberRegs; @@ -3815,7 +3815,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, } // Register operand. - if (Operand->isReg() && !Operand->isOffsetOf()) { + if (Operand->isReg() && !Operand->needAddressOf()) { unsigned NumDefs = Desc.getNumDefs(); // Clobber. if (NumDefs && Operand->getMCOperandNum() < NumDefs) { @@ -3829,11 +3829,12 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, // Expr/Input or Output. unsigned Size; + bool IsVarDecl; void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc, - Size); + Size, IsVarDecl); if (OpDecl) { bool isOutput = (i == 1) && Desc.mayStore(); - if (!Operand->isOffsetOf() && Operand->needSizeDirective()) + if (Operand->isMem() && Operand->needSizeDirective()) AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective, Operand->getStartLoc(), /*Len*/0, @@ -3842,7 +3843,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, std::string Constraint = "="; ++InputIdx; OutputDecls.push_back(OpDecl); - OutputDeclsOffsetOf.push_back(Operand->isOffsetOf()); + OutputDeclsAddressOf.push_back(Operand->needAddressOf()); Constraint += Operand->getConstraint().str(); OutputConstraints.push_back(Constraint); AsmStrRewrites.push_back(AsmRewrite(AOK_Output, @@ -3850,7 +3851,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, Operand->getNameLen())); } else { InputDecls.push_back(OpDecl); - InputDeclsOffsetOf.push_back(Operand->isOffsetOf()); + InputDeclsAddressOf.push_back(Operand->needAddressOf()); InputConstraints.push_back(Operand->getConstraint().str()); AsmStrRewrites.push_back(AsmRewrite(AOK_Input, Operand->getStartLoc(), @@ -3876,14 +3877,14 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, 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! + // constraint for addressof. This needs to be cleaned up! for (unsigned i = 0; i < NumOutputs; ++i) { - OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsOffsetOf[i]); - Constraints[i] = OutputDeclsOffsetOf[i] ? "=r" : OutputConstraints[i]; + OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]); + Constraints[i] = OutputDeclsAddressOf[i] ? "=r" : OutputConstraints[i]; } for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) { - OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsOffsetOf[i]); - Constraints[j] = InputDeclsOffsetOf[i] ? "r" : InputConstraints[i]; + OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]); + Constraints[j] = InputDeclsAddressOf[i] ? "r" : InputConstraints[i]; } } diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 5007803d93c..d26254bbd8c 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -168,6 +168,7 @@ struct X86Operand : public MCParsedAsmOperand { SMLoc StartLoc, EndLoc; SMLoc OffsetOfLoc; + bool AddressOf; union { struct { @@ -340,6 +341,10 @@ struct X86Operand : public MCParsedAsmOperand { return OffsetOfLoc.getPointer(); } + bool needAddressOf() const { + return AddressOf; + } + bool needSizeDirective() const { assert(Kind == Memory && "Invalid access!"); return Mem.NeedSizeDir; @@ -471,9 +476,11 @@ struct X86Operand : public MCParsedAsmOperand { } static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc, + bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc()) { X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc); Res->Reg.RegNo = RegNo; + Res->AddressOf = AddressOf; Res->OffsetOfLoc = OffsetOfLoc; return Res; } @@ -836,24 +843,39 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) { return 0; bool NeedSizeDir = false; - if (!Size && isParsingInlineAsm()) { + bool IsVarDecl = false; + if (isParsingInlineAsm()) { if (const MCSymbolRefExpr *SymRef = dyn_cast(Disp)) { const MCSymbol &Sym = SymRef->getSymbol(); // FIXME: The SemaLookup will fail if the name is anything other then an // identifier. // FIXME: Pass a valid SMLoc. - SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size); + unsigned tSize; + SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tSize, + IsVarDecl); + if (!Size) + Size = tSize; NeedSizeDir = Size > 0; } } if (!isParsingInlineAsm()) return X86Operand::CreateMem(Disp, Start, End, Size); - else + else { + // If this is not a VarDecl then assume it is a FuncDecl or some other label + // reference. We need an 'r' constraint here, so we need to create register + // operand to ensure proper matching. Just pick a GPR based on the size of + // a pointer. + if (!IsVarDecl) { + unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX; + return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true); + } + // When parsing inline assembly we set the base register to a non-zero value // as we don't know the actual value at this time. This is necessary to // get the matching correct in some cases. return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0, /*Scale*/1, Start, End, Size, NeedSizeDir); + } } /// Parse the '.' operator. @@ -929,7 +951,8 @@ X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) { // register operand to ensure proper matching. Just pick a GPR based on // the size of a pointer. unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX; - return X86Operand::CreateReg(RegNo, Start, End, OffsetOfLoc); + return X86Operand::CreateReg(RegNo, Start, End, /*GetAddress=*/true, + OffsetOfLoc); } /// Parse the 'TYPE' operator. The TYPE operator returns the size of a C or @@ -952,7 +975,9 @@ X86Operand *X86AsmParser::ParseIntelTypeOperator(SMLoc Start) { // FIXME: The SemaLookup will fail if the name is anything other then an // identifier. // FIXME: Pass a valid SMLoc. - if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size)) + bool IsVarDecl; + if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size, + IsVarDecl)) return ErrorOperand(Start, "Unable to lookup TYPE of expr!"); Size /= 8; // Size is in terms of bits, but we want bytes in the context. diff --git a/test/CodeGen/X86/ms-inline-asm.ll b/test/CodeGen/X86/ms-inline-asm.ll index 24d28adda89..9bca1acf656 100644 --- a/test/CodeGen/X86/ms-inline-asm.ll +++ b/test/CodeGen/X86/ms-inline-asm.ll @@ -61,3 +61,21 @@ entry: ; CHECK: .att_syntax ; CHECK: {{## InlineAsm End|#NO_APP}} } + +define void @t19_helper() nounwind { +entry: + ret void +} + +define void @t19() nounwind { +entry: + call void asm sideeffect inteldialect "call $0", "r,~{dirflag},~{fpsr},~{flags}"(void ()* @t19_helper) nounwind + ret void +; CHECK: t19 +; CHECK: movl $_t19_helper, %eax +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: call eax +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} +}