From 2fbc239e4fbdd12c24fb2cf9e3e915861fc12030 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Mon, 29 Oct 2012 18:01:54 +0000 Subject: [PATCH] [ms-inline asm] Add support for the [] operator. Essentially, [expr1][expr2] is equivalent to [expr1 + expr2]. See test cases for more examples. rdar://12470392 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@166949 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/AsmParser/X86AsmParser.cpp | 47 ++++++++-- test/CodeGen/X86/ms-inline-asm.ll | 107 ++++++++++++++++++++++ test/MC/X86/x86-32-ms-inline-asm.s | 50 ++++++++++ 3 files changed, 194 insertions(+), 10 deletions(-) diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 4bd9db98379..ce446e75737 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -695,6 +695,7 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, if (getLexer().isNot(AsmToken::RBrac)) return ErrorOperand(Start, "Expected ']' token!"); Parser.Lex(); + End = Tok.getLoc(); return X86Operand::CreateMem(Disp, Start, End, Size); } } else if (getLexer().is(AsmToken::Integer)) { @@ -704,6 +705,7 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, if (getLexer().is(AsmToken::RBrac)) { // Handle '[' number ']' Parser.Lex(); + End = Tok.getLoc(); const MCExpr *Disp = MCConstantExpr::Create(Val, getContext()); if (SegReg) return X86Operand::CreateMem(SegReg, Disp, 0, 0, Scale, @@ -720,9 +722,20 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, return ErrorOperand(Loc, "Unexpected token"); } - if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus)) { - bool isPlus = getLexer().is(AsmToken::Plus); + // Parse ][ as a plus. + bool ExpectRBrac = true; + if (getLexer().is(AsmToken::RBrac)) { + ExpectRBrac = false; Parser.Lex(); + End = Tok.getLoc(); + } + + if (getLexer().is(AsmToken::Plus) || getLexer().is(AsmToken::Minus) || + getLexer().is(AsmToken::LBrac)) { + ExpectRBrac = true; + bool isPlus = getLexer().is(AsmToken::Plus) || + getLexer().is(AsmToken::LBrac); + Parser.Lex(); SMLoc PlusLoc = Tok.getLoc(); if (getLexer().is(AsmToken::Integer)) { int64_t Val = Tok.getIntVal(); @@ -746,15 +759,29 @@ X86Operand *X86AsmParser::ParseIntelBracExpression(unsigned SegReg, else if (getParser().ParseExpression(Disp, End)) return 0; } } + + // Parse ][ as a plus. + if (getLexer().is(AsmToken::RBrac)) { + ExpectRBrac = false; + Parser.Lex(); + End = Tok.getLoc(); + if (getLexer().is(AsmToken::LBrac)) { + ExpectRBrac = true; + Parser.Lex(); + if (getParser().ParseExpression(Disp, End)) + return 0; + } + } else if (ExpectRBrac) { + if (getParser().ParseExpression(Disp, End)) + return 0; + } - if (getLexer().isNot(AsmToken::RBrac)) - if (getParser().ParseExpression(Disp, End)) return 0; - - End = Tok.getLoc(); - if (getLexer().isNot(AsmToken::RBrac)) - return ErrorOperand(End, "expected ']' token!"); - Parser.Lex(); - End = Tok.getLoc(); + if (ExpectRBrac) { + if (getLexer().isNot(AsmToken::RBrac)) + return ErrorOperand(End, "expected ']' token!"); + Parser.Lex(); + End = Tok.getLoc(); + } // Parse the dot operator (e.g., [ebx].foo.bar). if (Tok.getString().startswith(".")) { diff --git a/test/CodeGen/X86/ms-inline-asm.ll b/test/CodeGen/X86/ms-inline-asm.ll index 24d28adda89..403da3f34ea 100644 --- a/test/CodeGen/X86/ms-inline-asm.ll +++ b/test/CodeGen/X86/ms-inline-asm.ll @@ -61,3 +61,110 @@ entry: ; CHECK: .att_syntax ; CHECK: {{## InlineAsm End|#NO_APP}} } + +define void @t21() nounwind { +; CHECK: t21 +entry: + br label %foo + +foo: ; preds = %entry + call void asm sideeffect inteldialect "mov eax, [4*eax + 4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [4*eax + 4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [4*eax][4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [4*eax][4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi + eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi + eax] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi][eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi][eax] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi + 4*eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi + 4*eax] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi][4*eax]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi][4*eax] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi + eax + 4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi + eax + 4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi][eax + 4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi][eax + 4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi + eax][4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi + eax][4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi][eax][4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi][eax][4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi + 2*eax + 4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi + 2*eax + 4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi][2*eax + 4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi][2*eax + 4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi + 2*eax][4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi + 2*eax][4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + call void asm sideeffect inteldialect "mov eax, [esi][2*eax][4]", "~{eax},~{dirflag},~{fpsr},~{flags}"() nounwind +; CHECK: {{## InlineAsm Start|#APP}} +; CHECK: .intel_syntax +; CHECK: mov eax, [esi][2*eax][4] +; CHECK: .att_syntax +; CHECK: {{## InlineAsm End|#NO_APP}} + + ret void +} diff --git a/test/MC/X86/x86-32-ms-inline-asm.s b/test/MC/X86/x86-32-ms-inline-asm.s index a5e80b2c938..73d5878b41b 100644 --- a/test/MC/X86/x86-32-ms-inline-asm.s +++ b/test/MC/X86/x86-32-ms-inline-asm.s @@ -8,3 +8,53 @@ mov [ebx].4, ecx // CHECK: movl %ecx, 4(%ebx) // CHECK: encoding: [0x89,0x4b,0x04] +_t21: ## @t21 +// CHECK: t21 + mov eax, [4*eax + 4] +// CHECK: movl 4(,%eax,4), %eax +// CHECK: # encoding: [0x8b,0x04,0x85,0x04,0x00,0x00,0x00] + mov eax, [4*eax][4] +// CHECK: movl 4(,%eax,4), %eax +// CHECK: # encoding: [0x8b,0x04,0x85,0x04,0x00,0x00,0x00] + + mov eax, [esi + eax] +// CHECK: movl (%esi,%eax), %eax +// CHECK: # encoding: [0x8b,0x04,0x06] + mov eax, [esi][eax] +// CHECK: movl (%esi,%eax), %eax +// CHECK: # encoding: [0x8b,0x04,0x06] + + mov eax, [esi + 4*eax] +// CHECK: movl (%esi,%eax,4), %eax +// CHECK: # encoding: [0x8b,0x04,0x86] + mov eax, [esi][4*eax] +// CHECK: movl (%esi,%eax,4), %eax +// CHECK: # encoding: [0x8b,0x04,0x86] + + mov eax, [esi + eax + 4] +// CHECK: movl 4(%esi,%eax), %eax +// CHECK: # encoding: [0x8b,0x44,0x06,0x04] + mov eax, [esi][eax + 4] +// CHECK: movl 4(%esi,%eax), %eax +// CHECK: # encoding: [0x8b,0x44,0x06,0x04] + mov eax, [esi + eax][4] +// CHECK: movl 4(%esi,%eax), %eax +// CHECK: # encoding: [0x8b,0x44,0x06,0x04] + mov eax, [esi][eax][4] +// CHECK: movl 4(%esi,%eax), %eax +// CHECK: # encoding: [0x8b,0x44,0x06,0x04] + + mov eax, [esi + 2*eax + 4] +// CHECK: movl 4(%esi,%eax,2), %eax +// CHECK: # encoding: [0x8b,0x44,0x46,0x04] + mov eax, [esi][2*eax + 4] +// CHECK: movl 4(%esi,%eax,2), %eax +// CHECK: # encoding: [0x8b,0x44,0x46,0x04] + mov eax, [esi + 2*eax][4] +// CHECK: movl 4(%esi,%eax,2), %eax +// CHECK: # encoding: [0x8b,0x44,0x46,0x04] + mov eax, [esi][2*eax][4] +// CHECK: movl 4(%esi,%eax,2), %eax +// CHECK: # encoding: [0x8b,0x44,0x46,0x04] + + ret -- 2.34.1