diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h --- a/llvm/include/llvm/MC/MCAsmInfo.h +++ b/llvm/include/llvm/MC/MCAsmInfo.h @@ -171,12 +171,17 @@ //===--- Data Emission Directives -------------------------------------===// - /// This should be set to the directive used to get some number of zero bytes - /// emitted to the current section. Common cases are "\t.zero\t" and - /// "\t.space\t". If this is set to null, the Data*bitsDirective's will be - /// used to emit zero bytes. Defaults to "\t.zero\t" + /// This should be set to the directive used to get some number of zero (and + /// non-zero if supported by the directive) bytes emitted to the current + /// section. Common cases are "\t.zero\t" and "\t.space\t". Defaults to + /// "\t.zero\t" const char *ZeroDirective; + /// This should be set to true if the zero directive supports a value to emit + /// other than zero. If this is set to false, the Data*bitsDirective's will be + /// used to emit these bytes. Defaults to true. + bool ZeroDirectiveSupportsNonZeroValue = true; + /// This directive allows emission of an ascii string with the standard C /// escape characters embedded into it. If a target doesn't support this, it /// can be set to null. Defaults to "\t.ascii\t" @@ -543,6 +548,9 @@ } const char *getZeroDirective() const { return ZeroDirective; } + bool doesZeroDirectiveSupportNonZeroValue() const { + return ZeroDirectiveSupportsNonZeroValue; + } const char *getAsciiDirective() const { return AsciiDirective; } const char *getAscizDirective() const { return AscizDirective; } bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp --- a/llvm/lib/MC/MCAsmStreamer.cpp +++ b/llvm/lib/MC/MCAsmStreamer.cpp @@ -1098,16 +1098,27 @@ void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc) { int64_t IntNumBytes; - if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0) + const bool IsAbsolute = NumBytes.evaluateAsAbsolute(IntNumBytes); + if (IsAbsolute && IntNumBytes == 0) return; if (const char *ZeroDirective = MAI->getZeroDirective()) { - // FIXME: Emit location directives - OS << ZeroDirective; - NumBytes.print(OS, MAI); - if (FillValue != 0) - OS << ',' << (int)FillValue; - EmitEOL(); + if (MAI->doesZeroDirectiveSupportNonZeroValue() || FillValue == 0) { + // FIXME: Emit location directives + OS << ZeroDirective; + NumBytes.print(OS, MAI); + if (FillValue != 0) + OS << ',' << (int)FillValue; + EmitEOL(); + } else { + if (!IsAbsolute) + report_fatal_error( + "Cannot emit non-absolute expression lengths of fill."); + for (int i = 0; i < IntNumBytes; ++i) { + OS << MAI->getData8bitsDirective() << (int)FillValue; + EmitEOL(); + } + } return; } diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp @@ -60,5 +60,6 @@ assert(!IsLittleEndian && "Little-endian XCOFF not supported."); CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4; ZeroDirective = "\t.space\t"; + ZeroDirectiveSupportsNonZeroValue = false; SymbolsHaveSMC = true; } diff --git a/llvm/test/CodeGen/PowerPC/aix-nonzero-zerofill.ll b/llvm/test/CodeGen/PowerPC/aix-nonzero-zerofill.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-nonzero-zerofill.ll @@ -0,0 +1,10 @@ +; RUN: llc -verify-machineinstrs -O0 -mcpu=pwr4 -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s +; RUN: llc -verify-machineinstrs -O0 -mcpu=pwr4 -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s + +@a = constant [4 x i8] c"\02\02\02\02", align 1 + +; CHECK-NOT: .space 4,2 +; CHECK: .byte 2 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .byte 2 +; CHECK-NEXT: .byte 2