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; }
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)); }