mirror of https://github.com/microsoft/clang.git
[X86][MS-InlineAsm] Extended support for variables / identifiers on memory / immediate expressions
Allow the proper recognition of Enum values and global variables inside ms inline-asm memory / immediate expressions, as they require some additional overhead and treated incorrect if doesn't early recognized. supersedes D33278, D35774 Differential Revision: https://reviews.llvm.org/D37413 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@314494 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
8c6abdf1ba
commit
2fb39644fd
|
@ -1474,7 +1474,6 @@ public:
|
||||||
|
|
||||||
ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
||||||
unsigned &NumLineToksConsumed,
|
unsigned &NumLineToksConsumed,
|
||||||
void *Info,
|
|
||||||
bool IsUnevaluated);
|
bool IsUnevaluated);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -3788,15 +3788,15 @@ public:
|
||||||
Expr *AsmString, MultiExprArg Clobbers,
|
Expr *AsmString, MultiExprArg Clobbers,
|
||||||
SourceLocation RParenLoc);
|
SourceLocation RParenLoc);
|
||||||
|
|
||||||
|
void FillInlineAsmIdentifierInfo(Expr *Res,
|
||||||
|
llvm::InlineAsmIdentifierInfo &Info);
|
||||||
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
||||||
SourceLocation TemplateKWLoc,
|
SourceLocation TemplateKWLoc,
|
||||||
UnqualifiedId &Id,
|
UnqualifiedId &Id,
|
||||||
llvm::InlineAsmIdentifierInfo &Info,
|
|
||||||
bool IsUnevaluatedContext);
|
bool IsUnevaluatedContext);
|
||||||
bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
||||||
unsigned &Offset, SourceLocation AsmLoc);
|
unsigned &Offset, SourceLocation AsmLoc);
|
||||||
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
|
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
|
||||||
llvm::InlineAsmIdentifierInfo &Info,
|
|
||||||
SourceLocation AsmLoc);
|
SourceLocation AsmLoc);
|
||||||
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
|
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
|
||||||
ArrayRef<Token> AsmToks,
|
ArrayRef<Token> AsmToks,
|
||||||
|
|
|
@ -54,9 +54,9 @@ public:
|
||||||
assert(AsmToks.size() == AsmTokOffsets.size());
|
assert(AsmToks.size() == AsmTokOffsets.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void *LookupInlineAsmIdentifier(StringRef &LineBuf,
|
void LookupInlineAsmIdentifier(StringRef &LineBuf,
|
||||||
llvm::InlineAsmIdentifierInfo &Info,
|
llvm::InlineAsmIdentifierInfo &Info,
|
||||||
bool IsUnevaluatedContext) override {
|
bool IsUnevaluatedContext) override {
|
||||||
// Collect the desired tokens.
|
// Collect the desired tokens.
|
||||||
SmallVector<Token, 16> LineToks;
|
SmallVector<Token, 16> LineToks;
|
||||||
const Token *FirstOrigToken = nullptr;
|
const Token *FirstOrigToken = nullptr;
|
||||||
|
@ -64,7 +64,7 @@ public:
|
||||||
|
|
||||||
unsigned NumConsumedToks;
|
unsigned NumConsumedToks;
|
||||||
ExprResult Result = TheParser.ParseMSAsmIdentifier(
|
ExprResult Result = TheParser.ParseMSAsmIdentifier(
|
||||||
LineToks, NumConsumedToks, &Info, IsUnevaluatedContext);
|
LineToks, NumConsumedToks, IsUnevaluatedContext);
|
||||||
|
|
||||||
// If we consumed the entire line, tell MC that.
|
// If we consumed the entire line, tell MC that.
|
||||||
// Also do this if we consumed nothing as a way of reporting failure.
|
// Also do this if we consumed nothing as a way of reporting failure.
|
||||||
|
@ -89,9 +89,10 @@ public:
|
||||||
LineBuf = LineBuf.substr(0, TotalOffset);
|
LineBuf = LineBuf.substr(0, TotalOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the "decl" with the lookup result.
|
// Initialize Info with the lookup result.
|
||||||
Info.OpDecl = static_cast<void *>(Result.get());
|
if (!Result.isUsable())
|
||||||
return Info.OpDecl;
|
return;
|
||||||
|
TheParser.getActions().FillInlineAsmIdentifierInfo(Result.get(), Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
|
StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
|
||||||
|
@ -178,16 +179,9 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse an identifier in an MS-style inline assembly block.
|
/// Parse an identifier in an MS-style inline assembly block.
|
||||||
///
|
|
||||||
/// \param CastInfo - a void* so that we don't have to teach Parser.h
|
|
||||||
/// about the actual type.
|
|
||||||
ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
||||||
unsigned &NumLineToksConsumed,
|
unsigned &NumLineToksConsumed,
|
||||||
void *CastInfo,
|
|
||||||
bool IsUnevaluatedContext) {
|
bool IsUnevaluatedContext) {
|
||||||
llvm::InlineAsmIdentifierInfo &Info =
|
|
||||||
*(llvm::InlineAsmIdentifierInfo *)CastInfo;
|
|
||||||
|
|
||||||
// Push a fake token on the end so that we don't overrun the token
|
// Push a fake token on the end so that we don't overrun the token
|
||||||
// stream. We use ';' because it expression-parsing should never
|
// stream. We use ';' because it expression-parsing should never
|
||||||
// overrun it.
|
// overrun it.
|
||||||
|
@ -227,7 +221,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
||||||
/*AllowDeductionGuide=*/false,
|
/*AllowDeductionGuide=*/false,
|
||||||
/*ObjectType=*/nullptr, TemplateKWLoc, Id);
|
/*ObjectType=*/nullptr, TemplateKWLoc, Id);
|
||||||
// Perform the lookup.
|
// Perform the lookup.
|
||||||
Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
|
Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id,
|
||||||
IsUnevaluatedContext);
|
IsUnevaluatedContext);
|
||||||
}
|
}
|
||||||
// While the next two tokens are 'period' 'identifier', repeatedly parse it as
|
// While the next two tokens are 'period' 'identifier', repeatedly parse it as
|
||||||
|
@ -241,7 +235,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
||||||
IdentifierInfo *Id = Tok.getIdentifierInfo();
|
IdentifierInfo *Id = Tok.getIdentifierInfo();
|
||||||
ConsumeToken(); // Consume the identifier.
|
ConsumeToken(); // Consume the identifier.
|
||||||
Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(),
|
Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(),
|
||||||
Info, Tok.getLocation());
|
Tok.getLocation());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out how many tokens we are into LineToks.
|
// Figure out how many tokens we are into LineToks.
|
||||||
|
|
|
@ -48,10 +48,10 @@ static bool CheckAsmLValue(const Expr *E, Sema &S) {
|
||||||
if (E != E2 && E2->isLValue()) {
|
if (E != E2 && E2->isLValue()) {
|
||||||
if (!S.getLangOpts().HeinousExtensions)
|
if (!S.getLangOpts().HeinousExtensions)
|
||||||
S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
|
S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
|
||||||
<< E->getSourceRange();
|
<< E->getSourceRange();
|
||||||
else
|
else
|
||||||
S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
|
S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
|
||||||
<< E->getSourceRange();
|
<< E->getSourceRange();
|
||||||
// Accept, even if we emitted an error diagnostic.
|
// Accept, even if we emitted an error diagnostic.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -607,23 +607,31 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
|
||||||
return NS;
|
return NS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T,
|
void Sema::FillInlineAsmIdentifierInfo(Expr *Res,
|
||||||
llvm::InlineAsmIdentifierInfo &Info) {
|
llvm::InlineAsmIdentifierInfo &Info) {
|
||||||
// Compute the type size (and array length if applicable?).
|
QualType T = Res->getType();
|
||||||
Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
|
Expr::EvalResult Eval;
|
||||||
if (T->isArrayType()) {
|
if (T->isFunctionType() || T->isDependentType())
|
||||||
const ArrayType *ATy = Context.getAsArrayType(T);
|
return Info.setLabel(Res);
|
||||||
Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
|
if (Res->isRValue()) {
|
||||||
Info.Length = Info.Size / Info.Type;
|
if (isa<clang::EnumType>(T) && Res->EvaluateAsRValue(Eval, Context))
|
||||||
|
return Info.setEnum(Eval.Val.getInt().getSExtValue());
|
||||||
|
return Info.setLabel(Res);
|
||||||
}
|
}
|
||||||
|
unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
|
||||||
|
unsigned Type = Size;
|
||||||
|
if (const auto *ATy = Context.getAsArrayType(T))
|
||||||
|
Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
|
||||||
|
bool IsGlobalLV = false;
|
||||||
|
if (Res->EvaluateAsLValue(Eval, Context))
|
||||||
|
IsGlobalLV = Eval.isGlobalLValue();
|
||||||
|
Info.setVar(Res, IsGlobalLV, Size, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
||||||
SourceLocation TemplateKWLoc,
|
SourceLocation TemplateKWLoc,
|
||||||
UnqualifiedId &Id,
|
UnqualifiedId &Id,
|
||||||
llvm::InlineAsmIdentifierInfo &Info,
|
|
||||||
bool IsUnevaluatedContext) {
|
bool IsUnevaluatedContext) {
|
||||||
Info.clear();
|
|
||||||
|
|
||||||
if (IsUnevaluatedContext)
|
if (IsUnevaluatedContext)
|
||||||
PushExpressionEvaluationContext(
|
PushExpressionEvaluationContext(
|
||||||
|
@ -664,12 +672,6 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
||||||
return ExprError();
|
return ExprError();
|
||||||
}
|
}
|
||||||
|
|
||||||
fillInlineAsmTypeInfo(Context, T, Info);
|
|
||||||
|
|
||||||
// We can work with the expression as long as it's not an r-value.
|
|
||||||
if (!Result.get()->isRValue())
|
|
||||||
Info.IsVarDecl = true;
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,9 +745,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
|
||||||
|
|
||||||
ExprResult
|
ExprResult
|
||||||
Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
|
Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
|
||||||
llvm::InlineAsmIdentifierInfo &Info,
|
|
||||||
SourceLocation AsmLoc) {
|
SourceLocation AsmLoc) {
|
||||||
Info.clear();
|
|
||||||
|
|
||||||
QualType T = E->getType();
|
QualType T = E->getType();
|
||||||
if (T->isDependentType()) {
|
if (T->isDependentType()) {
|
||||||
|
@ -780,14 +780,6 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
|
||||||
ExprResult Result = BuildMemberReferenceExpr(
|
ExprResult Result = BuildMemberReferenceExpr(
|
||||||
E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
|
E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
|
||||||
SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
|
SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
|
||||||
if (Result.isInvalid())
|
|
||||||
return Result;
|
|
||||||
Info.OpDecl = Result.get();
|
|
||||||
|
|
||||||
fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info);
|
|
||||||
|
|
||||||
// Fields are "variables" as far as inline assembly is concerned.
|
|
||||||
Info.IsVarDecl = true;
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
// REQUIRES: x86-registered-target
|
||||||
|
// RUN: %clang_cc1 %s -fasm-blocks -triple i386-apple-darwin10 -emit-llvm -o - | FileCheck %s
|
||||||
|
|
||||||
|
namespace x {
|
||||||
|
enum { A = 12 };
|
||||||
|
struct y_t {
|
||||||
|
enum { A = 17 };
|
||||||
|
int r;
|
||||||
|
} y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: t1
|
||||||
|
void t1() {
|
||||||
|
enum { A = 1 };
|
||||||
|
// CHECK: call void asm
|
||||||
|
// CHECK-SAME: mov eax, $$12
|
||||||
|
__asm mov eax, x::A
|
||||||
|
// CHECK-SAME: mov eax, $$17
|
||||||
|
__asm mov eax, x::y_t::A
|
||||||
|
// CHECK-NEXT: call void asm
|
||||||
|
// CHECK-SAME: mov eax, $$1
|
||||||
|
__asm {mov eax, A}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: t2
|
||||||
|
void t2() {
|
||||||
|
enum { A = 1, B };
|
||||||
|
// CHECK: call void asm
|
||||||
|
// CHECK-SAME: mov eax, $$21
|
||||||
|
__asm mov eax, (A + 9) * 2 + A
|
||||||
|
// CHECK-SAME: mov eax, $$4
|
||||||
|
__asm mov eax, A << 2
|
||||||
|
// CHECK-SAME: mov eax, $$2
|
||||||
|
__asm mov eax, B & 3
|
||||||
|
// CHECK-SAME: mov eax, $$5
|
||||||
|
__asm mov eax, 3 + (B & 3)
|
||||||
|
// CHECK-SAME: mov eax, $$8
|
||||||
|
__asm mov eax, 2 << A * B
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: t3
|
||||||
|
void t3() {
|
||||||
|
int arr[4];
|
||||||
|
enum { A = 4, B };
|
||||||
|
// CHECK: call void asm
|
||||||
|
// CHECK-SAME: mov eax, [eax + $$47]
|
||||||
|
__asm { mov eax, [(x::A + 9) + A * B + 3 + 3 + eax] }
|
||||||
|
// CHECK-NEXT: call void asm
|
||||||
|
// CHECK-SAME: mov eax, dword ptr $0[$$4]
|
||||||
|
__asm { mov eax, dword ptr [arr + A] }
|
||||||
|
// CHECK-NEXT: call void asm
|
||||||
|
// CHECK-SAME: mov eax, dword ptr $0[$$8]
|
||||||
|
__asm { mov eax, dword ptr A[arr + A] }
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// REQUIRES: x86-registered-target
|
||||||
|
// RUN: %clang_cc1 %s -fasm-blocks -triple i386-apple-darwin10 -emit-llvm -o - | FileCheck %s
|
||||||
|
|
||||||
|
int gVar;
|
||||||
|
void t1() {
|
||||||
|
// CHECK: add eax, dword ptr gVar[eax]
|
||||||
|
__asm add eax, dword ptr gVar[eax]
|
||||||
|
// CHECK: add dword ptr gVar[eax], eax
|
||||||
|
__asm add dword ptr [eax+gVar], eax
|
||||||
|
// CHECK: add ebx, dword ptr gVar[ebx + $$270]
|
||||||
|
__asm add ebx, dword ptr gVar[271 - 82 + 81 + ebx]
|
||||||
|
// CHECK: add dword ptr gVar[ebx + $$828], ebx
|
||||||
|
__asm add dword ptr [ebx + gVar + 828], ebx
|
||||||
|
// CHECK: add ecx, dword ptr gVar[ecx + ecx * $$4 + $$4590]
|
||||||
|
__asm add ecx, dword ptr gVar[4590 + ecx + ecx*4]
|
||||||
|
// CHECK: add dword ptr gVar[ecx + ecx * $$8 + $$73], ecx
|
||||||
|
__asm add dword ptr [gVar + ecx + 45 + 23 - 53 + 60 - 2 + ecx*8], ecx
|
||||||
|
// CHECK: add gVar[ecx + ebx + $$7], eax
|
||||||
|
__asm add 1 + 1 + 2 + 3[gVar + ecx + ebx], eax
|
||||||
|
}
|
||||||
|
|
||||||
|
void t2() {
|
||||||
|
int lVar;
|
||||||
|
// CHECK: mov eax, dword ptr ${{[0-9]}}[eax]
|
||||||
|
__asm mov eax, dword ptr lVar[eax]
|
||||||
|
// CHECK: mov dword ptr ${{[0-9]}}[eax], eax
|
||||||
|
__asm mov dword ptr [eax+lVar], eax
|
||||||
|
// CHECK: mov ebx, dword ptr ${{[0-9]}}[ebx + $$270]
|
||||||
|
__asm mov ebx, dword ptr lVar[271 - 82 + 81 + ebx]
|
||||||
|
// CHECK: mov dword ptr ${{[0-9]}}[ebx + $$828], ebx
|
||||||
|
__asm mov dword ptr [ebx + lVar + 828], ebx
|
||||||
|
// CHECK: mov ${{[0-9]}}[ebx + $$47], eax
|
||||||
|
__asm mov 5 + 8 + 13 + 21[lVar + ebx], eax
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue