From fd00e2087200fd4cc129ae561c606f19470d828a Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 11 Nov 2008 15:52:29 +0000 Subject: [PATCH] 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 --- lib/Target/X86/X86ISelDAGToDAG.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp index 137944ac88d..b543e23c59b 100644 --- a/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/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(N)->getSExtValue(); + uint64_t Val = cast(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(N)->getSExtValue(); + uint64_t Val = cast(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(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(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(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;