[llvm] 20201dc - [ms] [llvm-ml] Add support for size queries in MASM
Eric Astor via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 14 11:28:12 PDT 2020
Author: Eric Astor
Date: 2020-09-14T14:27:06-04:00
New Revision: 20201dc76aaf68eb940eb14bfc6dd4983292fb79
URL: https://github.com/llvm/llvm-project/commit/20201dc76aaf68eb940eb14bfc6dd4983292fb79
DIFF: https://github.com/llvm/llvm-project/commit/20201dc76aaf68eb940eb14bfc6dd4983292fb79.diff
LOG: [ms] [llvm-ml] Add support for size queries in MASM
Add support for size inference, sizeof, typeof, and lengthof.
Reviewed By: thakis
Differential Revision: https://reviews.llvm.org/D86947
Added:
llvm/test/tools/llvm-ml/size_inference.test
llvm/test/tools/llvm-ml/type_operators.test
Modified:
llvm/include/llvm/MC/MCParser/MCAsmParser.h
llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
llvm/lib/MC/MCParser/AsmParser.cpp
llvm/lib/MC/MCParser/MasmParser.cpp
llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
llvm/test/tools/llvm-ml/struct.test
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
index a68066e0f50b..2040810eac14 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
@@ -90,6 +90,20 @@ struct InlineAsmIdentifierInfo {
IdKind Kind;
};
+// Generic type information for an assembly object.
+// All sizes measured in bytes.
+struct AsmTypeInfo {
+ StringRef Name;
+ unsigned Size = 0;
+ unsigned ElementSize = 0;
+ unsigned Length = 0;
+};
+
+struct AsmFieldInfo {
+ AsmTypeInfo Type;
+ unsigned Offset = 0;
+};
+
/// Generic Sema callback for assembly parser.
class MCAsmParserSemaCallback {
public:
@@ -170,12 +184,15 @@ class MCAsmParser {
virtual bool isParsingMasm() const { return false; }
- virtual bool lookUpField(StringRef Name, StringRef &Type,
- unsigned &Offset) const {
+ virtual bool lookUpField(StringRef Name, AsmFieldInfo &Info) const {
return true;
}
- virtual bool lookUpField(StringRef Base, StringRef Member, StringRef &Type,
- unsigned &Offset) const {
+ virtual bool lookUpField(StringRef Base, StringRef Member,
+ AsmFieldInfo &Info) const {
+ return true;
+ }
+
+ virtual bool lookUpType(StringRef Name, AsmTypeInfo &Info) const {
return true;
}
@@ -281,7 +298,8 @@ class MCAsmParser {
/// \param Res - The value of the expression. The result is undefined
/// on error.
/// \return - False on success.
- virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0;
+ virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
+ AsmTypeInfo *TypeInfo) = 0;
/// Parse an arbitrary expression, assuming that an initial '(' has
/// already been consumed.
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
index 1d10c66b4201..5d6511372f6e 100644
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -370,7 +370,7 @@ class MCTargetAsmParser : public MCAsmParserExtension {
// Target-specific parsing of expression.
virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
- return getParser().parsePrimaryExpr(Res, EndLoc);
+ return getParser().parsePrimaryExpr(Res, EndLoc, nullptr);
}
virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
index 497f73e41105..f5a06f0a91fe 100644
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -244,7 +244,8 @@ class AsmParser : public MCAsmParser {
bool parseExpression(const MCExpr *&Res);
bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
+ AsmTypeInfo *TypeInfo) override;
bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
SMLoc &EndLoc) override;
@@ -1068,7 +1069,8 @@ bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
/// primaryexpr ::= number
/// primaryexpr ::= '.'
/// primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
+ AsmTypeInfo *TypeInfo) {
SMLoc FirstTokenLoc = getLexer().getLoc();
AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
switch (FirstTokenKind) {
@@ -1079,7 +1081,7 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return true;
case AsmToken::Exclaim:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
return true;
Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
return false;
@@ -1238,19 +1240,19 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return parseBracketExpr(Res, EndLoc);
case AsmToken::Minus:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
return true;
Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
return false;
case AsmToken::Plus:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
return true;
Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
return false;
case AsmToken::Tilde:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, TypeInfo))
return true;
Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
return false;
diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
index c1917d729c85..cc82ffbcb7cb 100644
--- a/llvm/lib/MC/MCParser/MasmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -122,14 +123,14 @@ struct FieldInfo;
struct StructInfo {
StringRef Name;
bool IsUnion = false;
- size_t Alignment = 0;
- size_t Size = 0;
- size_t AlignmentSize = 0;
+ unsigned Alignment = 0;
+ unsigned Size = 0;
+ unsigned AlignmentSize = 0;
std::vector<FieldInfo> Fields;
StringMap<size_t> FieldsByName;
FieldInfo &addField(StringRef FieldName, FieldType FT,
- size_t FieldAlignmentSize);
+ unsigned FieldAlignmentSize);
StructInfo() = default;
@@ -319,13 +320,13 @@ struct FieldInfo {
size_t Offset = 0;
// Total size of the field (= LengthOf * Type).
- size_t SizeOf = 0;
+ unsigned SizeOf = 0;
// Number of elements in the field (1 if scalar, >1 if an array).
- size_t LengthOf = 0;
+ unsigned LengthOf = 0;
// Size of a single entry in this field, in bytes ("type" in MASM standards).
- size_t Type = 0;
+ unsigned Type = 0;
FieldInitializer Contents;
@@ -333,9 +334,9 @@ struct FieldInfo {
};
FieldInfo &StructInfo::addField(StringRef FieldName, FieldType FT,
- size_t FieldAlignmentSize) {
+ unsigned FieldAlignmentSize) {
if (!FieldName.empty())
- FieldsByName[FieldName] = Fields.size();
+ FieldsByName[FieldName.lower()] = Fields.size();
Fields.emplace_back(FT);
FieldInfo &Field = Fields.back();
if (IsUnion) {
@@ -390,8 +391,8 @@ class MasmParser : public MCAsmParser {
/// Maps struct tags to struct definitions.
StringMap<StructInfo> Structs;
- /// Maps data location names to user-defined types.
- StringMap<const StructInfo *> KnownType;
+ /// Maps data location names to types.
+ StringMap<AsmTypeInfo> KnownType;
/// Stack of active macro instantiations.
std::vector<MacroInstantiation*> ActiveMacros;
@@ -494,10 +495,11 @@ class MasmParser : public MCAsmParser {
bool isParsingMasm() const override { return true; }
- bool lookUpField(StringRef Name, StringRef &Type,
- unsigned &Offset) const override;
- bool lookUpField(StringRef Base, StringRef Member, StringRef &Type,
- unsigned &Offset) const override;
+ bool lookUpField(StringRef Name, AsmFieldInfo &Info) const override;
+ bool lookUpField(StringRef Base, StringRef Member,
+ AsmFieldInfo &Info) const override;
+
+ bool lookUpType(StringRef Name, AsmTypeInfo &Info) const override;
bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString,
unsigned &NumOutputs, unsigned &NumInputs,
@@ -509,7 +511,8 @@ class MasmParser : public MCAsmParser {
bool parseExpression(const MCExpr *&Res);
bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
- bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
+ bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
+ AsmTypeInfo *TypeInfo) override;
bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) override;
bool parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
SMLoc &EndLoc) override;
@@ -568,7 +571,7 @@ class MasmParser : public MCAsmParser {
static void DiagHandler(const SMDiagnostic &Diag, void *Context);
bool lookUpField(const StructInfo &Structure, StringRef Member,
- StringRef &Type, unsigned &Offset) const;
+ AsmFieldInfo &Info) const;
/// Should we emit DWARF describing this assembler source? (Returns false if
/// the source has .file directives, which means we don't want to generate
@@ -756,23 +759,24 @@ class MasmParser : public MCAsmParser {
bool parseScalarInstList(
unsigned Size, SmallVectorImpl<const MCExpr *> &Values,
const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
- bool emitIntegralValues(unsigned Size);
+ bool emitIntegralValues(unsigned Size, unsigned *Count = nullptr);
bool addIntegralField(StringRef Name, unsigned Size);
bool parseDirectiveValue(StringRef IDVal, unsigned Size);
- bool parseDirectiveNamedValue(StringRef IDVal, unsigned Size, StringRef Name,
- SMLoc NameLoc);
+ bool parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
+ StringRef Name, SMLoc NameLoc);
// "real4", "real8"
- bool emitRealValues(const fltSemantics &Semantics);
+ bool emitRealValues(const fltSemantics &Semantics, unsigned *Count = nullptr);
bool addRealField(StringRef Name, const fltSemantics &Semantics, size_t Size);
bool parseDirectiveRealValue(StringRef IDVal, const fltSemantics &Semantics,
size_t Size);
bool parseRealInstList(
const fltSemantics &Semantics, SmallVectorImpl<APInt> &Values,
const AsmToken::TokenKind EndToken = AsmToken::EndOfStatement);
- bool parseDirectiveNamedRealValue(StringRef IDVal,
- const fltSemantics &Semantics, size_t Size,
- StringRef Name, SMLoc NameLoc);
+ bool parseDirectiveNamedRealValue(StringRef TypeName,
+ const fltSemantics &Semantics,
+ unsigned Size, StringRef Name,
+ SMLoc NameLoc);
bool parseOptionalAngleBracketOpen();
bool parseAngleBracketClose(const Twine &Msg = "expected '>'");
@@ -816,7 +820,7 @@ class MasmParser : public MCAsmParser {
const StructInitializer &Initializer);
// User-defined types (structs, unions):
- bool emitStructValues(const StructInfo &Structure);
+ bool emitStructValues(const StructInfo &Structure, unsigned *Count = nullptr);
bool addStructField(StringRef Name, const StructInfo &Structure);
bool parseDirectiveStructValue(const StructInfo &Structure,
StringRef Directive, SMLoc DirLoc);
@@ -1321,7 +1325,8 @@ bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
/// primaryexpr ::= number
/// primaryexpr ::= '.'
/// primaryexpr ::= ~,+,-,'not' primaryexpr
-bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc,
+ AsmTypeInfo *TypeInfo) {
SMLoc FirstTokenLoc = getLexer().getLoc();
AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
switch (FirstTokenKind) {
@@ -1332,7 +1337,7 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return true;
case AsmToken::Exclaim:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, nullptr))
return true;
Res = MCUnaryExpr::createLNot(Res, getContext(), FirstTokenLoc);
return false;
@@ -1360,7 +1365,7 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
}
// Parse named bitwise negation.
if (Identifier.equals_lower("not")) {
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, nullptr))
return true;
Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
return false;
@@ -1415,24 +1420,19 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
}
// Find the field offset if used.
- StringRef Type;
- unsigned Offset = 0;
+ AsmFieldInfo Info;
Split = SymbolName.split('.');
- if (!Split.second.empty()) {
+ if (Split.second.empty()) {
+ } else {
SymbolName = Split.first;
- if (Structs.count(SymbolName.lower()) &&
- !lookUpField(SymbolName, Split.second, Type, Offset)) {
- // This is actually a reference to a field offset.
- Res = MCConstantExpr::create(Offset, getContext());
- return false;
- }
-
- auto TypeIt = KnownType.find(SymbolName);
- if (TypeIt == KnownType.end() ||
- lookUpField(*TypeIt->second, Split.second, Type, Offset)) {
+ if (lookUpField(SymbolName, Split.second, Info)) {
std::pair<StringRef, StringRef> BaseMember = Split.second.split('.');
StringRef Base = BaseMember.first, Member = BaseMember.second;
- lookUpField(Base, Member, Type, Offset);
+ lookUpField(Base, Member, Info);
+ } else if (Structs.count(SymbolName.lower())) {
+ // This is actually a reference to a field offset.
+ Res = MCConstantExpr::create(Info.Offset, getContext());
+ return false;
}
}
@@ -1458,13 +1458,23 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
// Otherwise create a symbol ref.
const MCExpr *SymRef =
MCSymbolRefExpr::create(Sym, Variant, getContext(), FirstTokenLoc);
- if (Offset) {
- Res = MCBinaryExpr::create(MCBinaryExpr::Add, SymRef,
- MCConstantExpr::create(Offset, getContext()),
- getContext());
+ if (Info.Offset) {
+ Res = MCBinaryExpr::create(
+ MCBinaryExpr::Add, SymRef,
+ MCConstantExpr::create(Info.Offset, getContext()), getContext());
} else {
Res = SymRef;
}
+ if (TypeInfo) {
+ if (Info.Type.Name.empty()) {
+ auto TypeIt = KnownType.find(Identifier.lower());
+ if (TypeIt != KnownType.end()) {
+ Info.Type = TypeIt->second;
+ }
+ }
+
+ *TypeInfo = Info.Type;
+ }
return false;
}
case AsmToken::BigNum:
@@ -1528,19 +1538,19 @@ bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
return parseBracketExpr(Res, EndLoc);
case AsmToken::Minus:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, nullptr))
return true;
Res = MCUnaryExpr::createMinus(Res, getContext(), FirstTokenLoc);
return false;
case AsmToken::Plus:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, nullptr))
return true;
Res = MCUnaryExpr::createPlus(Res, getContext(), FirstTokenLoc);
return false;
case AsmToken::Tilde:
Lex(); // Eat the operator.
- if (parsePrimaryExpr(Res, EndLoc))
+ if (parsePrimaryExpr(Res, EndLoc, nullptr))
return true;
Res = MCUnaryExpr::createNot(Res, getContext(), FirstTokenLoc);
return false;
@@ -3309,7 +3319,7 @@ bool MasmParser::parseScalarInstList(unsigned Size,
return false;
}
-bool MasmParser::emitIntegralValues(unsigned Size) {
+bool MasmParser::emitIntegralValues(unsigned Size, unsigned *Count) {
SmallVector<const MCExpr *, 1> Values;
if (checkForValidSection() || parseScalarInstList(Size, Values))
return true;
@@ -3317,6 +3327,8 @@ bool MasmParser::emitIntegralValues(unsigned Size) {
for (auto Value : Values) {
emitIntValue(Value, Size);
}
+ if (Count)
+ *Count = Values.size();
return false;
}
@@ -3356,16 +3368,24 @@ bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
/// parseDirectiveNamedValue
/// ::= name (byte | word | ... ) [ expression (, expression)* ]
-bool MasmParser::parseDirectiveNamedValue(StringRef IDVal, unsigned Size,
+bool MasmParser::parseDirectiveNamedValue(StringRef TypeName, unsigned Size,
StringRef Name, SMLoc NameLoc) {
if (StructInProgress.empty()) {
// Initialize named data value.
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
getStreamer().emitLabel(Sym);
- if (emitIntegralValues(Size))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ unsigned Count;
+ if (emitIntegralValues(Size, &Count))
+ return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
+
+ AsmTypeInfo Type;
+ Type.Name = TypeName;
+ Type.Size = Size * Count;
+ Type.ElementSize = Size;
+ Type.Length = Count;
+ KnownType[Name.lower()] = Type;
} else if (addIntegralField(Name, Size)) {
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return addErrorSuffix(" in '" + Twine(TypeName) + "' directive");
}
return false;
@@ -3482,7 +3502,8 @@ bool MasmParser::parseRealInstList(const fltSemantics &Semantics,
}
// Initialize real data values.
-bool MasmParser::emitRealValues(const fltSemantics &Semantics) {
+bool MasmParser::emitRealValues(const fltSemantics &Semantics,
+ unsigned *Count) {
if (checkForValidSection())
return true;
@@ -3494,6 +3515,8 @@ bool MasmParser::emitRealValues(const fltSemantics &Semantics) {
getStreamer().emitIntValue(AsInt.getLimitedValue(),
AsInt.getBitWidth() / 8);
}
+ if (Count)
+ *Count = ValuesAsInt.size();
return false;
}
@@ -3536,18 +3559,26 @@ bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
/// parseDirectiveNamedRealValue
/// ::= name (real4 | real8) [ expression (, expression)* ]
-bool MasmParser::parseDirectiveNamedRealValue(StringRef IDVal,
+bool MasmParser::parseDirectiveNamedRealValue(StringRef TypeName,
const fltSemantics &Semantics,
- size_t Size, StringRef Name,
+ unsigned Size, StringRef Name,
SMLoc NameLoc) {
if (StructInProgress.empty()) {
// Initialize named data value.
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
getStreamer().emitLabel(Sym);
- if (emitRealValues(Semantics))
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ unsigned Count;
+ if (emitRealValues(Semantics, &Count))
+ return addErrorSuffix(" in '" + TypeName + "' directive");
+
+ AsmTypeInfo Type;
+ Type.Name = TypeName;
+ Type.Size = Size * Count;
+ Type.ElementSize = Size;
+ Type.Length = Count;
+ KnownType[Name.lower()] = Type;
} else if (addRealField(Name, Semantics, Size)) {
- return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+ return addErrorSuffix(" in '" + TypeName + "' directive");
}
return false;
}
@@ -3960,7 +3991,8 @@ bool MasmParser::emitStructInitializer(const StructInfo &Structure,
}
// Set data values from initializers.
-bool MasmParser::emitStructValues(const StructInfo &Structure) {
+bool MasmParser::emitStructValues(const StructInfo &Structure,
+ unsigned *Count) {
std::vector<StructInitializer> Initializers;
if (parseStructInstList(Structure, Initializers))
return true;
@@ -3970,6 +4002,8 @@ bool MasmParser::emitStructValues(const StructInfo &Structure) {
return true;
}
+ if (Count)
+ *Count = Initializers.size();
return false;
}
@@ -4020,9 +4054,15 @@ bool MasmParser::parseDirectiveNamedStructValue(const StructInfo &Structure,
// Initialize named data value.
MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
getStreamer().emitLabel(Sym);
- KnownType[Name] = &Structure;
- if (emitStructValues(Structure))
+ unsigned Count;
+ if (emitStructValues(Structure, &Count))
return true;
+ AsmTypeInfo Type;
+ Type.Name = Structure.Name;
+ Type.Size = Structure.Size * Count;
+ Type.ElementSize = Structure.Size;
+ Type.Length = Count;
+ KnownType[Name.lower()] = Type;
} else if (addStructField(Name, Structure)) {
return addErrorSuffix(" in '" + Twine(Directive) + "' directive");
}
@@ -6564,37 +6604,39 @@ static int rewritesSort(const AsmRewrite *AsmRewriteA,
llvm_unreachable("Unstable rewrite sort.");
}
-bool MasmParser::lookUpField(StringRef Name, StringRef &Type,
- unsigned &Offset) const {
+bool MasmParser::lookUpField(StringRef Name, AsmFieldInfo &Info) const {
const std::pair<StringRef, StringRef> BaseMember = Name.split('.');
const StringRef Base = BaseMember.first, Member = BaseMember.second;
- return lookUpField(Base, Member, Type, Offset);
+ return lookUpField(Base, Member, Info);
}
-bool MasmParser::lookUpField(StringRef Base, StringRef Member, StringRef &Type,
- unsigned &Offset) const {
+bool MasmParser::lookUpField(StringRef Base, StringRef Member,
+ AsmFieldInfo &Info) const {
if (Base.empty())
return true;
- unsigned BaseOffset = 0;
- if (Base.contains('.') && !lookUpField(Base, Type, BaseOffset))
- Base = Type;
-
- auto TypeIt = KnownType.find(Base);
- if (TypeIt != KnownType.end())
- return lookUpField(*TypeIt->second, Member, Type, Offset);
+ AsmFieldInfo BaseInfo;
+ if (Base.contains('.') && !lookUpField(Base, BaseInfo))
+ Base = BaseInfo.Type.Name;
auto StructIt = Structs.find(Base.lower());
+ auto TypeIt = KnownType.find(Base.lower());
+ if (TypeIt != KnownType.end()) {
+ StructIt = Structs.find(TypeIt->second.Name.lower());
+ }
if (StructIt != Structs.end())
- return lookUpField(StructIt->second, Member, Type, Offset);
+ return lookUpField(StructIt->second, Member, Info);
return true;
}
bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
- StringRef &Type, unsigned &Offset) const {
+ AsmFieldInfo &Info) const {
if (Member.empty()) {
- Type = Structure.Name;
+ Info.Type.Name = Structure.Name;
+ Info.Type.Size = Structure.Size;
+ Info.Type.ElementSize = Structure.Size;
+ Info.Type.Length = 1;
return false;
}
@@ -6603,7 +6645,7 @@ bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
auto StructIt = Structs.find(FieldName.lower());
if (StructIt != Structs.end())
- return lookUpField(StructIt->second, FieldMember, Type, Offset);
+ return lookUpField(StructIt->second, FieldMember, Info);
auto FieldIt = Structure.FieldsByName.find(FieldName.lower());
if (FieldIt == Structure.FieldsByName.end())
@@ -6611,9 +6653,12 @@ bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
const FieldInfo &Field = Structure.Fields[FieldIt->second];
if (FieldMember.empty()) {
- Offset += Field.Offset;
+ Info.Offset += Field.Offset;
+ Info.Type.Size = Field.SizeOf;
+ Info.Type.ElementSize = Field.Type;
+ Info.Type.Length = Field.LengthOf;
if (Field.Contents.FT == FT_STRUCT)
- Type = Field.Contents.StructInfo.Structure.Name;
+ Info.Type.Name = Field.Contents.StructInfo.Structure.Name;
return false;
}
@@ -6621,14 +6666,44 @@ bool MasmParser::lookUpField(const StructInfo &Structure, StringRef Member,
return true;
const StructFieldInfo &StructInfo = Field.Contents.StructInfo;
- bool Result = lookUpField(StructInfo.Structure, FieldMember, Type, Offset);
- if (Result)
+ if (lookUpField(StructInfo.Structure, FieldMember, Info))
return true;
- Offset += Field.Offset;
+ Info.Offset += Field.Offset;
return false;
}
+bool MasmParser::lookUpType(StringRef Name, AsmTypeInfo &Info) const {
+ unsigned Size = StringSwitch<unsigned>(Name)
+ .CasesLower("byte", "db", "sbyte", 1)
+ .CasesLower("word", "dw", "sword", 2)
+ .CasesLower("dword", "dd", "sdword", 4)
+ .CasesLower("fword", "df", 6)
+ .CasesLower("qword", "dq", "sqword", 8)
+ .CaseLower("real4", 4)
+ .CaseLower("real8", 8)
+ .Default(0);
+ if (Size) {
+ Info.Name = Name;
+ Info.ElementSize = Size;
+ Info.Length = 1;
+ Info.Size = Size;
+ return false;
+ }
+
+ auto StructIt = Structs.find(Name.lower());
+ if (StructIt != Structs.end()) {
+ const StructInfo &Structure = StructIt->second;
+ Info.Name = Name;
+ Info.ElementSize = Structure.Size;
+ Info.Length = 1;
+ Info.Size = Structure.Size;
+ return false;
+ }
+
+ return true;
+}
+
bool MasmParser::parseMSInlineAsm(
void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
index d2eb7c1726e2..0460d861aebe 100644
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -2541,7 +2541,7 @@ AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) {
// This syntax is not compatible with syntax of standard
// MC expressions (due to the trailing '|').
SMLoc EndLoc;
- if (getParser().parsePrimaryExpr(Expr, EndLoc))
+ if (getParser().parsePrimaryExpr(Expr, EndLoc, nullptr))
return MatchOperand_ParseFail;
} else {
if (Parser.parseExpression(Expr))
diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
index 5694105dcbd1..361a6c04e3f2 100644
--- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
+++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp
@@ -32,6 +32,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Compiler.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
@@ -150,6 +151,13 @@ class X86AsmParser : public MCTargetAsmParser {
IOK_TYPE,
};
+ enum MasmOperatorKind {
+ MOK_INVALID = 0,
+ MOK_LENGTHOF,
+ MOK_SIZEOF,
+ MOK_TYPE,
+ };
+
class InfixCalculator {
typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;
@@ -367,7 +375,7 @@ class X86AsmParser : public MCTargetAsmParser {
bool MemExpr;
bool OffsetOperator;
SMLoc OffsetOperatorLoc;
- StringRef CurType;
+ AsmTypeInfo CurType;
bool setSymRef(const MCExpr *Val, StringRef ID, StringRef &ErrMsg) {
if (Sym) {
@@ -395,7 +403,10 @@ class X86AsmParser : public MCTargetAsmParser {
unsigned getScale() { return Scale; }
const MCExpr *getSym() { return Sym; }
StringRef getSymName() { return SymName; }
- StringRef getType() { return CurType; }
+ StringRef getType() { return CurType.Name; }
+ unsigned getSize() { return CurType.Size; }
+ unsigned getElementSize() { return CurType.ElementSize; }
+ unsigned getLength() { return CurType.Length; }
int64_t getImm() { return Imm + IC.execute(); }
bool isValidEndState() {
return State == IES_RBRAC || State == IES_INTEGER;
@@ -628,7 +639,8 @@ class X86AsmParser : public MCTargetAsmParser {
}
bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName,
const InlineAsmIdentifierInfo &IDInfo,
- bool ParsingMSInlineAsm, StringRef &ErrMsg) {
+ const AsmTypeInfo &Type, bool ParsingMSInlineAsm,
+ StringRef &ErrMsg) {
// InlineAsm: Treat an enum value as an integer
if (ParsingMSInlineAsm)
if (IDInfo.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
@@ -647,6 +659,7 @@ class X86AsmParser : public MCTargetAsmParser {
case IES_NOT:
case IES_INIT:
case IES_LBRAC:
+ case IES_LPAREN:
if (setSymRef(SymRef, SymRefName, ErrMsg))
return true;
MemExpr = true;
@@ -654,6 +667,7 @@ class X86AsmParser : public MCTargetAsmParser {
IC.pushOperand(IC_IMM);
if (ParsingMSInlineAsm)
Info = IDInfo;
+ setTypeInfo(Type);
break;
}
return false;
@@ -752,6 +766,8 @@ class X86AsmParser : public MCTargetAsmParser {
case IES_RPAREN:
State = IES_PLUS;
IC.pushOperator(IC_PLUS);
+ CurType.Length = 1;
+ CurType.Size = CurType.ElementSize;
break;
case IES_INIT:
case IES_CAST:
@@ -835,8 +851,8 @@ class X86AsmParser : public MCTargetAsmParser {
}
}
bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID,
- const InlineAsmIdentifierInfo &IDInfo, bool ParsingMSInlineAsm,
- StringRef &ErrMsg) {
+ const InlineAsmIdentifierInfo &IDInfo,
+ bool ParsingMSInlineAsm, StringRef &ErrMsg) {
PrevState = State;
switch (State) {
default:
@@ -860,19 +876,19 @@ class X86AsmParser : public MCTargetAsmParser {
}
return false;
}
- void onCast(StringRef Type) {
+ void onCast(AsmTypeInfo Info) {
PrevState = State;
switch (State) {
default:
State = IES_ERROR;
break;
case IES_LPAREN:
- setType(Type);
+ setTypeInfo(Info);
State = IES_CAST;
break;
}
}
- void setType(StringRef Type) { CurType = Type; }
+ void setTypeInfo(AsmTypeInfo Type) { CurType = Type; }
};
bool Error(SMLoc L, const Twine &Msg, SMRange Range = None,
@@ -909,6 +925,8 @@ class X86AsmParser : public MCTargetAsmParser {
bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);
unsigned IdentifyIntelInlineAsmOperator(StringRef Name);
unsigned ParseIntelInlineAsmOperator(unsigned OpKind);
+ unsigned IdentifyMasmOperator(StringRef Name);
+ bool ParseMasmOperator(unsigned OpKind, int64_t &Val);
bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands);
bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM,
bool &ParseError, SMLoc &End);
@@ -1653,6 +1671,13 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
if (ParseIntelDotOperator(SM, End))
return true;
break;
+ case AsmToken::Dollar:
+ if (!Parser.isParsingMasm()) {
+ if ((Done = SM.isValidEndState()))
+ break;
+ return Error(Tok.getLoc(), "unknown token in expression");
+ }
+ LLVM_FALLTHROUGH;
case AsmToken::At:
case AsmToken::String:
case AsmToken::Identifier: {
@@ -1664,7 +1689,10 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
const AsmToken &NextTok = getLexer().peekTok();
if (NextTok.is(AsmToken::Identifier) &&
NextTok.getIdentifier().equals_lower("ptr")) {
- SM.onCast(Identifier);
+ AsmTypeInfo Info;
+ if (Parser.lookUpType(Identifier, Info))
+ return Error(Tok.getLoc(), "unknown type");
+ SM.onCast(Info);
// Eat type and PTR.
consumeToken();
End = consumeToken();
@@ -1689,16 +1717,15 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
if (SM.onRegister(Reg, ErrMsg))
return Error(IdentLoc, ErrMsg);
- StringRef Type;
- unsigned Offset = 0;
+ AsmFieldInfo Info;
SMLoc FieldStartLoc = SMLoc::getFromPointer(Field.data());
- if (Parser.lookUpField(Field, Type, Offset))
+ if (Parser.lookUpField(Field, Info))
return Error(FieldStartLoc, "unknown offset");
else if (SM.onPlus(ErrMsg))
return Error(getTok().getLoc(), ErrMsg);
- else if (SM.onInteger(Offset, ErrMsg))
+ else if (SM.onInteger(Info.Offset, ErrMsg))
return Error(IdentLoc, ErrMsg);
- SM.setType(Type);
+ SM.setTypeInfo(Info.Type);
End = consumeToken();
break;
@@ -1714,6 +1741,7 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
}
// Symbol reference, when parsing assembly content
InlineAsmIdentifierInfo Info;
+ AsmTypeInfo Type;
const MCExpr *Val;
if (isParsingMSInlineAsm() || Parser.isParsingMasm()) {
// MS Dot Operator expression
@@ -1740,13 +1768,24 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
return Error(IdentLoc, "expected identifier");
if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info, false, End))
return true;
- else if (SM.onIdentifierExpr(Val, Identifier, Info, true, ErrMsg))
+ else if (SM.onIdentifierExpr(Val, Identifier, Info, Type, true, ErrMsg))
return Error(IdentLoc, ErrMsg);
break;
}
- if (getParser().parsePrimaryExpr(Val, End)) {
+ if (Parser.isParsingMasm()) {
+ if (unsigned OpKind = IdentifyMasmOperator(Identifier)) {
+ int64_t Val;
+ if (ParseMasmOperator(OpKind, Val))
+ return true;
+ if (SM.onInteger(Val, ErrMsg))
+ return Error(IdentLoc, ErrMsg);
+ break;
+ }
+ }
+ if (getParser().parsePrimaryExpr(Val, End, &Type)) {
return Error(Tok.getLoc(), "Unexpected identifier!");
- } else if (SM.onIdentifierExpr(Val, Identifier, Info, false, ErrMsg)) {
+ } else if (SM.onIdentifierExpr(Val, Identifier, Info, Type, false,
+ ErrMsg)) {
return Error(IdentLoc, ErrMsg);
}
break;
@@ -1769,8 +1808,9 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
return Error(Loc, "invalid reference to undefined symbol");
StringRef Identifier = Sym->getName();
InlineAsmIdentifierInfo Info;
- if (SM.onIdentifierExpr(Val, Identifier, Info, isParsingMSInlineAsm(),
- ErrMsg))
+ AsmTypeInfo Type;
+ if (SM.onIdentifierExpr(Val, Identifier, Info, Type,
+ isParsingMSInlineAsm(), ErrMsg))
return Error(Loc, ErrMsg);
End = consumeToken();
} else {
@@ -1957,8 +1997,7 @@ bool X86AsmParser::ParseRoundingModeOp(SMLoc Start, OperandVector &Operands) {
bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
SMLoc &End) {
const AsmToken &Tok = getTok();
- StringRef Type;
- unsigned Offset = 0;
+ AsmFieldInfo Info;
// Drop the optional '.'.
StringRef DotDispStr = Tok.getString();
@@ -1969,27 +2008,28 @@ bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
if (Tok.is(AsmToken::Real)) {
APInt DotDisp;
DotDispStr.getAsInteger(10, DotDisp);
- Offset = DotDisp.getZExtValue();
+ Info.Offset = DotDisp.getZExtValue();
} else if ((isParsingMSInlineAsm() || getParser().isParsingMasm()) &&
Tok.is(AsmToken::Identifier)) {
const std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.');
const StringRef Base = BaseMember.first, Member = BaseMember.second;
- if (getParser().lookUpField(SM.getType(), DotDispStr, Type, Offset) &&
- getParser().lookUpField(SM.getSymName(), DotDispStr, Type, Offset) &&
- getParser().lookUpField(DotDispStr, Type, Offset) &&
+ if (getParser().lookUpField(SM.getType(), DotDispStr, Info) &&
+ getParser().lookUpField(SM.getSymName(), DotDispStr, Info) &&
+ getParser().lookUpField(DotDispStr, Info) &&
(!SemaCallback ||
- SemaCallback->LookupInlineAsmField(Base, Member, Offset)))
+ SemaCallback->LookupInlineAsmField(Base, Member, Info.Offset)))
return Error(Tok.getLoc(), "Unable to lookup field reference!");
- } else
+ } else {
return Error(Tok.getLoc(), "Unexpected token type!");
+ }
// Eat the DotExpression and update End
End = SMLoc::getFromPointer(DotDispStr.data());
const char *DotExprEndLoc = DotDispStr.data() + DotDispStr.size();
while (Tok.getLoc().getPointer() < DotExprEndLoc)
Lex();
- SM.addImm(Offset);
- SM.setType(Type);
+ SM.addImm(Info.Offset);
+ SM.setTypeInfo(Info.Type);
return false;
}
@@ -2004,7 +2044,7 @@ bool X86AsmParser::ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
if (!isParsingMSInlineAsm()) {
if ((getTok().isNot(AsmToken::Identifier) &&
getTok().isNot(AsmToken::String)) ||
- getParser().parsePrimaryExpr(Val, End))
+ getParser().parsePrimaryExpr(Val, End, nullptr))
return Error(Start, "unexpected token!");
} else if (ParseIntelInlineAsmIdentifier(Val, ID, Info, false, End, true)) {
return Error(Start, "unable to lookup expression");
@@ -2059,6 +2099,73 @@ unsigned X86AsmParser::ParseIntelInlineAsmOperator(unsigned OpKind) {
return CVal;
}
+// Query a candidate string for being an Intel assembly operator
+// Report back its kind, or IOK_INVALID if does not evaluated as a known one
+unsigned X86AsmParser::IdentifyMasmOperator(StringRef Name) {
+ return StringSwitch<unsigned>(Name.lower())
+ .Case("type", MOK_TYPE)
+ .Cases("size", "sizeof", MOK_SIZEOF)
+ .Cases("length", "lengthof", MOK_LENGTHOF)
+ .Default(MOK_INVALID);
+}
+
+/// Parse the 'LENGTHOF', 'SIZEOF', and 'TYPE' operators. The LENGTHOF operator
+/// returns the number of elements in an array. It returns the value 1 for
+/// non-array variables. The SIZEOF operator returns the size of a type or
+/// variable in bytes. A variable's size is the product of its LENGTH and TYPE.
+/// The TYPE operator returns the size of a variable. If the variable is an
+/// array, TYPE returns the size of a single element.
+bool X86AsmParser::ParseMasmOperator(unsigned OpKind, int64_t &Val) {
+ MCAsmParser &Parser = getParser();
+ SMLoc OpLoc = Parser.getTok().getLoc();
+ Parser.Lex(); // Eat operator.
+
+ Val = 0;
+ if (OpKind == MOK_SIZEOF || OpKind == MOK_TYPE) {
+ // Check for SIZEOF(<type>) and TYPE(<type>).
+ bool InParens = Parser.getTok().is(AsmToken::LParen);
+ const AsmToken &IDTok = InParens ? getLexer().peekTok() : Parser.getTok();
+ AsmTypeInfo Type;
+ if (IDTok.is(AsmToken::Identifier) &&
+ !Parser.lookUpType(IDTok.getIdentifier(), Type)) {
+ Val = Type.Size;
+
+ // Eat tokens.
+ if (InParens)
+ parseToken(AsmToken::LParen);
+ parseToken(AsmToken::Identifier);
+ if (InParens)
+ parseToken(AsmToken::RParen);
+ }
+ }
+
+ if (!Val) {
+ IntelExprStateMachine SM;
+ SMLoc End, Start = Parser.getTok().getLoc();
+ if (ParseIntelExpression(SM, End))
+ return true;
+
+ switch (OpKind) {
+ default:
+ llvm_unreachable("Unexpected operand kind!");
+ case MOK_SIZEOF:
+ Val = SM.getSize();
+ break;
+ case MOK_LENGTHOF:
+ Val = SM.getLength();
+ break;
+ case MOK_TYPE:
+ Val = SM.getElementSize();
+ break;
+ }
+
+ if (!Val)
+ return Error(OpLoc, "expression has unknown type", SMRange(Start, End));
+ }
+
+ return false;
+}
+
bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
Size = StringSwitch<unsigned>(getTok().getString())
.Cases("BYTE", "byte", 8)
@@ -2161,6 +2268,8 @@ bool X86AsmParser::ParseIntelOperand(OperandVector &Operands) {
unsigned BaseReg = SM.getBaseReg();
unsigned IndexReg = SM.getIndexReg();
unsigned Scale = SM.getScale();
+ if (!PtrInOperand)
+ Size = SM.getElementSize() << 3;
if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&
(IndexReg == X86::ESP || IndexReg == X86::RSP))
@@ -2617,7 +2726,7 @@ bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
Res = X86MCExpr::create(RegNo, Parser.getContext());
return false;
}
- return Parser.parsePrimaryExpr(Res, EndLoc);
+ return Parser.parsePrimaryExpr(Res, EndLoc, nullptr);
}
bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
diff --git a/llvm/test/tools/llvm-ml/size_inference.test b/llvm/test/tools/llvm-ml/size_inference.test
new file mode 100644
index 000000000000..c24eb51fad42
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/size_inference.test
@@ -0,0 +1,27 @@
+; RUN: not llvm-ml -filetype=asm %s 2>&1 | FileCheck %s --dump-input=always
+
+.data
+
+FOO STRUCT
+ dword_field DWORD 3
+ byte_field BYTE 4 DUP (1)
+FOO ENDS
+
+var FOO <>
+
+.code
+
+t1 PROC
+
+mov eax, var.byte_field
+; CHECK: error: invalid operand for instruction
+
+mov eax, [var].byte_field
+; CHECK: error: invalid operand for instruction
+
+mov eax, [var.byte_field]
+; CHECK: error: invalid operand for instruction
+
+t1 ENDP
+
+END
diff --git a/llvm/test/tools/llvm-ml/struct.test b/llvm/test/tools/llvm-ml/struct.test
index 38fc763fc7e1..facd7c14e4f4 100644
--- a/llvm/test/tools/llvm-ml/struct.test
+++ b/llvm/test/tools/llvm-ml/struct.test
@@ -78,70 +78,70 @@ t2 FOOBAR <"gh",,<10,11>,<12>,"ijk">
.code
t3:
-mov eax, t2.f.h
-mov eax, [t2].f.h
-mov eax, [t2.f.h]
+mov al, t2.f.h
+mov al, [t2].f.h
+mov al, [t2.f.h]
; CHECK: t3:
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
t4:
-mov eax, j.FOOBAR.f.h
-mov eax, j.baz.b
+mov al, j.FOOBAR.f.h
+mov al, j.baz.b
; CHECK: t4:
-; CHECK-NEXT: mov eax, dword ptr [rip + j+11]
-; CHECK-NEXT: mov eax, dword ptr [rip + j+1]
+; CHECK-NEXT: mov al, byte ptr [rip + j+11]
+; CHECK-NEXT: mov al, byte ptr [rip + j+1]
t5:
-mov eax, [ebx].FOOBAR.f.h
-mov eax, [ebx.FOOBAR].f.h
-mov eax, [ebx.FOOBAR.f.h]
+mov al, [ebx].FOOBAR.f.h
+mov al, [ebx.FOOBAR].f.h
+mov al, [ebx.FOOBAR.f.h]
; CHECK: t5:
-; CHECK-NEXT: mov eax, dword ptr [ebx + 11]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 11]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 11]
+; CHECK-NEXT: mov al, byte ptr [ebx + 11]
+; CHECK-NEXT: mov al, byte ptr [ebx + 11]
+; CHECK-NEXT: mov al, byte ptr [ebx + 11]
t6:
-mov eax, t2.FOOBAR.f.h
-mov eax, [t2].FOOBAR.f.h
-mov eax, [t2.FOOBAR].f.h
-mov eax, [t2.FOOBAR.f.h]
+mov al, t2.FOOBAR.f.h
+mov al, [t2].FOOBAR.f.h
+mov al, [t2.FOOBAR].f.h
+mov al, [t2.FOOBAR.f.h]
; CHECK: t6:
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+11]
t7:
-mov eax, [ebx].FOOBAR.e.b
-mov eax, [ebx.FOOBAR].e.b
-mov eax, [ebx.FOOBAR.e].b
-mov eax, [ebx.FOOBAR.e.b]
+mov al, [ebx].FOOBAR.e.b
+mov al, [ebx.FOOBAR].e.b
+mov al, [ebx.FOOBAR.e].b
+mov al, [ebx.FOOBAR.e.b]
; CHECK: t7:
-; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 9]
+; CHECK-NEXT: mov al, byte ptr [ebx + 9]
+; CHECK-NEXT: mov al, byte ptr [ebx + 9]
+; CHECK-NEXT: mov al, byte ptr [ebx + 9]
+; CHECK-NEXT: mov al, byte ptr [ebx + 9]
t8:
-mov eax, t2.FOOBAR.e.b
-mov eax, [t2].FOOBAR.e.b
-mov eax, [t2.FOOBAR].e.b
-mov eax, [t2.FOOBAR.e].b
-mov eax, [t2.FOOBAR.e.b]
+mov al, t2.FOOBAR.e.b
+mov al, [t2].FOOBAR.e.b
+mov al, [t2.FOOBAR].e.b
+mov al, [t2.FOOBAR.e].b
+mov al, [t2.FOOBAR.e.b]
; CHECK: t8:
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
-; CHECK-NEXT: mov eax, dword ptr [rip + (t2+8)+1]
-; CHECK-NEXT: mov eax, dword ptr [rip + t2+9]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+9]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+9]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+9]
+; CHECK-NEXT: mov al, byte ptr [rip + (t2+8)+1]
+; CHECK-NEXT: mov al, byte ptr [rip + t2+9]
QUUX STRUCT
u DWORD ?
@@ -159,20 +159,20 @@ QUUX ENDS
t9:
mov eax, [ebx].QUUX.u
-mov eax, [ebx].QUUX.v
+mov ax, [ebx].QUUX.v
mov eax, [ebx].QUUX.w
-mov eax, [ebx].QUUX.x
-mov eax, [ebx].QUUX.y
-mov eax, [ebx].QUUX.after_struct
+mov al, [ebx].QUUX.x
+mov al, [ebx].QUUX.y
+mov al, [ebx].QUUX.after_struct
mov eax, [ebx].QUUX.z
; CHECK: t9:
; CHECK-NEXT: mov eax, dword ptr [ebx]
+; CHECK-NEXT: mov ax, word ptr [ebx + 4]
; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 5]
-; CHECK-NEXT: mov eax, dword ptr [ebx + 4]
+; CHECK-NEXT: mov al, byte ptr [ebx + 4]
+; CHECK-NEXT: mov al, byte ptr [ebx + 5]
+; CHECK-NEXT: mov al, byte ptr [ebx + 4]
; CHECK-NEXT: mov eax, dword ptr [ebx + 8]
t10:
@@ -184,11 +184,11 @@ mov eax, FOOBAR.f.h
; CHECK-NEXT: mov eax, 11
t11:
-mov eax, (FOOBAR PTR [ebx]).f
-mov eax, (FOOBAR PTR t1).f
+mov ax, (FOOBAR PTR [ebx]).f
+mov ax, (FOOBAR PTR t1).f
; CHECK: t11:
-; CHECK-NEXT: mov eax, dword ptr [ebx + 10]
-; CHECK-NEXT: mov eax, dword ptr [rip + t1+10]
+; CHECK-NEXT: mov ax, word ptr [ebx + 10]
+; CHECK-NEXT: mov ax, word ptr [rip + t1+10]
END
diff --git a/llvm/test/tools/llvm-ml/type_operators.test b/llvm/test/tools/llvm-ml/type_operators.test
new file mode 100644
index 000000000000..b8546927e3ef
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/type_operators.test
@@ -0,0 +1,237 @@
+# RUN: llvm-ml -filetype=asm %s | FileCheck %s
+
+.data
+
+FOO STRUCT 2
+ x BYTE ?
+ y WORD 5 DUP (?)
+FOO ENDS
+
+.code
+
+t1:
+; CHECK-LABEL: t1:
+
+mov eax, sizeof BYTE
+mov eax, (sizeof sBYTE)
+mov eax, sizeof(Db)
+mov eax, type BYTE
+mov eax, (type sBYTE)
+mov eax, type(Db)
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+
+mov eax, sizeof(word)
+mov eax, type(word)
+; CHECK: mov eax, 2
+; CHECK: mov eax, 2
+mov eax, sizeof(dword)
+mov eax, type(dword)
+; CHECK: mov eax, 4
+; CHECK: mov eax, 4
+mov eax, sizeof(fword)
+mov eax, type(fword)
+; CHECK: mov eax, 6
+; CHECK: mov eax, 6
+mov eax, sizeof(qword)
+mov eax, type(qword)
+; CHECK: mov eax, 8
+; CHECK: mov eax, 8
+
+mov eax, sizeof(real4)
+mov eax, type(real4)
+; CHECK: mov eax, 4
+; CHECK: mov eax, 4
+mov eax, sizeof(real8)
+mov eax, type(real8)
+; CHECK: mov eax, 8
+; CHECK: mov eax, 8
+
+mov eax, sizeof(FOO)
+mov eax, type(FOO)
+; CHECK: mov eax, 12
+; CHECK: mov eax, 12
+
+
+t2_full BYTE "ab"
+t2_short DB ?
+t2_signed SBYTE 3 DUP (?)
+
+t2:
+; CHECK-LABEL: t2:
+
+mov eax, sizeof(t2_full)
+mov eax, lengthof(t2_full)
+mov eax, type(t2_full)
+; CHECK: mov eax, 2
+; CHECK: mov eax, 2
+; CHECK: mov eax, 1
+
+mov eax, sizeof(t2_short)
+mov eax, lengthof(t2_short)
+mov eax, type(t2_short)
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+; CHECK: mov eax, 1
+
+mov eax, sizeof(t2_signed)
+mov eax, lengthof(t2_signed)
+mov eax, type(t2_signed)
+; CHECK: mov eax, 3
+; CHECK: mov eax, 3
+; CHECK: mov eax, 1
+
+
+t3_full WORD 2 DUP (?)
+t3_short DW ?
+t3_signed SWORD 3 DUP (?)
+
+t3:
+; CHECK-LABEL: t3:
+
+mov eax, sizeof(t3_full)
+mov eax, lengthof(t3_full)
+mov eax, type(t3_full)
+; CHECK: mov eax, 4
+; CHECK: mov eax, 2
+; CHECK: mov eax, 2
+
+mov eax, sizeof(t3_short)
+mov eax, lengthof(t3_short)
+mov eax, type(t3_short)
+; CHECK: mov eax, 2
+; CHECK: mov eax, 1
+; CHECK: mov eax, 2
+
+mov eax, sizeof(t3_signed)
+mov eax, lengthof(t3_signed)
+mov eax, type(t3_signed)
+; CHECK: mov eax, 6
+; CHECK: mov eax, 3
+; CHECK: mov eax, 2
+
+
+t4_full DWORD 2 DUP (?)
+t4_short DD ?
+t4_signed SDWORD 3 DUP (?)
+
+t4:
+; CHECK-LABEL: t4:
+
+mov eax, sizeof(t4_full)
+mov eax, lengthof(t4_full)
+mov eax, type(t4_full)
+; CHECK: mov eax, 8
+; CHECK: mov eax, 2
+; CHECK: mov eax, 4
+
+mov eax, sizeof(t4_short)
+mov eax, lengthof(t4_short)
+mov eax, type(t4_short)
+; CHECK: mov eax, 4
+; CHECK: mov eax, 1
+; CHECK: mov eax, 4
+
+mov eax, sizeof(t4_signed)
+mov eax, lengthof(t4_signed)
+mov eax, type(t4_signed)
+; CHECK: mov eax, 12
+; CHECK: mov eax, 3
+; CHECK: mov eax, 4
+
+
+t5_full FWORD 2 DUP (?)
+t5_short DF ?
+
+t5:
+; CHECK-LABEL: t5:
+
+mov eax, sizeof(t5_full)
+mov eax, lengthof(t5_full)
+mov eax, type(t5_full)
+; CHECK: mov eax, 12
+; CHECK: mov eax, 2
+; CHECK: mov eax, 6
+
+mov eax, sizeof(t5_short)
+mov eax, lengthof(t5_short)
+mov eax, type(t5_short)
+; CHECK: mov eax, 6
+; CHECK: mov eax, 1
+; CHECK: mov eax, 6
+
+
+t6_full QWORD 2 DUP (?)
+t6_short DQ ?
+t6_signed SQWORD 3 DUP (?)
+
+t6:
+; CHECK-LABEL: t6:
+
+mov eax, sizeof(t6_full)
+mov eax, lengthof(t6_full)
+mov eax, type(t6_full)
+; CHECK: mov eax, 16
+; CHECK: mov eax, 2
+; CHECK: mov eax, 8
+
+mov eax, sizeof(t6_short)
+mov eax, lengthof(t6_short)
+mov eax, type(t6_short)
+; CHECK: mov eax, 8
+; CHECK: mov eax, 1
+; CHECK: mov eax, 8
+
+mov eax, sizeof(t6_signed)
+mov eax, lengthof(t6_signed)
+mov eax, type(t6_signed)
+; CHECK: mov eax, 24
+; CHECK: mov eax, 3
+; CHECK: mov eax, 8
+
+
+t7_single REAL4 2 DUP (?)
+t7_double REAL8 ?
+
+t7:
+; CHECK-LABEL: t7:
+
+mov eax, sizeof(t7_single)
+mov eax, lengthof(t7_single)
+mov eax, type(t7_single)
+; CHECK: mov eax, 8
+; CHECK: mov eax, 2
+; CHECK: mov eax, 4
+
+mov eax, sizeof(t7_double)
+mov eax, lengthof(t7_double)
+mov eax, type(t7_double)
+; CHECK: mov eax, 8
+; CHECK: mov eax, 1
+; CHECK: mov eax, 8
+
+
+t8_var FOO <>, <>
+
+t8:
+; CHECK-LABEL: t8:
+
+mov eax, sizeof(t8_var)
+mov eax, lengthof(t8_var)
+mov eax, type(t8_var)
+; CHECK: mov eax, 24
+; CHECK: mov eax, 2
+; CHECK: mov eax, 12
+
+mov eax, sizeof(t8_var.y)
+mov eax, lengthof(t8_var.y)
+mov eax, type(t8_var.y)
+; CHECK: mov eax, 10
+; CHECK: mov eax, 5
+; CHECK: mov eax, 2
+
+END
More information about the llvm-commits
mailing list