diff options
| author | Chad Rosier <mcrosier@apple.com> | 2013-01-10 22:10:27 +0000 |
|---|---|---|
| committer | Chad Rosier <mcrosier@apple.com> | 2013-01-10 22:10:27 +0000 |
| commit | a4bc9437a26612233826caa42ce1365270f7a088 (patch) | |
| tree | e2c76a68473b5818b5e41547e39c020a2b043c51 /llvm/lib | |
| parent | 8a11f77cf3e99c70cfa143ead76828feeb39d741 (diff) | |
| download | bcm5719-llvm-a4bc9437a26612233826caa42ce1365270f7a088.tar.gz bcm5719-llvm-a4bc9437a26612233826caa42ce1365270f7a088.zip | |
[ms-inline asm] Add support for calling functions from inline assembly.
Part of rdar://12991541
llvm-svn: 172121
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/MC/MCParser/AsmParser.cpp | 25 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp | 35 |
2 files changed, 43 insertions, 17 deletions
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 7c3fea56400..64a08857741 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -3777,8 +3777,8 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString, MCAsmParserSemaCallback &SI) { SmallVector<void *, 4> InputDecls; SmallVector<void *, 4> OutputDecls; - SmallVector<bool, 4> InputDeclsOffsetOf; - SmallVector<bool, 4> OutputDeclsOffsetOf; + SmallVector<bool, 4> InputDeclsAddressOf; + SmallVector<bool, 4> OutputDeclsAddressOf; SmallVector<std::string, 4> InputConstraints; SmallVector<std::string, 4> OutputConstraints; std::set<std::string> 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/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 5007803d93c..d26254bbd8c 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/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<MCSymbolRefExpr>(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. |

