Skip to content

Commit 175d0ae

Browse files
author
Chad Rosier
committed
[ms-inline asm] Add support for operands that include both a symbol and an
immediate displacement. Specifically, add support for generating the proper IR. We've been able to parse this for some time now. Test case to be added on the clang side. Part of rdar://13453209 llvm-svn: 179393
1 parent 1b58f33 commit 175d0ae

File tree

1 file changed

+103
-41
lines changed

1 file changed

+103
-41
lines changed

llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp

Lines changed: 103 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ class X86AsmParser : public MCTargetAsmParser {
6767
StringRef &Identifier);
6868
X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
6969

70-
X86Operand *CreateMemForInlineAsm(const MCExpr *Disp, SMLoc Start, SMLoc End,
70+
X86Operand *CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
71+
unsigned BaseReg, unsigned IndexReg,
72+
unsigned Scale, SMLoc Start, SMLoc End,
7173
SMLoc SizeDirLoc, unsigned Size,
7274
StringRef SymName);
7375

@@ -851,15 +853,20 @@ class IntelBracExprStateMachine {
851853
IntelBracExprState State;
852854
unsigned BaseReg, IndexReg, TmpReg, Scale;
853855
int64_t Disp;
856+
const MCExpr *Sym;
857+
StringRef SymName;
854858
InfixCalculator IC;
855859
public:
856860
IntelBracExprStateMachine(MCAsmParser &parser, int64_t disp) :
857-
State(IBES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Disp(disp){}
861+
State(IBES_PLUS), BaseReg(0), IndexReg(0), TmpReg(0), Scale(1), Disp(disp),
862+
Sym(0) {}
858863

859864
unsigned getBaseReg() { return BaseReg; }
860865
unsigned getIndexReg() { return IndexReg; }
861866
unsigned getScale() { return Scale; }
862-
int64_t getDisp() { return Disp + IC.execute(); }
867+
const MCExpr *getSym() { return Sym; }
868+
StringRef getSymName() { return SymName; }
869+
int64_t getImmDisp() { return Disp + IC.execute(); }
863870
bool isValidEndState() { return State == IBES_RBRAC; }
864871

865872
void onPlus() {
@@ -936,14 +943,16 @@ class IntelBracExprStateMachine {
936943
break;
937944
}
938945
}
939-
void onDispExpr() {
946+
void onDispExpr(const MCExpr *SymRef, StringRef SymRefName) {
940947
switch (State) {
941948
default:
942949
State = IBES_ERROR;
943950
break;
944951
case IBES_PLUS:
945952
case IBES_MINUS:
946953
State = IBES_INTEGER;
954+
Sym = SymRef;
955+
SymName = SymRefName;
947956
IC.pushOperand(IC_IMM);
948957
break;
949958
}
@@ -1070,45 +1079,47 @@ class IntelBracExprStateMachine {
10701079
}
10711080
};
10721081

1073-
X86Operand *X86AsmParser::CreateMemForInlineAsm(const MCExpr *Disp, SMLoc Start,
1074-
SMLoc End, SMLoc SizeDirLoc,
1075-
unsigned Size, StringRef SymName) {
1082+
X86Operand *
1083+
X86AsmParser::CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp,
1084+
unsigned BaseReg, unsigned IndexReg,
1085+
unsigned Scale, SMLoc Start, SMLoc End,
1086+
SMLoc SizeDirLoc, unsigned Size,
1087+
StringRef SymName) {
10761088
bool NeedSizeDir = false;
1077-
bool IsVarDecl = false;
1078-
10791089
if (const MCSymbolRefExpr *SymRef = dyn_cast<MCSymbolRefExpr>(Disp)) {
10801090
const MCSymbol &Sym = SymRef->getSymbol();
10811091
// FIXME: The SemaLookup will fail if the name is anything other then an
10821092
// identifier.
10831093
// FIXME: Pass a valid SMLoc.
1094+
bool IsVarDecl = false;
10841095
unsigned tLength, tSize, tType;
10851096
SemaCallback->LookupInlineAsmIdentifier(Sym.getName(), NULL, tLength, tSize,
10861097
tType, IsVarDecl);
10871098
if (!Size) {
10881099
Size = tType * 8; // Size is in terms of bits in this context.
10891100
NeedSizeDir = Size > 0;
10901101
}
1091-
}
1092-
1093-
// If this is not a VarDecl then assume it is a FuncDecl or some other label
1094-
// reference. We need an 'r' constraint here, so we need to create register
1095-
// operand to ensure proper matching. Just pick a GPR based on the size of
1096-
// a pointer.
1097-
if (!IsVarDecl) {
1098-
unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
1099-
return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true, SMLoc(),
1100-
SymName);
1102+
// If this is not a VarDecl then assume it is a FuncDecl or some other label
1103+
// reference. We need an 'r' constraint here, so we need to create register
1104+
// operand to ensure proper matching. Just pick a GPR based on the size of
1105+
// a pointer.
1106+
if (!IsVarDecl) {
1107+
unsigned RegNo = is64BitMode() ? X86::RBX : X86::EBX;
1108+
return X86Operand::CreateReg(RegNo, Start, End, /*AddressOf=*/true,
1109+
SMLoc(), SymName);
1110+
}
11011111
}
11021112

11031113
if (NeedSizeDir)
11041114
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_SizeDirective, SizeDirLoc,
11051115
/*Len*/0, Size));
11061116

11071117
// When parsing inline assembly we set the base register to a non-zero value
1108-
// as we don't know the actual value at this time. This is necessary to
1118+
// if we don't know the actual value at this time. This is necessary to
11091119
// get the matching correct in some cases.
1110-
return X86Operand::CreateMem(/*SegReg*/0, Disp, /*BaseReg*/1, /*IndexReg*/0,
1111-
/*Scale*/1, Start, End, Size, SymName);
1120+
BaseReg = BaseReg ? BaseReg : 1;
1121+
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
1122+
End, Size, SymName);
11121123
}
11131124

11141125
X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
@@ -1118,12 +1129,12 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
11181129
const AsmToken &Tok = Parser.getTok();
11191130
SMLoc Start = Tok.getLoc(), End = Tok.getEndLoc();
11201131

1121-
// Eat '['
11221132
if (getLexer().isNot(AsmToken::LBrac))
11231133
return ErrorOperand(Start, "Expected '[' token!");
1124-
Parser.Lex();
1134+
Parser.Lex(); // Eat '['
11251135

11261136
unsigned TmpReg = 0;
1137+
SMLoc StartInBrac = Tok.getLoc();
11271138

11281139
// Try to handle '[' 'Symbol' ']'
11291140
if (getLexer().is(AsmToken::Identifier)) {
@@ -1148,8 +1159,9 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
11481159
Parser.Lex(); // Eat ']'
11491160
if (!isParsingInlineAsm())
11501161
return X86Operand::CreateMem(Disp, Start, End, Size);
1151-
return CreateMemForInlineAsm(Disp, Start, End, SizeDirLoc, Size,
1152-
Identifier);
1162+
return CreateMemForInlineAsm(/*SegReg=*/0, Disp, /*BaseReg=*/0,
1163+
/*IndexReg=*/0, /*Scale*/1, Start, End,
1164+
SizeDirLoc, Size, Identifier);
11531165
}
11541166
}
11551167

@@ -1164,7 +1176,6 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
11641176
if (TmpReg)
11651177
SM.onRegister(TmpReg);
11661178

1167-
const MCExpr *Disp = 0;
11681179
while (!Done) {
11691180
bool UpdateLocLex = true;
11701181

@@ -1182,14 +1193,17 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
11821193
return ErrorOperand(Tok.getLoc(), "Unexpected token!");
11831194
}
11841195
case AsmToken::Identifier: {
1185-
// This could be a register or a displacement expression.
1186-
SMLoc Loc = Tok.getLoc();
1187-
if(!ParseRegister(TmpReg, Loc, End)) {
1196+
// This could be a register or a symbolic displacement.
1197+
unsigned TmpReg;
1198+
const MCExpr *Disp = 0;
1199+
AsmToken IdentTok = Parser.getTok();
1200+
SMLoc IdentLoc = IdentTok.getLoc();
1201+
if(!ParseRegister(TmpReg, IdentLoc, End)) {
11881202
SM.onRegister(TmpReg);
11891203
UpdateLocLex = false;
11901204
break;
11911205
} else if (!getParser().parsePrimaryExpr(Disp, End)) {
1192-
SM.onDispExpr();
1206+
SM.onDispExpr(Disp, IdentTok.getString());
11931207
UpdateLocLex = false;
11941208
break;
11951209
}
@@ -1215,14 +1229,58 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
12151229
Parser.Lex(); // Consume the token.
12161230
}
12171231
}
1218-
if (isParsingInlineAsm() && Disp && isa<MCSymbolRefExpr>(Disp)) {
1219-
// Remove the '[' and ']' from the IR string.
1220-
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, Start, 1));
1221-
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, End, 1));
1222-
}
12231232

1224-
if (!Disp)
1225-
Disp = MCConstantExpr::Create(SM.getDisp(), getContext());
1233+
const MCExpr *Disp;
1234+
if (const MCExpr *Sym = SM.getSym()) {
1235+
Disp = Sym;
1236+
1237+
if (isParsingInlineAsm()) {
1238+
// Remove the '[' and ']' from the IR string.
1239+
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, Start, 1));
1240+
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, End, 1));
1241+
1242+
// If ImmDisp is non-zero, then we parsed a displacement before the
1243+
// bracketed expression (i.e., ImmDisp [ BaseReg + Scale*IndexReg + Disp ])
1244+
uint64_t FinalImmDisp = SM.getImmDisp();
1245+
if (ImmDisp && ImmDisp != FinalImmDisp) {
1246+
// If ImmDisp doesn't match the displacement computed by the state machine
1247+
// then we have an additional displacement in the bracketed expression.
1248+
1249+
} else if (FinalImmDisp) {
1250+
// We have a symbolic and an immediate displacement, but no displacement
1251+
// before the bracketed expression.
1252+
1253+
// Put the immediate displacement before the bracketed expression.
1254+
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Imm, Start, 0,
1255+
FinalImmDisp));
1256+
}
1257+
// Remove all the ImmPrefix rewrites within the brackets.
1258+
for (SmallVectorImpl<AsmRewrite>::iterator
1259+
I = InstInfo->AsmRewrites->begin(),
1260+
E = InstInfo->AsmRewrites->end(); I != E; ++I) {
1261+
if ((*I).Loc.getPointer() < StartInBrac.getPointer())
1262+
continue;
1263+
if ((*I).Kind == AOK_ImmPrefix)
1264+
(*I).Kind = AOK_Delete;
1265+
}
1266+
StringRef SymName = SM.getSymName();
1267+
const char *SymLocPtr = SymName.data();
1268+
// Skip everything before the symbol.
1269+
if (unsigned Len = SymLocPtr - StartInBrac.getPointer()) {
1270+
assert(Len > 0 && "Expected a non-negative length.");
1271+
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, StartInBrac, Len));
1272+
}
1273+
// Skip everything after the symbol.
1274+
if (unsigned Len = End.getPointer() - (SymLocPtr + SymName.size())) {
1275+
SMLoc Loc = SMLoc::getFromPointer(SymLocPtr + SymName.size());
1276+
assert(Len > 0 && "Expected a non-negative length.");
1277+
InstInfo->AsmRewrites->push_back(AsmRewrite(AOK_Skip, Loc, Len));
1278+
}
1279+
}
1280+
} else {
1281+
// An immediate displacement only.
1282+
Disp = MCConstantExpr::Create(SM.getImmDisp(), getContext());
1283+
}
12261284

12271285
// Parse the dot operator (e.g., [ebx].foo.bar).
12281286
if (Tok.getString().startswith(".")) {
@@ -1238,6 +1296,11 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
12381296

12391297
int BaseReg = SM.getBaseReg();
12401298
int IndexReg = SM.getIndexReg();
1299+
int Scale = SM.getScale();
1300+
1301+
if (isParsingInlineAsm())
1302+
return CreateMemForInlineAsm(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
1303+
End, SizeDirLoc, Size, SM.getSymName());
12411304

12421305
// handle [-42]
12431306
if (!BaseReg && !IndexReg) {
@@ -1246,8 +1309,6 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg,
12461309
else
12471310
return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, Start, End, Size);
12481311
}
1249-
1250-
int Scale = SM.getScale();
12511312
return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale, Start,
12521313
End, Size);
12531314
}
@@ -1345,7 +1406,8 @@ X86Operand *X86AsmParser::ParseIntelMemOperand(unsigned SegReg,
13451406
if (X86Operand *Err = ParseIntelVarWithQualifier(Disp, Identifier))
13461407
return Err;
13471408

1348-
return CreateMemForInlineAsm(Disp, Start, End, Start, Size, Identifier);
1409+
return CreateMemForInlineAsm(/*SegReg=*/0, Disp, /*BaseReg=*/0,/*IndexReg=*/0,
1410+
/*Scale=*/1, Start, End, Start, Size,Identifier);
13491411
}
13501412

13511413
/// Parse the '.' operator.

0 commit comments

Comments
 (0)