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 36fc616..6f0d957 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 <list>
namespace llvm {
@@ -377,6 +379,31 @@
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 @@
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 @@
/// local symbols first in the list).
std::vector<MachOSym> 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<MachOSym> PendingSyms;
+
/// DynamicSymbolTable - This is just a vector of indices into
/// SymbolTable to aid in emitting the DYSYMTAB load command.
std::vector<unsigned> DynamicSymbolTable;
@@ -586,6 +619,7 @@
}
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 e3228cb..d9e3b88 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 <iostream>
using namespace llvm;
@@ -137,10 +136,9 @@
// 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 @@
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.
}