diff options
-rw-r--r-- | include/llvm/MC/MCContext.h | 18 | ||||
-rw-r--r-- | include/llvm/MC/MCLabel.h | 56 | ||||
-rw-r--r-- | lib/MC/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/MC/MCContext.cpp | 45 | ||||
-rw-r--r-- | lib/MC/MCLabel.cpp | 21 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmLexer.cpp | 12 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 47 | ||||
-rw-r--r-- | test/MC/MachO/direction_labels.s | 92 |
8 files changed, 283 insertions, 9 deletions
diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 50ae9cc..03b5fb0 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -20,6 +20,7 @@ namespace llvm { class MCExpr; class MCSection; class MCSymbol; + class MCLabel; class StringRef; class Twine; class MCSectionMachO; @@ -43,6 +44,15 @@ namespace llvm { /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary /// symbol. unsigned NextUniqueID; + + /// Instances of directional local labels. + DenseMap<unsigned, MCLabel *> Instances; + /// NextInstance() creates the next instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned NextInstance(int64_t LocalLabelVal); + /// GetInstance() gets the current instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned GetInstance(int64_t LocalLabelVal); /// Allocator - Allocator object used for creating machine code objects. /// @@ -64,6 +74,14 @@ namespace llvm { /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); + /// CreateDirectionalLocalSymbol - Create the defintion of a directional + /// local symbol for numbered label (used for "1:" defintions). + MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); + + /// GetDirectionalLocalSymbol - Create and return a directional local + /// symbol for numbered label (used for "1b" or 1f" references). + MCSymbol *GetDirectionalLocalSymbol(int64_t LocalLabelVal, int bORf); + /// GetOrCreateSymbol - Lookup the symbol inside with the specified /// @p Name. If it exists, return it. If not, create a forward /// reference and return it. diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h new file mode 100644 index 0000000..727520d --- /dev/null +++ b/include/llvm/MC/MCLabel.h @@ -0,0 +1,56 @@ +//===- MCLabel.h - Machine Code Directional Local Labels --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCLabel class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCLABEL_H +#define LLVM_MC_MCLABEL_H + +namespace llvm { + class MCContext; + class raw_ostream; + + /// MCLabel - Instances of this class represent a label name in the MC file, + /// and MCLabel are created and unique'd by the MCContext class. MCLabel + /// should only be constructed for valid instances in the object file. + class MCLabel { + // Instance - the instance number of this Directional Local Label + unsigned Instance; + + private: // MCContext creates and uniques these. + friend class MCContext; + MCLabel(unsigned instance) + : Instance(instance) {} + + MCLabel(const MCLabel&); // DO NOT IMPLEMENT + void operator=(const MCLabel&); // DO NOT IMPLEMENT + public: + /// getInstance - Get the current instance of this Directional Local Label. + unsigned getInstance() const { return Instance; } + + /// incInstance - Increment the current instance of this Directional Local + /// Label. + unsigned incInstance() { return ++Instance; } + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) { + Label.print(OS); + return OS; + } +} // end namespace llvm + +#endif diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 7ddeef7..af979f7 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -10,6 +10,7 @@ add_llvm_library(LLVMMC MCExpr.cpp MCInst.cpp MCInstPrinter.cpp + MCLabel.cpp MCMachOStreamer.cpp MCNullStreamer.cpp MCObjectWriter.cpp diff --git a/lib/MC/MCContext.cpp b/lib/MC/MCContext.cpp index 5a65b8a..5cc72e8 100644 --- a/lib/MC/MCContext.cpp +++ b/lib/MC/MCContext.cpp @@ -13,6 +13,7 @@ #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCLabel.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" using namespace llvm; @@ -71,6 +72,50 @@ MCSymbol *MCContext::CreateTempSymbol() { "tmp" + Twine(NextUniqueID++)); } +unsigned MCContext::NextInstance(int64_t LocalLabelVal) { + unsigned Instance; + MCLabel *Label; + Label = Instances[LocalLabelVal]; + if (Label) { + Instance = Label->incInstance(); + } + else { + Instance = 1; + Label = new MCLabel(Instance); + Instances[LocalLabelVal] = Label; + } + return Instance; +} + +unsigned MCContext::GetInstance(int64_t LocalLabelVal) { + int Instance; + MCLabel *Label; + Label = Instances[LocalLabelVal]; + if (Label) { + Instance = Label->getInstance(); + } + else { + Instance = 0; + Label = new MCLabel(Instance); + Instances[LocalLabelVal] = Label; + } + return Instance; +} + +MCSymbol *MCContext::CreateDirectionalLocalSymbol(int64_t LocalLabelVal) { + return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + + Twine(LocalLabelVal) + + "\2" + + Twine(NextInstance(LocalLabelVal))); +} +MCSymbol *MCContext::GetDirectionalLocalSymbol(int64_t LocalLabelVal, + int bORf) { + return GetOrCreateSymbol(Twine(MAI.getPrivateGlobalPrefix()) + + Twine(LocalLabelVal) + + "\2" + + Twine(GetInstance(LocalLabelVal) + bORf)); +} + MCSymbol *MCContext::LookupSymbol(StringRef Name) const { return Symbols.lookup(Name); } diff --git a/lib/MC/MCLabel.cpp b/lib/MC/MCLabel.cpp new file mode 100644 index 0000000..9c0fc92 --- /dev/null +++ b/lib/MC/MCLabel.cpp @@ -0,0 +1,21 @@ +//===- lib/MC/MCLabel.cpp - MCLabel implementation ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCLabel.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +void MCLabel::print(raw_ostream &OS) const { + OS << '"' << getInstance() << '"'; +} + +void MCLabel::dump() const { + print(dbgs()); +} diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index 1183312..e74eac5 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -132,11 +132,6 @@ AsmToken AsmLexer::LexLineComment() { /// Decimal integer: [1-9][0-9]* /// TODO: FP literal. AsmToken AsmLexer::LexDigit() { - if (*CurPtr == ':') - return ReturnError(TokStart, "FIXME: local label not implemented"); - if (*CurPtr == 'f' || *CurPtr == 'b') - return ReturnError(TokStart, "FIXME: directional label not implemented"); - // Decimal integer: [1-9][0-9]* if (CurPtr[-1] != '0') { while (isdigit(*CurPtr)) @@ -158,6 +153,13 @@ AsmToken AsmLexer::LexDigit() { if (*CurPtr == 'b') { ++CurPtr; + // See if we actually have "0b" as part of something like "jmp 0b\n" + if (CurPtr[0] == '\n') { + --CurPtr; + StringRef Result(TokStart, CurPtr - TokStart); + ++CurPtr; + return AsmToken(AsmToken::Integer, Result, 0); + } const char *NumStart = CurPtr; while (CurPtr[0] == '0' || CurPtr[0] == '1') ++CurPtr; diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 2a60a67..6a89df1 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -214,11 +214,28 @@ bool AsmParser::ParsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { Res = MCSymbolRefExpr::Create(Sym, Variant, getContext()); return false; } - case AsmToken::Integer: - Res = MCConstantExpr::Create(getTok().getIntVal(), getContext()); + case AsmToken::Integer: { + SMLoc Loc = getTok().getLoc(); + int64_t IntVal = getTok().getIntVal(); + Res = MCConstantExpr::Create(IntVal, getContext()); EndLoc = Lexer.getLoc(); Lex(); // Eat token. + // Look for 'b' or 'f' following an Integer as a directional label + if (Lexer.getKind() == AsmToken::Identifier) { + StringRef IDVal = getTok().getString(); + if (IDVal == "f" || IDVal == "b"){ + MCSymbol *Sym = Ctx.GetDirectionalLocalSymbol(IntVal, + IDVal == "f" ? 1 : 0); + Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, + getContext()); + if(IDVal == "b" && Sym->isUndefined()) + return Error(Loc, "invalid reference to undefined symbol"); + EndLoc = Lexer.getLoc(); + Lex(); // Eat identifier. + } + } return false; + } case AsmToken::Dot: { // This is a '.' reference, which references the current PC. Emit a // temporary label to the streamer and refer to it. @@ -422,7 +439,25 @@ bool AsmParser::ParseStatement() { AsmToken ID = getTok(); SMLoc IDLoc = ID.getLoc(); StringRef IDVal; - if (ParseIdentifier(IDVal)) { + int64_t LocalLabelVal = -1; + // GUESS allow an integer followed by a ':' as a directional local label + if (Lexer.is(AsmToken::Integer)) { + LocalLabelVal = getTok().getIntVal(); + if (LocalLabelVal < 0) { + if (!TheCondState.Ignore) + return TokError("unexpected token at start of statement"); + IDVal = ""; + } + else { + IDVal = getTok().getString(); + Lex(); // Consume the integer token to be used as an identifier token. + if (Lexer.getKind() != AsmToken::Colon) { + if (!TheCondState.Ignore) + return TokError("unexpected token at start of statement"); + } + } + } + else if (ParseIdentifier(IDVal)) { if (!TheCondState.Ignore) return TokError("unexpected token at start of statement"); IDVal = ""; @@ -459,7 +494,11 @@ bool AsmParser::ParseStatement() { // FIXME: Diagnostics. Note the location of the definition as a label. // FIXME: This doesn't diagnose assignment to a symbol which has been // implicitly marked as external. - MCSymbol *Sym = CreateSymbol(IDVal); + MCSymbol *Sym; + if (LocalLabelVal == -1) + Sym = CreateSymbol(IDVal); + else + Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal); if (!Sym->isUndefined() || Sym->isVariable()) return Error(IDLoc, "invalid symbol redefinition"); diff --git a/test/MC/MachO/direction_labels.s b/test/MC/MachO/direction_labels.s new file mode 100644 index 0000000..c3d4869 --- /dev/null +++ b/test/MC/MachO/direction_labels.s @@ -0,0 +1,92 @@ +// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s + +direction_labels: +10: nop + jmp 10b + nop + jmp 11f +11: nop + ret + +// CHECK: ('cputype', 7) +// CHECK: ('cpusubtype', 3) +// CHECK: ('filetype', 1) +// CHECK: ('num_load_commands', 1) +// CHECK: ('load_commands_size', 228) +// CHECK: ('flag', 0) +// CHECK: ('load_commands', [ +// CHECK: # Load Command 0 +// CHECK: (('command', 1) +// CHECK: ('size', 124) +// CHECK: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +// CHECK: ('vm_addr', 0) +// CHECK: ('vm_size', 8) +// CHECK: ('file_offset', 256) +// CHECK: ('file_size', 8) +// CHECK: ('maxprot', 7) +// CHECK: ('initprot', 7) +// CHECK: ('num_sections', 1) +// CHECK: ('flags', 0) +// CHECK: ('sections', [ +// CHECK: # Section 0 +// CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +// CHECK: ('address', 0) +// CHECK: ('size', 8) +// CHECK: ('offset', 256) +// CHECK: ('alignment', 0) +// CHECK: ('reloc_offset', 0) +// CHECK: ('num_reloc', 0) +// CHECK: ('flags', 0x80000400) +// CHECK: ('reserved1', 0) +// CHECK: ('reserved2', 0) +// CHECK: ), +// CHECK: ('_relocations', [ +// CHECK: ]) +// CHECK: ('_section_data', '\x90\xeb\xfd\x90\xeb\x00\x90\xc3') +// CHECK: ]) +// CHECK: ), +// CHECK: # Load Command 1 +// CHECK: (('command', 2) +// CHECK: ('size', 24) +// CHECK: ('symoff', 264) +// CHECK: ('nsyms', 1) +// CHECK: ('stroff', 276) +// CHECK: ('strsize', 20) +// CHECK: ('_string_data', '\x00direction_labels\x00\x00\x00') +// CHECK: ('_symbols', [ +// CHECK: # Symbol 0 +// CHECK: (('n_strx', 1) +// CHECK: ('n_type', 0xe) +// CHECK: ('n_sect', 1) +// CHECK: ('n_desc', 0) +// CHECK: ('n_value', 0) +// CHECK: ('_string', 'direction_labels') +// CHECK: ), +// CHECK: ]) +// CHECK: ), +// CHECK: # Load Command 2 +// CHECK: (('command', 11) +// CHECK: ('size', 80) +// CHECK: ('ilocalsym', 0) +// CHECK: ('nlocalsym', 1) +// CHECK: ('iextdefsym', 1) +// CHECK: ('nextdefsym', 0) +// CHECK: ('iundefsym', 1) +// CHECK: ('nundefsym', 0) +// CHECK: ('tocoff', 0) +// CHECK: ('ntoc', 0) +// CHECK: ('modtaboff', 0) +// CHECK: ('nmodtab', 0) +// CHECK: ('extrefsymoff', 0) +// CHECK: ('nextrefsyms', 0) +// CHECK: ('indirectsymoff', 0) +// CHECK: ('nindirectsyms', 0) +// CHECK: ('extreloff', 0) +// CHECK: ('nextrel', 0) +// CHECK: ('locreloff', 0) +// CHECK: ('nlocrel', 0) +// CHECK: ('_indirect_symbols', [ +// CHECK: ]) +// CHECK: ), +// CHECK: ]) |