/// 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.
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 {
/// @{
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);
/// @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.
GPRel32Directive = 0;
GlobalDirective = "\t.globl\t";
HasSetDirective = true;
+ NeedsSetToChangeDiffSize = false;
HasLCOMMDirective = false;
COMMDirectiveAlignmentIsInBytes = true;
HasDotTypeDotSizeDirective = true;
unsigned IsVerboseAsm : 1;
unsigned ShowInst : 1;
+ bool needsSet(const MCExpr *Value);
+
public:
MCAsmStreamer(MCContext &Context, formatted_raw_ostream &os,
bool isLittleEndian, bool isVerboseAsm,
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);
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) {
}
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;
// 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);
// 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);
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);
}
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,
}
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();
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);
}
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) {
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.
}
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
// 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)