forked from OSchip/llvm-project
llvm-mc: Clean up some handling of symbol/section association to be more correct
(external was really undefined and there wasn't an explicit representation for absolute symbols). - This still needs some cleanup to how the absolute "pseudo" section is dealt with, but I haven't figured out the nicest approach yet. llvm-svn: 79733
This commit is contained in:
parent
81c0524102
commit
6860ac7375
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class MCSection;
|
class MCSection;
|
||||||
|
@ -30,39 +31,69 @@ namespace llvm {
|
||||||
/// it is a reference to an external entity, it has a null section.
|
/// it is a reference to an external entity, it has a null section.
|
||||||
///
|
///
|
||||||
class MCSymbol {
|
class MCSymbol {
|
||||||
|
// Special sentinal value for the absolute pseudo section.
|
||||||
|
//
|
||||||
|
// FIXME: Use a PointerInt wrapper for this?
|
||||||
|
static const MCSection *AbsolutePseudoSection;
|
||||||
|
|
||||||
/// Name - The name of the symbol.
|
/// Name - The name of the symbol.
|
||||||
std::string Name;
|
std::string Name;
|
||||||
/// Section - The section the symbol is defined in, or null if the symbol
|
|
||||||
/// has not been defined in the associated translation unit.
|
/// Section - The section the symbol is defined in. This is null for
|
||||||
|
/// undefined symbols, and the special AbsolutePseudoSection value for
|
||||||
|
/// absolute symbols.
|
||||||
const MCSection *Section;
|
const MCSection *Section;
|
||||||
|
|
||||||
/// IsTemporary - True if this is an assembler temporary label, which
|
/// IsTemporary - True if this is an assembler temporary label, which
|
||||||
/// typically does not survive in the .o file's symbol table. Usually
|
/// typically does not survive in the .o file's symbol table. Usually
|
||||||
/// "Lfoo" or ".foo".
|
/// "Lfoo" or ".foo".
|
||||||
unsigned IsTemporary : 1;
|
unsigned IsTemporary : 1;
|
||||||
|
|
||||||
/// IsExternal - True if this symbol has been implicitly defined as an
|
|
||||||
/// external, for example by using it in an expression without ever emitting
|
|
||||||
/// it as a label. The @var Section for an external symbol is always null.
|
|
||||||
unsigned IsExternal : 1;
|
|
||||||
|
|
||||||
private: // MCContext creates and uniques these.
|
private: // MCContext creates and uniques these.
|
||||||
friend class MCContext;
|
friend class MCContext;
|
||||||
MCSymbol(const StringRef &_Name, bool _IsTemporary)
|
MCSymbol(const StringRef &_Name, bool _IsTemporary)
|
||||||
: Name(_Name), Section(0), IsTemporary(_IsTemporary), IsExternal(false) {}
|
: Name(_Name), Section(0),
|
||||||
|
IsTemporary(_IsTemporary) {}
|
||||||
|
|
||||||
MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT
|
MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT
|
||||||
void operator=(const MCSymbol&); // DO NOT IMPLEMENT
|
void operator=(const MCSymbol&); // DO NOT IMPLEMENT
|
||||||
public:
|
public:
|
||||||
|
/// getName - Get the symbol name.
|
||||||
const MCSection *getSection() const { return Section; }
|
|
||||||
void setSection(const MCSection *S) { Section = S; }
|
|
||||||
|
|
||||||
bool isExternal() const { return IsExternal; }
|
|
||||||
void setExternal(bool Value) { IsExternal = Value; }
|
|
||||||
|
|
||||||
const std::string &getName() const { return Name; }
|
const std::string &getName() const { return Name; }
|
||||||
|
|
||||||
|
/// @name Symbol Location Functions
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
|
||||||
|
bool isUndefined() const {
|
||||||
|
return Section == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// isAbsolute - Check if this this is an absolute symbol.
|
||||||
|
bool isAbsolute() const {
|
||||||
|
return Section == AbsolutePseudoSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getSection - Get the section associated with a defined, non-absolute
|
||||||
|
/// symbol.
|
||||||
|
const MCSection &getSection() const {
|
||||||
|
assert(!isUndefined() && !isAbsolute() && "Invalid accessor!");
|
||||||
|
return *Section;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// setSection - Mark the symbol as defined in the section \arg S.
|
||||||
|
void setSection(const MCSection &S) { Section = &S; }
|
||||||
|
|
||||||
|
/// setUndefined - Mark the symbol as undefined.
|
||||||
|
void setUndefined() {
|
||||||
|
Section = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// setAbsolute - Mark the symbol as absolute.
|
||||||
|
void setAbsolute() { Section = AbsolutePseudoSection; }
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
/// print - Print the value to the stream \arg OS.
|
/// print - Print the value to the stream \arg OS.
|
||||||
void print(raw_ostream &OS) const;
|
void print(raw_ostream &OS) const;
|
||||||
|
|
||||||
|
|
|
@ -49,9 +49,10 @@ public:
|
||||||
///
|
///
|
||||||
/// @result - The value's associated section, or null for external or constant
|
/// @result - The value's associated section, or null for external or constant
|
||||||
/// values.
|
/// values.
|
||||||
const MCSection *getAssociatedSection() const {
|
//
|
||||||
return SymA ? SymA->getSection() : 0;
|
// FIXME: Switch to a tagged section, so this can return the tagged section
|
||||||
}
|
// value.
|
||||||
|
const MCSection *getAssociatedSection() const;
|
||||||
|
|
||||||
/// print - Print the value to the stream \arg OS.
|
/// print - Print the value to the stream \arg OS.
|
||||||
void print(raw_ostream &OS) const;
|
void print(raw_ostream &OS) const;
|
||||||
|
|
|
@ -107,14 +107,11 @@ void MCAsmStreamer::SwitchSection(const MCSection *Section) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
|
void MCAsmStreamer::EmitLabel(MCSymbol *Symbol) {
|
||||||
assert(Symbol->getSection() == 0 && "Cannot emit a symbol twice!");
|
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
|
||||||
assert(CurSection && "Cannot emit before setting section!");
|
assert(CurSection && "Cannot emit before setting section!");
|
||||||
assert(!getContext().GetSymbolValue(Symbol) &&
|
|
||||||
"Cannot emit symbol which was directly assigned to!");
|
|
||||||
|
|
||||||
OS << Symbol << ":\n";
|
OS << Symbol << ":\n";
|
||||||
Symbol->setSection(CurSection);
|
Symbol->setSection(*CurSection);
|
||||||
Symbol->setExternal(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
|
void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
|
||||||
|
@ -127,7 +124,9 @@ void MCAsmStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
|
||||||
|
|
||||||
void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
|
void MCAsmStreamer::EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
|
||||||
bool MakeAbsolute) {
|
bool MakeAbsolute) {
|
||||||
assert(!Symbol->getSection() && "Cannot assign to a label!");
|
// Only absolute symbols can be redefined.
|
||||||
|
assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
|
||||||
|
"Cannot define a symbol twice!");
|
||||||
|
|
||||||
if (MakeAbsolute) {
|
if (MakeAbsolute) {
|
||||||
OS << ".set " << Symbol << ", " << Value << '\n';
|
OS << ".set " << Symbol << ", " << Value << '\n';
|
||||||
|
|
|
@ -91,15 +91,12 @@ void MCMachOStreamer::SwitchSection(const MCSection *Section) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
|
void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
|
||||||
assert(Symbol->getSection() == 0 && "Cannot emit a symbol twice!");
|
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
|
||||||
assert(CurSection && "Cannot emit before setting section!");
|
assert(CurSection && "Cannot emit before setting section!");
|
||||||
assert(!getContext().GetSymbolValue(Symbol) &&
|
|
||||||
"Cannot emit symbol which was directly assigned to!");
|
|
||||||
|
|
||||||
llvm_unreachable("FIXME: Not yet implemented!");
|
llvm_unreachable("FIXME: Not yet implemented!");
|
||||||
|
|
||||||
Symbol->setSection(CurSection);
|
Symbol->setSection(*CurSection);
|
||||||
Symbol->setExternal(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
|
void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
|
||||||
|
@ -109,7 +106,9 @@ void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
|
||||||
void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol,
|
void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol,
|
||||||
const MCValue &Value,
|
const MCValue &Value,
|
||||||
bool MakeAbsolute) {
|
bool MakeAbsolute) {
|
||||||
assert(!Symbol->getSection() && "Cannot assign to a label!");
|
// Only absolute symbols can be redefined.
|
||||||
|
assert((Symbol->isUndefined() || Symbol->isAbsolute()) &&
|
||||||
|
"Cannot define a symbol twice!");
|
||||||
|
|
||||||
llvm_unreachable("FIXME: Not yet implemented!");
|
llvm_unreachable("FIXME: Not yet implemented!");
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,10 @@
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
|
// Sentinel value for the absolute pseudo section.
|
||||||
|
const MCSection *MCSymbol::AbsolutePseudoSection =
|
||||||
|
reinterpret_cast<const MCSection *>(1);
|
||||||
|
|
||||||
/// NeedsQuoting - Return true if the string \arg Str needs quoting, i.e., it
|
/// NeedsQuoting - Return true if the string \arg Str needs quoting, i.e., it
|
||||||
/// does not match [a-zA-Z_.][a-zA-Z0-9_.]*.
|
/// does not match [a-zA-Z_.][a-zA-Z0-9_.]*.
|
||||||
//
|
//
|
||||||
|
|
|
@ -2,32 +2,56 @@
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
import StringIO
|
||||||
|
|
||||||
class Reader:
|
class Reader:
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
if path == '-':
|
if path == '-':
|
||||||
self.file = sys.stdin
|
# Snarf all the data so we can seek.
|
||||||
|
self.file = StringIO.StringIO(sys.stdin.read())
|
||||||
else:
|
else:
|
||||||
self.file = open(path,'rb')
|
self.file = open(path,'rb')
|
||||||
self.isLSB = None
|
self.isLSB = None
|
||||||
self.pos = 0
|
|
||||||
|
self.string_table = None
|
||||||
|
|
||||||
def setLSB(self, isLSB):
|
def setLSB(self, isLSB):
|
||||||
self.isLSB = bool(isLSB)
|
self.isLSB = bool(isLSB)
|
||||||
|
|
||||||
def tell(self):
|
def tell(self):
|
||||||
return self.pos
|
return self.file.tell()
|
||||||
|
|
||||||
|
def seek(self, pos):
|
||||||
|
self.file.seek(pos)
|
||||||
|
|
||||||
def read(self, N):
|
def read(self, N):
|
||||||
data = self.file.read(N)
|
data = self.file.read(N)
|
||||||
self.pos += len(data)
|
|
||||||
if len(data) != N:
|
if len(data) != N:
|
||||||
raise ValueError,"Out of data!"
|
raise ValueError,"Out of data!"
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def read8(self):
|
||||||
|
return ord(self.read(1))
|
||||||
|
|
||||||
|
def read16(self):
|
||||||
|
return struct.unpack('><'[self.isLSB] + 'H', self.read(2))[0]
|
||||||
|
|
||||||
def read32(self):
|
def read32(self):
|
||||||
return struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0]
|
return struct.unpack('><'[self.isLSB] + 'I', self.read(4))[0]
|
||||||
|
|
||||||
|
def registerStringTable(self, strings):
|
||||||
|
if self.string_table is not None:
|
||||||
|
raise ValueError,"%s: warning: multiple string tables" % sys.argv[0]
|
||||||
|
|
||||||
|
self.string_table = strings
|
||||||
|
|
||||||
|
def getString(self, index):
|
||||||
|
if self.string_table is None:
|
||||||
|
raise ValueError,"%s: warning: no string table registered" % sys.argv[0]
|
||||||
|
|
||||||
|
end = self.string_table.index('\x00', index)
|
||||||
|
return self.string_table[index:end]
|
||||||
|
|
||||||
def dumpmacho(path, opts):
|
def dumpmacho(path, opts):
|
||||||
f = Reader(path)
|
f = Reader(path)
|
||||||
|
|
||||||
|
@ -60,7 +84,7 @@ def dumpmacho(path, opts):
|
||||||
print "])"
|
print "])"
|
||||||
|
|
||||||
if f.tell() - start != loadCommandsSize:
|
if f.tell() - start != loadCommandsSize:
|
||||||
raise ValueError,"%s: warning: invalid load commands size: %r" % (sys.argv, loadCommandsSize)
|
raise ValueError,"%s: warning: invalid load commands size: %r" % (sys.argv[0], loadCommandsSize)
|
||||||
|
|
||||||
def dumpLoadCommand(f, i, opts):
|
def dumpLoadCommand(f, i, opts):
|
||||||
start = f.tell()
|
start = f.tell()
|
||||||
|
@ -83,7 +107,7 @@ def dumpLoadCommand(f, i, opts):
|
||||||
print " ),"
|
print " ),"
|
||||||
|
|
||||||
if f.tell() - start != cmdSize:
|
if f.tell() - start != cmdSize:
|
||||||
raise ValueError,"%s: warning: invalid load command size: %r" % (sys.argv, cmdSize)
|
raise ValueError,"%s: warning: invalid load command size: %r" % (sys.argv[0], cmdSize)
|
||||||
|
|
||||||
def dumpSegmentLoadCommand32(f, opts):
|
def dumpSegmentLoadCommand32(f, opts):
|
||||||
print " ('segment_name', %r)" % f.read(16)
|
print " ('segment_name', %r)" % f.read(16)
|
||||||
|
@ -103,10 +127,45 @@ def dumpSegmentLoadCommand32(f, opts):
|
||||||
print " ])"
|
print " ])"
|
||||||
|
|
||||||
def dumpSymtabCommand(f, opts):
|
def dumpSymtabCommand(f, opts):
|
||||||
print " ('symoff', %r)" % f.read32()
|
symoff = f.read32()
|
||||||
print " ('nsyms', %r)" % f.read32()
|
print " ('symoff', %r)" % symoff
|
||||||
print " ('stroff', %r)" % f.read32()
|
nsyms = f.read32()
|
||||||
print " ('strsize', %r)" % f.read32()
|
print " ('nsyms', %r)" % nsyms
|
||||||
|
stroff = f.read32()
|
||||||
|
print " ('stroff', %r)" % stroff
|
||||||
|
strsize = f.read32()
|
||||||
|
print " ('strsize', %r)" % strsize
|
||||||
|
|
||||||
|
prev_pos = f.tell()
|
||||||
|
|
||||||
|
f.seek(stroff)
|
||||||
|
string_data = f.read(strsize)
|
||||||
|
print " ('_string_data', %r)" % string_data
|
||||||
|
|
||||||
|
f.registerStringTable(string_data)
|
||||||
|
|
||||||
|
f.seek(symoff)
|
||||||
|
print " ('_symbols', ["
|
||||||
|
for i in range(nsyms):
|
||||||
|
dumpNlist32(f, i, opts)
|
||||||
|
print " ])"
|
||||||
|
|
||||||
|
f.seek(prev_pos)
|
||||||
|
|
||||||
|
def dumpNlist32(f, i, opts):
|
||||||
|
print " # Symbol %r" % i
|
||||||
|
n_strx = f.read32()
|
||||||
|
print " (('n_strx', %r)" % n_strx
|
||||||
|
n_type = f.read8()
|
||||||
|
print " ('n_type', %#x)" % n_type
|
||||||
|
n_sect = f.read8()
|
||||||
|
print " ('n_type', %r)" % n_sect
|
||||||
|
n_desc = f.read16()
|
||||||
|
print " ('n_desc', %r)" % n_desc
|
||||||
|
n_value = f.read32()
|
||||||
|
print " ('n_value', %r)" % n_value
|
||||||
|
print " ('_string', %r)" % f.getString(n_strx)
|
||||||
|
print " ),"
|
||||||
|
|
||||||
def dumpDysymtabCommand(f, opts):
|
def dumpDysymtabCommand(f, opts):
|
||||||
print " ('ilocalsym', %r)" % f.read32()
|
print " ('ilocalsym', %r)" % f.read32()
|
||||||
|
@ -121,13 +180,26 @@ def dumpDysymtabCommand(f, opts):
|
||||||
print " ('nmodtab', %r)" % f.read32()
|
print " ('nmodtab', %r)" % f.read32()
|
||||||
print " ('extrefsymoff', %r)" % f.read32()
|
print " ('extrefsymoff', %r)" % f.read32()
|
||||||
print " ('nextrefsyms', %r)" % f.read32()
|
print " ('nextrefsyms', %r)" % f.read32()
|
||||||
print " ('indirectsymoff', %r)" % f.read32()
|
indirectsymoff = f.read32()
|
||||||
print " ('nindirectsyms', %r)" % f.read32()
|
print " ('indirectsymoff', %r)" % indirectsymoff
|
||||||
|
nindirectsyms = f.read32()
|
||||||
|
print " ('nindirectsyms', %r)" % nindirectsyms
|
||||||
print " ('extreloff', %r)" % f.read32()
|
print " ('extreloff', %r)" % f.read32()
|
||||||
print " ('nextrel', %r)" % f.read32()
|
print " ('nextrel', %r)" % f.read32()
|
||||||
print " ('locreloff', %r)" % f.read32()
|
print " ('locreloff', %r)" % f.read32()
|
||||||
print " ('nlocrel', %r)" % f.read32()
|
print " ('nlocrel', %r)" % f.read32()
|
||||||
|
|
||||||
|
prev_pos = f.tell()
|
||||||
|
|
||||||
|
f.seek(indirectsymoff)
|
||||||
|
print " ('_indirect_symbols', ["
|
||||||
|
for i in range(nindirectsyms):
|
||||||
|
print " # Indirect Symbol %r" % i
|
||||||
|
print " (('symbol_index', %r),)," % f.read32()
|
||||||
|
print " ])"
|
||||||
|
|
||||||
|
f.seek(prev_pos)
|
||||||
|
|
||||||
def dumpSection32(f, i, opts):
|
def dumpSection32(f, i, opts):
|
||||||
print " # Section %r" % i
|
print " # Section %r" % i
|
||||||
print " (('section_name', %r)" % f.read(16)
|
print " (('section_name', %r)" % f.read(16)
|
||||||
|
|
|
@ -149,10 +149,6 @@ bool AsmParser::ParsePrimaryExpr(AsmExpr *&Res) {
|
||||||
// This is a label, this should be parsed as part of an expression, to
|
// This is a label, this should be parsed as part of an expression, to
|
||||||
// handle things like LFOO+4.
|
// handle things like LFOO+4.
|
||||||
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getTok().getIdentifier());
|
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Lexer.getTok().getIdentifier());
|
||||||
|
|
||||||
// If this is use of an undefined symbol then mark it external.
|
|
||||||
if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym))
|
|
||||||
Sym->setExternal(true);
|
|
||||||
|
|
||||||
Res = new AsmSymbolRefExpr(Sym);
|
Res = new AsmSymbolRefExpr(Sym);
|
||||||
Lexer.Lex(); // Eat identifier.
|
Lexer.Lex(); // Eat identifier.
|
||||||
|
@ -376,10 +372,8 @@ bool AsmParser::ParseStatement() {
|
||||||
// FIXME: This doesn't diagnose assignment to a symbol which has been
|
// FIXME: This doesn't diagnose assignment to a symbol which has been
|
||||||
// implicitly marked as external.
|
// implicitly marked as external.
|
||||||
MCSymbol *Sym = Ctx.GetOrCreateSymbol(IDVal);
|
MCSymbol *Sym = Ctx.GetOrCreateSymbol(IDVal);
|
||||||
if (Sym->getSection())
|
if (!Sym->isUndefined())
|
||||||
return Error(IDLoc, "invalid symbol redefinition");
|
return Error(IDLoc, "invalid symbol redefinition");
|
||||||
if (Ctx.GetSymbolValue(Sym))
|
|
||||||
return Error(IDLoc, "symbol already used as assembler variable");
|
|
||||||
|
|
||||||
// Since we saw a label, create a symbol and emit it.
|
// Since we saw a label, create a symbol and emit it.
|
||||||
// FIXME: If the label starts with L it is an assembler temporary label.
|
// FIXME: If the label starts with L it is an assembler temporary label.
|
||||||
|
@ -687,15 +681,11 @@ bool AsmParser::ParseAssignment(const StringRef &Name, bool IsDotSet) {
|
||||||
// Diagnose assignment to a label.
|
// Diagnose assignment to a label.
|
||||||
//
|
//
|
||||||
// FIXME: Diagnostics. Note the location of the definition as a label.
|
// 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.
|
|
||||||
// FIXME: Handle '.'.
|
// FIXME: Handle '.'.
|
||||||
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
|
// FIXME: Diagnose assignment to protected identifier (e.g., register name).
|
||||||
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
|
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
|
||||||
if (Sym->getSection())
|
if (!Sym->isUndefined() && !Sym->isAbsolute())
|
||||||
return Error(EqualLoc, "invalid assignment to symbol emitted as a label");
|
return Error(EqualLoc, "symbol has already been defined");
|
||||||
if (Sym->isExternal())
|
|
||||||
return Error(EqualLoc, "invalid assignment to external symbol");
|
|
||||||
|
|
||||||
// Do the assignment.
|
// Do the assignment.
|
||||||
Out.EmitAssignment(Sym, Value, IsDotSet);
|
Out.EmitAssignment(Sym, Value, IsDotSet);
|
||||||
|
@ -1117,10 +1107,6 @@ bool AsmParser::ParseDirectiveSymbolAttribute(MCStreamer::SymbolAttr Attr) {
|
||||||
|
|
||||||
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
|
MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name);
|
||||||
|
|
||||||
// If this is use of an undefined symbol then mark it external.
|
|
||||||
if (!Sym->getSection() && !Ctx.GetSymbolValue(Sym))
|
|
||||||
Sym->setExternal(true);
|
|
||||||
|
|
||||||
Out.EmitSymbolAttribute(Sym, Attr);
|
Out.EmitSymbolAttribute(Sym, Attr);
|
||||||
|
|
||||||
if (Lexer.is(AsmToken::EndOfStatement))
|
if (Lexer.is(AsmToken::EndOfStatement))
|
||||||
|
@ -1213,8 +1199,7 @@ bool AsmParser::ParseDirectiveComm(bool IsLocal) {
|
||||||
return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
|
return Error(Pow2AlignmentLoc, "invalid '.comm' or '.lcomm' directive "
|
||||||
"alignment, can't be less than zero");
|
"alignment, can't be less than zero");
|
||||||
|
|
||||||
// TODO: Symbol must be undefined or it is a error to re-defined the symbol
|
if (!Sym->isUndefined())
|
||||||
if (Sym->getSection() || Ctx.GetSymbolValue(Sym))
|
|
||||||
return Error(IDLoc, "invalid symbol redefinition");
|
return Error(IDLoc, "invalid symbol redefinition");
|
||||||
|
|
||||||
// Create the Symbol as a common or local common with Size and Pow2Alignment
|
// Create the Symbol as a common or local common with Size and Pow2Alignment
|
||||||
|
@ -1305,8 +1290,7 @@ bool AsmParser::ParseDirectiveDarwinZerofill() {
|
||||||
return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
|
return Error(Pow2AlignmentLoc, "invalid '.zerofill' directive alignment, "
|
||||||
"can't be less than zero");
|
"can't be less than zero");
|
||||||
|
|
||||||
// TODO: Symbol must be undefined or it is a error to re-defined the symbol
|
if (!Sym->isUndefined())
|
||||||
if (Sym->getSection() || Ctx.GetSymbolValue(Sym))
|
|
||||||
return Error(IDLoc, "invalid symbol redefinition");
|
return Error(IDLoc, "invalid symbol redefinition");
|
||||||
|
|
||||||
// FIXME: Arch specific.
|
// FIXME: Arch specific.
|
||||||
|
|
Loading…
Reference in New Issue