From 9be3fee2bdc3126fb87e4e1b31935905f4bcc4d0 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 10 Jul 2009 22:20:30 +0000 Subject: [PATCH] add support for .zerofill, patch by Kevin Enderby! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@75301 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCStreamer.h | 11 +++ lib/MC/MCAsmStreamer.cpp | 18 +++++ test/MC/AsmParser/directive_zerofill.s | 10 +++ tools/llvm-mc/AsmParser.cpp | 94 ++++++++++++++++++++++++++ tools/llvm-mc/AsmParser.h | 2 +- 5 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 test/MC/AsmParser/directive_zerofill.s diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 6e204571d60..e0c50ebb72b 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -125,6 +125,17 @@ namespace llvm { virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, unsigned Pow2Alignment, bool IsLocal) = 0; + /// EmitZerofill - Emit a the zerofill section and possiblity a symbol, if + /// @param Symbol is non-NULL, for @param Size and with the @param + /// Pow2Alignment if non-zero. + /// + /// @param Section - The zerofill section to create and or to put the symbol + /// @param Symbol - The zerofill symbol to emit, if non-NULL. + /// @param Size - The size of the zerofill symbol. + /// @param Pow2Alignment - The alignment of the zerofill symbol if non-zero. + virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = 0, + unsigned Size = 0,unsigned Pow2Alignment = 0) = 0; + /// @} /// @name Generating Data /// @{ diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index b7f198232f3..9640fd9121c 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -44,6 +44,9 @@ namespace { virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, unsigned Pow2Alignment, bool IsLocal); + virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = NULL, + unsigned Size = 0, unsigned Pow2Alignment = 0); + virtual void EmitBytes(const char *Data, unsigned Length); virtual void EmitValue(const MCValue &Value, unsigned Size); @@ -157,6 +160,21 @@ void MCAsmStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size, OS << '\n'; } +void MCAsmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, + unsigned Size, unsigned Pow2Alignment) { + // Note: a .zerofill directive does not switch sections + // FIXME: Really we would like the segment and section names as well as the + // section type to be separate values instead of embedded in the name. Not + // all assemblers understand all this stuff though. + OS << ".zerofill " << Section->getName(); + if (Symbol != NULL) { + OS << ',' << Symbol->getName() << ',' << Size; + if (Pow2Alignment != 0) + OS << ',' << Pow2Alignment; + } + OS << '\n'; +} + void MCAsmStreamer::EmitBytes(const char *Data, unsigned Length) { assert(CurSection && "Cannot emit contents before setting section!"); for (unsigned i = 0; i != Length; ++i) diff --git a/test/MC/AsmParser/directive_zerofill.s b/test/MC/AsmParser/directive_zerofill.s new file mode 100644 index 00000000000..2218aba0452 --- /dev/null +++ b/test/MC/AsmParser/directive_zerofill.s @@ -0,0 +1,10 @@ +# RUN: llvm-mc %s | FileCheck %s + +# CHECK: TEST0: +# CHECK: .zerofill __FOO,__bar,x,1 +# CHECK: .zerofill __FOO,__bar,y,8,2 +# CHECK: .zerofill __EMPTY,__NoSymbol +TEST0: + .zerofill __FOO, __bar, x, 2-1 + .zerofill __FOO, __bar, y , 8 , 1+1 + .zerofill __EMPTY,__NoSymbol diff --git a/tools/llvm-mc/AsmParser.cpp b/tools/llvm-mc/AsmParser.cpp index 65ec9628a38..1d9e1b6cac9 100644 --- a/tools/llvm-mc/AsmParser.cpp +++ b/tools/llvm-mc/AsmParser.cpp @@ -524,6 +524,8 @@ bool AsmParser::ParseStatement() { return ParseDirectiveComm(/*IsLocal=*/false); if (!strcmp(IDVal, ".lcomm")) return ParseDirectiveComm(/*IsLocal=*/true); + if (!strcmp(IDVal, ".zerofill")) + return ParseDirectiveDarwinZerofill(); Warning(IDLoc, "ignoring directive for now"); EatToEndOfStatement(); @@ -958,3 +960,95 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) { return false; } + +/// ParseDirectiveDarwinZerofill +/// ::= .zerofill segname , sectname [, identifier , size_expression [ +/// , align_expression ]] +bool AsmParser::ParseDirectiveDarwinZerofill() { + if (Lexer.isNot(asmtok::Identifier)) + return TokError("expected segment name after '.zerofill' directive"); + std::string Section = Lexer.getCurStrVal(); + Lexer.Lex(); + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Section += ','; + Lexer.Lex(); + + if (Lexer.isNot(asmtok::Identifier)) + return TokError("expected section name after comma in '.zerofill' " + "directive"); + Section += Lexer.getCurStrVal(); + Lexer.Lex(); + + // FIXME: we will need to tell GetSection() that this is to be created with or + // must have the Mach-O section type of S_ZEROFILL. Something like the code + // below could be done but for now it is not as EmitZerofill() does not know + // how to deal with a section type in the section name like + // ParseDirectiveDarwinSection() allows. + // Section += ','; + // Section += "zerofill"; + + // If this is the end of the line all that was wanted was to create the + // the section but with no symbol. + if (Lexer.is(asmtok::EndOfStatement)) { + // Create the zerofill section but no symbol + Out.EmitZerofill(Ctx.GetSection(Section.c_str())); + return false; + } + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + + if (Lexer.isNot(asmtok::Identifier)) + return TokError("expected identifier in directive"); + + // handle the identifier as the key symbol. + SMLoc IDLoc = Lexer.getLoc(); + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getCurStrVal()); + Lexer.Lex(); + + if (Lexer.isNot(asmtok::Comma)) + return TokError("unexpected token in directive"); + Lexer.Lex(); + + int64_t Size; + SMLoc SizeLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(Size)) + return true; + + int64_t Pow2Alignment = 0; + SMLoc Pow2AlignmentLoc; + if (Lexer.is(asmtok::Comma)) { + Lexer.Lex(); + Pow2AlignmentLoc = Lexer.getLoc(); + if (ParseAbsoluteExpression(Pow2Alignment)) + return true; + } + + if (Lexer.isNot(asmtok::EndOfStatement)) + return TokError("unexpected token in '.zerofill' directive"); + + Lexer.Lex(); + + if (Size < 0) + return Error(SizeLoc, "invalid '.zerofill' directive size, can't be less " + "than zero"); + + // NOTE: The alignment in the directive is a power of 2 value, the assember + // may internally end up wanting an alignment in bytes. + // FIXME: Diagnose overflow. + if (Pow2Alignment < 0) + return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, " + "can't be less than zero"); + + // TODO: Symbol must be undefined or it is a error to re-defined the symbol + if (Sym->getSection() || Ctx.GetSymbolValue(Sym)) + return Error(IDLoc, "invalid symbol redefinition"); + + // Create the zerofill Symbol with Size and Pow2Alignment + Out.EmitZerofill(Ctx.GetSection(Section.c_str()), Sym, Size, Pow2Alignment); + + return false; +} diff --git a/tools/llvm-mc/AsmParser.h b/tools/llvm-mc/AsmParser.h index 8bfeaac2a7e..620ac19c986 100644 --- a/tools/llvm-mc/AsmParser.h +++ b/tools/llvm-mc/AsmParser.h @@ -111,7 +111,7 @@ private: bool ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr); bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" - + bool ParseDirectiveDarwinZerofill(); // Darwin specific ".zerofill" }; } // end namespace llvm -- 2.34.1