Index: llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -38,6 +38,7 @@ #include "llvm/Support/raw_ostream.h" #include #include +#include using namespace llvm; @@ -432,6 +433,8 @@ short BracCount; bool MemExpr; bool OffsetOperator; + bool AttachToOperandIdx; + bool IsPIC; SMLoc OffsetOperatorLoc; AsmTypeInfo CurType; @@ -449,7 +452,8 @@ IntelExprStateMachine() : State(IES_INIT), PrevState(IES_ERROR), BaseReg(0), IndexReg(0), TmpReg(0), Scale(0), Imm(0), Sym(nullptr), BracCount(0), - MemExpr(false), OffsetOperator(false) {} + MemExpr(false), OffsetOperator(false), + AttachToOperandIdx(false), IsPIC(false) {} void addImm(int64_t imm) { Imm += imm; } short getBracCount() const { return BracCount; } @@ -469,9 +473,29 @@ bool isValidEndState() const { return State == IES_RBRAC || State == IES_INTEGER; } + + // Is the intel expression appended after an operand index. + // [OperandIdx][Intel Expression] + // This is neccessary for checking if it is an independent + // intel expression at back end when parse inline asm. + void setAppendAfterOperand() { AttachToOperandIdx = true; } + + bool isPIC() const { return IsPIC; } + void setPIC() { IsPIC = true; } + bool hadError() const { return State == IES_ERROR; } const InlineAsmIdentifierInfo &getIdentifierInfo() const { return Info; } + bool regsUseUpError(StringRef &ErrMsg) { + // This case mostly happen in inline asm, e.g. Arr[BaseReg + IndexReg] + // can not intruduce additional register in inline asm in PIC model. + if (IsPIC && (!SymName.empty() || AttachToOperandIdx)) + ErrMsg = "Don't use 2 or more regs for mem offset in PIC model!"; + else + ErrMsg = "BaseReg/IndexReg already set!"; + return true; + } + void onOr() { IntelExprState CurrState = State; switch (State) { @@ -655,10 +679,8 @@ if (!BaseReg) { BaseReg = TmpReg; } else { - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; - return true; - } + if (IndexReg) + return regsUseUpError(ErrMsg); IndexReg = TmpReg; Scale = 0; } @@ -716,10 +738,8 @@ if (!BaseReg) { BaseReg = TmpReg; } else { - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; - return true; - } + if (IndexReg) + return regsUseUpError(ErrMsg); IndexReg = TmpReg; Scale = 0; } @@ -777,10 +797,8 @@ case IES_MULTIPLY: // Index Register - Scale * Register if (PrevState == IES_INTEGER) { - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; - return true; - } + if (IndexReg) + return regsUseUpError(ErrMsg); State = IES_REGISTER; IndexReg = Reg; // Get the scale and replace the 'Scale * Register' with '0'. @@ -820,8 +838,20 @@ case IES_INIT: case IES_LBRAC: case IES_LPAREN: - if (setSymRef(SymRef, SymRefName, ErrMsg)) - return true; + // The InineAsm can also be parsed from emitInlineAsm (not from FE) + // which may generate "Sym - BaseSym" for pic-base-offset addressing + // model (e.g. i386-darwin). + // Here we remove "- BaseSym" in inlineasm if it exists. + // TODO(RefineMe): Here is an architecture defect for both FE parser + // and BE emitInlineAsm share the same way to parse the inline asm. + // So the 2 symbol syntax checking may not be always right. + if (isPIC()) { + if (!Sym && setSymRef(SymRef, SymRefName, ErrMsg)) + return true; + } else { + if (setSymRef(SymRef, SymRefName, ErrMsg)) + return true; + } MemExpr = true; State = IES_INTEGER; IC.pushOperand(IC_IMM); @@ -861,10 +891,8 @@ State = IES_INTEGER; if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) { // Index Register - Register * Scale - if (IndexReg) { - ErrMsg = "BaseReg/IndexReg already set!"; - return true; - } + if (IndexReg) + return regsUseUpError(ErrMsg); IndexReg = TmpReg; Scale = TmpInt; if (checkScale(Scale, ErrMsg)) @@ -945,7 +973,7 @@ BracCount++; return false; } - bool onRBrac() { + bool onRBrac(StringRef &ErrMsg) { IntelExprState CurrState = State; switch (State) { default: @@ -955,8 +983,10 @@ case IES_OFFSET: case IES_REGISTER: case IES_RPAREN: - if (BracCount-- != 1) + if (BracCount-- != 1) { + ErrMsg = "unexpected bracket encountered"; return true; + } State = IES_RBRAC; if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) { // If we already have a BaseReg, then assume this is the IndexReg with @@ -964,7 +994,8 @@ if (!BaseReg) { BaseReg = TmpReg; } else { - assert (!IndexReg && "BaseReg/IndexReg already set!"); + if (IndexReg) + return regsUseUpError(ErrMsg); IndexReg = TmpReg; Scale = 0; } @@ -1033,8 +1064,20 @@ case IES_PLUS: case IES_INIT: case IES_LBRAC: - if (setSymRef(Val, ID, ErrMsg)) - return true; + // The InineAsm can also be parsed from emitInlineAsm (not from FE) + // which may generate "Sym - BaseSym" for pic-base-offset addressing + // model (e.g. i386-darwin). + // Here we remove "- BaseSym" in inlineasm if it exists. + // TODO(RefineMe): Here is an architecture defect for both FE parser + // and BE emitInlineAsm share the same way to parse the inline asm. + // So the 2 symbol syntax checking may not be always right. + if (isPIC()) { + if (!Sym && setSymRef(Val, ID, ErrMsg)) + return true; + } else { + if (setSymRef(Val, ID, ErrMsg)) + return true; + } OffsetOperator = true; OffsetOperatorLoc = OffsetLoc; State = IES_OFFSET; @@ -1111,6 +1154,8 @@ InlineAsmIdentifierInfo &Info, bool IsUnevaluatedOperand, SMLoc &End, bool IsParsingOffsetOperator = false); + void tryParseOperandIdx(std::queue &PrevTKs, + IntelExprStateMachine &SM); bool ParseMemOperand(unsigned SegReg, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, OperandVector &Operands); @@ -1841,15 +1886,39 @@ return true; } +// Check if current intel expression append after an operand. +// Like: [Operand][Intel Expression] +void X86AsmParser::tryParseOperandIdx(std::queue &PrevTKs, + IntelExprStateMachine &SM) { + if (PrevTKs.size() != 3) + return; + + if (PrevTKs.front() != AsmToken::LBrac || + PrevTKs.back() != AsmToken::RBrac) + return; + + PrevTKs.pop(); + if (PrevTKs.front() != AsmToken::Integer && + PrevTKs.front() != AsmToken::Identifier) + return; + + SM.setAppendAfterOperand(); +} + bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { MCAsmParser &Parser = getParser(); StringRef ErrMsg; - AsmToken::TokenKind PrevTK = AsmToken::Error; + std::queue PrevTKs; + PrevTKs.push(AsmToken::Error); + + if (getContext().getObjectFileInfo()->isPositionIndependent()) + SM.setPIC(); + bool Done = false; while (!Done) { // Get a fresh reference on each loop iteration in case the previous - // iteration moved the token storage during UnLex(). + // iteration moved the token storage during UnLenx(). const AsmToken &Tok = Parser.getTok(); bool UpdateLocLex = true; @@ -1998,7 +2067,8 @@ if (isParsingMSInlineAsm() || Parser.isParsingMasm()) { // MS Dot Operator expression if (Identifier.count('.') && - (PrevTK == AsmToken::RBrac || PrevTK == AsmToken::RParen)) { + (PrevTKs.back() == AsmToken::RBrac || + PrevTKs.back() == AsmToken::RParen)) { if (ParseIntelDotOperator(SM, End)) return true; break; @@ -2123,10 +2193,12 @@ case AsmToken::LBrac: if (SM.onLBrac()) return Error(Tok.getLoc(), "unexpected bracket encountered"); + tryParseOperandIdx(PrevTKs, SM); break; case AsmToken::RBrac: - if (SM.onRBrac()) - return Error(Tok.getLoc(), "unexpected bracket encountered"); + if (SM.onRBrac(ErrMsg)) { + return Error(Tok.getLoc(), ErrMsg); + } break; case AsmToken::LParen: SM.onLParen(); break; case AsmToken::RParen: SM.onRParen(); break; @@ -2137,7 +2209,11 @@ if (!Done && UpdateLocLex) End = consumeToken(); - PrevTK = TK; + // Update history token kinds. + // Currently we only need to keep 3 token kinds. + PrevTKs.push(TK); + if (PrevTKs.size() > 3) + PrevTKs.pop(); } return false; } @@ -2592,6 +2668,7 @@ CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(), ErrMsg)) return Error(Start, ErrMsg); + if (isParsingMSInlineAsm()) return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale, Start, End, Size, SM.getSymName(), Index: llvm/lib/Target/X86/X86AsmPrinter.cpp =================================================================== --- llvm/lib/Target/X86/X86AsmPrinter.cpp +++ llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -362,6 +362,14 @@ BaseReg.getReg() == X86::RIP) HasBaseReg = false; + // If we really just want to print out displacement. + bool HasIndexReg = IndexReg.getReg() != 0; + if (Modifier && (DispSpec.isGlobal() || DispSpec.isSymbol()) && + !strcmp(Modifier, "disp-only")) { + HasBaseReg = false; + HasIndexReg = false; + } + // If this has a segment register, print it. if (SegReg.getReg()) { PrintOperand(MI, OpNo + X86::AddrSegmentReg, O); @@ -607,7 +615,7 @@ return false; case 'P': // Don't print @PLT, but do print as memory. if (MI->getInlineAsmDialect() == InlineAsm::AD_Intel) { - PrintIntelMemReference(MI, OpNo, O, "no-rip"); + PrintIntelMemReference(MI, OpNo, O, "disp-only"); } else { PrintMemReference(MI, OpNo, O, "no-rip"); } Index: llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-1.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-1.ll @@ -0,0 +1,95 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-unknown-unknown -relocation-model=pic %s -o - | FileCheck %s + +; Tests come from "clang/test/CodeGen/ms-inline-asm-variables.c" +; int gVar; +; void t1() { +; __asm add eax, dword ptr gVar[rax] +; __asm add dword ptr [rax+gVar], eax +; __asm add ebx, dword ptr gVar[271 - 82 + 81 + rbx] +; __asm add dword ptr [rbx + gVar + 828], ebx +; gVar = 3; +; } +; +; void t2(void) { +; int lVar; +; __asm mov eax, dword ptr lVar[rax] +; __asm mov dword ptr [rax+lVar], eax +; __asm mov ebx, dword ptr lVar[271 - 82 + 81 + rbx] +; __asm mov dword ptr [rbx + lVar + 828], ebx +; __asm mov 5 + 8 + 13 + 21[lVar + rbx], eax +; lVar = 2; +; } + +@gVar = global i32 0, align 4 + +; Function Attrs: noinline nounwind optnone uwtable +define void @t1() #0 { +; CHECK-LABEL: t1: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset %rbp, -16 +; CHECK-NEXT: movq %rsp, %rbp +; CHECK-NEXT: .cfi_def_cfa_register %rbp +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: .cfi_offset %rbx, -24 +; CHECK-NEXT: movq gVar@GOTPCREL(%rip), %rcx +; CHECK-NEXT: #APP +; CHECK-EMPTY: +; CHECK-NEXT: addl (%rcx,%rax), %eax +; CHECK-NEXT: addl %eax, (%rcx,%rax) +; CHECK-NEXT: addl 270(%rcx,%rbx), %ebx +; CHECK-NEXT: addl %ebx, 828(%rcx,%rbx) +; CHECK-EMPTY: +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: movq gVar@GOTPCREL(%rip), %rax +; CHECK-NEXT: movl $3, (%rax) +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: .cfi_def_cfa %rsp, 8 +; CHECK-NEXT: retq +entry: + call void asm sideeffect inteldialect "add eax, dword ptr $2[rax]\0A\09add dword ptr $0[rax], eax\0A\09add ebx, dword ptr $3[rbx + $$270]\0A\09add dword ptr $1[rbx + $$828], ebx", "=*m,=*m,*m,*m,~{eax},~{ebx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) #1 + store i32 3, i32* @gVar, align 4 + ret void +} + +; Function Attrs: noinline nounwind optnone uwtable +define void @t2() #0 { +; CHECK-LABEL: t2: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .cfi_offset %rbp, -16 +; CHECK-NEXT: movq %rsp, %rbp +; CHECK-NEXT: .cfi_def_cfa_register %rbp +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: .cfi_offset %rbx, -24 +; CHECK-NEXT: #APP +; CHECK-EMPTY: +; CHECK-NEXT: movl -12(%rbp,%rax), %eax +; CHECK-NEXT: movl %eax, -12(%rbp,%rax) +; CHECK-NEXT: movl 258(%rbp,%rbx), %ebx +; CHECK-NEXT: movl %ebx, 816(%rbp,%rbx) +; CHECK-NEXT: movl %eax, 35(%rbp,%rbx) +; CHECK-EMPTY: +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: movl $2, -12(%rbp) +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: .cfi_def_cfa %rsp, 8 +; CHECK-NEXT: retq +entry: + %lVar = alloca i32, align 4 + call void asm sideeffect inteldialect "mov eax, dword ptr $3[rax]\0A\09mov dword ptr $0[rax], eax\0A\09mov ebx, dword ptr $4[rbx + $$270]\0A\09mov dword ptr $1[rbx + $$828], ebx\0A\09mov $2[rbx + $$47], eax", "=*m,=*m,=*m,*m,*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar) #1 + store i32 2, i32* %lVar, align 4 + ret void +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nounwind } + +!llvm.module.flags = !{!0} + +!0 = !{i32 1, !"wchar_size", i32 4} Index: llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-2.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/ms-inline-asm-variables-x64-2.ll @@ -0,0 +1,31 @@ +; RUN: not llc -mtriple=x86_64-unknown-unknown -relocation-model=pic %s -o /dev/null 2>&1 | FileCheck %s + +; Tests come from "clang/test/CodeGen/ms-inline-asm-variables.c" +; +; int gVar; +; void t1() { +; __asm add ecx, dword ptr gVar[4590 + rax + rcx*4] +; __asm add dword ptr [gVar + rax + 45 + 23 - 53 + 60 - 2 + rcx*8], ecx +; __asm add 1 + 1 + 2 + 3[gVar + rcx + rbx], eax +; gVar = 3; +; } + +@gVar = global i32 0, align 4 + +; Function Attrs: noinline nounwind optnone uwtable +define void @t1() #0 { +; CHECK: error: Don't use 2 or more regs for mem offset in PIC model +; CHECK: error: Don't use 2 or more regs for mem offset in PIC model +; CHECK: error: Don't use 2 or more regs for mem offset in PIC model +entry: + call void asm sideeffect inteldialect "add ecx, dword ptr ${2:P}[rax + rcx * $$4 + $$4590]\0A\09add dword ptr ${0:P}[rcx + rcx * $$8 + $$73], ecx\0A\09add ${1:P}[rcx + rbx + $$7], eax", "=*m,=*m,*m,~{ecx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) + store i32 3, i32* @gVar, align 4 + ret void +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nounwind } + +!llvm.module.flags = !{!0} + +!0 = !{i32 1, !"wchar_size", i32 4} Index: llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-1.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-1.ll @@ -0,0 +1,153 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=i386-unknown-unknown %s -o - | FileCheck --check-prefix=X86 %s +; RUN: llc -mtriple=i386-unknown-unknown -relocation-model=pic %s -o -| FileCheck --check-prefix=X86PIC %s + +; Tests come from clang/test/CodeGen/ms-inline-asm-variables.c +; +; int gVar; +; void t1() { +; __asm add eax, dword ptr gVar[eax] +; __asm add dword ptr [eax+gVar], eax +; __asm add ebx, dword ptr gVar[271 - 82 + 81 + ebx] +; __asm add dword ptr [ebx + gVar + 828], ebx +; gVar = 3; +; } +; +; void t2(void) { +; int lVar; +; __asm mov eax, dword ptr lVar[eax] +; __asm mov dword ptr [eax+lVar], eax +; __asm mov ebx, dword ptr lVar[271 - 82 + 81 + ebx] +; __asm mov dword ptr [ebx + lVar + 828], ebx +; __asm mov 5 + 8 + 13 + 21[lVar + ebx], eax +; lVar = 2; +; } + +@gVar = global i32 0, align 4 + +; Function Attrs: noinline nounwind optnone uwtable +define void @t1() #0 { +; X86-LABEL: t1: +; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: .cfi_offset %ebx, -12 +; X86-NEXT: #APP +; X86-EMPTY: +; X86-NEXT: addl gVar(%eax), %eax +; X86-NEXT: addl %eax, gVar(%eax) +; X86-NEXT: addl gVar+270(%ebx), %ebx +; X86-NEXT: addl %ebx, gVar+828(%ebx) +; X86-EMPTY: +; X86-NEXT: #NO_APP +; X86-NEXT: movl $3, gVar +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 +; X86-NEXT: retl +; +; X86PIC-LABEL: t1: +; X86PIC: # %bb.0: # %entry +; X86PIC-NEXT: pushl %ebp +; X86PIC-NEXT: .cfi_def_cfa_offset 8 +; X86PIC-NEXT: .cfi_offset %ebp, -8 +; X86PIC-NEXT: movl %esp, %ebp +; X86PIC-NEXT: .cfi_def_cfa_register %ebp +; X86PIC-NEXT: pushl %ebx +; X86PIC-NEXT: .cfi_offset %ebx, -12 +; X86PIC-NEXT: calll .L0$pb +; X86PIC-NEXT: .L0$pb: +; X86PIC-NEXT: popl %ecx +; X86PIC-NEXT: .Ltmp0: +; X86PIC-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb), %ecx +; X86PIC-NEXT: movl gVar@GOT(%ecx), %edx +; X86PIC-NEXT: #APP +; X86PIC-EMPTY: +; X86PIC-NEXT: addl (%edx,%eax), %eax +; X86PIC-NEXT: addl %eax, (%edx,%eax) +; X86PIC-NEXT: addl 270(%edx,%ebx), %ebx +; X86PIC-NEXT: addl %ebx, 828(%edx,%ebx) +; X86PIC-EMPTY: +; X86PIC-NEXT: #NO_APP +; X86PIC-NEXT: movl gVar@GOT(%ecx), %eax +; X86PIC-NEXT: movl $3, (%eax) +; X86PIC-NEXT: popl %ebx +; X86PIC-NEXT: popl %ebp +; X86PIC-NEXT: .cfi_def_cfa %esp, 4 +; X86PIC-NEXT: retl +entry: + call void asm sideeffect inteldialect "add eax, dword ptr $2[eax]\0A\09add dword ptr $0[eax], eax\0A\09add ebx, dword ptr $3[ebx + $$270]\0A\09add dword ptr $1[ebx + $$828], ebx", "=*m,=*m,*m,*m,~{eax},~{ebx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) + store i32 3, i32* @gVar, align 4 + ret void +} + +; Function Attrs: noinline nounwind optnone uwtable +define void @t2() #0 { +; X86-LABEL: t2: +; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: pushl %ebx +; X86-NEXT: pushl %eax +; X86-NEXT: .cfi_offset %ebx, -12 +; X86-NEXT: #APP +; X86-EMPTY: +; X86-NEXT: movl -8(%ebp,%eax), %eax +; X86-NEXT: movl %eax, -8(%ebp,%eax) +; X86-NEXT: movl 262(%ebp,%ebx), %ebx +; X86-NEXT: movl %ebx, 820(%ebp,%ebx) +; X86-NEXT: movl %eax, 39(%ebp,%ebx) +; X86-EMPTY: +; X86-NEXT: #NO_APP +; X86-NEXT: movl $2, -8(%ebp) +; X86-NEXT: addl $4, %esp +; X86-NEXT: popl %ebx +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 +; X86-NEXT: retl +; +; X86PIC-LABEL: t2: +; X86PIC: # %bb.0: # %entry +; X86PIC-NEXT: pushl %ebp +; X86PIC-NEXT: .cfi_def_cfa_offset 8 +; X86PIC-NEXT: .cfi_offset %ebp, -8 +; X86PIC-NEXT: movl %esp, %ebp +; X86PIC-NEXT: .cfi_def_cfa_register %ebp +; X86PIC-NEXT: pushl %ebx +; X86PIC-NEXT: pushl %eax +; X86PIC-NEXT: .cfi_offset %ebx, -12 +; X86PIC-NEXT: #APP +; X86PIC-EMPTY: +; X86PIC-NEXT: movl -8(%ebp,%eax), %eax +; X86PIC-NEXT: movl %eax, -8(%ebp,%eax) +; X86PIC-NEXT: movl 262(%ebp,%ebx), %ebx +; X86PIC-NEXT: movl %ebx, 820(%ebp,%ebx) +; X86PIC-NEXT: movl %eax, 39(%ebp,%ebx) +; X86PIC-EMPTY: +; X86PIC-NEXT: #NO_APP +; X86PIC-NEXT: movl $2, -8(%ebp) +; X86PIC-NEXT: addl $4, %esp +; X86PIC-NEXT: popl %ebx +; X86PIC-NEXT: popl %ebp +; X86PIC-NEXT: .cfi_def_cfa %esp, 4 +; X86PIC-NEXT: retl +entry: + %lVar = alloca i32, align 4 + call void asm sideeffect inteldialect "mov eax, dword ptr $3[eax]\0A\09mov dword ptr $0[eax], eax\0A\09mov ebx, dword ptr $4[ebx + $$270]\0A\09mov dword ptr $1[ebx + $$828], ebx\0A\09mov $2[ebx + $$47], eax", "=*m,=*m,=*m,*m,*m,~{eax},~{ebx},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar, i32* elementtype(i32) %lVar) + store i32 2, i32* %lVar, align 4 + ret void +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nounwind } + +!llvm.module.flags = !{!0} + +!0 = !{i32 1, !"NumRegisterParameters", i32 0} Index: llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-2.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/ms-inline-asm-variables-x86-2.ll @@ -0,0 +1,54 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=i386-unknown-unknown %s -o - | FileCheck --check-prefix=X86 %s +; RUN: not llc -mtriple=i386-unknown-unknown -relocation-model=pic %s -o /dev/null 2>&1 | FileCheck --check-prefix=X86PIC %s + +; Tests come from "clang/test/CodeGen/ms-inline-asm-variables.c" +; +; int gVar; +; void t1() { +; __asm add ecx, dword ptr gVar[4590 + eax + ecx*4] +; __asm add dword ptr [gVar + eax + 45 + 23 - 53 + 60 - 2 + ecx*8], ecx +; __asm add 1 + 1 + 2 + 3[gVar + ecx + ebx], eax +; +; gVar = 3; +; } + +@gVar = global i32 0, align 4 + +; Function Attrs: noinline nounwind optnone uwtable +define void @t1() #0 { +; X86-LABEL: t1: +; X86: # %bb.0: # %entry +; X86-NEXT: pushl %ebp +; X86-NEXT: .cfi_def_cfa_offset 8 +; X86-NEXT: .cfi_offset %ebp, -8 +; X86-NEXT: movl %esp, %ebp +; X86-NEXT: .cfi_def_cfa_register %ebp +; X86-NEXT: #APP +; X86-EMPTY: +; X86-NEXT: addl gVar+4590(%eax,%ecx,4), %ecx +; X86-NEXT: addl %ecx, gVar+73(%eax,%ecx,8) +; X86-NEXT: addl %eax, gVar+7(%ecx,%ebx) +; X86-EMPTY: +; X86-NEXT: #NO_APP +; X86-NEXT: movl $3, gVar +; X86-NEXT: popl %ebp +; X86-NEXT: .cfi_def_cfa %esp, 4 +; X86-NEXT: retl + +; X86PIC: error: Don't use 2 or more regs for mem offset in PIC model +; X86PIC: error: Don't use 2 or more regs for mem offset in PIC model +; X86PIC: error: Don't use 2 or more regs for mem offset in PIC model + +entry: + call void asm sideeffect inteldialect "add ecx, dword ptr ${2:P}[eax + ecx * $$4 + $$4590]\0A\09add dword ptr ${0:P}[eax + ecx * $$8 + $$73], ecx\0A\09add ${1:P}[ecx + ebx + $$7], eax", "=*m,=*m,*m,~{eax},~{ecx},~{flags},~{dirflag},~{fpsr},~{flags}"(i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar, i32* elementtype(i32) @gVar) #1 + store i32 3, i32* @gVar, align 4 + ret void +} + +attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +attributes #1 = { nounwind } + +!llvm.module.flags = !{!0} + +!0 = !{i32 1, !"NumRegisterParameters", i32 0}