[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