mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-26 09:18:56 +00:00
[ms-inline asm] Add support for the 'SIZE' and 'LENGTH' operators.
Part of rdar://12576868 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172743 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -35,7 +35,9 @@ class MCAsmParserSemaCallback {
|
|||||||
public:
|
public:
|
||||||
virtual ~MCAsmParserSemaCallback();
|
virtual ~MCAsmParserSemaCallback();
|
||||||
virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc,
|
virtual void *LookupInlineAsmIdentifier(StringRef Name, void *Loc,
|
||||||
unsigned &Size, bool &IsVarDecl) = 0;
|
unsigned &Length, unsigned &Size,
|
||||||
|
unsigned &Type, bool &IsVarDecl) = 0;
|
||||||
|
|
||||||
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
virtual bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
||||||
unsigned &Offset) = 0;
|
unsigned &Offset) = 0;
|
||||||
};
|
};
|
||||||
|
@@ -3956,10 +3956,10 @@ bool AsmParser::ParseMSInlineAsm(void *AsmLoc, std::string &AsmString,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Expr/Input or Output.
|
// Expr/Input or Output.
|
||||||
unsigned Size;
|
|
||||||
bool IsVarDecl;
|
bool IsVarDecl;
|
||||||
|
unsigned Length, Size, Type;
|
||||||
void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc,
|
void *OpDecl = SI.LookupInlineAsmIdentifier(Operand->getName(), AsmLoc,
|
||||||
Size, IsVarDecl);
|
Length, Size, Type, IsVarDecl);
|
||||||
if (OpDecl) {
|
if (OpDecl) {
|
||||||
bool isOutput = (i == 1) && Desc.mayStore();
|
bool isOutput = (i == 1) && Desc.mayStore();
|
||||||
if (Operand->isMem() && Operand->needSizeDirective())
|
if (Operand->isMem() && Operand->needSizeDirective())
|
||||||
|
@@ -57,7 +57,7 @@ private:
|
|||||||
X86Operand *ParseATTOperand();
|
X86Operand *ParseATTOperand();
|
||||||
X86Operand *ParseIntelOperand();
|
X86Operand *ParseIntelOperand();
|
||||||
X86Operand *ParseIntelOffsetOfOperator(SMLoc StartLoc);
|
X86Operand *ParseIntelOffsetOfOperator(SMLoc StartLoc);
|
||||||
X86Operand *ParseIntelTypeOperator(SMLoc StartLoc);
|
X86Operand *ParseIntelOperator(SMLoc StartLoc, unsigned OpKind);
|
||||||
X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc);
|
X86Operand *ParseIntelMemOperand(unsigned SegReg, SMLoc StartLoc);
|
||||||
X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
|
X86Operand *ParseIntelBracExpression(unsigned SegReg, unsigned Size);
|
||||||
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
|
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
|
||||||
@@ -1043,11 +1043,11 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg, 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.
|
||||||
unsigned tSize;
|
unsigned tLength, tSize, tType;
|
||||||
SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tSize,
|
SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tLength,
|
||||||
IsVarDecl);
|
tSize, tType, IsVarDecl);
|
||||||
if (!Size)
|
if (!Size)
|
||||||
Size = tSize;
|
Size = tType * 8; // Size is in terms of bits in this context.
|
||||||
NeedSizeDir = Size > 0;
|
NeedSizeDir = Size > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1148,10 +1148,19 @@ X86Operand *X86AsmParser::ParseIntelOffsetOfOperator(SMLoc Start) {
|
|||||||
OffsetOfLoc);
|
OffsetOfLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the 'TYPE' operator. The TYPE operator returns the size of a C or
|
enum IntelOperatorKind {
|
||||||
/// C++ type or variable. If the variable is an array, TYPE returns the size of
|
IOK_LENGTH,
|
||||||
/// a single element of the array.
|
IOK_SIZE,
|
||||||
X86Operand *X86AsmParser::ParseIntelTypeOperator(SMLoc Start) {
|
IOK_TYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators. The LENGTH operator
|
||||||
|
/// returns the number of elements in an array. It returns the value 1 for
|
||||||
|
/// non-array variables. The SIZE operator returns the size of a C or C++
|
||||||
|
/// variable. A variable's size is the product of its LENGTH and TYPE. The
|
||||||
|
/// TYPE operator returns the size of a C or C++ type or variable. If the
|
||||||
|
/// variable is an array, TYPE returns the size of a single element.
|
||||||
|
X86Operand *X86AsmParser::ParseIntelOperator(SMLoc Start, unsigned OpKind) {
|
||||||
SMLoc TypeLoc = Start;
|
SMLoc TypeLoc = Start;
|
||||||
Parser.Lex(); // Eat offset.
|
Parser.Lex(); // Eat offset.
|
||||||
Start = Parser.getTok().getLoc();
|
Start = Parser.getTok().getLoc();
|
||||||
@@ -1162,50 +1171,51 @@ X86Operand *X86AsmParser::ParseIntelTypeOperator(SMLoc Start) {
|
|||||||
if (getParser().ParseExpression(Val, End))
|
if (getParser().ParseExpression(Val, End))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unsigned Size = 0;
|
unsigned Length = 0, Size = 0, Type = 0;
|
||||||
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Val)) {
|
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Val)) {
|
||||||
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.
|
||||||
bool IsVarDecl;
|
bool IsVarDecl;
|
||||||
if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Size,
|
if (!SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, Length,
|
||||||
IsVarDecl))
|
Size, Type, 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.
|
unsigned CVal;
|
||||||
|
switch(OpKind) {
|
||||||
|
default: llvm_unreachable("Unexpected operand kind!");
|
||||||
|
case IOK_LENGTH: CVal = Length; break;
|
||||||
|
case IOK_SIZE: CVal = Size; break;
|
||||||
|
case IOK_TYPE: CVal = Type; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rewrite the type operator and the C or C++ type or variable in terms of an
|
// Rewrite the type operator and the C or C++ type or variable in terms of an
|
||||||
// immediate. E.g. TYPE foo -> $$4
|
// immediate. E.g. TYPE foo -> $$4
|
||||||
unsigned Len = End.getPointer() - TypeLoc.getPointer();
|
unsigned Len = End.getPointer() - TypeLoc.getPointer();
|
||||||
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, Size));
|
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, TypeLoc, Len, CVal));
|
||||||
|
|
||||||
const MCExpr *Imm = MCConstantExpr::Create(Size, getContext());
|
const MCExpr *Imm = MCConstantExpr::Create(CVal, getContext());
|
||||||
return X86Operand::CreateImm(Imm, Start, End, /*NeedAsmRewrite*/false);
|
return X86Operand::CreateImm(Imm, Start, End, /*NeedAsmRewrite*/false);
|
||||||
}
|
}
|
||||||
|
|
||||||
X86Operand *X86AsmParser::ParseIntelOperand() {
|
X86Operand *X86AsmParser::ParseIntelOperand() {
|
||||||
SMLoc Start = Parser.getTok().getLoc(), End;
|
SMLoc Start = Parser.getTok().getLoc(), End;
|
||||||
|
|
||||||
// offset operator.
|
|
||||||
StringRef AsmTokStr = Parser.getTok().getString();
|
StringRef AsmTokStr = Parser.getTok().getString();
|
||||||
if ((AsmTokStr == "offset" || AsmTokStr == "OFFSET") &&
|
|
||||||
isParsingInlineAsm())
|
|
||||||
return ParseIntelOffsetOfOperator(Start);
|
|
||||||
|
|
||||||
// Type directive.
|
// Offset, length, type and size operators.
|
||||||
if ((AsmTokStr == "type" || AsmTokStr == "TYPE") &&
|
if (isParsingInlineAsm()) {
|
||||||
isParsingInlineAsm())
|
if (AsmTokStr == "offset" || AsmTokStr == "OFFSET")
|
||||||
return ParseIntelTypeOperator(Start);
|
return ParseIntelOffsetOfOperator(Start);
|
||||||
|
if (AsmTokStr == "length" || AsmTokStr == "LENGTH")
|
||||||
|
return ParseIntelOperator(Start, IOK_LENGTH);
|
||||||
|
if (AsmTokStr == "size" || AsmTokStr == "SIZE")
|
||||||
|
return ParseIntelOperator(Start, IOK_SIZE);
|
||||||
|
if (AsmTokStr == "type" || AsmTokStr == "TYPE")
|
||||||
|
return ParseIntelOperator(Start, IOK_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
// Unsupported directives.
|
// Immediate.
|
||||||
if (isParsingIntelSyntax() &&
|
|
||||||
(AsmTokStr == "size" || AsmTokStr == "SIZE" ||
|
|
||||||
AsmTokStr == "length" || AsmTokStr == "LENGTH"))
|
|
||||||
return ErrorOperand(Start, "Unsupported directive!");
|
|
||||||
|
|
||||||
// immediate.
|
|
||||||
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
|
if (getLexer().is(AsmToken::Integer) || getLexer().is(AsmToken::Real) ||
|
||||||
getLexer().is(AsmToken::Minus)) {
|
getLexer().is(AsmToken::Minus)) {
|
||||||
const MCExpr *Val;
|
const MCExpr *Val;
|
||||||
@@ -1214,7 +1224,7 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// register
|
// Register.
|
||||||
unsigned RegNo = 0;
|
unsigned RegNo = 0;
|
||||||
if (!ParseRegister(RegNo, Start, End)) {
|
if (!ParseRegister(RegNo, Start, End)) {
|
||||||
// If this is a segment register followed by a ':', then this is the start
|
// If this is a segment register followed by a ':', then this is the start
|
||||||
@@ -1226,7 +1236,7 @@ X86Operand *X86AsmParser::ParseIntelOperand() {
|
|||||||
return ParseIntelMemOperand(RegNo, Start);
|
return ParseIntelMemOperand(RegNo, Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mem operand
|
// Memory operand.
|
||||||
return ParseIntelMemOperand(0, Start);
|
return ParseIntelMemOperand(0, Start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user