diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc index cab50a048b..95868fbcc3 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/cast.cc @@ -166,6 +166,57 @@ int4 CastStrategyC::intPromotionType(const Varnode *vn) const return UNKNOWN_PROMOTION; } +bool CastStrategyC::isExtensionCastImplied(const PcodeOp *op,const PcodeOp *readOp) const + +{ + const Varnode *outVn = op->getOut(); + if (outVn->isExplicit()) { + + } + else { + if (readOp == (PcodeOp *) 0) + return false; + type_metatype metatype = outVn->getHigh()->getType()->getMetatype(); + const Varnode *otherVn; + int4 slot; + switch (readOp->code()) { + case CPUI_PTRADD: + break; + case CPUI_INT_ADD: + case CPUI_INT_SUB: + case CPUI_INT_MULT: + case CPUI_INT_DIV: + case CPUI_INT_AND: + case CPUI_INT_OR: + case CPUI_INT_XOR: + case CPUI_INT_EQUAL: + case CPUI_INT_NOTEQUAL: + case CPUI_INT_LESS: + case CPUI_INT_LESSEQUAL: + case CPUI_INT_SLESS: + case CPUI_INT_SLESSEQUAL: + slot = readOp->getSlot(outVn); + otherVn = readOp->getIn(1 - slot); + // Check if the expression involves an explicit variable of the right integer type + if (otherVn->isConstant()) { + // Integer tokens do not naturally indicate their size, and + // integers that are bigger than the promotion size are NOT naturally extended. + if (otherVn->getSize() > promoteSize) // So if the integer is bigger than the promotion size + return false; // The extension cast on the other side must be explicit + } + else if (!otherVn->isExplicit()) + return false; + if (otherVn->getHigh()->getType()->getMetatype() != metatype) + return false; + break; + default: + return false; + } + return true; // Everything is integer promotion + } + return false; +} + Datatype *CastStrategyC::castStandard(Datatype *reqtype,Datatype *curtype, bool care_uint_int,bool care_ptr_uint) const diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/cast.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/cast.hh index fed43e0db0..e6a8e25062 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/cast.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/cast.hh @@ -88,6 +88,16 @@ public: /// \return \b true if a cast is required before extending virtual bool checkIntPromotionForExtension(const PcodeOp *op) const=0; + + /// \brief Is the given ZEXT/SEXT cast implied by the expression its in? + /// + /// We've already determined that the given ZEXT or SEXT op can be viewed as a natural \e cast operation. + /// Determine if the cast is implied by the expression its and doesn't need to be printed. + /// \param op is the given ZEXT or SEXT PcodeOp + /// \param readOp is the PcodeOp consuming the output of the extensions (or null) + /// \return \b true if the op as a cast does not need to be printed + virtual bool isExtensionCastImplied(const PcodeOp *op,const PcodeOp *readOp) const=0; + /// \brief Does there need to be a visible cast between the given data-types /// /// The cast is from a \e current data-type to an \e expected data-type. NULL is returned @@ -151,6 +161,7 @@ public: virtual int4 intPromotionType(const Varnode *vn) const; virtual bool checkIntPromotionForCompare(const PcodeOp *op,int4 slot) const; virtual bool checkIntPromotionForExtension(const PcodeOp *op) const; + virtual bool isExtensionCastImplied(const PcodeOp *op,const PcodeOp *readOp) const; virtual Datatype *castStandard(Datatype *reqtype,Datatype *curtype,bool care_uint_int,bool care_ptr_uint) const; virtual Datatype *arithmeticOutputStandard(const PcodeOp *op); virtual bool isSubpieceCast(Datatype *outtype,Datatype *intype,uint4 offset) const; diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc index a47f348ee6..dbad39fe1e 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.cc @@ -595,7 +595,7 @@ void PrintC::opIntZext(const PcodeOp *op,const PcodeOp *readOp) { if (castStrategy->isZextCast(op->getOut()->getHigh()->getType(),op->getIn(0)->getHigh()->getType())) { - if (isExtensionCastImplied(op,readOp)) + if (option_hide_exts && castStrategy->isExtensionCastImplied(op,readOp)) opHiddenFunc(op); else opTypeCast(op); @@ -608,7 +608,7 @@ void PrintC::opIntSext(const PcodeOp *op,const PcodeOp *readOp) { if (castStrategy->isSextCast(op->getOut()->getHigh()->getType(),op->getIn(0)->getHigh()->getType())) { - if (isExtensionCastImplied(op,readOp)) + if (option_hide_exts && castStrategy->isExtensionCastImplied(op,readOp)) opHiddenFunc(op); else opTypeCast(op); @@ -1282,61 +1282,6 @@ bool PrintC::printCharacterConstant(ostream &s,const Address &addr,int4 charsize return res; } -/// \brief Is the given ZEXT/SEXT cast implied by the expression its in -/// -/// We know that the given ZEXT or SEXT op can be viewed as a natural \e cast operation. -/// Sometimes such a cast is implied by the expression its in, and the cast itself -/// doesn't need to be printed. -/// \param op is the given ZEXT or SEXT PcodeOp -/// \param readOp is the PcodeOp consuming the output of the extensions (or null) -/// \return \b true if the op as a cast does not need to be printed -bool PrintC::isExtensionCastImplied(const PcodeOp *op,const PcodeOp *readOp) const - -{ - if (!option_hide_exts) - return false; // If hiding extensions is not on, we must always print extension - const Varnode *outVn = op->getOut(); - if (outVn->isExplicit()) { - - } - else { - if (readOp == (PcodeOp *) 0) - return false; - type_metatype metatype = outVn->getHigh()->getType()->getMetatype(); - const Varnode *otherVn; - int4 slot; - switch (readOp->code()) { - case CPUI_PTRADD: - break; - case CPUI_INT_ADD: - case CPUI_INT_SUB: - case CPUI_INT_MULT: - case CPUI_INT_DIV: - case CPUI_INT_AND: - case CPUI_INT_OR: - case CPUI_INT_XOR: - case CPUI_INT_EQUAL: - case CPUI_INT_NOTEQUAL: - case CPUI_INT_LESS: - case CPUI_INT_LESSEQUAL: - case CPUI_INT_SLESS: - case CPUI_INT_SLESSEQUAL: - slot = readOp->getSlot(outVn); - otherVn = readOp->getIn(1 - slot); - // Check if the expression involves an explicit variable of the right integer type - if (!otherVn->isExplicit() && !otherVn->isConstant()) - return false; - if (otherVn->getHigh()->getType()->getMetatype() != metatype) - return false; - break; - default: - return false; - } - return true; // Everything is integer promotion - } - return false; -} - /// \brief Push a single character constant to the RPN stack /// /// For C, a character constant is usually emitted as the character in single quotes. diff --git a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh index e91ffea0c5..ebc15f0693 100644 --- a/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh +++ b/Ghidra/Features/Decompiler/src/decompile/cpp/printc.hh @@ -159,7 +159,6 @@ protected: void opHiddenFunc(const PcodeOp *op); ///< Push the given p-code op as a hidden token static bool hasCharTerminator(uint1 *buffer,int4 size,int4 charsize); bool printCharacterConstant(ostream &s,const Address &addr,int4 charsize) const; - bool isExtensionCastImplied(const PcodeOp *op,const PcodeOp *readOp) const; virtual void pushConstant(uintb val,const Datatype *ct, const Varnode *vn,const PcodeOp *op); virtual bool pushEquate(uintb val,int4 sz,const EquateSymbol *sym,