[llvm] 4b56693 - [ms] [llvm-ml] Add support for the (many) optional SEGMENT parameters

Eric Astor via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 10 08:56:50 PDT 2022


Author: Eric Astor
Date: 2022-08-10T15:55:23Z
New Revision: 4b566933cf7b76fb437d671d2b64e971baeba5c8

URL: https://github.com/llvm/llvm-project/commit/4b566933cf7b76fb437d671d2b64e971baeba5c8
DIFF: https://github.com/llvm/llvm-project/commit/4b566933cf7b76fb437d671d2b64e971baeba5c8.diff

LOG: [ms] [llvm-ml] Add support for the (many) optional SEGMENT parameters

Add support for many parameters to the SEGMENT directive

Reviewed By: thakis

Differential Revision: https://reviews.llvm.org/D131523

Added: 
    llvm/test/tools/llvm-ml/segment.asm

Modified: 
    llvm/lib/MC/MCParser/COFFMasmParser.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/MC/MCParser/COFFMasmParser.cpp b/llvm/lib/MC/MCParser/COFFMasmParser.cpp
index c5fedef407828..b89eea498d680 100644
--- a/llvm/lib/MC/MCParser/COFFMasmParser.cpp
+++ b/llvm/lib/MC/MCParser/COFFMasmParser.cpp
@@ -9,9 +9,11 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCAsmMacro.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
 #include "llvm/MC/MCSectionCOFF.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSymbolCOFF.h"
@@ -33,12 +35,12 @@ class COFFMasmParser : public MCAsmParserExtension {
     getParser().addDirectiveHandler(Directive, Handler);
   }
 
-  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+  bool ParseSectionSwitch(StringRef SectionName, unsigned Characteristics,
                           SectionKind Kind);
 
-  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+  bool ParseSectionSwitch(StringRef SectionName, unsigned Characteristics,
                           SectionKind Kind, StringRef COMDATSymName,
-                          COFF::COMDATType Type);
+                          COFF::COMDATType Type, Align Alignment);
 
   bool ParseDirectiveProc(StringRef, SMLoc);
   bool ParseDirectiveEndProc(StringRef, SMLoc);
@@ -213,33 +215,24 @@ class COFFMasmParser : public MCAsmParserExtension {
 
 } // end anonymous namespace.
 
-static SectionKind computeSectionKind(unsigned Flags) {
-  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
-    return SectionKind::getText();
-  if (Flags & COFF::IMAGE_SCN_MEM_READ &&
-      (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
-    return SectionKind::getReadOnly();
-  return SectionKind::getData();
-}
-
-bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+bool COFFMasmParser::ParseSectionSwitch(StringRef SectionName,
                                         unsigned Characteristics,
                                         SectionKind Kind) {
-  return ParseSectionSwitch(Section, Characteristics, Kind, "",
-                            (COFF::COMDATType)0);
+  return ParseSectionSwitch(SectionName, Characteristics, Kind, "",
+                            (COFF::COMDATType)0, Align(16));
 }
 
-bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
-                                        unsigned Characteristics,
-                                        SectionKind Kind,
-                                        StringRef COMDATSymName,
-                                        COFF::COMDATType Type) {
+bool COFFMasmParser::ParseSectionSwitch(
+    StringRef SectionName, unsigned Characteristics, SectionKind Kind,
+    StringRef COMDATSymName, COFF::COMDATType Type, Align Alignment) {
   if (getLexer().isNot(AsmToken::EndOfStatement))
     return TokError("unexpected token in section switching directive");
   Lex();
 
-  getStreamer().switchSection(getContext().getCOFFSection(
-      Section, Characteristics, Kind, COMDATSymName, Type));
+  MCSection *Section = getContext().getCOFFSection(SectionName, Characteristics,
+                                                   Kind, COMDATSymName, Type);
+  Section->setAlignment(Alignment);
+  getStreamer().switchSection(Section);
 
   return false;
 }
@@ -253,8 +246,8 @@ bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
 
   StringRef SectionName = SegmentName;
   SmallVector<char, 247> SectionNameVector;
-  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
-                   COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
+
+  StringRef Class;
   if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
     if (SegmentName.size() == 5) {
       SectionName = ".text";
@@ -262,12 +255,119 @@ bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
       SectionName =
           (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
     }
-    Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
-            COFF::IMAGE_SCN_MEM_READ;
+    Class = "CODE";
   }
-  SectionKind Kind = computeSectionKind(Flags);
-  getStreamer().switchSection(getContext().getCOFFSection(
-      SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
+
+  // Parse all options to end of statement.
+  // Alignment defaults to PARA if unspecified.
+  int64_t Alignment = 16;
+  // Default flags are used only if no characteristics are set.
+  bool DefaultCharacteristics = true;
+  unsigned Flags = 0;
+  // "obsolete" according to the documentation, but still supported.
+  bool Readonly = false;
+  while (getLexer().isNot(AsmToken::EndOfStatement)) {
+    switch (getTok().getKind()) {
+    default:
+      break;
+    case AsmToken::String: {
+      // Class identifier; overrides Kind.
+      Class = getTok().getStringContents();
+      Lex();
+      break;
+    }
+    case AsmToken::Identifier: {
+      SMLoc KeywordLoc = getTok().getLoc();
+      StringRef Keyword;
+      if (getParser().parseIdentifier(Keyword)) {
+        llvm_unreachable("failed to parse identifier at an identifier token");
+      }
+      if (Keyword.equals_insensitive("byte")) {
+        Alignment = 1;
+      } else if (Keyword.equals_insensitive("word")) {
+        Alignment = 2;
+      } else if (Keyword.equals_insensitive("dword")) {
+        Alignment = 4;
+      } else if (Keyword.equals_insensitive("para")) {
+        Alignment = 16;
+      } else if (Keyword.equals_insensitive("page")) {
+        Alignment = 256;
+      } else if (Keyword.equals_insensitive("align")) {
+        if (getParser().parseToken(AsmToken::LParen) ||
+            getParser().parseIntToken(Alignment,
+                                      "Expected integer alignment") ||
+            getParser().parseToken(AsmToken::RParen)) {
+          return Error(getTok().getLoc(),
+                       "Expected (n) following ALIGN in SEGMENT directive");
+        }
+        if (!isPowerOf2_64(Alignment) || Alignment > 8192) {
+          return Error(KeywordLoc,
+                       "ALIGN argument must be a power of 2 from 1 to 8192");
+        }
+      } else if (Keyword.equals_insensitive("alias")) {
+        if (getParser().parseToken(AsmToken::LParen) ||
+            !getTok().is(AsmToken::String))
+          return Error(
+              getTok().getLoc(),
+              "Expected (string) following ALIAS in SEGMENT directive");
+        SectionName = getTok().getStringContents();
+        Lex();
+        if (getParser().parseToken(AsmToken::RParen))
+          return Error(
+              getTok().getLoc(),
+              "Expected (string) following ALIAS in SEGMENT directive");
+      } else if (Keyword.equals_insensitive("readonly")) {
+        Readonly = true;
+      } else {
+        unsigned Characteristic =
+            StringSwitch<unsigned>(Keyword)
+                .CaseLower("info", COFF::IMAGE_SCN_LNK_INFO)
+                .CaseLower("read", COFF::IMAGE_SCN_MEM_READ)
+                .CaseLower("write", COFF::IMAGE_SCN_MEM_WRITE)
+                .CaseLower("execute", COFF::IMAGE_SCN_MEM_EXECUTE)
+                .CaseLower("shared", COFF::IMAGE_SCN_MEM_SHARED)
+                .CaseLower("nopage", COFF::IMAGE_SCN_MEM_NOT_PAGED)
+                .CaseLower("nocache", COFF::IMAGE_SCN_MEM_NOT_CACHED)
+                .CaseLower("discard", COFF::IMAGE_SCN_MEM_DISCARDABLE)
+                .Default(-1);
+        if (Characteristic == -1) {
+          return Error(KeywordLoc,
+                       "Expected characteristic in SEGMENT directive; found '" +
+                           Keyword + "'");
+        }
+        Flags |= Characteristic;
+        DefaultCharacteristics = false;
+      }
+    }
+    }
+  }
+
+  SectionKind Kind = StringSwitch<SectionKind>(Class)
+                         .CaseLower("data", SectionKind::getData())
+                         .CaseLower("code", SectionKind::getText())
+                         .CaseLower("const", SectionKind::getReadOnly())
+                         .Default(SectionKind::getData());
+  if (Kind.isText()) {
+    if (DefaultCharacteristics) {
+      Flags |= COFF::IMAGE_SCN_MEM_EXECUTE | COFF::IMAGE_SCN_MEM_READ;
+    }
+    Flags |= COFF::IMAGE_SCN_CNT_CODE;
+  } else {
+    if (DefaultCharacteristics) {
+      Flags |= COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
+    }
+    Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
+  }
+  if (Readonly) {
+    Flags &= ~COFF::IMAGE_SCN_MEM_WRITE;
+  }
+
+  MCSection *Section = getContext().getCOFFSection(SectionName, Flags, Kind, "",
+                                                   (COFF::COMDATType)(0));
+  if (Alignment != 0) {
+    Section->setAlignment(Align(Alignment));
+  }
+  getStreamer().switchSection(Section);
   return false;
 }
 
@@ -292,7 +392,7 @@ bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
     return TokError("expected identifier in includelib directive");
 
   unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
-  SectionKind Kind = computeSectionKind(Flags);
+  SectionKind Kind = SectionKind::getData();
   getStreamer().pushSection();
   getStreamer().switchSection(getContext().getCOFFSection(
       ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));

diff  --git a/llvm/test/tools/llvm-ml/segment.asm b/llvm/test/tools/llvm-ml/segment.asm
new file mode 100644
index 0000000000000..984e5d20c8880
--- /dev/null
+++ b/llvm/test/tools/llvm-ml/segment.asm
@@ -0,0 +1,143 @@
+; RUN: llvm-ml %s /Fo - | llvm-readobj --section-headers - | FileCheck %s
+
+t1 SEGMENT BYTE
+t1 ENDS
+; CHECK-LABEL: Name: t1
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_1BYTES
+
+t2 SEGMENT WORD
+t2 ENDS
+; CHECK-LABEL: Name: t2
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_2BYTES
+
+t3 SEGMENT DWORD
+t3 ENDS
+; CHECK-LABEL: Name: t3
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_4BYTES
+
+t4 SEGMENT PARA
+t4 ENDS
+; CHECK-LABEL: Name: t4
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_16BYTES
+
+t5 SEGMENT PAGE
+t5 ENDS
+; CHECK-LABEL: Name: t5
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_256BYTES
+
+; Default alignment (should match PARA)
+t6 SEGMENT
+t6 ENDS
+; CHECK-LABEL: Name: t6
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_16BYTES
+
+; Unnamed alignment
+t7 SEGMENT ALIGN(32)
+t7 ENDS
+; CHECK-LABEL: Name: t7
+; CHECK-NOT: }
+; CHECK: IMAGE_SCN_ALIGN_32BYTES
+
+t8 SEGMENT ALIAS('t8_alias')
+t8 ENDS
+; CHECK-LABEL: Name: t8_alias
+
+t9 SEGMENT 'DATA'
+t9 ENDS
+; CHECK-LABEL: Name: t9
+; CHECK-NOT: }
+; CHECK-DAG: IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-DAG: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+t10 SEGMENT 'CODE'
+t10 ENDS
+; CHECK-LABEL: Name: t10
+; CHECK-NOT: }
+; CHECK-NOT: IMAGE_SCN_MEM_WRITE
+; CHECK-DAG: IMAGE_SCN_CNT_CODE
+; CHECK-DAG: IMAGE_SCN_MEM_EXECUTE
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-NOT: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+t11 SEGMENT 'CONST'
+t11 ENDS
+; CHECK-LABEL: Name: t11
+; CHECK-NOT: }
+; CHECK-DAG: IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-DAG: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+t12 SEGMENT 'STACK'
+t12 ENDS
+; CHECK-LABEL: Name: t12
+; CHECK-NOT: }
+; CHECK-DAG: IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-DAG: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+t13 SEGMENT 'DOESNTEXIST'
+t13 ENDS
+; CHECK-LABEL: Name: t13
+; CHECK-NOT: }
+; CHECK-DAG: IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-DAG: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+t14 SEGMENT READONLY 'CONST'
+t14 ENDS
+; CHECK-LABEL: Name: t14
+; CHECK-NOT: }
+; CHECK-NOT: IMAGE_SCN_MEM_WRITE
+; CHECK-DAG: IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-NOT: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+t15 SEGMENT WRITE
+t15 ENDS
+; CHECK-LABEL: Name: t15
+; CHECK-NOT: }
+; CHECK-NOT: IMAGE_SCN_MEM_READ
+; CHECK-DAG: IMAGE_SCN_CNT_INITIALIZED_DATA
+; CHECK-DAG: IMAGE_SCN_MEM_WRITE
+; CHECK-NOT: IMAGE_SCN_MEM_READ
+; CHECK: }
+
+t16 SEGMENT SHARED NOPAGE NOCACHE INFO READ WRITE EXECUTE DISCARD
+t16 ENDS
+; CHECK-LABEL: Name: t16
+; CHECK-NOT: }
+; CHECK-DAG: IMAGE_SCN_LNK_INFO
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-DAG: IMAGE_SCN_MEM_WRITE
+; CHECK-DAG: IMAGE_SCN_MEM_EXECUTE
+; CHECK-DAG: IMAGE_SCN_MEM_SHARED
+; CHECK-DAG: IMAGE_SCN_MEM_NOT_PAGED
+; CHECK-DAG: IMAGE_SCN_MEM_NOT_CACHED
+; CHECK-DAG: IMAGE_SCN_MEM_DISCARDABLE
+; CHECK: }
+
+_TEXT SEGMENT
+_TEXT ENDS
+; CHECK-LABEL: Name: .text
+; CHECK-NOT: }
+; CHECK-NOT: IMAGE_SCN_MEM_WRITE
+; CHECK-DAG: IMAGE_SCN_CNT_CODE
+; CHECK-DAG: IMAGE_SCN_MEM_EXECUTE
+; CHECK-DAG: IMAGE_SCN_MEM_READ
+; CHECK-NOT: IMAGE_SCN_MEM_WRITE
+; CHECK: }
+
+END


        


More information about the llvm-commits mailing list