mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 16:33:28 +00:00
[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
This commit is contained in:
parent
48fdf9b379
commit
c1ec207b61
@ -36,7 +36,7 @@ class MCAsmParserSemaCallback {
|
|||||||
public:
|
public:
|
||||||
virtual ~MCAsmParserSemaCallback();
|
virtual ~MCAsmParserSemaCallback();
|
||||||
virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc,
|
virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc,
|
||||||
unsigned &Size) = 0;
|
unsigned &Size, bool &IsVarDecl) = 0;
|
||||||
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
||||||
unsigned &Offset) = 0;
|
unsigned &Offset) = 0;
|
||||||
};
|
};
|
||||||
|
@ -70,6 +70,10 @@ public:
|
|||||||
/// care of the rewrites. Only valid when parsing MS-style inline assembly.
|
/// care of the rewrites. Only valid when parsing MS-style inline assembly.
|
||||||
virtual bool needAsmRewrite() const { return true; }
|
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,
|
/// 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
|
/// rather then the value of the variable? Only valid when parsing MS-style
|
||||||
/// inline assembly.
|
/// inline assembly.
|
||||||
|
@ -3777,8 +3777,8 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
MCAsmParserSemaCallback &SI) {
|
MCAsmParserSemaCallback &SI) {
|
||||||
SmallVector<void *, 4> InputDecls;
|
SmallVector<void *, 4> InputDecls;
|
||||||
SmallVector<void *, 4> OutputDecls;
|
SmallVector<void *, 4> OutputDecls;
|
||||||
SmallVector<bool, 4> InputDeclsOffsetOf;
|
SmallVector<bool, 4> InputDeclsAddressOf;
|
||||||
SmallVector<bool, 4> OutputDeclsOffsetOf;
|
SmallVector<bool, 4> OutputDeclsAddressOf;
|
||||||
SmallVector<std::string, 4> InputConstraints;
|
SmallVector<std::string, 4> InputConstraints;
|
||||||
SmallVector<std::string, 4> OutputConstraints;
|
SmallVector<std::string, 4> OutputConstraints;
|
||||||
std::set<std::string> ClobberRegs;
|
std::set<std::string> ClobberRegs;
|
||||||
@ -3815,7 +3815,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Register operand.
|
// Register operand.
|
||||||
if (Operand->isReg() && !Operand->isOffsetOf()) {
|
if (Operand->isReg() && !Operand->needAddressOf()) {
|
||||||
unsigned NumDefs = Desc.getNumDefs();
|
unsigned NumDefs = Desc.getNumDefs();
|
||||||
// Clobber.
|
// Clobber.
|
||||||
if (NumDefs && Operand->getMCOperandNum() < NumDefs) {
|
if (NumDefs && Operand->getMCOperandNum() < NumDefs) {
|
||||||
@ -3829,11 +3829,12 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
|
|
||||||
// Expr/Input or Output.
|
// Expr/Input or Output.
|
||||||
unsigned Size;
|
unsigned Size;
|
||||||
|
bool IsVarDecl;
|
||||||
void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc,
|
void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc,
|
||||||
Size);
|
Size, IsVarDecl);
|
||||||
if (OpDecl) {
|
if (OpDecl) {
|
||||||
bool isOutput = (i == 1) && Desc.mayStore();
|
bool isOutput = (i == 1) && Desc.mayStore();
|
||||||
if (!Operand->isOffsetOf() && Operand->needSizeDirective())
|
if (Operand->isMem() && Operand->needSizeDirective())
|
||||||
AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective,
|
AsmStrRewrites.push_back(AsmRewrite(AOK_SizeDirective,
|
||||||
Operand->getStartLoc(),
|
Operand->getStartLoc(),
|
||||||
/*Len*/0,
|
/*Len*/0,
|
||||||
@ -3842,7 +3843,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
std::string Constraint = "=";
|
std::string Constraint = "=";
|
||||||
++InputIdx;
|
++InputIdx;
|
||||||
OutputDecls.push_back(OpDecl);
|
OutputDecls.push_back(OpDecl);
|
||||||
OutputDeclsOffsetOf.push_back(Operand->isOffsetOf());
|
OutputDeclsAddressOf.push_back(Operand->needAddressOf());
|
||||||
Constraint += Operand->getConstraint().str();
|
Constraint += Operand->getConstraint().str();
|
||||||
OutputConstraints.push_back(Constraint);
|
OutputConstraints.push_back(Constraint);
|
||||||
AsmStrRewrites.push_back(AsmRewrite(AOK_Output,
|
AsmStrRewrites.push_back(AsmRewrite(AOK_Output,
|
||||||
@ -3850,7 +3851,7 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
Operand->getNameLen()));
|
Operand->getNameLen()));
|
||||||
} else {
|
} else {
|
||||||
InputDecls.push_back(OpDecl);
|
InputDecls.push_back(OpDecl);
|
||||||
InputDeclsOffsetOf.push_back(Operand->isOffsetOf());
|
InputDeclsAddressOf.push_back(Operand->needAddressOf());
|
||||||
InputConstraints.push_back(Operand->getConstraint().str());
|
InputConstraints.push_back(Operand->getConstraint().str());
|
||||||
AsmStrRewrites.push_back(AsmRewrite(AOK_Input,
|
AsmStrRewrites.push_back(AsmRewrite(AOK_Input,
|
||||||
Operand->getStartLoc(),
|
Operand->getStartLoc(),
|
||||||
@ -3876,14 +3877,14 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
OpDecls.resize(NumExprs);
|
OpDecls.resize(NumExprs);
|
||||||
Constraints.resize(NumExprs);
|
Constraints.resize(NumExprs);
|
||||||
// FIXME: Constraints are hard coded to 'm', but we need an 'r'
|
// 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) {
|
for (unsigned i = 0; i < NumOutputs; ++i) {
|
||||||
OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsOffsetOf[i]);
|
OpDecls[i] = std::make_pair(OutputDecls[i], OutputDeclsAddressOf[i]);
|
||||||
Constraints[i] = OutputDeclsOffsetOf[i] ? "=r" : OutputConstraints[i];
|
Constraints[i] = OutputDeclsAddressOf[i] ? "=r" : OutputConstraints[i];
|
||||||
}
|
}
|
||||||
for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
|
for (unsigned i = 0, j = NumOutputs; i < NumInputs; ++i, ++j) {
|
||||||
OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsOffsetOf[i]);
|
OpDecls[j] = std::make_pair(InputDecls[i], InputDeclsAddressOf[i]);
|
||||||
Constraints[j] = InputDeclsOffsetOf[i] ? "r" : InputConstraints[i];
|
Constraints[j] = InputDeclsAddressOf[i] ? "r" : InputConstraints[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +168,7 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
|
|
||||||
SMLoc StartLoc, EndLoc;
|
SMLoc StartLoc, EndLoc;
|
||||||
SMLoc OffsetOfLoc;
|
SMLoc OffsetOfLoc;
|
||||||
|
bool AddressOf;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@ -340,6 +341,10 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
return OffsetOfLoc.getPointer();
|
return OffsetOfLoc.getPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool needAddressOf() const {
|
||||||
|
return AddressOf;
|
||||||
|
}
|
||||||
|
|
||||||
bool needSizeDirective() const {
|
bool needSizeDirective() const {
|
||||||
assert(Kind == Memory && "Invalid access!");
|
assert(Kind == Memory && "Invalid access!");
|
||||||
return Mem.NeedSizeDir;
|
return Mem.NeedSizeDir;
|
||||||
@ -471,9 +476,11 @@ struct X86Operand : public MCParsedAsmOperand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
|
static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
|
||||||
|
bool AddressOf = false,
|
||||||
SMLoc OffsetOfLoc = SMLoc()) {
|
SMLoc OffsetOfLoc = SMLoc()) {
|
||||||
X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
|
X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
|
||||||
Res->Reg.RegNo = RegNo;
|
Res->Reg.RegNo = RegNo;
|
||||||
|
Res->AddressOf = AddressOf;
|
||||||
Res->OffsetOfLoc = OffsetOfLoc;
|
Res->OffsetOfLoc = OffsetOfLoc;
|
||||||
return Res;
|
return Res;
|
||||||
}
|
}
|
||||||
@ -836,24 +843,39 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, SMLoc Start) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bool NeedSizeDir = false;
|
bool NeedSizeDir = false;
|
||||||
if (!Size && isParsingInlineAsm()) {
|
bool IsVarDecl = false;
|
||||||
|
if (isParsingInlineAsm()) {
|
||||||
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Disp)) {
|
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Disp)) {
|
||||||
const MCSymbol &Sym = SymRef->getSymbol();
|
const MCSymbol &Sym = SymRef->getSymbol();
|
||||||
// FIXME: The SemaLookup will fail if the name is anything other then an
|
// FIXME: The SemaLookup will fail if the name is anything other then an
|
||||||
// identifier.
|
// identifier.
|
||||||
// FIXME: Pass a valid SMLoc.
|
// 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;
|
NeedSizeDir = Size > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isParsingInlineAsm())
|
if (!isParsingInlineAsm())
|
||||||
return X86Operand::CreateMem(Disp, Start, End, Size);
|
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
|
// 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
|
// as we don't know the actual value at this time. This is necessary to
|
||||||
// get the matching correct in some cases.
|
// get the matching correct in some cases.
|
||||||
return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0,
|
return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0,
|
||||||
/*Scale*/1, Start, End, Size, NeedSizeDir);
|
/*Scale*/1, Start, End, Size, NeedSizeDir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the '.' operator.
|
/// Parse the '.' operator.
|
||||||
@ -929,7 +951,8 @@ X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) {
|
|||||||
// register operand to ensure proper matching. Just pick a GPR based on
|
// register operand to ensure proper matching. Just pick a GPR based on
|
||||||
// the size of a pointer.
|
// the size of a pointer.
|
||||||
unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
|
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
|
/// 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
|
// FIXME: The SemaLookup will fail if the name is anything other then an
|
||||||
// identifier.
|
// identifier.
|
||||||
// FIXME: Pass a valid SMLoc.
|
// 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!");
|
return ErrorOperand(Start, "Unable to lookup TYPE of expr!");
|
||||||
|
|
||||||
Size /= 8; // Size is in terms of bits, but we want bytes in the context.
|
Size /= 8; // Size is in terms of bits, but we want bytes in the context.
|
||||||
|
@ -61,3 +61,21 @@ entry:
|
|||||||
; CHECK: .att_syntax
|
; CHECK: .att_syntax
|
||||||
; CHECK: {{## InlineAsm End|#NO_APP}}
|
; 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}}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user