From: Nate Begeman Date: Fri, 25 Aug 2006 06:36:58 +0000 (+0000) Subject: Get closer to handling globals correctly. We now generally get them in the X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=f8f2c5a1723b46290c0e2d4ba6cf05ee11993002;p=oota-llvm.git Get closer to handling globals correctly. We now generally get them in the right section. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29871 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/MachOWriter.h b/include/llvm/CodeGen/MachOWriter.h index 36fc6169e78..6f0d9575a69 100644 --- a/include/llvm/CodeGen/MachOWriter.h +++ b/include/llvm/CodeGen/MachOWriter.h @@ -14,8 +14,10 @@ #ifndef LLVM_CODEGEN_MACHOWRITER_H #define LLVM_CODEGEN_MACHOWRITER_H -#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/DerivedTypes.h" #include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" #include namespace llvm { @@ -377,6 +379,31 @@ namespace llvm { MachOSection::S_ATTR_PURE_INSTRUCTIONS | MachOSection::S_ATTR_SOME_INSTRUCTIONS); } + MachOSection &getBSSSection() { + return getSection("__DATA", "__bss", MachOSection::S_ZEROFILL); + } + MachOSection &getDataSection() { + return getSection("__DATA", "__data"); + } + MachOSection &getConstSection(const Type *Ty) { + // FIXME: support cstring literals and pointer literal + if (Ty->isPrimitiveType()) { + unsigned Size = TM.getTargetData()->getTypeSize(Ty); + switch(Size) { + default: break; // Fall through to __TEXT,__const + case 4: + return getSection("__TEXT", "__literal4", + MachOSection::S_4BYTE_LITERALS); + case 8: + return getSection("__TEXT", "__literal8", + MachOSection::S_8BYTE_LITERALS); + case 16: + return getSection("__TEXT", "__literal16", + MachOSection::S_16BYTE_LITERALS); + } + } + return getSection("__TEXT", "__const"); + } /// MachOSymTab - This struct contains information about the offsets and /// size of symbol table information. @@ -488,7 +515,8 @@ namespace llvm { static unsigned entrySize() { return 12; } MachOSym(const GlobalValue *gv, uint8_t sect) : GV(gv), n_strx(0), - n_type(N_UNDF), n_sect(sect), n_desc(0), n_value(0) {} + n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect), n_desc(0), + n_value(0) {} }; /// SymbolTable - This is the list of symbols we have emitted to the file. @@ -496,6 +524,11 @@ namespace llvm { /// local symbols first in the list). std::vector SymbolTable; + /// PendingSyms - This is a list of externally defined symbols that we have + /// been asked to emit, but have not seen a reference to. When a reference + /// is seen, the symbol will move from this list to the SymbolTable. + std::vector PendingSyms; + /// DynamicSymbolTable - This is just a vector of indices into /// SymbolTable to aid in emitting the DYSYMTAB load command. std::vector DynamicSymbolTable; @@ -586,6 +619,7 @@ namespace llvm { } private: + void AddSymbolToSection(MachOSection &MOS, GlobalVariable *GV); void EmitGlobal(GlobalVariable *GV); void EmitHeaderAndLoadCommands(); void EmitSections(); diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index e3228cb5c77..d9e3b880585 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -27,10 +27,9 @@ #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineRelocation.h" #include "llvm/CodeGen/MachOWriter.h" -#include "llvm/Target/TargetData.h" #include "llvm/Target/TargetJITInfo.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" #include using namespace llvm; @@ -137,10 +136,9 @@ bool MachOCodeEmitter::finishFunction(MachineFunction &F) { // appending linkage is illegal for functions. assert(0 && "Unknown linkage type!"); case GlobalValue::ExternalLinkage: - FnSym.n_type = MachOWriter::MachOSym::N_SECT | MachOWriter::MachOSym::N_EXT; + FnSym.n_type |= MachOWriter::MachOSym::N_EXT; break; case GlobalValue::InternalLinkage: - FnSym.n_type = MachOWriter::MachOSym::N_SECT; break; } @@ -188,8 +186,75 @@ MachOWriter::~MachOWriter() { delete MCE; } +void MachOWriter::AddSymbolToSection(MachOSection &Sec, GlobalVariable *GV) { + const Type *Ty = GV->getType()->getElementType(); + unsigned Size = TM.getTargetData()->getTypeSize(Ty); + unsigned Align = Log2_32(TM.getTargetData()->getTypeAlignment(Ty)); + + MachOSym Sym(GV, Sec.Index); + // Reserve space in the .bss section for this symbol while maintaining the + // desired section alignment, which must be at least as much as required by + // this symbol. + if (Align) { + Sec.align = std::max(Sec.align, Align); + Sec.size = (Sec.size + Align - 1) & ~(Align-1); + } + // Record the offset of the symbol, and then allocate space for it. + Sym.n_value = Sec.size; + Sec.size += Size; + + switch (GV->getLinkage()) { + default: // weak/linkonce handled above + assert(0 && "Unexpected linkage type!"); + case GlobalValue::ExternalLinkage: + Sym.n_type |= MachOSym::N_EXT; + break; + case GlobalValue::InternalLinkage: + break; + } + SymbolTable.push_back(Sym); +} + void MachOWriter::EmitGlobal(GlobalVariable *GV) { - // FIXME: do something smart here. + const Type *Ty = GV->getType()->getElementType(); + unsigned Size = TM.getTargetData()->getTypeSize(Ty); + bool NoInit = !GV->hasInitializer(); + + // If this global has a zero initializer, it is part of the .bss or common + // section. + if (NoInit || GV->getInitializer()->isNullValue()) { + // If this global is part of the common block, add it now. Variables are + // part of the common block if they are zero initialized and allowed to be + // merged with other symbols. + if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage()) { + MachOWriter::MachOSym ExtOrCommonSym(GV, MachOSym::NO_SECT); + ExtOrCommonSym.n_type |= MachOSym::N_EXT; + // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in + // bytes of the symbol. + ExtOrCommonSym.n_value = Size; + // If the symbol is external, we'll put it on a list of symbols whose + // addition to the symbol table is being pended until we find a reference + if (NoInit) + PendingSyms.push_back(ExtOrCommonSym); + else + SymbolTable.push_back(ExtOrCommonSym); + return; + } + // Otherwise, this symbol is part of the .bss section. + MachOSection &BSS = getBSSSection(); + AddSymbolToSection(BSS, GV); + return; + } + + // Scalar read-only data goes in a literal section if the scalar is 4, 8, or + // 16 bytes, or a cstring. Other read only data goes into a regular const + // section. Read-write data goes in the data section. + MachOSection &Sec = GV->isConstant() ? getConstSection(Ty) : getDataSection(); + AddSymbolToSection(Sec, GV); + + // FIXME: actually write out the initializer to the section. This will + // require ExecutionEngine's InitializeMemory() function, which will need to + // be enhanced to support relocations. }