summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorKevin Enderby <enderby@apple.com>2010-02-23 18:26:34 +0000
committerKevin Enderby <enderby@apple.com>2010-02-23 18:26:34 +0000
commite83d74f6264278d99996570a258f4dd38f912256 (patch)
tree2020cacc6fc9bc4f34b7f20b22a272f244f622ec /llvm/lib
parent1e6bc133cea342a1bd2e9f97e88ba54c22154f71 (diff)
downloadbcm5719-llvm-e83d74f6264278d99996570a258f4dd38f912256.tar.gz
bcm5719-llvm-e83d74f6264278d99996570a258f4dd38f912256.zip
This is the first patch to put the needed bits in place to eventually allow code
to be aligned with optimal nops. This patch does not change any functionality and when the compiler is changed to use EmitCodeAlignment() it should also not change the resulting output. Once the compiler change is made and everything looks good the next patch with the table of optimal X86 nops will be added to WriteNopData() changing the output. There are many FIXMEs in this patch which will be removed when we have better target hooks (coming soon I hear). llvm-svn: 96963
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp9
-rw-r--r--llvm/lib/MC/MCAssembler.cpp23
-rw-r--r--llvm/lib/MC/MCMachOStreamer.cpp17
-rw-r--r--llvm/lib/MC/MCNullStreamer.cpp3
4 files changed, 51 insertions, 1 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 6add1b4abaa..07a9553ff1d 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -134,6 +134,9 @@ public:
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
+ virtual void EmitCodeAlignment(unsigned ByteAlignment,
+ unsigned MaxBytesToEmit = 0);
+
virtual void EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0);
@@ -513,6 +516,12 @@ void MCAsmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
EmitEOL();
}
+void MCAsmStreamer::EmitCodeAlignment(unsigned ByteAlignment,
+ unsigned MaxBytesToEmit) {
+ // FIXME: a hack for now to only work for x86 using the 0x90 nop opcode.
+ EmitValueToAlignment(ByteAlignment, 0x90, 1, MaxBytesToEmit);
+}
+
void MCAsmStreamer::EmitValueToOffset(const MCExpr *Offset,
unsigned char Value) {
// FIXME: Verify that Offset is associated with the current section.
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index 528c5c025d5..2c698e76f92 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -42,6 +42,8 @@ STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
MachObjectWriter &MOW);
+static uint64_t WriteNopData(uint64_t Count, MachObjectWriter &MOW);
+
/// isVirtualSection - Check if this is a section which does not actually exist
/// in the object file.
static bool isVirtualSection(const MCSection &Section) {
@@ -1058,6 +1060,19 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
SD.setFileSize(Address - SD.getAddress());
}
+/// WriteNopData - Write optimal nops to the output file for the \arg Count
+/// bytes. This returns the number of bytes written. It may return 0 if
+/// the \arg Count is more than the maximum optimal nops.
+///
+/// FIXME this is X86 32-bit specific and should move to a better place.
+static uint64_t WriteNopData(uint64_t Count, MachObjectWriter &MOW) {
+ // FIXME for now just use the 0x90 nop opcode byte.
+ for (uint64_t i = 0; i < Count; i++)
+ MOW.Write8 (uint8_t(0x90));
+
+ return Count;
+}
+
/// WriteFileData - Write the \arg F data to the output file.
static void WriteFileData(raw_ostream &OS, const MCFragment &F,
MachObjectWriter &MOW) {
@@ -1081,6 +1096,14 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
"' is not a divisor of padding size '" +
Twine(AF.getFileSize()) + "'");
+ // See if we are aligning with nops, and if so do that first to try to fill
+ // the Count bytes. Then if that did not fill any bytes or there are any
+ // bytes left to fill use the the Value and ValueSize to fill the rest.
+ if (AF.getEmitNops()) {
+ uint64_t NopByteCount = WriteNopData(Count, MOW);
+ Count -= NopByteCount;
+ }
+
for (uint64_t i = 0; i != Count; ++i) {
switch (AF.getValueSize()) {
default:
diff --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 797be86caf2..a7a8a5daed9 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -137,6 +137,8 @@ public:
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0);
+ virtual void EmitCodeAlignment(unsigned ByteAlignment,
+ unsigned MaxBytesToEmit = 0);
virtual void EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0);
@@ -357,7 +359,20 @@ void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment,
if (MaxBytesToEmit == 0)
MaxBytesToEmit = ByteAlignment;
new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit,
- CurSectionData);
+ false /* EmitNops */, CurSectionData);
+
+ // Update the maximum alignment on the current section if necessary.
+ if (ByteAlignment > CurSectionData->getAlignment())
+ CurSectionData->setAlignment(ByteAlignment);
+}
+
+void MCMachOStreamer::EmitCodeAlignment(unsigned ByteAlignment,
+ unsigned MaxBytesToEmit) {
+ if (MaxBytesToEmit == 0)
+ MaxBytesToEmit = ByteAlignment;
+ // FIXME the 0x90 is the default x86 1 byte nop opcode.
+ new MCAlignFragment(ByteAlignment, 0x90, 1, MaxBytesToEmit,
+ true /* EmitNops */, CurSectionData);
// Update the maximum alignment on the current section if necessary.
if (ByteAlignment > CurSectionData->getAlignment())
diff --git a/llvm/lib/MC/MCNullStreamer.cpp b/llvm/lib/MC/MCNullStreamer.cpp
index 46e9ebfa886..ab6179907e8 100644
--- a/llvm/lib/MC/MCNullStreamer.cpp
+++ b/llvm/lib/MC/MCNullStreamer.cpp
@@ -55,6 +55,9 @@ namespace {
unsigned ValueSize = 1,
unsigned MaxBytesToEmit = 0) {}
+ virtual void EmitCodeAlignment(unsigned ByteAlignment,
+ unsigned MaxBytesToEmit = 0) {}
+
virtual void EmitValueToOffset(const MCExpr *Offset,
unsigned char Value = 0) {}
OpenPOWER on IntegriCloud