DLTree* TAxiom :: createAnAxiom ( const DLTree* skip ) const { // create new OR vertex for the axiom: DLTree* Or = createTop(); for ( const_iterator p = begin(), p_end = end(); p != p_end; ++p ) if ( *p != skip ) Or = createSNFAnd ( clone(*p), Or ); return createSNFNot(Or); }
DLTree* TAxiom :: createAnAxiom ( const DLTree* skip ) const { // create new OR vertex for the axiom: DLTree* Or = createTop(); for ( const auto& C: Disjuncts ) if ( C != skip ) Or = createSNFAnd ( clone(C), Or ); return createSNFNot(Or); }
bool TAxiom :: absorbIntoTop ( TBox& KB ) const { TConcept* C = NULL; // check whether the axiom is Top [= C for ( const_iterator p = begin(), p_end = end(); p != p_end; ++p ) if ( InAx::isBot(*p) ) // BOTTOMS are fine continue; else if ( InAx::isPosCN(*p) ) // CN found { if ( C != NULL ) // more than one concept return false; C = InAx::getConcept((*p)->Left()); if ( C->isSingleton() ) // doesn't work with nominals return false; } else return false; if ( C == NULL ) return false; // make an absorption Stat::SAbsTApply(); DLTree* desc = KB.makeNonPrimitive ( C, createTop() ); #ifdef RKG_DEBUG_ABSORPTION std::cout << " T-Absorb GCI to axiom"; if ( desc ) std::cout << "s *TOP* [=" << desc << " and"; std::cout << " " << C->getName() << " = *TOP*"; #endif if ( desc ) KB.addSubsumeAxiom ( createTop(), desc ); return true; }
bool TAxiom :: absorbIntoTop ( TBox& KB ) const { TConcept* Cand = nullptr; // check whether the axiom is Top [= C for ( const auto& C: Disjuncts ) if ( InAx::isBot(C) ) // BOTTOMS are fine continue; else if ( InAx::isPosCN(C) ) // CN found { if ( Cand != nullptr ) // more than one concept return false; Cand = InAx::getConcept(C->Left()); if ( Cand->isSingleton() ) // doesn't work with nominals return false; } else return false; if ( Cand == nullptr ) return false; // make an absorption Stat::SAbsTApply(); DLTree* desc = KB.makeNonPrimitive ( Cand, createTop() ); #ifdef RKG_DEBUG_ABSORPTION std::cout << " T-Absorb GCI to axiom"; if ( desc ) std::cout << "s *TOP* [=" << desc << " and"; std::cout << " " << Cand->getName() << " = *TOP*"; #endif if ( desc ) KB.addSubsumeAxiom ( createTop(), desc ); return true; }
/// create negation of given formula DLTree* createSNFNot ( DLTree* C ) { fpp_assert ( C != NULL ); // sanity check if ( C->Element() == BOTTOM ) { // \not F = T deleteTree(C); return createTop(); } if ( C->Element() == TOP ) { // \not T = F deleteTree(C); return createBottom(); } if ( C->Element () == NOT ) { // \not\not C = C DLTree* p = clone(C->Left()); deleteTree(C); return p; } // general case return new DLTree ( TLexeme(NOT), C ); }
namespace rift { char TypeAnalysis::ID = 0; AType * AType::top = createTop(); void TypeAnalysis::genericArithmetic(CallInst * ci) { AType * lhs = state.get(ci->getOperand(0)); AType * rhs = state.get(ci->getOperand(1)); state.update(ci, lhs->merge(rhs)); } void TypeAnalysis::genericRelational(CallInst * ci) { AType * lhs = state.get(ci->getOperand(0)); AType * rhs = state.get(ci->getOperand(1)); if (lhs->isScalar() and rhs->isScalar()) { state.update(ci, new AType(AType::Kind::R, AType::Kind::DV, AType::Kind::D)); } else { state.update(ci, new AType(AType::Kind::R, AType::Kind::DV)); } } void TypeAnalysis::genericGetElement(CallInst * ci) { AType * from = state.get(ci->getOperand(0)); AType * index = state.get(ci->getOperand(1)); if (from->isDouble()) { if (index->isScalar()) { state.update(ci, new AType(AType::Kind::R, AType::Kind::DV, AType::Kind::D)); } else { state.update(ci, new AType(AType::Kind::R, AType::Kind::DV)); } } else if (from->isCharacter()) { state.update(ci, new AType(AType::Kind::R, AType::Kind::CV)); } else { state.update(ci, new AType(AType::Kind::T)); } } bool TypeAnalysis::runOnFunction(llvm::Function & f) { state.clear(); if (DEBUG) std::cout << "runnning TypeAnalysis..." << std::endl; // for all basic blocks, for all instructions do { // cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl; state.iterationStart(); for (auto & b : f) { for (auto & i : b) { if (CallInst * ci = dyn_cast<CallInst>(&i)) { StringRef s = ci->getCalledFunction()->getName(); if (s == "doubleVectorLiteral") { // when creating literal from a double, it is // always double scalar llvm::Value * op = ci->getOperand(0); AType * t = new AType(AType::Kind::D); state.update(op, t); state.update(ci, new AType(AType::Kind::DV, t)); } else if (s == "characterVectorLiteral") { state.update(ci, new AType(AType::Kind::CV)); } else if (s == "fromDoubleVector") { state.update(ci, new AType(AType::Kind::R, state.get(ci->getOperand(0)))); } else if (s == "fromCharacterVector") { state.update(ci, new AType(AType::Kind::R, state.get(ci->getOperand(0)))); } else if (s == "fromFunction") { state.update(ci, new AType(AType::Kind::R, state.get(ci->getOperand(0)))); } else if (s == "genericGetElement") { genericGetElement(ci); } else if (s == "genericSetElement") { // don't do anything for set element as it does not // produce any new value } else if (s == "genericAdd") { genericArithmetic(ci); } else if (s == "genericSub") { genericArithmetic(ci); } else if (s == "genericMul") { genericArithmetic(ci); } else if (s == "genericDiv") { genericArithmetic(ci); } else if (s == "genericEq") { genericRelational(ci); } else if (s == "genericNeq") { genericRelational(ci); } else if (s == "genericLt") { genericRelational(ci); } else if (s == "genericGt") { genericRelational(ci); } else if (s == "length") { // result of length operation is always // double scalar state.update(ci, new AType(AType::Kind::D)); } else if (s == "type") { // result of type operation is always // character vector state.update(ci, new AType(AType::Kind::CV)); } else if (s == "c") { // make sure the types to c are correct AType * t1 = state.get(ci->getArgOperand(1)); for (unsigned i = 2; i < ci->getNumArgOperands(); ++i) t1 = t1->merge(state.get(ci->getArgOperand(i))); if (t1->isScalar()) // concatenation of scalars is a vector t1 = new AType(AType::Kind::R, AType::Kind::DV); state.update(ci, t1); } else if (s == "genericEval") { state.update(ci, new AType(AType::Kind::R)); } else if (s == "envGet") { state.update(ci, new AType(AType::Kind::R)); } } else if (PHINode * phi = dyn_cast<PHINode>(&i)) { AType * first = state.get(phi->getOperand(0)); AType * second = state.get(phi->getOperand(1)); AType * result = first->merge(second); state.update(phi, result); } } } } while (!state.hasReachedFixpoint()); if (DEBUG) { f.dump(); cout << state << endl; } return false; } std::ostream & operator << (std::ostream & s, MachineState & m) { s << "Abstract State: " << "\n"; for (auto const & v : m.type) { auto st = std::get<1>(v); st->print(s, m); s << endl; } return s; } void AType::print(std::ostream & s, MachineState & m) { llvm::raw_os_ostream ss(s); if (auto loc = m.getLocation(this)) loc->printAsOperand(ss, false); switch (kind) { case AType::Kind::D: ss << " D "; break; case AType::Kind::DV: ss << " DV "; break; case AType::Kind::CV: ss << " CV "; break; case AType::Kind::F: ss << " F "; break; case AType::Kind::R: ss << " R "; break; case AType::Kind::T: ss << " T "; break; case AType::Kind::B: ss << " B "; break; } ss.flush(); if (not payload->isTop()) { s << " -> "; payload->print(s, m); } } } // namespace rift