+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 COFFAsmParser::ParseSectionFlags(StringRef FlagsString, unsigned* Flags) {
+ enum {
+ None = 0,
+ Alloc = 1 << 0,
+ Code = 1 << 1,
+ Load = 1 << 2,
+ InitData = 1 << 3,
+ Shared = 1 << 4,
+ NoLoad = 1 << 5,
+ NoRead = 1 << 6,
+ NoWrite = 1 << 7
+ };
+
+ bool ReadOnlyRemoved = false;
+ unsigned SecFlags = None;
+
+ for (char FlagChar : FlagsString) {
+ switch (FlagChar) {
+ case 'a':
+ // Ignored.
+ break;
+
+ case 'b': // bss section
+ SecFlags |= Alloc;
+ if (SecFlags & InitData)
+ return TokError("conflicting section flags 'b' and 'd'.");
+ SecFlags &= ~Load;
+ break;
+
+ case 'd': // data section
+ SecFlags |= InitData;
+ if (SecFlags & Alloc)
+ return TokError("conflicting section flags 'b' and 'd'.");
+ SecFlags &= ~NoWrite;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 'n': // section is not loaded
+ SecFlags |= NoLoad;
+ SecFlags &= ~Load;
+ break;
+
+ case 'r': // read-only
+ ReadOnlyRemoved = false;
+ SecFlags |= NoWrite;
+ if ((SecFlags & Code) == 0)
+ SecFlags |= InitData;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 's': // shared section
+ SecFlags |= Shared | InitData;
+ SecFlags &= ~NoWrite;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ break;
+
+ case 'w': // writable
+ SecFlags &= ~NoWrite;
+ ReadOnlyRemoved = true;
+ break;
+
+ case 'x': // executable section
+ SecFlags |= Code;
+ if ((SecFlags & NoLoad) == 0)
+ SecFlags |= Load;
+ if (!ReadOnlyRemoved)
+ SecFlags |= NoWrite;
+ break;
+
+ case 'y': // not readable
+ SecFlags |= NoRead | NoWrite;
+ break;
+
+ default:
+ return TokError("unknown flag");
+ }
+ }
+
+ *Flags = 0;
+
+ if (SecFlags == None)
+ SecFlags = InitData;
+
+ if (SecFlags & Code)
+ *Flags |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
+ if (SecFlags & InitData)
+ *Flags |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
+ if ((SecFlags & Alloc) && (SecFlags & Load) == 0)
+ *Flags |= COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ if (SecFlags & NoLoad)
+ *Flags |= COFF::IMAGE_SCN_LNK_REMOVE;
+ if ((SecFlags & NoRead) == 0)
+ *Flags |= COFF::IMAGE_SCN_MEM_READ;
+ if ((SecFlags & NoWrite) == 0)
+ *Flags |= COFF::IMAGE_SCN_MEM_WRITE;
+ if (SecFlags & Shared)
+ *Flags |= COFF::IMAGE_SCN_MEM_SHARED;
+
+ return false;
+}
+
+/// ParseDirectiveSymbolAttribute
+/// ::= { ".weak", ... } [ identifier ( , identifier )* ]
+bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
+ MCSymbolAttr Attr = StringSwitch<MCSymbolAttr>(Directive)
+ .Case(".weak", MCSA_Weak)
+ .Default(MCSA_Invalid);
+ assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ for (;;) {
+ StringRef Name;
+
+ if (getParser().parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+
+ MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
+
+ getStreamer().EmitSymbolAttribute(Sym, Attr);
+
+ if (getLexer().is(AsmToken::EndOfStatement))
+ break;
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("unexpected token in directive");
+ Lex();
+ }
+ }
+
+ Lex();
+ return false;
+}
+