/// This function converts a Constant* into a GenericValue. The interesting /// part is if C is a ConstantExpr. /// @brief Get a GenericValue for a Constant* GenericValue ExecutionEngine::getConstantValue(const Constant *C) { // If its undefined, return the garbage. if (isa<UndefValue>(C)) return GenericValue(); // If the value is a ConstantExpr if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) { Constant *Op0 = CE->getOperand(0); switch (CE->getOpcode()) { case Instruction::GetElementPtr: { // Compute the index GenericValue Result = getConstantValue(Op0); SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end()); uint64_t Offset = TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size()); char* tmp = (char*) Result.PointerVal; Result = PTOGV(tmp + Offset); return Result; } case Instruction::Trunc: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.trunc(BitWidth); return GV; } case Instruction::ZExt: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.zext(BitWidth); return GV; } case Instruction::SExt: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); GV.IntVal = GV.IntVal.sext(BitWidth); return GV; } case Instruction::FPTrunc: { // FIXME long double GenericValue GV = getConstantValue(Op0); GV.FloatVal = float(GV.DoubleVal); return GV; } case Instruction::FPExt:{ // FIXME long double GenericValue GV = getConstantValue(Op0); GV.DoubleVal = double(GV.FloatVal); return GV; } case Instruction::UIToFP: { GenericValue GV = getConstantValue(Op0); if (CE->getType() == Type::FloatTy) GV.FloatVal = float(GV.IntVal.roundToDouble()); else if (CE->getType() == Type::DoubleTy) GV.DoubleVal = GV.IntVal.roundToDouble(); else if (CE->getType() == Type::X86_FP80Ty) { const uint64_t zero[] = {0, 0}; APFloat apf = APFloat(APInt(80, 2, zero)); (void)apf.convertFromAPInt(GV.IntVal, false, APFloat::rmNearestTiesToEven); GV.IntVal = apf.bitcastToAPInt(); } return GV; } case Instruction::SIToFP: { GenericValue GV = getConstantValue(Op0); if (CE->getType() == Type::FloatTy) GV.FloatVal = float(GV.IntVal.signedRoundToDouble()); else if (CE->getType() == Type::DoubleTy) GV.DoubleVal = GV.IntVal.signedRoundToDouble(); else if (CE->getType() == Type::X86_FP80Ty) { const uint64_t zero[] = { 0, 0}; APFloat apf = APFloat(APInt(80, 2, zero)); (void)apf.convertFromAPInt(GV.IntVal, true, APFloat::rmNearestTiesToEven); GV.IntVal = apf.bitcastToAPInt(); } return GV; } case Instruction::FPToUI: // double->APInt conversion handles sign case Instruction::FPToSI: { GenericValue GV = getConstantValue(Op0); uint32_t BitWidth = cast<IntegerType>(CE->getType())->getBitWidth(); if (Op0->getType() == Type::FloatTy) GV.IntVal = APIntOps::RoundFloatToAPInt(GV.FloatVal, BitWidth); else if (Op0->getType() == Type::DoubleTy) GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth); else if (Op0->getType() == Type::X86_FP80Ty) { APFloat apf = APFloat(GV.IntVal); uint64_t v; bool ignored; (void)apf.convertToInteger(&v, BitWidth, CE->getOpcode()==Instruction::FPToSI, APFloat::rmTowardZero, &ignored); GV.IntVal = v; // endian? } return GV; } case Instruction::PtrToInt: { GenericValue GV = getConstantValue(Op0); uint32_t PtrWidth = TD->getPointerSizeInBits(); GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); return GV; } case Instruction::IntToPtr: { GenericValue GV = getConstantValue(Op0); uint32_t PtrWidth = TD->getPointerSizeInBits(); if (PtrWidth != GV.IntVal.getBitWidth()) GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); return GV; } case Instruction::BitCast: { GenericValue GV = getConstantValue(Op0); const Type* DestTy = CE->getType(); switch (Op0->getType()->getTypeID()) { default: assert(0 && "Invalid bitcast operand"); case Type::IntegerTyID: assert(DestTy->isFloatingPoint() && "invalid bitcast"); if (DestTy == Type::FloatTy) GV.FloatVal = GV.IntVal.bitsToFloat(); else if (DestTy == Type::DoubleTy) GV.DoubleVal = GV.IntVal.bitsToDouble(); break; case Type::FloatTyID: assert(DestTy == Type::Int32Ty && "Invalid bitcast"); GV.IntVal.floatToBits(GV.FloatVal); break; case Type::DoubleTyID: assert(DestTy == Type::Int64Ty && "Invalid bitcast"); GV.IntVal.doubleToBits(GV.DoubleVal); break; case Type::PointerTyID: assert(isa<PointerType>(DestTy) && "Invalid bitcast"); break; // getConstantValue(Op0) above already converted it } return GV; } case Instruction::Add: case Instruction::Sub: case Instruction::Mul: case Instruction::UDiv: case Instruction::SDiv: case Instruction::URem: case Instruction::SRem: case Instruction::And: case Instruction::Or: case Instruction::Xor: { GenericValue LHS = getConstantValue(Op0); GenericValue RHS = getConstantValue(CE->getOperand(1)); GenericValue GV; switch (CE->getOperand(0)->getType()->getTypeID()) { default: assert(0 && "Bad add type!"); abort(); case Type::IntegerTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid integer opcode"); case Instruction::Add: GV.IntVal = LHS.IntVal + RHS.IntVal; break; case Instruction::Sub: GV.IntVal = LHS.IntVal - RHS.IntVal; break; case Instruction::Mul: GV.IntVal = LHS.IntVal * RHS.IntVal; break; case Instruction::UDiv:GV.IntVal = LHS.IntVal.udiv(RHS.IntVal); break; case Instruction::SDiv:GV.IntVal = LHS.IntVal.sdiv(RHS.IntVal); break; case Instruction::URem:GV.IntVal = LHS.IntVal.urem(RHS.IntVal); break; case Instruction::SRem:GV.IntVal = LHS.IntVal.srem(RHS.IntVal); break; case Instruction::And: GV.IntVal = LHS.IntVal & RHS.IntVal; break; case Instruction::Or: GV.IntVal = LHS.IntVal | RHS.IntVal; break; case Instruction::Xor: GV.IntVal = LHS.IntVal ^ RHS.IntVal; break; } break; case Type::FloatTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid float opcode"); abort(); case Instruction::Add: GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break; case Instruction::Sub: GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break; case Instruction::Mul: GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break; case Instruction::FDiv: GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break; case Instruction::FRem: GV.FloatVal = ::fmodf(LHS.FloatVal,RHS.FloatVal); break; } break; case Type::DoubleTyID: switch (CE->getOpcode()) { default: assert(0 && "Invalid double opcode"); abort(); case Instruction::Add: GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break; case Instruction::Sub: GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break; case Instruction::Mul: GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break; case Instruction::FDiv: GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break; case Instruction::FRem: GV.DoubleVal = ::fmod(LHS.DoubleVal,RHS.DoubleVal); break; } break; case Type::X86_FP80TyID: case Type::PPC_FP128TyID: case Type::FP128TyID: { APFloat apfLHS = APFloat(LHS.IntVal); switch (CE->getOpcode()) { default: assert(0 && "Invalid long double opcode"); abort(); case Instruction::Add: apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::Sub: apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::Mul: apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::FDiv: apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; case Instruction::FRem: apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven); GV.IntVal = apfLHS.bitcastToAPInt(); break; } } break; } return GV; } default: break; } cerr << "ConstantExpr not handled: " << *CE << "\n"; abort(); } GenericValue Result; switch (C->getType()->getTypeID()) { case Type::FloatTyID: Result.FloatVal = cast<ConstantFP>(C)->getValueAPF().convertToFloat(); break; case Type::DoubleTyID: Result.DoubleVal = cast<ConstantFP>(C)->getValueAPF().convertToDouble(); break; case Type::X86_FP80TyID: case Type::FP128TyID: case Type::PPC_FP128TyID: Result.IntVal = cast <ConstantFP>(C)->getValueAPF().bitcastToAPInt(); break; case Type::IntegerTyID: Result.IntVal = cast<ConstantInt>(C)->getValue(); break; case Type::PointerTyID: if (isa<ConstantPointerNull>(C)) Result.PointerVal = 0; else if (const Function *F = dyn_cast<Function>(C)) Result = PTOGV(getPointerToFunctionOrStub(const_cast<Function*>(F))); else if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C)) Result = PTOGV(getOrEmitGlobalVariable(const_cast<GlobalVariable*>(GV))); else assert(0 && "Unknown constant pointer type!"); break; default: cerr << "ERROR: Constant unimplemented for type: " << *C->getType() << "\n"; abort(); } return Result; }
/// \brief Fold binary operations. /// /// The list of operations we constant fold might not be complete. Start with /// folding the operations used by the standard library. static SILInstruction *constantFoldBinary(BuiltinInst *BI, BuiltinValueKind ID, Optional<bool> &ResultsInError) { switch (ID) { default: llvm_unreachable("Not all BUILTIN_BINARY_OPERATIONs are covered!"); // Not supported yet (not easily computable for APInt). case BuiltinValueKind::ExactSDiv: case BuiltinValueKind::ExactUDiv: return nullptr; // Not supported now. case BuiltinValueKind::FRem: return nullptr; // Fold constant division operations and report div by zero. case BuiltinValueKind::SDiv: case BuiltinValueKind::SRem: case BuiltinValueKind::UDiv: case BuiltinValueKind::URem: { return constantFoldAndCheckDivision(BI, ID, ResultsInError); } // Are there valid uses for these in stdlib? case BuiltinValueKind::Add: case BuiltinValueKind::Mul: case BuiltinValueKind::Sub: return nullptr; case BuiltinValueKind::And: case BuiltinValueKind::AShr: case BuiltinValueKind::LShr: case BuiltinValueKind::Or: case BuiltinValueKind::Shl: case BuiltinValueKind::Xor: { OperandValueArrayRef Args = BI->getArguments(); auto *LHS = dyn_cast<IntegerLiteralInst>(Args[0]); auto *RHS = dyn_cast<IntegerLiteralInst>(Args[1]); if (!RHS || !LHS) return nullptr; APInt LHSI = LHS->getValue(); APInt RHSI = RHS->getValue(); bool IsShift = ID == BuiltinValueKind::AShr || ID == BuiltinValueKind::LShr || ID == BuiltinValueKind::Shl; // Reject shifting all significant bits if (IsShift && RHSI.getZExtValue() >= LHSI.getBitWidth()) { diagnose(BI->getModule().getASTContext(), RHS->getLoc().getSourceLoc(), diag::shifting_all_significant_bits); ResultsInError = Optional<bool>(true); return nullptr; } APInt ResI = constantFoldBitOperation(LHSI, RHSI, ID); // Add the literal instruction to represent the result. SILBuilderWithScope B(BI); return B.createIntegerLiteral(BI->getLoc(), BI->getType(), ResI); } case BuiltinValueKind::FAdd: case BuiltinValueKind::FDiv: case BuiltinValueKind::FMul: case BuiltinValueKind::FSub: { OperandValueArrayRef Args = BI->getArguments(); auto *LHS = dyn_cast<FloatLiteralInst>(Args[0]); auto *RHS = dyn_cast<FloatLiteralInst>(Args[1]); if (!RHS || !LHS) return nullptr; APFloat LHSF = LHS->getValue(); APFloat RHSF = RHS->getValue(); switch (ID) { default: llvm_unreachable("Not all cases are covered!"); case BuiltinValueKind::FAdd: LHSF.add(RHSF, APFloat::rmNearestTiesToEven); break; case BuiltinValueKind::FDiv: LHSF.divide(RHSF, APFloat::rmNearestTiesToEven); break; case BuiltinValueKind::FMul: LHSF.multiply(RHSF, APFloat::rmNearestTiesToEven); break; case BuiltinValueKind::FSub: LHSF.subtract(RHSF, APFloat::rmNearestTiesToEven); break; } // Add the literal instruction to represent the result. SILBuilderWithScope B(BI); return B.createFloatLiteral(BI->getLoc(), BI->getType(), LHSF); } } }