Exemple #1
0
/*******************  FUNCTION  *********************/
void ProjectActionOld::genItLoopCCode ( ostream& out, const CMRProjectContext& context, int depth ) const
{
	CMRProjectContext localContext(&context);

	//errors
	assert(name == "cmrSubBlock" && description == "cmrIteratorLoop");
	
	//search the related iterator definition
	const CMRProjectEntity * entity = context.parent->find(eq->latexEntity);
	if (entity == NULL)
	{
		cerr << "Can't find the definition of iterator " << eq->compute << " in current context." << endl;
		abort();
	}

	const CMRProjectIterator * iterator = dynamic_cast<const CMRProjectIterator*>(entity);
	if (iterator == NULL)
	{
		cerr << "Cuation, expect iterator " << eq->compute << " but get another type." << endl;
		context.printDebug();
		abort();
	}
	assert(iterator != NULL);
	
	CMRProjectLocalVariable localVar(eq->compute,eq->compute);
	localContext.addEntry(&localVar);
	out << genCCodeIndent(depth) << "for (int " << eq->compute << " = " << iterator->start << " ; " << eq->compute << " < " << iterator->end << " ; " << eq->compute << "++ )" <<endl;
	out << genCCodeIndent(depth) << "{" << endl;
	for (ConstIterator it = getFirstChild() ; ! it.isEnd() ; ++it)
		it->genCCode(out,it->context,depth+1);
		//it->genCCode(out,localContext,depth+1);
	out << genCCodeIndent(depth) << "}" << endl;
	
	//checkContext(localContext);
}
Exemple #2
0
ExprType ExprAssignNode::prep(bool wantScalar, ExprVarEnvBuilder& envBuilder) {
    _assignedType = child(0)->prep(false, envBuilder);

    std::unique_ptr<ExprLocalVar> localVar(new ExprLocalVar(child(0)->type()));
    _localVar = localVar.get();
    envBuilder.current()->add(_name, std::move(localVar));
    bool error = false;
    checkCondition(
        _assignedType.isValid(), std::string("Assignment operation has bad type: ") + _type.toString(), error);

    if (error)
        setType(ExprType().Error());
    else
        setTypeWithChildLife(ExprType().None());
    return _type;
}
Exemple #3
0
		std::string Value::toString() const {
			switch (kind()) {
				case SELF:
					return "self";
				case THIS:
					return "this";
				case CONSTANT:
					return makeString("Constant(%s)", constant().toString().c_str());
				case ALIAS:
					return makeString("Alias(alias: %s, templateArguments: %s)",
					                  alias().toString().c_str(),
					                  makeArrayString(aliasTemplateArguments()).c_str());
				case PREDICATE:
					return makeString("Predicate(%s)", predicate().toString().c_str());
				case LOCALVAR:
					return makeString("LocalVar(%s)", localVar().toString().c_str());
				case REINTERPRET:
					return makeString("Reinterpret(value: %s)", reinterpretOperand().toString().c_str());
				case DEREF_REFERENCE:
					return makeString("DerefReference(%s)", derefOperand().toString().c_str());
				case TERNARY:
					return makeString("Ternary(cond: %s, ifTrue: %s, ifFalse: %s)",
						ternaryCondition().toString().c_str(),
						ternaryIfTrue().toString().c_str(),
						ternaryIfFalse().toString().c_str());
				case CAST:
					return makeString("Cast(value: %s, targetType: %s)",
						castOperand().toString().c_str(),
						castTargetType()->toString().c_str());
				case POLYCAST:
					return makeString("PolyCast(value: %s, targetType: %s)",
						polyCastOperand().toString().c_str(),
						polyCastTargetType()->toString().c_str());
				case INTERNALCONSTRUCT:
					return makeString("InternalConstruct(args: %s)",
						makeArrayString(internalConstructParameters()).c_str());
				case MEMBERACCESS:
					return makeString("MemberAccess(object: %s, var: %s)",
						memberAccessObject().toString().c_str(),
						memberAccessVar().toString().c_str());
				case BIND_REFERENCE:
					return makeString("BindReference(value: %s)", bindReferenceOperand().toString().c_str());
				case TYPEREF:
					return makeString("TypeRef(targetType: %s)", typeRefType()->toString().c_str());
				case TEMPLATEVARREF:
					return makeString("TemplateVarRef(templateVar: %s)", templateVar()->toString().c_str());
				case CALL:
					return makeString("Call(funcValue: %s, args: %s)",
						callValue().toString().c_str(),
						makeArrayString(callParameters()).c_str());
				case FUNCTIONREF:
					return makeString("FunctionRef(name: %s, type: %s, parentType: %s, templateArgs: %s)",
						functionRefFunction().fullName().toString().c_str(),
						type()->toString().c_str(),
						functionRefParentType() != nullptr ?
							functionRefParentType()->toString().c_str() :
							"[NONE]",
						makeArrayString(functionRefTemplateArguments()).c_str());
				case TEMPLATEFUNCTIONREF:
					return makeString("TemplateFunctionRef(name: %s, parentType: %s)",
						templateFunctionRefName().c_str(),
						templateFunctionRefParentType()->toString().c_str());
				case METHODOBJECT:
					return makeString("MethodObject(method: %s, object: %s)",
						methodObject().toString().c_str(),
						methodOwner().toString().c_str());
				case INTERFACEMETHODOBJECT:
					return makeString("InterfaceMethodObject(method: %s, object: %s)",
						interfaceMethodObject().toString().c_str(),
						interfaceMethodOwner().toString().c_str());
				case STATICINTERFACEMETHODOBJECT:
					return makeString("StaticInterfaceMethodObject(method: %s, typeRef: %s)",
						staticInterfaceMethodObject().toString().c_str(),
						staticInterfaceMethodOwner().toString().c_str());
				case CAPABILITYTEST:
					return makeString("CapabilityTest(checkType: %s, capabilityType: %s)",
					                  capabilityTestCheckType()->toString().c_str(),
					                  capabilityTestCapabilityType()->toString().c_str());
				case Value::ARRAYLITERAL:
					return makeString("ArrayLiteral(type: %s, values: %s)",
					                  type()->toString().c_str(),
					                  makeArrayString(arrayLiteralValues()).c_str());
				case NEW:
					return makeString("New(placementArg: %s, operand: %s)",
					                  newPlacementArg().toString().c_str(),
					                  newOperand().toString().c_str());
				case CASTDUMMYOBJECT:
					return makeString("[CAST DUMMY OBJECT (FOR SEMANTIC ANALYSIS)](type: %s)",
						type()->toString().c_str());
			}
			
			locic_unreachable("Unknown value kind.");
		}
Exemple #4
0
		bool Value::operator==(const Value& value) const {
			if (kind() != value.kind()) {
				return false;
			}
			
			if (type() != value.type()) {
				return false;
			}
			
			switch (value.kind()) {
				case Value::SELF:
					return true;
				case Value::THIS:
					return true;
				case Value::CONSTANT:
					return constant() == value.constant();
				case Value::ALIAS:
					return &(alias()) == &(value.alias()) &&
						aliasTemplateArguments() == value.aliasTemplateArguments();
				case Value::PREDICATE:
					return predicate() == value.predicate();
				case Value::LOCALVAR:
					return &(localVar()) == &(value.localVar());
				case Value::REINTERPRET:
					return reinterpretOperand() == value.reinterpretOperand();
				case Value::DEREF_REFERENCE:
					return derefOperand() == value.derefOperand();
				case Value::TERNARY:
					return ternaryCondition() == value.ternaryCondition() && ternaryIfTrue() == value.ternaryIfTrue() && ternaryIfFalse() == value.ternaryIfFalse();
				case Value::CAST:
					return castTargetType() == value.castTargetType() && castOperand() == value.castOperand();
				case Value::POLYCAST:
					return polyCastTargetType() == value.polyCastTargetType() && polyCastOperand() == value.polyCastOperand();
				case Value::INTERNALCONSTRUCT:
					return internalConstructParameters() == value.internalConstructParameters();
				case Value::MEMBERACCESS:
					return memberAccessObject() == value.memberAccessObject() && &(memberAccessVar()) == &(value.memberAccessVar());
				case Value::BIND_REFERENCE:
					return bindReferenceOperand() == value.bindReferenceOperand();
				case Value::TYPEREF:
					return typeRefType() == value.typeRefType();
				case Value::TEMPLATEVARREF:
					return templateVar() == value.templateVar();
				case Value::CALL:
					return callValue() == value.callValue() && callParameters() == value.callParameters();
				case Value::FUNCTIONREF:
					return functionRefParentType() == value.functionRefParentType() && &(functionRefFunction()) == &(value.functionRefFunction()) &&
						functionRefTemplateArguments() == value.functionRefTemplateArguments();
				case Value::TEMPLATEFUNCTIONREF:
					return templateFunctionRefParentType() == value.templateFunctionRefParentType() && templateFunctionRefName() == value.templateFunctionRefName() &&
						templateFunctionRefFunctionType() == value.templateFunctionRefFunctionType();
				case Value::METHODOBJECT:
					return methodObject() == value.methodObject() && methodOwner() == value.methodOwner();
				case Value::INTERFACEMETHODOBJECT:
					return interfaceMethodObject() == value.interfaceMethodObject() && interfaceMethodOwner() == value.interfaceMethodOwner();
				case Value::STATICINTERFACEMETHODOBJECT:
					return staticInterfaceMethodObject() == value.staticInterfaceMethodObject() && staticInterfaceMethodOwner() == value.staticInterfaceMethodOwner();
				case Value::CAPABILITYTEST:
					return capabilityTestCheckType() == value.capabilityTestCheckType() &&
					       capabilityTestCapabilityType() == value.capabilityTestCapabilityType();
				case Value::ARRAYLITERAL:
					return arrayLiteralValues() == value.arrayLiteralValues();
				case Value::NEW:
					return newPlacementArg() == value.newPlacementArg() &&
					       newOperand() == value.newOperand();
				case Value::CASTDUMMYOBJECT:
					return true;
			}
			
			locic_unreachable("Unknown value kind.");
		}
Exemple #5
0
		size_t Value::hash() const {
			Hasher hasher;
			hasher.add(kind());
			hasher.add(type());
			
			switch (kind()) {
				case Value::SELF:
					break;
				case Value::THIS:
					break;
				case Value::CONSTANT:
					hasher.add(constant());
					break;
				case Value::ALIAS:
					hasher.add(&(alias()));
					hasher.add(aliasTemplateArguments().size());
					for (const auto& argument: aliasTemplateArguments()) {
						hasher.add(argument);
					}
					break;
				case Value::PREDICATE:
					hasher.add(predicate());
					break;
				case Value::LOCALVAR:
					hasher.add(&(localVar()));
					break;
				case Value::REINTERPRET:
					hasher.add(reinterpretOperand());
					break;
				case Value::DEREF_REFERENCE:
					hasher.add(derefOperand());
					break;
				case Value::TERNARY:
					hasher.add(ternaryCondition());
					hasher.add(ternaryIfTrue());
					hasher.add(ternaryIfFalse());
					break;
				case Value::CAST:
					hasher.add(castTargetType());
					hasher.add(castOperand());
					break;
				case Value::POLYCAST:
					hasher.add(polyCastTargetType());
					hasher.add(polyCastOperand());
					break;
				case Value::INTERNALCONSTRUCT:
					hasher.add(internalConstructParameters().size());
					for (const auto& param: internalConstructParameters()) {
						hasher.add(param);
					}
					break;
				case Value::MEMBERACCESS:
					hasher.add(memberAccessObject());
					hasher.add(&(memberAccessVar()));
					break;
				case Value::BIND_REFERENCE:
					hasher.add(bindReferenceOperand());
					break;
				case Value::TYPEREF:
					hasher.add(typeRefType());
					break;
				case Value::TEMPLATEVARREF:
					hasher.add(templateVar());
					break;
				case Value::CALL:
					hasher.add(callValue());
					hasher.add(callParameters().size());
					for (const auto& param: callParameters()) {
						hasher.add(param);
					}
					break;
				case Value::FUNCTIONREF:
					hasher.add(functionRefParentType());
					hasher.add(&(functionRefFunction()));
					hasher.add(functionRefTemplateArguments().size());
					for (const auto& arg: functionRefTemplateArguments()) {
						hasher.add(arg);
					}
					break;
				case Value::TEMPLATEFUNCTIONREF:
					hasher.add(templateFunctionRefParentType());
					hasher.add(templateFunctionRefName());
					hasher.add(templateFunctionRefFunctionType());
					break;
				case Value::METHODOBJECT:
					hasher.add(methodObject());
					hasher.add(methodOwner());
					break;
				case Value::INTERFACEMETHODOBJECT:
					hasher.add(interfaceMethodObject());
					hasher.add(interfaceMethodOwner());
					break;
				case Value::STATICINTERFACEMETHODOBJECT:
					hasher.add(staticInterfaceMethodObject());
					hasher.add(staticInterfaceMethodOwner());
					break;
				case Value::CAPABILITYTEST:
					hasher.add(capabilityTestCheckType());
					hasher.add(capabilityTestCapabilityType());
					break;
				case Value::ARRAYLITERAL:
					hasher.add(arrayLiteralValues().size());
					for (const auto& value: arrayLiteralValues()) {
						hasher.add(value);
					}
					break;
				case Value::NEW:
					hasher.add(newPlacementArg());
					hasher.add(newOperand());
					break;
				case Value::CASTDUMMYOBJECT:
					break;
			}
			
			return hasher.get();
		}
Exemple #6
0
		std::string Value::toDiagString() const {
			switch (kind()) {
				case SELF:
					return "self";
				case THIS:
					return "this";
				case CONSTANT:
					return constant().toString();
				case ALIAS:
					return alias().toString();
				case PREDICATE:
					return predicate().toString();
				case LOCALVAR:
					return localVar().name().asStdString();
				case REINTERPRET:
					return reinterpretOperand().toDiagString();
				case DEREF_REFERENCE:
					return makeString("<deref> %s", derefOperand().toDiagString().c_str());
				case TERNARY:
					return makeString("%s ? %s : %s",
						ternaryCondition().toDiagString().c_str(),
						ternaryIfTrue().toDiagString().c_str(),
						ternaryIfFalse().toDiagString().c_str());
				case CAST:
					return castOperand().toDiagString();
				case POLYCAST:
					return polyCastOperand().toDiagString();
				case INTERNALCONSTRUCT:
					return makeString("@(%s)",
						makeArrayString(internalConstructParameters()).c_str());
				case MEMBERACCESS:
					return makeString("%s.%s",
						memberAccessObject().toDiagString().c_str(),
						memberAccessVar().name().c_str());
				case BIND_REFERENCE:
					return makeString("<bind> %s", bindReferenceOperand().toDiagString().c_str());
				case TYPEREF:
					return typeRefType()->toDiagString();
				case TEMPLATEVARREF:
					return templateVar()->fullName().last().asStdString();
				case CALL:
					return makeString("%s(%s)", callValue().toDiagString().c_str(),
						makeArrayString(callParameters()).c_str());
				case FUNCTIONREF:
					return functionRefFunction().fullName().toString();
				case TEMPLATEFUNCTIONREF:
					return makeString("%s::%s",
					                  templateFunctionRefParentType()->toDiagString().c_str(),
					                  templateFunctionRefName().c_str());
				case METHODOBJECT:
					return makeString("%s.%s",
					                  methodOwner().toDiagString().c_str(),
					                  methodObject().toDiagString().c_str());
				case INTERFACEMETHODOBJECT:
					return makeString("%s.%s",
					                  interfaceMethodOwner().toDiagString().c_str(),
					                  interfaceMethodObject().toDiagString().c_str());
				case STATICINTERFACEMETHODOBJECT:
					return makeString("%s.%s",
					                  staticInterfaceMethodOwner().toDiagString().c_str(),
					                  staticInterfaceMethodObject().toDiagString().c_str());
				case CAPABILITYTEST:
					return makeString("%s : %s",
					                  capabilityTestCheckType()->toDiagString().c_str(),
					                  capabilityTestCapabilityType()->toDiagString().c_str());
				case Value::ARRAYLITERAL:
					return makeString("{ %s }", makeArrayString(arrayLiteralValues()).c_str());
				case NEW:
					return makeString("new(%s) %s", newPlacementArg().toDiagString().c_str(),
					                  newOperand().toDiagString().c_str());
				case CASTDUMMYOBJECT:
					locic_unreachable("Shouldn't reach CASTDUMMYOBJECT.");
			}
			
			locic_unreachable("Unknown value kind.");
		}
/**
* @brief Computes the FuncInfo and returns it.
*/
ShPtr<OptimFuncInfo> OptimFuncInfoCFGTraversal::performComputation() {
	// First, we pre-compute varsAlwaysModifiedBeforeRead. The reason is that
	// their computation differs from the computation of the rest of the sets.
	precomputeAlwaysModifiedVarsBeforeRead();

	// Every function's body is of the following form:
	//
	//    (1) definitions of local variables, including assignments of global
	//        variables into local variables
	//    (2) other statements
	//
	// We store which variables are read/modified in (1). Then, we start the
	// traversal from (2). During the traversal, we check which variables are
	// read/modified and update funcInfo accordingly. The stored information
	// from (1) is used to compute the set of global variables which are read
	// in the function, but not modified.
	//
	// To give a specific example, consider the following code:
	//
	// def func(mango):
	//    global orange
	//    global plum
	//    lychee = orange
	//    achira = plum
	//    orange = mango
	//    plum = rand()
	//    result = plum * apple + orange
	//    orange = lychee
	//    plum = achira
	//    return result
	//
	// Here, even though the global variable orange is modified, its value
	// before calling func() is the same as after calling func(). Indeed, its
	// value is restored before the return statement. Hence, we may put it into
	// funcInfo->varsWithNeverChangedValue.
	// TODO Implement a more robust analysis.
	ShPtr<Statement> currStmt = traversedFunc->getBody();
	while (isVarDefOrAssignStmt(currStmt)) {
		updateFuncInfo(currStmt);

		ShPtr<Expression> lhs(getLhs(currStmt));
		ShPtr<Expression> rhs(getRhs(currStmt));

		// If there is no right-hand side, it is a VarDefStmt with no
		// initializer, which we may skip.
		if (!rhs) {
			currStmt = currStmt->getSuccessor();
			continue;
		}

		// If there are any function calls or dereferences, we have reached
		// (2).
		ShPtr<ValueData> currStmtData(va->getValueData(currStmt));
		if (currStmtData->hasCalls() || currStmtData->hasDerefs()) {
			break;
		}

		// Check whether the statement is of the form localVar = globalVar.
		ShPtr<Variable> localVar(cast<Variable>(lhs));
		ShPtr<Variable> globalVar(cast<Variable>(rhs));
		if (!localVar || !globalVar || hasItem(globalVars, localVar) ||
				!hasItem(globalVars, globalVar)) {
			// It is not of the abovementioned form, so skip it.
			currStmt = currStmt->getSuccessor();
			continue;
		}

		storedGlobalVars[globalVar] = localVar;
		currStmt = currStmt->getSuccessor();
	}

	// Perform the traversal only if we haven't reached the end of the function
	// yet. Since empty statements are not present in a CFG, skip them before
	// the traversal.
	if ((currStmt = skipEmptyStmts(currStmt))) {
		performTraversal(currStmt);
	}

	// We use the exit node of the CFG to check that every variable from
	// storedGlobalVars is retrieved its original value before every return.
	ShPtr<CFG::Node> exitNode(cfg->getExitNode());
	// For every predecessor of the exit node...
	for (auto i = exitNode->pred_begin(), e = exitNode->pred_end(); i != e; ++i) {
		bool checkingShouldContinue = checkExitNodesPredecessor((*i)->getSrc());
		if (!checkingShouldContinue) {
			break;
		}
	}

	// Update funcInfo using the remaining variables in storedGlobalVars.
	for (const auto &p : storedGlobalVars) {
		funcInfo->varsWithNeverChangedValue.insert(p.first);
	}

	// Update funcInfo->never{Read,Modified}Vars by global variables which are
	// untouched in this function.
	for (auto i = module->global_var_begin(), e = module->global_var_end();
			i != e; ++i) {
		ShPtr<Variable> var((*i)->getVar());
		if (!hasItem(funcInfo->mayBeReadVars, var) &&
				!hasItem(funcInfo->mayBeModifiedVars, var)) {
			funcInfo->neverReadVars.insert(var);
			funcInfo->neverModifiedVars.insert(var);
		}
	}

	// If the cfg contains only a single non-{entry,exit} node, every
	// mayBe{Read,Modifed} variable can be turned into a always{Read,Modified}
	// variable.
	if (cfg->getNumberOfNodes() == 3) {
		addToSet(funcInfo->mayBeReadVars, funcInfo->alwaysReadVars);
		addToSet(funcInfo->mayBeModifiedVars, funcInfo->alwaysModifiedVars);
	}

	// Add all variables which are never read and never modified to
	// varsWithNeverChangedValue.
	VarSet neverReadAndModifedVars(setIntersection(funcInfo->neverReadVars,
		funcInfo->neverModifiedVars));
	addToSet(neverReadAndModifedVars, funcInfo->varsWithNeverChangedValue);

	// Add all global variables are not read in this function into
	// varsAlwaysModifiedBeforeRead.
	addToSet(setDifference(globalVars, funcInfo->mayBeReadVars),
		funcInfo->varsAlwaysModifiedBeforeRead);

	return funcInfo;
}