summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/MCAsmStreamer.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2010-12-04 03:21:47 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2010-12-04 03:21:47 +0000
commit1c8ac8f027d4a7af830e91513f37a2139c684f19 (patch)
tree55a7d4f84240669759d3fbb0f15e301960e720fb /llvm/lib/MC/MCAsmStreamer.cpp
parent4fb115d2f3e353f1c3fdba2a2e060c5d7dfb9f40 (diff)
downloadbcm5719-llvm-1c8ac8f027d4a7af830e91513f37a2139c684f19.tar.gz
bcm5719-llvm-1c8ac8f027d4a7af830e91513f37a2139c684f19.zip
There are two reasons why we might want to use
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. llvm-svn: 120889
Diffstat (limited to 'llvm/lib/MC/MCAsmStreamer.cpp')
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp35
1 files changed, 31 insertions, 4 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index 40a234ea85f..ab807edd9ea 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/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<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;
OpenPOWER on IntegriCloud