diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index d53318c6631..0e6c4e7c75e 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -197,6 +197,13 @@ namespace llvm { /// HasSetDirective - True if the assembler supports the .set directive. bool HasSetDirective; // Defaults to true. + /// NeedsSetToChangeDiffSize - True if the assembler requires that we do + /// Lc = a - b + /// .long Lc + /// instead of doing + /// .long a - b + bool NeedsSetToChangeDiffSize; // Defaults to false. + /// HasLCOMMDirective - This is true if the target supports the .lcomm /// directive. bool HasLCOMMDirective; // Defaults to false. @@ -400,6 +407,7 @@ namespace llvm { return ExternDirective; } bool hasSetDirective() const { return HasSetDirective; } + bool needsSetToChangeDiffSize() const { return NeedsSetToChangeDiffSize; } bool hasLCOMMDirective() const { return HasLCOMMDirective; } bool hasDotTypeDotSizeDirective() const {return HasDotTypeDotSizeDirective;} bool getCOMMDirectiveAlignmentIsInBytes() const { diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index a3f532d8c00..d130ba4bcda 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -60,8 +60,7 @@ public: /// @{ virtual void EmitLabel(MCSymbol *Symbol); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace, - bool UseSet = false); + virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 16646c96d3e..d89ee9ae126 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -242,7 +242,7 @@ namespace llvm { /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. virtual void EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0, bool UseSet = false) = 0; + unsigned AddrSpace = 0) = 0; /// EmitIntValue - Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index 9cf4019e312..1bc63d03fba 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -54,6 +54,7 @@ MCAsmInfo::MCAsmInfo() { GPRel32Directive = 0; GlobalDirective = "\t.globl\t"; HasSetDirective = true; + NeedsSetToChangeDiffSize = false; HasLCOMMDirective = false; COMMDirectiveAlignmentIsInBytes = true; HasDotTypeDotSizeDirective = true; diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 40a234ea85f..ab807edd9ea 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -44,6 +44,8 @@ class MCAsmStreamer : public MCStreamer { unsigned IsVerboseAsm : 1; unsigned ShowInst : 1; + bool needsSet(const MCExpr *Value); + public: MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os, bool isLittleEndian, bool isVerboseAsm, @@ -150,8 +152,7 @@ public: virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace, - bool UseSet = false); + virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace = 0); @@ -511,8 +512,34 @@ void MCAsmStreamer::EmitIntValue(uint64_t Value, unsigned Size, EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace); } +static bool hasSymbolDifference(const MCExpr *Value) { + switch (Value->getKind()) { + case MCExpr::Target: llvm_unreachable("Can't handle target exprs yet!"); + case MCExpr::Constant: + case MCExpr::SymbolRef: + return false; + case MCExpr::Unary: + return hasSymbolDifference(cast(Value)->getSubExpr()); + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast(Value); + if (BE->getOpcode() == MCBinaryExpr::Sub && + BE->getLHS()->getKind() == MCExpr::SymbolRef && + BE->getRHS()->getKind() == MCExpr::SymbolRef) + return true; + return hasSymbolDifference(BE->getLHS()) || + hasSymbolDifference(BE->getRHS()); + } + } + llvm_unreachable("Switch covers all cases"); +} + +bool MCAsmStreamer::needsSet(const MCExpr *Value) { + return getContext().getAsmInfo().needsSetToChangeDiffSize() && + hasSymbolDifference(Value); +} + void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace, bool UseSet) { + unsigned AddrSpace) { assert(CurSection && "Cannot emit contents before setting section!"); const char *Directive = 0; switch (Size) { @@ -538,7 +565,7 @@ void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, } assert(Directive && "Invalid size for machine code value!"); - if (UseSet && MAI.hasSetDirective()) { + if (needsSet(Value)) { MCSymbol *SetLabel = getContext().CreateTempSymbol(); EmitAssignment(SetLabel, Value); OS << Directive << *SetLabel; diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index a33b0c596ba..1b1d5097042 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -213,8 +213,15 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS, // The first 4 bytes is the total length of the information for this // compilation unit (not including these 4 bytes for the length). - MCOS->EmitValue(MakeStartMinusEndExpr(MCOS, LineStartSym, LineEndSym, 4), - 4, 0, true /*UseSet*/); + // FIXME: We create the dummy TotalLength variable because LineEndSym points + // to the end of the section and the darwin assembler doesn't consider that + // difference an assembly time constant. It might be better for this to be + // proected by a flag. + MCSymbol *TotalLength = MCOS->getContext().CreateTempSymbol(); + MCOS->EmitAssignment(TotalLength, + MakeStartMinusEndExpr(MCOS, LineStartSym, LineEndSym, + 4)); + MCOS->EmitSymbolValue(TotalLength, 4, 0); // Next 2 bytes is the Version, which is Dwarf 2. MCOS->EmitIntValue(2, 2); @@ -228,7 +235,7 @@ void MCDwarfFileTable::Emit(MCStreamer *MCOS, // length of the prologue. MCOS->EmitValue(MakeStartMinusEndExpr(MCOS, LineStartSym, ProEndSym, (4 + 2 + 4)), - 4, 0, true /*UseSet*/); + 4, 0); // Parameters of the state machine, are next. MCOS->EmitIntValue(DWARF2_LINE_MIN_INSN_LENGTH, 1); diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp index 6cbef0b0250..134554b8006 100644 --- a/lib/MC/MCLoggingStreamer.cpp +++ b/lib/MC/MCLoggingStreamer.cpp @@ -154,8 +154,7 @@ public: return Child->EmitBytes(Data, AddrSpace); } - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace, - bool UseSet = false){ + virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace){ LogCall("EmitValue"); return Child->EmitValue(Value, Size, AddrSpace); } diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index 86ab628e602..c8f9c636174 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -69,7 +69,7 @@ namespace { virtual void EmitBytes(StringRef Data, unsigned AddrSpace) {} virtual void EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace, bool UseSet = false) {} + unsigned AddrSpace) {} virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0) {} virtual void EmitSLEB128Value(const MCExpr *Value, diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 1538a589966..ad8fb495840 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -77,7 +77,7 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) { } void MCObjectStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace, bool UseSet) { + unsigned AddrSpace) { assert(AddrSpace == 0 && "Address space must be 0!"); MCDataFragment *DF = getOrCreateDataFragment(); diff --git a/lib/Target/PTX/PTXMCAsmStreamer.cpp b/lib/Target/PTX/PTXMCAsmStreamer.cpp index 8043baf8cfc..4e517ad76a2 100644 --- a/lib/Target/PTX/PTXMCAsmStreamer.cpp +++ b/lib/Target/PTX/PTXMCAsmStreamer.cpp @@ -147,8 +147,7 @@ public: virtual void EmitBytes(StringRef Data, unsigned AddrSpace); - virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace, - bool UseSet = false); + virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace); virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0); virtual void EmitGPRel32Value(const MCExpr *Value); @@ -361,7 +360,7 @@ void PTXMCAsmStreamer::EmitBytes(StringRef Data, unsigned AddrSpace) { } void PTXMCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace, bool UseSet) { + unsigned AddrSpace) { assert(CurSection && "Cannot emit contents before setting section!"); const char *Directive = 0; switch (Size) { diff --git a/lib/Target/PowerPC/PPCMCAsmInfo.cpp b/lib/Target/PowerPC/PPCMCAsmInfo.cpp index 3644c79d041..89c8cb664c7 100644 --- a/lib/Target/PowerPC/PPCMCAsmInfo.cpp +++ b/lib/Target/PowerPC/PPCMCAsmInfo.cpp @@ -21,6 +21,10 @@ PPCMCAsmInfoDarwin::PPCMCAsmInfoDarwin(bool is64Bit) { if (!is64Bit) Data64bitsDirective = 0; // We can't emit a 64-bit unit in PPC32 mode. + + if (is64Bit) + NeedsSetToChangeDiffSize = true; + AssemblerDialect = 1; // New-Style mnemonics. SupportsDebugInformation= true; // Debug information. } diff --git a/lib/Target/X86/X86MCAsmInfo.cpp b/lib/Target/X86/X86MCAsmInfo.cpp index f45fdf5a3fb..1ac2d7e6c6d 100644 --- a/lib/Target/X86/X86MCAsmInfo.cpp +++ b/lib/Target/X86/X86MCAsmInfo.cpp @@ -56,6 +56,10 @@ X86MCAsmInfoDarwin::X86MCAsmInfoDarwin(const Triple &Triple) { if (!is64Bit) Data64bitsDirective = 0; // we can't emit a 64-bit unit + // FIXME: Darwin 10 doesn't need this. + if (is64Bit) + NeedsSetToChangeDiffSize = true; + // Use ## as a comment string so that .s files generated by llvm can go // through the GCC preprocessor without causing an error. This is needed // because "clang foo.s" runs the C preprocessor, which is usually reserved diff --git a/test/MC/MachO/empty-dwarf-lines.s b/test/MC/MachO/empty-dwarf-lines.s index 29ef218fddc..8d06d7363da 100644 --- a/test/MC/MachO/empty-dwarf-lines.s +++ b/test/MC/MachO/empty-dwarf-lines.s @@ -17,7 +17,7 @@ _c: // CHECK-NEXT: ('offset', 452) // CHECK-NEXT: ('alignment', 0) // CHECK-NEXT: ('reloc_offset', 496) -// CHECK-NEXT: ('num_reloc', 4) +// CHECK-NEXT: ('num_reloc', 2) // CHECK-NEXT: ('flags', 0x2000000) // CHECK-NEXT: ('reserved1', 0) // CHECK-NEXT: ('reserved2', 0)