Index: lib/Target/X86/AsmParser/X86AsmParser.cpp =================================================================== --- lib/Target/X86/AsmParser/X86AsmParser.cpp +++ lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -2666,13 +2666,20 @@ MatchFPUWaitAlias(IDLoc, Op, Operands, Out, MatchingInlineAsm); MCInst Inst; - - // Find one unsized memory operand, if present. + + bool RelaxationMode = + STI.getTargetTriple().getOS() == STI.getTargetTriple().Win32; + + // Find one unsized memory operand, if present, or a memory operand that + // may need relaxation. X86Operand *UnsizedMemOp = nullptr; + X86Operand *RelaxedMemOp = nullptr; for (const auto &Op : Operands) { X86Operand *X86Op = static_cast(Op.get()); if (X86Op->isMemUnsized()) UnsizedMemOp = X86Op; + else if (RelaxationMode && X86Op->isMem()) + RelaxedMemOp = X86Op; } // Allow some instructions to have implicitly pointer-sized operands. This is @@ -2686,32 +2693,56 @@ } } } + // Set the pointer that we will want to strip of size information + uint64_t ErrorInfoIgnore; + X86Operand *StripSizeMemOp = nullptr; + bool DoRelaxation = false; + if (RelaxedMemOp) { + StripSizeMemOp = RelaxedMemOp; + // Determine if we'll need relaxation - if there are no matches with the + // original memory size + DoRelaxation = + !MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, + MatchingInlineAsm,isParsingIntelSyntax()); + // Erase Inst info + Inst.clear(); + Inst.setOpcode(0); + } + else { + StripSizeMemOp = UnsizedMemOp; + } // If an unsized memory operand is present, try to match with each memory // operand size. In Intel assembly, the size is not part of the instruction // mnemonic. + unsigned FirstMatch; SmallVector Match; uint64_t ErrorInfoMissingFeature = 0; - if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) { + if ((UnsizedMemOp && UnsizedMemOp->isMemUnsized()) || DoRelaxation) { + // Save the original memory size so that it can be restored + unsigned OrigSize = StripSizeMemOp->Mem.Size; static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512}; for (unsigned Size : MopSizes) { - UnsizedMemOp->Mem.Size = Size; - uint64_t ErrorInfoIgnore; + StripSizeMemOp->Mem.Size = Size; unsigned LastOpcode = Inst.getOpcode(); unsigned M = MatchInstructionImpl(Operands, Inst, ErrorInfoIgnore, MatchingInlineAsm, isParsingIntelSyntax()); if (Match.empty() || LastOpcode != Inst.getOpcode()) Match.push_back(M); + // In case this is relaxation, we're only looking for the first match + if (DoRelaxation) + break; // If this returned as a missing feature failure, remember that. if (Match.back() == Match_MissingFeature) ErrorInfoMissingFeature = ErrorInfoIgnore; } - // Restore the size of the unsized memory operand if we modified it. - if (UnsizedMemOp) - UnsizedMemOp->Mem.Size = 0; + // Restore the size of the relaxed/unsized memory + // operand if we modified it. + if (StripSizeMemOp) + StripSizeMemOp->Mem.Size = OrigSize; } // If we haven't matched anything yet, this is not a basic integer or FPU Index: test/MC/X86/intel-syntax-ambiguous.s =================================================================== --- test/MC/X86/intel-syntax-ambiguous.s +++ test/MC/X86/intel-syntax-ambiguous.s @@ -1,47 +1,58 @@ -// RUN: not llvm-mc -triple i686-unknown-unknown %s -o /dev/null 2>&1 | FileCheck %s +// RUN: not llvm-mc -triple i686-unknown-unknown %s -o /dev/null 2>&1 | FileCheck %s -check-prefix=NOT_MICROSOFT +// RUN: not llvm-mc -triple -x86-64-microsoft-pc-masm < %s 2>&1 | FileCheck %s -check-prefix=MICROSOFT .intel_syntax // Basic case of ambiguity for inc. inc [eax] -// CHECK: error: ambiguous operand size for instruction 'inc' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'inc' +// MICROSOFT: incb (%eax) inc dword ptr [eax] inc word ptr [eax] inc byte ptr [eax] -// CHECK-NOT: error: +// NOT_MICROSOFT-NOT: error: // Other ambiguous instructions. Anything that doesn't take a register, // basically. dec [eax] -// CHECK: error: ambiguous operand size for instruction 'dec' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'dec' +// MICROSOFT: decb (%eax) mov [eax], 1 -// CHECK: error: ambiguous operand size for instruction 'mov' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'mov' +// MICROSOFT: movb $1, (%eax) and [eax], 0 -// CHECK: error: ambiguous operand size for instruction 'and' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'and' +// MICROSOFT: andb $0, (%eax) or [eax], 1 -// CHECK: error: ambiguous operand size for instruction 'or' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'or' +// MICROSOFT: orb $1, (%eax) add [eax], 1 -// CHECK: error: ambiguous operand size for instruction 'add' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'add' +// MICROSOFT: addb $1, (%eax) sub [eax], 1 -// CHECK: error: ambiguous operand size for instruction 'sub' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'sub' +// MICROSOFT: subb $1, (%eax) // gas assumes these instructions are pointer-sized by default, and we follow // suit. push [eax] call [eax] jmp [eax] -// CHECK-NOT: error: +// NOT_MICROSOFT-NOT: error: add byte ptr [eax], eax -// CHECK: error: invalid operand for instruction +// NOT_MICROSOFT: error: invalid operand for instruction +// MICROSOFT: addl %eax, (%eax) add byte ptr [eax], eax -// CHECK: error: invalid operand for instruction +// NOT_MICROSOFT: error: invalid operand for instruction +// MICROSOFT: addl %eax, (%eax) add rax, 3 -// CHECK: error: register %rax is only available in 64-bit mode +// NOT_MICROSOFT: error: register %rax is only available in 64-bit mode +// MICROSOFT: addq $3, %rax fadd "?half@?0??bar@@YAXXZ@4NA" -// CHECK: error: ambiguous operand size for instruction 'fadd' +// NOT_MICROSOFT: error: ambiguous operand size for instruction 'fadd'