summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Rosier <mcrosier@apple.com>2013-01-10 22:10:27 +0000
committerChad Rosier <mcrosier@apple.com>2013-01-10 22:10:27 +0000
commitc1ec207b615cb058d30dc642ee311ed06fe59cfe (patch)
tree095d4d76964f829b11bfa53361d3c2b80da7ef08
parent48fdf9b37926a9c3debd3f0b5814a2a4b6bb5097 (diff)
downloadllvm-c1ec207b615cb058d30dc642ee311ed06fe59cfe.tar.gz
llvm-c1ec207b615cb058d30dc642ee311ed06fe59cfe.tar.bz2
llvm-c1ec207b615cb058d30dc642ee311ed06fe59cfe.tar.xz
[ms-inline asm] Add support for calling functions from inline assembly.
Part of rdar://12991541 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172121 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCParser/MCAsmParser.h2
-rw-r--r--include/llvm/MC/MCParser/MCParsedAsmOperand.h4
-rw-r--r--lib/MC/MCParser/AsmParser.cpp25
-rw-r--r--lib/Target/X86/AsmParser/X86AsmParser.cpp35
-rw-r--r--test/CodeGen/X86/ms-inline-asm.ll18
5 files changed, 66 insertions, 18 deletions
diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h
index 05a1d0027e..8c4c06bf4d 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 e03974c190..c78cd976f2 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 7c3fea5640..64a0885774 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<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/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 5007803d93..d26254bbd8 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<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.
diff --git a/test/CodeGen/X86/ms-inline-asm.ll b/test/CodeGen/X86/ms-inline-asm.ll
index 24d28adda8..9bca1acf65 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}}
+}