[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