From ef920552d4fb0959097f1c165cfc81c69db19934 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 8 Aug 2012 06:30:30 +0000 Subject: [PATCH] Add `.pushsection', `.popsection', and `.previous' directives to Darwin ASM. There are situations where inline ASM may want to change the section -- for instance, to create a variable in the .data section. However, it cannot do this without (potentially) restoring to the wrong section. E.g.: asm volatile (".section __DATA, __data\n\t" ".globl _fnord\n\t" "_fnord: .quad 1f\n\t" ".text\n\t" "1:" :::); This may be wrong if this is inlined into a function that has a "section" attribute. The user should use `.pushsection' and `.popsection' here instead. The addition of `.previous' is added for completeness. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161477 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/MCParser/DarwinAsmParser.cpp | 41 +++++++++++++++++++++++++++-- test/MC/MachO/previous.s | 13 +++++++++ test/MC/MachO/pushsection.s | 16 +++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 test/MC/MachO/previous.s create mode 100644 test/MC/MachO/pushsection.s diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index 5662fea86ce..18033d05eb7 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -50,6 +50,9 @@ public: AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".dump"); AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveDumpOrLoad>(".load"); AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSection>(".section"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePushSection>(".pushsection"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePopSection>(".popsection"); + AddDirectiveHandler<&DarwinAsmParser::ParseDirectivePrevious>(".previous"); AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogUnique>( ".secure_log_unique"); AddDirectiveHandler<&DarwinAsmParser::ParseDirectiveSecureLogReset>( @@ -112,6 +115,9 @@ public: bool ParseDirectiveDumpOrLoad(StringRef, SMLoc); bool ParseDirectiveLsym(StringRef, SMLoc); bool ParseDirectiveSection(StringRef, SMLoc); + bool ParseDirectivePushSection(StringRef, SMLoc); + bool ParseDirectivePopSection(StringRef, SMLoc); + bool ParseDirectivePrevious(StringRef, SMLoc); bool ParseDirectiveSecureLogReset(StringRef, SMLoc); bool ParseDirectiveSecureLogUnique(StringRef, SMLoc); bool ParseDirectiveSubsectionsViaSymbols(StringRef, SMLoc); @@ -297,7 +303,7 @@ public: }; -} +} // end anonymous namespace bool DarwinAsmParser::ParseSectionSwitch(const char *Segment, const char *Section, @@ -457,6 +463,37 @@ bool DarwinAsmParser::ParseDirectiveSection(StringRef, SMLoc) { return false; } +/// ParseDirectivePushSection: +/// ::= .pushsection identifier (',' identifier)* +bool DarwinAsmParser::ParseDirectivePushSection(StringRef S, SMLoc Loc) { + getStreamer().PushSection(); + + if (ParseDirectiveSection(S, Loc)) { + getStreamer().PopSection(); + return true; + } + + return false; +} + +/// ParseDirectivePopSection: +/// ::= .popsection +bool DarwinAsmParser::ParseDirectivePopSection(StringRef, SMLoc) { + if (!getStreamer().PopSection()) + return TokError(".popsection without corresponding .pushsection"); + return false; +} + +/// ParseDirectivePrevious: +/// ::= .previous +bool DarwinAsmParser::ParseDirectivePrevious(StringRef DirName, SMLoc) { + const MCSection *PreviousSection = getStreamer().getPreviousSection(); + if (PreviousSection == NULL) + return TokError(".previous without corresponding .section"); + getStreamer().SwitchSection(PreviousSection); + return false; +} + /// ParseDirectiveSecureLogUnique /// ::= .secure_log_unique ... message ... bool DarwinAsmParser::ParseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { @@ -707,4 +744,4 @@ MCAsmParserExtension *createDarwinAsmParser() { return new DarwinAsmParser; } -} +} // end llvm namespace diff --git a/test/MC/MachO/previous.s b/test/MC/MachO/previous.s new file mode 100644 index 00000000000..41077cd0c0d --- /dev/null +++ b/test/MC/MachO/previous.s @@ -0,0 +1,13 @@ +// RUN: llvm-mc -triple i386-apple-darwin9 %s -o - | FileCheck %s + +.text +// CHECK: .section __TEXT,__text + +.data +// CHECK: .section __DATA,__data + +.previous +// CHECK: .section __TEXT,__text + +.previous +// CHECK: .section __DATA,__data diff --git a/test/MC/MachO/pushsection.s b/test/MC/MachO/pushsection.s new file mode 100644 index 00000000000..6881323a4df --- /dev/null +++ b/test/MC/MachO/pushsection.s @@ -0,0 +1,16 @@ +// RUN: llvm-mc -triple i386-apple-darwin9 %s -o - | FileCheck %s + +.text +// CHECK: .section __TEXT,__text + +.pushsection __DATA, __data +// CHECK: .section __DATA,__data + +.pushsection __TEXT, initcode +// CHECK: .section __TEXT,initcode + +.popsection +// CHECK: .section __DATA,__data + +.popsection +// CHECK: .section __TEXT,__text