There are two reasons why we might want to use
authorRafael Espindola <rafael.espindola@gmail.com>
Sat, 4 Dec 2010 03:21:47 +0000 (03:21 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sat, 4 Dec 2010 03:21:47 +0000 (03:21 +0000)
foo = a - b
.long foo
instead of just
.long a - b

First, on darwin9 64 bits the assembler produces the wrong result. Second,
if "a" is the end of the section all darwin assemblers (9, 10 and mc) will not
consider a - b to be a constant but will if the dummy foo is created.

Split how we handle these cases. The first one is something MC should take care
of. The second one has to be handled by the caller.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@120889 91177308-0d34-0410-b5e6-96231b3b80d8

13 files changed:
include/llvm/MC/MCAsmInfo.h
include/llvm/MC/MCObjectStreamer.h
include/llvm/MC/MCStreamer.h
lib/MC/MCAsmInfo.cpp
lib/MC/MCAsmStreamer.cpp
lib/MC/MCDwarf.cpp
lib/MC/MCLoggingStreamer.cpp
lib/MC/MCNullStreamer.cpp
lib/MC/MCObjectStreamer.cpp
lib/Target/PTX/PTXMCAsmStreamer.cpp
lib/Target/PowerPC/PPCMCAsmInfo.cpp
lib/Target/X86/X86MCAsmInfo.cpp
test/MC/MachO/empty-dwarf-lines.s

index d53318c6631934d1b90926add2b9b0cdf10118b1..0e6c4e7c75edaf5e73b9a80802da414ba539daef 100644 (file)
@@ -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 {
index a3f532d8c00854c2c651101614822082f4b0395e..d130ba4bcda4e8d60bb3235d79378f27c82a8af7 100644 (file)
@@ -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);
index 16646c96d3ed4174f279a11cd78b003f4b8c563d..d89ee9ae12603b0c873bd77aa8d30dcfe1726319 100644 (file)
@@ -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.
index 9cf4019e31232af7bee6846440973c9071734f6a..1bc63d03fba7107d176e24d5f0d7019c19d99dd2 100644 (file)
@@ -54,6 +54,7 @@ MCAsmInfo::MCAsmInfo() {
   GPRel32Directive = 0;
   GlobalDirective = "\t.globl\t";
   HasSetDirective = true;
+  NeedsSetToChangeDiffSize = false;
   HasLCOMMDirective = false;
   COMMDirectiveAlignmentIsInBytes = true;
   HasDotTypeDotSizeDirective = true;
index 40a234ea85ff36e327ab8e2c40093cf41dce8c8b..ab807edd9eabd5040983eea82ebdd8a35c53d76b 100644 (file)
@@ -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<MCUnaryExpr>(Value)->getSubExpr());
+  case MCExpr::Binary: {
+    const MCBinaryExpr *BE = cast<MCBinaryExpr>(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;
index a33b0c596ba19a386ed3b033f8c3d971acb0a89c..1b1d50970420d6338d98a47408110cee682f76be 100644 (file)
@@ -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);
index 6cbef0b0250b13663cf8b63a29f9d4496d231320..134554b8006d620f915622208acc4583c93689ee 100644 (file)
@@ -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);
   }
index 86ab628e60222c3b7f033b95c3aafd3ef5e288af..c8f9c636174e66b64d284bfe4da6cb79561107ab 100644 (file)
@@ -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,
index 1538a58996656fe7da4eb26355ae3f05324926b8..ad8fb4958401f1ac8e3dea3ef87cd366279179fc 100644 (file)
@@ -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();
 
index 8043baf8cfc88d28e3419ae21260f1019d44a79c..4e517ad76a273740bfa96474bcfb3b7f01173de9 100644 (file)
@@ -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) {
index 3644c79d04101be2d3c7cde5923957b14247d25f..89c8cb664c7122a2f04dcb28142866d98f617f93 100644 (file)
@@ -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.
 }
index f45fdf5a3fb3da9d506759553951c6f788acb394..1ac2d7e6c6d476189c55acfb08df68349ee148f1 100644 (file)
@@ -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
index 29ef218fddc0b7b936acc6d7ee87e385a86023b9..8d06d7363da3d33765c4db3cb075b879e502d850 100644 (file)
@@ -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)