summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2008-11-11 15:52:29 +0000
committerDan Gohman <gohman@apple.com>2008-11-11 15:52:29 +0000
commit059c4fa8d876a96b31dff905a82018c088cb9666 (patch)
tree9f245fd435070096a69ee4f826a2fb05ad44f77b
parent3987b17e2861c274b6dc2b96cc0f22645f0a8922 (diff)
downloadbcm5719-llvm-059c4fa8d876a96b31dff905a82018c088cb9666.tar.gz
bcm5719-llvm-059c4fa8d876a96b31dff905a82018c088cb9666.zip
The 32-bit displacement field in an x86 address is signed. Arrange for it
to be sign-extended when it is promoted to 64 bits for intermediate offset calculations. The offset calculations are done as uint64_t so that overflow conditions are well defined. This fixes a problem which is currently hidden by the x86 AsmPrinter but which was exposed by r58917 (which is temporarily reverted). See PR3027 for details. llvm-svn: 59044
-rw-r--r--llvm/lib/Target/X86/X86ISelDAGToDAG.cpp23
1 files changed, 13 insertions, 10 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 137944ac88d..b543e23c59b 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -66,7 +66,7 @@ namespace {
bool isRIPRel; // RIP as base?
unsigned Scale;
SDValue IndexReg;
- unsigned Disp;
+ int32_t Disp;
GlobalValue *GV;
Constant *CP;
const char *ES;
@@ -201,7 +201,7 @@ namespace {
else if (AM.JT != -1)
Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32);
else
- Disp = getI32Imm(AM.Disp);
+ Disp = CurDAG->getTargetConstant(AM.Disp, MVT::i32);
}
/// getI8Imm - Return a target constant with the specified value, of type
@@ -768,7 +768,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
// RIP relative addressing: %rip + 32-bit displacement!
if (AM.isRIPRel) {
if (!AM.ES && AM.JT != -1 && N.getOpcode() == ISD::Constant) {
- int64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
+ uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
if (!is64Bit || isInt32(AM.Disp + Val)) {
AM.Disp += Val;
return false;
@@ -780,7 +780,7 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
switch (N.getOpcode()) {
default: break;
case ISD::Constant: {
- int64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
+ uint64_t Val = cast<ConstantSDNode>(N)->getSExtValue();
if (!is64Bit || isInt32(AM.Disp + Val)) {
AM.Disp += Val;
return false;
@@ -804,18 +804,20 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
{
SDValue N0 = N.getOperand(0);
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
- if (!is64Bit || isInt32(AM.Disp + G->getOffset())) {
+ uint64_t Offset = G->getOffset();
+ if (!is64Bit || isInt32(AM.Disp + Offset)) {
GlobalValue *GV = G->getGlobal();
AM.GV = GV;
- AM.Disp += G->getOffset();
+ AM.Disp += Offset;
AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
return false;
}
} else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
- if (!is64Bit || isInt32(AM.Disp + CP->getOffset())) {
+ uint64_t Offset = CP->getOffset();
+ if (!is64Bit || isInt32(AM.Disp + Offset)) {
AM.CP = CP->getConstVal();
AM.Align = CP->getAlignment();
- AM.Disp += CP->getOffset();
+ AM.Disp += Offset;
AM.isRIPRel = TM.symbolicAddressesAreRIPRel();
return false;
}
@@ -935,15 +937,16 @@ bool X86DAGToDAGISel::MatchAddress(SDValue N, X86ISelAddressMode &AM,
// Handle "X | C" as "X + C" iff X is known to have C bits clear.
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) {
X86ISelAddressMode Backup = AM;
+ uint64_t Offset = CN->getSExtValue();
// Start with the LHS as an addr mode.
if (!MatchAddress(N.getOperand(0), AM, false) &&
// Address could not have picked a GV address for the displacement.
AM.GV == NULL &&
// On x86-64, the resultant disp must fit in 32-bits.
- (!is64Bit || isInt32(AM.Disp + CN->getSExtValue())) &&
+ (!is64Bit || isInt32(AM.Disp + Offset)) &&
// Check to see if the LHS & C is zero.
CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
- AM.Disp += CN->getZExtValue();
+ AM.Disp += Offset;
return false;
}
AM = Backup;
OpenPOWER on IntegriCloud