Author: rnk Date: Wed Aug 26 16:57:20 2015 New Revision: 246088 URL: http://llvm.org/viewvc/llvm-project?rev=246088&view=rev Log: [ms-inline-asm] Add field access to MS inline asm identifier lookup
Now we can parse code like this: struct A { int field; }; int f(A o) { __asm mov eax, o.field } Fixes PR19117. Added: cfe/trunk/test/CodeGenCXX/ms-inline-asm-fields.cpp cfe/trunk/test/SemaCXX/ms-inline-asm.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Parse/ParseStmtAsm.cpp cfe/trunk/lib/Sema/SemaStmtAsm.cpp cfe/trunk/test/CodeGen/ms-inline-asm.c Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=246088&r1=246087&r2=246088&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 26 16:57:20 2015 @@ -3375,6 +3375,10 @@ public: bool IsUnevaluatedContext); bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc); + ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, + unsigned &Offset, + llvm::InlineAsmIdentifierInfo &Info, + SourceLocation AsmLoc); StmtResult ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef<Token> AsmToks, StringRef AsmString, Modified: cfe/trunk/lib/Parse/ParseStmtAsm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmtAsm.cpp?rev=246088&r1=246087&r2=246088&view=diff ============================================================================== --- cfe/trunk/lib/Parse/ParseStmtAsm.cpp (original) +++ cfe/trunk/lib/Parse/ParseStmtAsm.cpp Wed Aug 26 16:57:20 2015 @@ -222,6 +222,25 @@ ExprResult Parser::ParseMSAsmIdentifier( /*AllowConstructorName=*/false, /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); + // Perform the lookup. + ExprResult Result = Actions.LookupInlineAsmIdentifier( + SS, TemplateKWLoc, Id, Info, IsUnevaluatedContext); + + // While the next two tokens are 'period' 'identifier', repeatedly parse it as + // a field access. We have to avoid consuming assembler directives that look + // like '.' 'else'. + while (Result.isUsable() && Tok.is(tok::period)) { + Token IdTok = PP.LookAhead(0); + if (IdTok.isNot(tok::identifier)) + break; + ConsumeToken(); // Consume the period. + IdentifierInfo *Id = Tok.getIdentifierInfo(); + ConsumeToken(); // Consume the identifier. + unsigned OffsetUnused; + Result = Actions.LookupInlineAsmVarDeclField( + Result.get(), Id->getName(), OffsetUnused, Info, Tok.getLocation()); + } + // Figure out how many tokens we are into LineToks. unsigned LineIndex = 0; if (Tok.is(EndOfStream)) { @@ -254,9 +273,7 @@ ExprResult Parser::ParseMSAsmIdentifier( LineToks.pop_back(); LineToks.pop_back(); - // Perform the lookup. - return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, - IsUnevaluatedContext); + return Result; } /// Turn a sequence of our tokens back into a string that we can hand Modified: cfe/trunk/lib/Sema/SemaStmtAsm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmtAsm.cpp?rev=246088&r1=246087&r2=246088&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaStmtAsm.cpp (original) +++ cfe/trunk/lib/Sema/SemaStmtAsm.cpp Wed Aug 26 16:57:20 2015 @@ -528,6 +528,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceL 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; + } +} + ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, @@ -575,13 +586,7 @@ ExprResult Sema::LookupInlineAsmIdentifi return ExprError(); } - // 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; - } + fillInlineAsmTypeInfo(Context, T, Info); // We can work with the expression as long as it's not an r-value. if (!Result.get()->isRValue()) @@ -636,6 +641,49 @@ bool Sema::LookupInlineAsmField(StringRe return false; } +ExprResult +Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member, unsigned &Offset, + llvm::InlineAsmIdentifierInfo &Info, + SourceLocation AsmLoc) { + Info.clear(); + + const RecordType *RT = E->getType()->getAs<RecordType>(); + // FIXME: Diagnose this as field access into a scalar type. + if (!RT) + return ExprResult(); + + LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc, + LookupMemberName); + + if (!LookupQualifiedName(FieldResult, RT->getDecl())) + return ExprResult(); + + // Only normal and indirect field results will work. + ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl()); + if (!FD) + return ExprResult(); + + Offset = (unsigned)Context.toCharUnitsFromBits(Context.getFieldOffset(FD)) + .getQuantity(); + + // Make an Expr to thread through OpDecl. + ExprResult Result = BuildMemberReferenceExpr( + E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(), + SourceLocation(), nullptr, FieldResult, 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; +} + StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, ArrayRef<Token> AsmToks, StringRef AsmString, Modified: cfe/trunk/test/CodeGen/ms-inline-asm.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ms-inline-asm.c?rev=246088&r1=246087&r2=246088&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/ms-inline-asm.c (original) +++ cfe/trunk/test/CodeGen/ms-inline-asm.c Wed Aug 26 16:57:20 2015 @@ -563,3 +563,21 @@ void label4() { // CHECK-LABEL: define void @label4 // CHECK: call void asm sideeffect inteldialect "{{.*}}__MSASMLABEL_.4__label:\0A\09mov eax, {{.*}}__MSASMLABEL_.4__label", "~{eax},~{dirflag},~{fpsr},~{flags}"() } + +typedef union _LARGE_INTEGER { + struct { + unsigned int LowPart; + unsigned int HighPart; + }; + struct { + unsigned int LowPart; + unsigned int HighPart; + } u; + unsigned long long QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +int test_indirect_field(LARGE_INTEGER LargeInteger) { + __asm mov eax, LargeInteger.LowPart +} +// CHECK-LABEL: define i32 @test_indirect_field( +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", Added: cfe/trunk/test/CodeGenCXX/ms-inline-asm-fields.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-inline-asm-fields.cpp?rev=246088&view=auto ============================================================================== --- cfe/trunk/test/CodeGenCXX/ms-inline-asm-fields.cpp (added) +++ cfe/trunk/test/CodeGenCXX/ms-inline-asm-fields.cpp Wed Aug 26 16:57:20 2015 @@ -0,0 +1,31 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -fasm-blocks -emit-llvm -o - | FileCheck %s + +struct A { + int a1; + int a2; + struct B { + int b1; + int b2; + } a3; +}; + +namespace asdf { +A a_global; +} + +extern "C" int test_param_field(A p) { +// CHECK: define i32 @test_param_field(%struct.A* byval align 4 %p) +// CHECK: getelementptr inbounds %struct.A, %struct.A* %p, i32 0, i32 0 +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1" +// CHECK: ret i32 + __asm mov eax, p.a1 +} + +extern "C" int test_namespace_global() { +// CHECK: define i32 @test_namespace_global() +// CHECK: call i32 asm sideeffect inteldialect "mov eax, dword ptr $1", "{{.*}}"(i32* getelementptr inbounds (%struct.A, %struct.A* @_ZN4asdf8a_globalE, i32 0, i32 2, i32 1)) +// CHECK: ret i32 + __asm mov eax, asdf::a_global.a3.b2 +} + Added: cfe/trunk/test/SemaCXX/ms-inline-asm.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ms-inline-asm.cpp?rev=246088&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/ms-inline-asm.cpp (added) +++ cfe/trunk/test/SemaCXX/ms-inline-asm.cpp Wed Aug 26 16:57:20 2015 @@ -0,0 +1,54 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 %s -triple i386-apple-darwin10 -fasm-blocks -verify + +struct A { + int a1; + int a2; + struct B { + int b1; + int b2; + enum { kValue = 42 }; + } a3; + struct { + int indirect_field; + }; +}; + +namespace asdf { +A a_global; +} + +// The parser combines adjacent __asm blocks into one. Avoid that by calling +// this. +void split_inline_asm_call(); + +void test_field_lookup() { + __asm mov eax, asdf::a_global.a3.b2 + split_inline_asm_call(); + + // FIXME: These diagnostics are crap. + + // expected-error@+1 {{undeclared label}} + __asm mov eax, asdf::a_global.not_a_field.b2 + split_inline_asm_call(); + + // expected-error@+1 {{undeclared label}} + __asm mov eax, asdf::a_global.a3.not_a_field + split_inline_asm_call(); + + __asm mov eax, A::B::kValue + split_inline_asm_call(); + + // expected-error@+1 {{undeclared label}} + __asm mov eax, asdf::a_global.a3.kValue + split_inline_asm_call(); + + __asm mov eax, asdf :: a_global.a3.b2 + split_inline_asm_call(); + + __asm mov eax, asdf::a_global . a3 . b2 + split_inline_asm_call(); + + __asm mov eax, asdf::a_global.indirect_field + split_inline_asm_call(); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits