Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 47 additions & 6 deletions llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@
#include "MCTargetDesc/X86TargetStreamer.h"
#include "TargetInfo/X86TargetInfo.h"
#include "X86Operand.h"
#include "X86RegisterInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/MC/MCContext.h"
Expand All @@ -27,6 +29,7 @@
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
Expand All @@ -38,6 +41,7 @@
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdint>
#include <memory>

using namespace llvm;
Expand Down Expand Up @@ -1150,7 +1154,7 @@ class X86AsmParser : public MCTargetAsmParser {

X86::CondCode ParseConditionCode(StringRef CCode);

bool ParseIntelMemoryOperandSize(unsigned &Size);
bool ParseIntelMemoryOperandSize(unsigned &Size, StringRef *SizeStr);
bool CreateMemForMSInlineAsm(MCRegister SegReg, const MCExpr *Disp,
MCRegister BaseReg, MCRegister IndexReg,
unsigned Scale, bool NonAbsMem, SMLoc Start,
Expand Down Expand Up @@ -2551,7 +2555,8 @@ bool X86AsmParser::ParseMasmOperator(unsigned OpKind, int64_t &Val) {
return false;
}

bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size,
StringRef *SizeStr) {
Size = StringSwitch<unsigned>(getTok().getString())
.Cases("BYTE", "byte", 8)
.Cases("WORD", "word", 16)
Expand All @@ -2569,6 +2574,8 @@ bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
.Cases("ZMMWORD", "zmmword", 512)
.Default(0);
if (Size) {
if (SizeStr)
*SizeStr = getTok().getString();
const AsmToken &Tok = Lex(); // Eat operand size (e.g., byte, word).
if (!(Tok.getString() == "PTR" || Tok.getString() == "ptr"))
return Error(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!");
Expand All @@ -2577,14 +2584,37 @@ bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
return false;
}

uint16_t RegSizeInBits(const MCRegisterInfo &MRI, MCRegister RegNo) {
if (X86MCRegisterClasses[X86::GR8RegClassID].contains(RegNo))
return 8;
if (X86MCRegisterClasses[X86::GR16RegClassID].contains(RegNo))
return 16;
if (X86MCRegisterClasses[X86::GR32RegClassID].contains(RegNo))
return 32;
if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
return 64;
if (X86MCRegisterClasses[X86::RFP80RegClassID].contains(RegNo))
return 80;
if (X86MCRegisterClasses[X86::VR128RegClassID].contains(RegNo))
return 128;
if (X86MCRegisterClasses[X86::VR128XRegClassID].contains(RegNo))
return 128;
if (X86MCRegisterClasses[X86::VR256XRegClassID].contains(RegNo))
return 256;
if (X86MCRegisterClasses[X86::VR512RegClassID].contains(RegNo))
return 512;
llvm_unreachable("Register without known register class");
}

bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
MCAsmParser &Parser = getParser();
const AsmToken &Tok = Parser.getTok();
SMLoc Start, End;

// Parse optional Size directive.
unsigned Size;
if (ParseIntelMemoryOperandSize(Size))
StringRef SizeStr;
if (ParseIntelMemoryOperandSize(Size, &SizeStr))
return true;
bool PtrInOperand = bool(Size);

Expand All @@ -2601,9 +2631,20 @@ bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
return Error(Start, "rip can only be used as a base register");
// A Register followed by ':' is considered a segment override
if (Tok.isNot(AsmToken::Colon)) {
if (PtrInOperand)
return Error(Start, "expected memory operand after 'ptr', "
"found register operand instead");
if (PtrInOperand) {
if (!Parser.isParsingMasm())
return Error(Start, "expected memory operand after 'ptr', "
"found register operand instead");

// If we are parsing MASM, we are allowed to cast registers to their own
// sizes, but not to other types.
if (RegSizeInBits(*getContext().getRegisterInfo(), RegNo) != Size)
return Error(
Start,
"cannot cast register '" +
StringRef(getContext().getRegisterInfo()->getName(RegNo)) +
"' to '" + SizeStr + "'; size does not match");
}
Operands.push_back(X86Operand::CreateReg(RegNo, Start, End));
return false;
}
Expand Down
25 changes: 25 additions & 0 deletions llvm/test/tools/llvm-ml/cast.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
; RUN: llvm-ml -m64 -filetype=s %s /Fo - | FileCheck %s

.code

mov byte ptr al, al
mov al, byte ptr al
; CHECK: mov al, al
; CHECK-NEXT: mov al, al

mov word ptr ax, ax
mov ax, word ptr ax
; CHECK: mov ax, ax
; CHECK-NEXT: mov ax, ax

mov dword ptr eax, eax
mov eax, dword ptr eax
; CHECK: mov eax, eax
; CHECK-NEXT: mov eax, eax

mov qword ptr rax, rax
mov rax, qword ptr rax
; CHECK: mov rax, rax
; CHECK-NEXT: mov rax, rax

END
41 changes: 41 additions & 0 deletions llvm/test/tools/llvm-ml/cast_errors.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
; RUN: not llvm-ml -m64 -filetype=s %s /Fo /dev/null 2>&1 | FileCheck %s

.code

mov word ptr al, ax
; CHECK: error: cannot cast register 'AL' to 'word'; size does not match

mov dword ptr al, eax
; CHECK: error: cannot cast register 'AL' to 'dword'; size does not match

mov qword ptr al, rax
; CHECK: error: cannot cast register 'AL' to 'qword'; size does not match

mov byte ptr ax, al
; CHECK: error: cannot cast register 'AX' to 'byte'; size does not match

mov dword ptr ax, eax
; CHECK: error: cannot cast register 'AX' to 'dword'; size does not match

mov qword ptr ax, rax
; CHECK: error: cannot cast register 'AX' to 'qword'; size does not match

mov byte ptr eax, al
; CHECK: error: cannot cast register 'EAX' to 'byte'; size does not match

mov word ptr eax, ax
; CHECK: error: cannot cast register 'EAX' to 'word'; size does not match

mov qword ptr eax, rax
; CHECK: error: cannot cast register 'EAX' to 'qword'; size does not match

mov byte ptr rax, al
; CHECK: error: cannot cast register 'RAX' to 'byte'; size does not match

mov word ptr rax, ax
; CHECK: error: cannot cast register 'RAX' to 'word'; size does not match

mov dword ptr rax, eax
; CHECK: error: cannot cast register 'RAX' to 'dword'; size does not match

END