From 70a7a50a498a108b46844223eaeef1afd46ade52 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Sat, 26 Jan 2013 17:15:15 -0700 Subject: [PATCH] fix int-to-long conversions from memory on x86_32 The instruction for 32-bit-to-64-bit sign extension on x86_32 requires that the input value be placed in EAX and the sign extension in EDX. However, the compiler can get confused if the input value is in memory addressed via one of those registers and doesn't know how to move it. This patch works around that limitation by doing the move explicitly in MemoryEvent::compile if necessary. --- src/compiler.cpp | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/compiler.cpp b/src/compiler.cpp index 8e118008bb..988cdb33fb 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -2003,6 +2003,13 @@ class MemorySite: public Site { } } + bool conflicts(const SiteMask& mask) { + return (mask.typeMask & (1 << RegisterOperand)) != 0 + and (((1 << base) & mask.registerMask) == 0 + or (index != NoRegister + and ((1 << index) & mask.registerMask) == 0)); + } + virtual bool match(Context* c, const SiteMask& mask) { assert(c, acquired); @@ -4574,8 +4581,20 @@ class OperationEvent: public Event { void appendOperation(Context* c, Operation op) { - append - (c, new(c->zone) OperationEvent(c, op)); + append(c, new(c->zone) OperationEvent(c, op)); +} + +void +moveIfConflict(Context* c, Value* v, MemorySite* s) +{ + if (v->reads) { + SiteMask mask(1 << RegisterOperand, ~0, AnyFrameIndex); + v->reads->intersect(&mask); + if (s->conflicts(mask)) { + maybeMove(c, v->reads, true, false); + removeSite(c, v, s); + } + } } class MemoryEvent: public Event { @@ -4626,22 +4645,24 @@ class MemoryEvent: public Event { popRead(c, this, index); } - Site* site = memorySite + MemorySite* site = memorySite (c, baseRegister, displacement, indexRegister, scale); - Site* low; + MemorySite* low; if (result->nextWord != result) { - Site* high = site->copyHigh(c); - low = site->copyLow(c); + MemorySite* high = static_cast(site->copyHigh(c)); + low = static_cast(site->copyLow(c)); result->nextWord->target = high; addSite(c, result->nextWord, high); + moveIfConflict(c, result->nextWord, high); } else { low = site; } result->target = low; addSite(c, result, low); + moveIfConflict(c, result, low); } Value* base;