forked from OSchip/llvm-project
[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 llvm-svn: 314494
This commit is contained in:
parent
c3d24118e8
commit
6150419d71
|
@ -1474,7 +1474,6 @@ public:
|
|||
|
||||
ExprResult ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
||||
unsigned &NumLineToksConsumed,
|
||||
void *Info,
|
||||
bool IsUnevaluated);
|
||||
|
||||
private:
|
||||
|
|
|
@ -3788,15 +3788,15 @@ public:
|
|||
Expr *AsmString, MultiExprArg Clobbers,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
void FillInlineAsmIdentifierInfo(Expr *Res,
|
||||
llvm::InlineAsmIdentifierInfo &Info);
|
||||
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
||||
SourceLocation TemplateKWLoc,
|
||||
UnqualifiedId &Id,
|
||||
llvm::InlineAsmIdentifierInfo &Info,
|
||||
bool IsUnevaluatedContext);
|
||||
bool LookupInlineAsmField(StringRef Base, StringRef Member,
|
||||
unsigned &Offset, SourceLocation AsmLoc);
|
||||
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member,
|
||||
llvm::InlineAsmIdentifierInfo &Info,
|
||||
SourceLocation AsmLoc);
|
||||
StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
|
||||
ArrayRef<Token> AsmToks,
|
||||
|
|
|
@ -54,9 +54,9 @@ public:
|
|||
assert(AsmToks.size() == AsmTokOffsets.size());
|
||||
}
|
||||
|
||||
void *LookupInlineAsmIdentifier(StringRef &LineBuf,
|
||||
llvm::InlineAsmIdentifierInfo &Info,
|
||||
bool IsUnevaluatedContext) override {
|
||||
void LookupInlineAsmIdentifier(StringRef &LineBuf,
|
||||
llvm::InlineAsmIdentifierInfo &Info,
|
||||
bool IsUnevaluatedContext) override {
|
||||
// Collect the desired tokens.
|
||||
SmallVector<Token, 16> LineToks;
|
||||
const Token *FirstOrigToken = nullptr;
|
||||
|
@ -64,7 +64,7 @@ public:
|
|||
|
||||
unsigned NumConsumedToks;
|
||||
ExprResult Result = TheParser.ParseMSAsmIdentifier(
|
||||
LineToks, NumConsumedToks, &Info, IsUnevaluatedContext);
|
||||
LineToks, NumConsumedToks, IsUnevaluatedContext);
|
||||
|
||||
// If we consumed the entire line, tell MC that.
|
||||
// Also do this if we consumed nothing as a way of reporting failure.
|
||||
|
@ -89,9 +89,10 @@ public:
|
|||
LineBuf = LineBuf.substr(0, TotalOffset);
|
||||
}
|
||||
|
||||
// Initialize the "decl" with the lookup result.
|
||||
Info.OpDecl = static_cast<void *>(Result.get());
|
||||
return Info.OpDecl;
|
||||
// Initialize Info with the lookup result.
|
||||
if (!Result.isUsable())
|
||||
return;
|
||||
TheParser.getActions().FillInlineAsmIdentifierInfo(Result.get(), Info);
|
||||
}
|
||||
|
||||
StringRef LookupInlineAsmLabel(StringRef Identifier, llvm::SourceMgr &LSM,
|
||||
|
@ -178,16 +179,9 @@ private:
|
|||
}
|
||||
|
||||
/// 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,
|
||||
unsigned &NumLineToksConsumed,
|
||||
void *CastInfo,
|
||||
bool IsUnevaluatedContext) {
|
||||
llvm::InlineAsmIdentifierInfo &Info =
|
||||
*(llvm::InlineAsmIdentifierInfo *)CastInfo;
|
||||
|
||||
// Push a fake token on the end so that we don't overrun the token
|
||||
// stream. We use ';' because it expression-parsing should never
|
||||
// overrun it.
|
||||
|
@ -227,7 +221,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks,
|
|||
/*AllowDeductionGuide=*/false,
|
||||
/*ObjectType=*/nullptr, TemplateKWLoc, Id);
|
||||
// Perform the lookup.
|
||||
Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info,
|
||||
Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id,
|
||||
IsUnevaluatedContext);
|
||||
}
|
||||
// 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();
|
||||
ConsumeToken(); // Consume the identifier.
|
||||
Result = Actions.LookupInlineAsmVarDeclField(Result.get(), Id->getName(),
|
||||
Info, Tok.getLocation());
|
||||
Tok.getLocation());
|
||||
}
|
||||
|
||||
// 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 (!S.getLangOpts().HeinousExtensions)
|
||||
S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
|
||||
<< E->getSourceRange();
|
||||
<< E->getSourceRange();
|
||||
else
|
||||
S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
|
||||
<< E->getSourceRange();
|
||||
<< E->getSourceRange();
|
||||
// Accept, even if we emitted an error diagnostic.
|
||||
return false;
|
||||
}
|
||||
|
@ -607,23 +607,31 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
|
|||
return NS;
|
||||
}
|
||||
|
||||
static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T,
|
||||
llvm::InlineAsmIdentifierInfo &Info) {
|
||||
// Compute the type size (and array length if applicable?).
|
||||
Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
|
||||
if (T->isArrayType()) {
|
||||
const ArrayType *ATy = Context.getAsArrayType(T);
|
||||
Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
|
||||
Info.Length = Info.Size / Info.Type;
|
||||
void Sema::FillInlineAsmIdentifierInfo(Expr *Res,
|
||||
llvm::InlineAsmIdentifierInfo &Info) {
|
||||
QualType T = Res->getType();
|
||||
Expr::EvalResult Eval;
|
||||
if (T->isFunctionType() || T->isDependentType())
|
||||
return Info.setLabel(Res);
|
||||
if (Res->isRValue()) {
|
||||
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,
|
||||
SourceLocation TemplateKWLoc,
|
||||
UnqualifiedId &Id,
|
||||
llvm::InlineAsmIdentifierInfo &Info,
|
||||
bool IsUnevaluatedContext) {
|
||||
Info.clear();
|
||||
|
||||
if (IsUnevaluatedContext)
|
||||
PushExpressionEvaluationContext(
|
||||
|
@ -664,12 +672,6 @@ ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -743,9 +745,7 @@ bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
|
|||
|
||||
ExprResult
|
||||
Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
|
||||
llvm::InlineAsmIdentifierInfo &Info,
|
||||
SourceLocation AsmLoc) {
|
||||
Info.clear();
|
||||
|
||||
QualType T = E->getType();
|
||||
if (T->isDependentType()) {
|
||||
|
@ -780,14 +780,6 @@ Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
|
|||
ExprResult Result = BuildMemberReferenceExpr(
|
||||
E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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