Exemplo n.º 1
0
void FunctionCall::checkParamTypeCodeErrors(AnalysisResultPtr ar) {
  if (!m_funcScope || m_arrayParams) return;
  for (int i = 0, n = m_funcScope->getMaxParamCount(); i < n; ++i) {
    TypePtr specType = m_funcScope->getParamTypeSpec(i);
    if (!specType) continue;

    const char *fmt = 0;
    string ptype;
    if (!m_params || m_params->getCount() <= i) {
      if (i >= m_funcScope->getMinParamCount()) break;
      fmt = "parameter %d of %s() requires %s, none given";
    } else {
      ExpressionPtr param = (*m_params)[i];
      if (!Type::Inferred(ar, param->getType(), specType)) {
        fmt = "parameter %d of %s() requires %s, called with %s";
      }
      ptype = param->getType()->toString();
    }
    if (fmt) {
      string msg;
      string_printf
        (msg, fmt,
         i + 1,
         escapeStringForCPP(m_funcScope->getOriginalName()).c_str(),
         specType->toString().c_str(), ptype.c_str());
      Compiler::Error(Compiler::BadArgumentType,
                      shared_from_this(), msg);
    }
  }
}
Exemplo n.º 2
0
	ExpressionPtr buildPtrOfFunction(const ExpressionPtr& funExpr) {
		assert_true(funExpr->getType().isa<FunctionTypePtr>()) << "Trying to build a ptr of a non-function type:\n" << dumpColor(funExpr)
			                                                   << "\nType: " << dumpColor(funExpr->getType());
		IRBuilder builder(funExpr->getNodeManager());
		auto& pExt = funExpr->getNodeManager().getLangExtension<PointerExtension>();
		return builder.callExpr(pExt.getPtrOfFunction(), funExpr);
	}
Exemplo n.º 3
0
void FunctionCall::analyzeProgram(AnalysisResultPtr ar) {
  if (m_class) m_class->analyzeProgram(ar);
  if (m_nameExp) m_nameExp->analyzeProgram(ar);
  if (m_params) m_params->analyzeProgram(ar);
  if (ar->getPhase() == AnalysisResult::AnalyzeFinal) {
    if (m_funcScope && !m_arrayParams) {
      for (int i = 0, n = m_funcScope->getMaxParamCount(); i < n; ++i) {
        if (TypePtr specType = m_funcScope->getParamTypeSpec(i)) {
          const char *fmt = 0;
          string ptype;
          if (!m_params || m_params->getCount() <= i) {
            if (i >= m_funcScope->getMinParamCount()) break;
            fmt = "parameter %d of %s() requires %s, none given";
          } else {
            ExpressionPtr param = (*m_params)[i];
            if (!Type::Inferred(ar, param->getType(), specType)) {
              fmt = "parameter %d of %s() requires %s, called with %s";
            }
            ptype = param->getType()->toString();
          }
          if (fmt) {
            string msg;
            Util::string_printf
              (msg, fmt,
               i + 1,
               Util::escapeStringForCPP(m_funcScope->getOriginalName()).c_str(),
               specType->toString().c_str(), ptype.c_str());
            Compiler::Error(Compiler::BadArgumentType,
                            shared_from_this(), msg);
          }
        }
      }
    }
  }
}
Exemplo n.º 4
0
/*
 * Changes the type of the field of a struct
 */
void updateStruct(const ExpressionPtr& structure, TypePtr& type, const ExpressionPtr& identifier) {
	NodeManager& mgr = structure->getNodeManager();
	IRBuilder builder(mgr);

	TypePtr baseType = structure->getType();
	RefTypePtr refTy = baseType.isa<RefTypePtr>();
	StructTypePtr kst = refTy ? refTy->getElementType().as<StructTypePtr>() : structure->getType().as<StructTypePtr>();
	std::string name = identifier->toString();
	NamedTypePtr oldType = kst->getNamedTypeEntryOf(name);
	NamedTypePtr newType = builder.namedType(name, refTy ? builder.refType(type) : type);

	TypePtr newStructType = transform::replaceAll(mgr, baseType, oldType, newType).as<TypePtr>();

	type = newStructType;
}
Exemplo n.º 5
0
	ExpressionPtr buildPtrFromIntegral(const ExpressionPtr& intExpr, const TypePtr& ptrType) {
		assert_pred1(intExpr->getNodeManager().getLangBasic().isInt, intExpr->getType()) << "Trying to build ptr from non-integral.";
		assert_pred1(isPointer, ptrType) << "Trying to build non-ptr-type from integral.";
		IRBuilder builder(intExpr->getNodeManager());
		auto& pExt = intExpr->getNodeManager().getLangExtension<PointerExtension>();
		return builder.callExpr(pExt.getPtrFromIntegral(), intExpr, builder.getTypeLiteral(ptrType));
	}
Exemplo n.º 6
0
	ExpressionPtr buildPtrSubscript(const ExpressionPtr& ptrExpr, const ExpressionPtr& subscriptExpr) {
		assert_pred1(isPointer, ptrExpr) << "Trying to build a ptr subscript from non-ptr.";
		assert_pred1(ptrExpr->getNodeManager().getLangBasic().isInt, subscriptExpr->getType()) << "Trying to build a ptr subscript with non-integral subscript.";
		IRBuilder builder(ptrExpr->getNodeManager());
		auto& pExt = ptrExpr->getNodeManager().getLangExtension<PointerExtension>();
		return builder.callExpr(pExt.getPtrSubscript(), ptrExpr, subscriptExpr);
	}
TypePtr ClosureExpression::inferTypes(AnalysisResultPtr ar, TypePtr type,
                                      bool coerce) {
  if (m_vars) {
    assert(m_values && m_values->getCount() == m_vars->getCount());

    // containing function's variable table (not closure function's)
    VariableTablePtr variables = getScope()->getVariables();

    // closure function's variable table
    VariableTablePtr cvariables = m_func->getFunctionScope()->getVariables();

    // force all reference use vars into variant for this function scope
    for (int i = 0; i < m_vars->getCount(); i++) {
      ParameterExpressionPtr param =
        dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
      const string &name = param->getName();
      if (param->isRef()) {
        variables->forceVariant(ar, name, VariableTable::AnyVars);
      }
    }

    // infer the types of the values
    m_values->inferAndCheck(ar, Type::Some, false);

    // coerce the types inferred from m_values into m_vars
    for (int i = 0; i < m_vars->getCount(); i++) {
      ExpressionPtr value = (*m_values)[i];
      ParameterExpressionPtr var =
        dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
      assert(!var->getExpectedType());
      assert(!var->getImplementedType());
      if (var->isRef()) {
        var->setActualType(Type::Variant);
      } else {
        TypePtr origVarType(var->getActualType() ?
                            var->getActualType() : Type::Some);
        var->setActualType(Type::Coerce(ar, origVarType, value->getType()));
      }
    }

    {
      // this lock isn't technically needed for thread-safety, since
      // the dependencies are all set up. however, the lock assertions
      // will fail if we don't acquire it.
      GET_LOCK(m_func->getFunctionScope());

      // bootstrap the closure function's variable table with
      // the types from m_vars
      for (int i = 0; i < m_vars->getCount(); i++) {
        ParameterExpressionPtr param =
          dynamic_pointer_cast<ParameterExpression>((*m_vars)[i]);
        const string &name = param->getName();
        cvariables->addParamLike(name, param->getType(), ar,
                                 shared_from_this(),
                                 getScope()->isFirstPass());
      }
    }
  }
  return s_ClosureType;
}
Exemplo n.º 8
0
ExpressionPtr Expression::replaceValue(ExpressionPtr rep) {
  if (hasContext(Expression::RefValue) &&
      isRefable(true) && !rep->isRefable(true)) {
    /*
      An assignment isRefable, but the rhs may not be. Need this to
      prevent "bad pass by reference" errors.
    */
    ExpressionListPtr el(new ExpressionList(getScope(), getRange(),
                                            ExpressionList::ListKindWrapped));
    el->addElement(rep);
    rep->clearContext(AssignmentRHS);
    rep = el;
  }
  if (rep->is(KindOfSimpleVariable) && !is(KindOfSimpleVariable)) {
    static_pointer_cast<SimpleVariable>(rep)->setAlwaysStash();
  }
  rep->copyContext(m_context & ~(DeadStore|AccessContext));
  if (TypePtr t1 = getType()) {
    if (TypePtr t2 = rep->getType()) {
      if (!Type::SameType(t1, t2)) {
        rep->setExpectedType(t1);
      }
    }
  }

  if (rep->getScope() != getScope()) {
    rep->resetScope(getScope());
  }

  return rep;
}
Exemplo n.º 9
0
	ExpressionPtr buildPtrFromArray(const ExpressionPtr& arrExpr) {
		assert_pred1(isReference, arrExpr) << "Trying to buildPtrFromArray from non-ref.";
		assert_pred1(isArray, core::analysis::getReferencedType(arrExpr->getType())) << "Trying to buildPtrFromArray from non-array.";
		IRBuilder builder(arrExpr->getNodeManager());
		auto& pExt = arrExpr->getNodeManager().getLangExtension<PointerExtension>();
		return builder.callExpr(pExt.getPtrFromArray(), arrExpr);
	}
Exemplo n.º 10
0
	ExpressionPtr buildPtrReinterpret(const ExpressionPtr& ptrExpr, const TypePtr& newElementType) {
		assert_pred1(core::lang::isPointer, ptrExpr) << "Trying to build a ptr reinterpret from non-ptr.";
		PointerType srcTy(ptrExpr->getType());
		// early exit if there is nothing to do
		if(srcTy.getElementType() == newElementType) return ptrExpr;
		// otherwise, build reinterpret
		IRBuilder builder(ptrExpr->getNodeManager());
		auto& pExt = ptrExpr->getNodeManager().getLangExtension<PointerExtension>();
		return builder.callExpr(pExt.getPtrReinterpret(), ptrExpr, builder.getTypeLiteral(newElementType));
	}
Exemplo n.º 11
0
	ExpressionPtr buildPtrCast(const ExpressionPtr& ptrExpr, bool newConst, bool newVolatile) {
		assert_pred1(core::lang::isPointer, ptrExpr) << "Trying to build a ptr cast from non-ptr.";
		PointerType srcTy(ptrExpr->getType());
		// early exit if there is nothing to do
		if(srcTy.isConst() == newConst && srcTy.isVolatile() == newVolatile) return ptrExpr;
		// otherwise, build cast
		IRBuilder builder(ptrExpr->getNodeManager());
		auto& pExt = ptrExpr->getNodeManager().getLangExtension<PointerExtension>();
		auto& bmExt = ptrExpr->getNodeManager().getLangExtension<BooleanMarkerExtension>();
		return builder.callExpr(pExt.getPtrCast(), ptrExpr, bmExt.getMarkerTypeLiteral(newConst), bmExt.getMarkerTypeLiteral(newVolatile));
	}
Exemplo n.º 12
0
void QOpExpression::wrapBoolean(CodeGenerator &cg,
                                AnalysisResultPtr ar,
                                ExpressionPtr exp) {
  TypePtr t(exp->getType());
  ASSERT(t);
  bool wrap = false;
  if (!t->is(Type::KindOfBoolean)) {
    wrap = true;
    cg_printf("toBoolean(");
  }
  exp->outputCPP(cg, ar);
  if (wrap) cg_printf(")");
}
Exemplo n.º 13
0
	ExpressionPtr buildPtrOperation(BasicGenerator::Operator op, const ExpressionPtr& ptrExpr) {
		assert_true(isReference(ptrExpr) && isPointer(core::analysis::getReferencedType(ptrExpr->getType())))
			<< "Trying to build a unary pointer operation with non-ref<ptr>.";
		IRBuilder builder(ptrExpr->getNodeManager());
		auto& pExt = ptrExpr->getNodeManager().getLangExtension<PointerExtension>();
		switch(op) {
		case BasicGenerator::Operator::PostInc: return builder.callExpr(pExt.getPtrPostInc(), ptrExpr);
		case BasicGenerator::Operator::PostDec: return builder.callExpr(pExt.getPtrPostDec(), ptrExpr);
		case BasicGenerator::Operator::PreInc: return builder.callExpr(pExt.getPtrPreInc(), ptrExpr);
		case BasicGenerator::Operator::PreDec: return builder.callExpr(pExt.getPtrPreDec(), ptrExpr);
		default: break;
		}

		assert_fail() << "Unsupported unary pointer operation " << op;
		return ExpressionPtr();
	}
Exemplo n.º 14
0
bool Expression::CheckNeededRHS(ExpressionPtr value) {
  bool needed = true;
  always_assert(value);
  while (value->is(KindOfAssignmentExpression)) {
    value = dynamic_pointer_cast<AssignmentExpression>(value)->getValue();
  }
  if (value->isScalar()) {
    needed = false;
  } else {
    TypePtr type = value->getType();
    if (type && (type->is(Type::KindOfSome) || type->is(Type::KindOfAny))) {
      type = value->getActualType();
    }
    if (type && type->isNoObjectInvolved()) needed = false;
  }
  return needed;
}
Exemplo n.º 15
0
void RefDict::updateParams() {
  ControlFlowGraph *g = m_am.graph();
  ControlBlock *b     = g->getDfBlock(1);

  BitOps::Bits *refbv = b->getRow(DataFlow::PRefIn);
  BitOps::Bits *objbv = b->getRow(DataFlow::PObjIn);

  for (int i = size(); i--; ) {
    if (ExpressionPtr e = get(i)) {
      always_assert(e->is(Expression::KindOfSimpleVariable));
      always_assert(((unsigned int)i) == e->getCanonID());
      Symbol *sym = static_pointer_cast<SimpleVariable>(e)->getSymbol();
      if (sym && (sym->isParameter() || sym->isClosureVar())) {
        TypePtr paramType;
        bool isRef;
        if (sym->isParameter()) {
          ExpressionListPtr methodParams = m_method_stmt->getParams();
          ExpressionPtr paramExprPtr =
              (*methodParams)[sym->getParameterIndex()];
          paramType = paramExprPtr->getType();
          isRef = m_method_stmt->isRef(sym->getParameterIndex());
        } else {
          assert(sym->isClosureVar());
          // can only assume it is a Variant for now
          paramType = Type::Variant;
          isRef = sym->isRefClosureVar();
        }
        if (first_pass) {
          if (isRef || sym->isCallTimeRef()) {
            BitOps::set_bit(i, refbv, true);
          }
        } else {
          if (paramType) {
            if (!paramType->isNoObjectInvolved()) {
              BitOps::set_bit(i, objbv, true);
            }
          } else {
            // no type information, so we must assume it holds an object
            BitOps::set_bit(i, objbv, true);
          }
        }
      }
    }
  }
}
Exemplo n.º 16
0
ExpressionPtr Function::execute (vector<ExpressionPtr> * params) {
    symbol::Table * table = symbol::Table::getInstance ();
    table->enterFunBlock (shared_from_this ());
    _ret.push_back (NullExpression ());

    if (_params != NULL) {
    	if (params == NULL || (params->size () != _params->size ())) {
    	    cout << "[!] Invalid parameters" << endl;
    	    throw -1;
    	}

    	for (int i = 0; i < params->size (); i++) {
    	    ParamPtr param = _params->at (i);
    	    ExpressionPtr value = params->at (i);
	    cout << "param  : "; value->print (cout); cout << endl;
    	    if (value->getType ()->value != param->getType ()->value) {
    		cout << "[!] Invalid param type !" << endl;
    		throw -1;
    	    }
    	    table->addSymbol (new symbol::Symbol (param->getVarId ()->getName (), value), param->getPos ());
    	}
    } else {
    	if (params != NULL) {
    	    cout << "[!] Invalid parameter." << endl;
    	    throw -1;
    	}
    }
    
    /* We interpret the content function while we don't meet a return statement */
    vector<InstructionPtr> * vec_inst = _content->getContent ();

    int i = 0;
    int vec_size = vec_inst->size ();
    while (i < vec_size && _ret.back () == NULL) {
    	(*vec_inst)[i]->interpret ();
    	i++;
    }

    table->exitFunBlock ();

    ExpressionPtr ret = _ret.back ();
    _ret.pop_back ();

    return ret;
}
Exemplo n.º 17
0
static bool checkCopyElision(FunctionScopePtr func, ExpressionPtr exp) {
  if (!exp->getType()->is(Type::KindOfVariant) || func->isRefReturn()) {
    return false;
  }

  TypePtr imp = exp->getImplementedType();
  if (!imp) imp = exp->getActualType();
  if (!imp || !imp->is(Type::KindOfVariant)) return false;

  if (func->getNRVOFix() && exp->is(Expression::KindOfSimpleVariable)) {
    return true;
  }

  if (FunctionCallPtr fc = dynamic_pointer_cast<FunctionCall>(exp)) {
    FunctionScopePtr fs = fc->getFuncScope();
    if (!fs || fs->isRefReturn()) {
      return true;
    }
  }

  return false;
}
Exemplo n.º 18
0
ExpressionPtr KernelReplacer::handleArgument(const TypePtr& argTy, const TypePtr& memberTy, const ExpressionPtr& tupleMemberAccess, StatementList& body) {
	NodeManager& mgr = argTy->getNodeManager();
	IRBuilder builder(mgr);
	const core::lang::BasicGenerator& gen = builder.getLangBasic();

	ExpressionPtr argument;
	// check for local memory arguments
	if(*memberTy == *gen.getUInt8()) {
		argument = tupleMemberAccess;
	} else {

		argument = builder.callExpr(gen.getArrayRefElem1D(), tupleMemberAccess, builder.castExpr(gen.getUInt8(), builder.intLit(0)));


		TypePtr refArtTy = builder.refType(argTy);
		if(!types::isSubTypeOf(argument->getType(), refArtTy)) {// e.g. argument of kernel is an ocl vector type

			argument = builder.callExpr(refArtTy, gen.getRefReinterpret(), argument, builder.getTypeLiteral(argTy));
		}
		argument = utils::tryDeref(argument);
	}
	return argument;
}
Exemplo n.º 19
0
static void outputStringExpr(CodeGenerator &cg, AnalysisResultPtr ar,
                             ExpressionPtr exp, bool asLitStr) {
  if (asLitStr && exp->isLiteralString()) {
    const std::string &s = exp->getLiteralString();
    char *enc = string_cplus_escape(s.c_str(), s.size());
    cg_printf("\"%s\", %d", enc, s.size());
    free(enc);
    return;
  }

  bool close = false;
  if ((exp->hasContext(Expression::LValue) &&
       (!exp->getActualType()->is(Type::KindOfString) ||
        (exp->getImplementedType() &&
         !exp->getImplementedType()->is(Type::KindOfString))))
      ||
      !exp->getType()->is(Type::KindOfString)) {
    cg_printf("toString(");
    close = true;
  }
  exp->outputCPP(cg, ar);
  if (close) cg_printf(")");
}
Exemplo n.º 20
0
void SemanticAnalyzer::visitValueBinding(const ValueBindingPtr& node)
{
    PatternPtr name = node->getName();
    //tuple was already exploded in declaration analyzer
    if(name->getNodeType() == NodeType::Tuple)
    {
        validateTupleTypeDeclaration(node);
    }
    if (name->getNodeType() != NodeType::Identifier)
        return;
    if(node->getOwner()->isReadOnly() && !node->getInitializer() && ctx->currentType == nullptr)
    {
        error(node, Errors::E_LET_REQUIRES_INITIALIZER);
        return;
    }
    //handle type inference for temporary variable
    if(node->isTemporary() && node->getInitializer())
    {
        //temporary variable always has an initializer
        TypePtr initializerType;
        TypePtr declaredType = node->getType();

        SCOPED_SET(ctx->contextualType, declaredType);
        node->getInitializer()->accept(this);
        initializerType = node->getInitializer()->getType();
        assert(initializerType != nullptr);

        if(declaredType)
        {
            //it has both type definition and initializer, then we need to check if the initializer expression matches the type annotation
            if(!initializerType->canAssignTo(declaredType))
            {
                error(node, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, initializerType->toString(), declaredType->toString());
                return;
            }
        }
        else
        {
            node->setType(initializerType);
        }
    }
    

    //add implicitly constructor for Optional
    IdentifierPtr id = static_pointer_cast<Identifier>(node->getName());
    SymbolScope* currentScope = symbolRegistry->getCurrentScope();


    TypePtr declaredType = node->getType() ? node->getType() : lookupType(node->getDeclaredType());
    SCOPED_SET(ctx->contextualType, declaredType);
    if(!declaredType && !node->getInitializer())
    {
        error(node, Errors::E_TYPE_ANNOTATION_MISSING_IN_PATTERN);
        return;
    }
    SymbolPtr sym = currentScope->lookup(id->getIdentifier());
    assert(sym != nullptr);
    SymbolPlaceHolderPtr placeholder = std::dynamic_pointer_cast<SymbolPlaceHolder>(sym);
    assert(placeholder != nullptr);
    if(declaredType)
    {
        placeholder->setType(declaredType);
    }
    ExpressionPtr initializer = node->getInitializer();
    if(initializer)
    {
        placeholder->setFlags(SymbolFlagInitializing, true);
        ExpressionPtr initializer = transformExpression(declaredType, node->getInitializer());
        node->setInitializer(initializer);
        TypePtr actualType = initializer->getType();
        assert(actualType != nullptr);
        if(declaredType)
        {
            if(!Type::equals(actualType, declaredType) && !canConvertTo(initializer, declaredType))
            {
                error(initializer, Errors::E_CANNOT_CONVERT_EXPRESSION_TYPE_2, actualType->toString(), declaredType->toString());
                return;
            }
        }

        if(!declaredType)
            placeholder->setType(actualType);
    }
    assert(placeholder->getType() != nullptr);
    placeholder->setFlags(SymbolFlagInitializing, false);
    //optional type always considered initialized, compiler will make it has a default value nil
    TypePtr symbolType = sym->getType();
    GlobalScope* global = symbolRegistry->getGlobalScope();
    if(initializer || global->isOptional(symbolType) || global->isImplicitlyUnwrappedOptional(symbolType))
        markInitialized(placeholder);

    if (initializer)
        placeholder->setFlags(SymbolFlagHasInitializer, true);
    if(node->isTemporary())
    {
        placeholder->setFlags(SymbolFlagTemporary, true);
        markInitialized(placeholder);
    }

    if(!node->isTemporary())
    {
        //check access control level
        DeclarationType decl = ctx->currentType ? DeclarationTypeProperty : DeclarationTypeVariable;
        declarationAnalyzer->verifyAccessLevel(node->getOwner(), placeholder->getType(), decl, ComponentTypeType);
    }
    if(ctx->currentType && ctx->currentType->getCategory() == Type::Protocol)
    {
        error(node, Errors::E_PROTOCOL_VAR_MUST_BE_COMPUTED_PROPERTY_1);
    }
}
void DeclarationAnalyzer::visitEnum(const EnumDefPtr& node)
{
    TypeBuilderPtr type = static_pointer_cast<TypeBuilder>(defineType(node));
    SCOPED_SET(ctx->currentType, type);

    GlobalScope* global = symbolRegistry->getGlobalScope();
    SymbolScope* local = symbolRegistry->getCurrentScope();
    //check if it's raw value enum
    bool isRawValues = false;
    if(node->numParents() > 0)
    {
        TypePtr firstParent = lookupType(node->getParent(0));
        if(firstParent)
        {
            Type::Category  category = firstParent->getCategory();
            isRawValues = category == Type::Struct || category == Type::Enum || category == Type::Aggregate || category == Type::Class;
            if(isRawValues)
                type->setParentType(firstParent);
        }
    }

    //initialize enum's cases
    if(isRawValues)
    {
        if(!node->numCases())
        {
            error(node, Errors::E_ENUM_WITH_NO_CASES_CANNOT_DECLARE_A_RAW_TYPE);
            return;
        }
        //Add RawRepresentable protocol if it's not implemented
        if(!type->canAssignTo(global->RawRepresentable()))
        {
            makeRawRepresentable(type, global);
        }

        TypePtr rawType = type->getParentType();
        assert(rawType != nullptr);
        bool integerConvertible = rawType->canAssignTo(global->IntegerLiteralConvertible());
        for(auto c : node->getCases())
        {
            if(!c.value && !integerConvertible)
            {
                //Enum cases require explicit raw values when the raw type is not integer literal convertible
                error(node, Errors::E_ENUM_CASES_REQUIRE_EXPLICIT_RAW_VALUES_WHEN_THE_RAW_TYPE_IS_NOT_INTEGER_LITERAL_CONVERTIBLE);
                return;
            }
            if(c.value)
            {
                if(dynamic_pointer_cast<TupleType>(c.value))
                {
                    error(node, Errors::E_ENUM_WITH_RAW_TYPE_CANNOT_HAVE_CASES_WITH_ARGUMENTS);
                    return;
                }
                ExpressionPtr initializer = dynamic_pointer_cast<Expression>(c.value);
                assert(initializer != nullptr);
                if(!isLiteralExpression(initializer))
                {
                    error(node, Errors::E_RAW_VALUE_FOR_ENUM_CASE_MUST_BE_LITERAL);
                    return;
                }

                SCOPED_SET(ctx->contextualType, rawType);
                initializer->accept(semanticAnalyzer);
                TypePtr caseType = initializer->getType();
                assert(caseType != nullptr);
                if(!caseType->canAssignTo(rawType))
                {
                    error(node, Errors::E_A_IS_NOT_CONVERTIBLE_TO_B_2, caseType->toString(), rawType->toString());
                    return;
                }
            }
            type->addEnumCase(c.name, global->Void());
            //register it to scope
            local->addSymbol(SymbolPlaceHolderPtr(new SymbolPlaceHolder(c.name, type, SymbolPlaceHolder::R_PARAMETER, SymbolFlagReadable | SymbolFlagMember | SymbolFlagStatic | SymbolFlagInitialized)));
        }
    }
    else
    {
        //it's an associated-values enum
        for(auto c : node->getCases())
        {
            TypePtr associatedType = global->Void();
            if(c.value)
            {
                TypeNodePtr typeNode = dynamic_pointer_cast<TypeNode>(c.value);
                if(!typeNode)
                {
                    error(node, Errors::E_ENUM_CASE_CANNOT_HAVE_A_RAW_VALUE_IF_THE_ENUM_DOES_NOT_HAVE_A_RAW_TYPE);
                    return;
                }
                assert(typeNode != nullptr);
                associatedType = lookupType(typeNode);
            }
            type->addEnumCase(c.name, associatedType);
            if(associatedType == global->Void())
                local->addSymbol(SymbolPlaceHolderPtr(new SymbolPlaceHolder(c.name, type, SymbolPlaceHolder::R_PARAMETER, SymbolFlagReadable | SymbolFlagMember | SymbolFlagStatic | SymbolFlagInitialized)));
        }
    }
    //check member declaration of enum
    {
        SCOPED_SET(ctx->flags, (ctx->flags & (~SemanticContext::FLAG_PROCESS_IMPLEMENTATION)) | SemanticContext::FLAG_PROCESS_DECLARATION);
        for (const DeclarationPtr &decl : *node)
        {
            bool isStatic = decl->hasModifier(DeclarationModifiers::Class) || decl->hasModifier(DeclarationModifiers::Static);
            if (!isStatic && (decl->getNodeType() == NodeType::ValueBindings))
            {
                error(node, Errors::E_ENUMS_MAY_NOT_CONTAIN_STORED_PROPERTIES);
                continue;
            }
            decl->accept(semanticAnalyzer);
        }
        //add a default initializer for raw value enum
        if(isRawValues)
        {
            vector<Parameter> params = {Parameter(L"rawValue", false, type->getParentType())};
            TypePtr initType = Type::newFunction(params, global->Void(), false, nullptr);
            initType->setFlags(SymbolFlagAllocatingInit, true);
            static_pointer_cast<TypeBuilder>(initType)->setDeclaringType(type);
            initType->setFlags(SymbolFlagInit | SymbolFlagFailableInitializer | SymbolFlagMember | SymbolFlagAllocatingInit);
            FunctionSymbolPtr init(new FunctionSymbol(L"init", initType, FunctionRoleInit, nullptr));
            declarationFinished(init->getName(), init, nullptr);
        }
    }
    if(type->getParentType() != nullptr)
        verifyAccessLevel(node, type->getParentType(), D_ENUM, C_RAW_TYPE);
    validateDeclarationModifiers(node);
    visitImplementation(node);
}
Exemplo n.º 22
0
NegateExpr::NegateExpr(ExpressionPtr expr) {
	m_expr = expr;
	setType(expr->getType());
}
Exemplo n.º 23
0
bool ExpressionList::preOutputCPP(CodeGenerator &cg, AnalysisResultPtr ar,
                                  int state) {
  if (m_kind == ListKindParam && !m_arrayElements) {
    return Expression::preOutputCPP(cg, ar, state|StashKidVars);
  }

  unsigned n = m_exps.size();
  bool inExpression = cg.inExpression();
  if (!inExpression && (state & FixOrder)) {
    return true;
  }

  cg.setInExpression(false);
  bool ret = false;
  if (m_arrayElements) {
    /*
     * would like to do:
     *  ret = Expression::preOutputCPP(cg, ar, state);
     * but icc has problems with the generated code.
     */
    ret = hasEffect();
  } else if (n > 1 && m_kind == ListKindLeft) {
    ret = true;
  } else {
    for (unsigned int i = 0; i < n; i++) {
      if (m_exps[i]->preOutputCPP(cg, ar, 0)) {
        ret = true;
        break;
      }
    }
  }

  if (!inExpression) return ret;

  cg.setInExpression(true);
  if (!ret) {
    if (state & FixOrder) {
      preOutputStash(cg, ar, state);
      return true;
    }
    return false;
  }

  cg.wrapExpressionBegin();
  if (m_arrayElements) {
    setCPPTemp(genCPPTemp(cg, ar));
    outputCPPInternal(cg, ar, true, true);
  } else {
    unsigned ix = m_kind == ListKindLeft ? 0 : n - 1;
    for (unsigned int i = 0; i < n; i++) {
      ExpressionPtr e = m_exps[i];
      e->preOutputCPP(cg, ar, i == ix ? state : 0);
      if (i != ix) {
        if (e->outputCPPUnneeded(cg, ar)) {
          cg_printf(";\n");
        }
        e->setCPPTemp("/**/");
      } else if (e->hasCPPTemp() && Type::SameType(e->getType(), getType())) {
        setCPPTemp(e->cppTemp());
      } else if (!i && n > 1) {
        e->Expression::preOutputStash(cg, ar, state | FixOrder);
        if (!(state & FixOrder)) {
          cg_printf("id(%s);\n", e->cppTemp().c_str());
        }
        setCPPTemp(e->cppTemp());
      }
    }
  }
  return true;
}
Exemplo n.º 24
0
void BinaryOpExpression::outputCPPImpl(CodeGenerator &cg,
                                       AnalysisResultPtr ar) {

    if (isOpEqual() && outputCPPImplOpEqual(cg, ar)) return;

    bool wrapped = true;
    switch (m_op) {
    case T_CONCAT_EQUAL:
        if (const char *prefix = stringBufferPrefix(cg, ar, m_exp1)) {
            SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(m_exp1);
            ExpressionPtrVec ev;
            bool hasVoid = false;
            getConcatList(ev, m_exp2, hasVoid);
            cg_printf("%s", stringBufferName(Option::TempPrefix, prefix,
                                             sv->getName().c_str()).c_str());
            outputStringBufExprs(ev, cg, ar);
            return;
        }
        cg_printf("concat_assign");
        break;
    case '.':
    {
        ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this());
        ExpressionPtrVec ev;
        bool hasVoid = false;
        int num = getConcatList(ev, self, hasVoid);
        assert(!hasVoid);
        if (num <= MAX_CONCAT_ARGS) {
            assert(num >= 2);
            if (num == 2) {
                cg_printf("concat(");
            } else {
                if (num > MAX_CONCAT_ARGS) ar->m_concatLengths.insert(num);
                cg_printf("concat%d(", num);
            }
            for (size_t i = 0; i < ev.size(); i++) {
                ExpressionPtr exp = ev[i];
                if (i) cg_printf(", ");
                outputStringExpr(cg, ar, exp, false);
            }
            cg_printf(")");
        } else {
            cg_printf("StringBuffer()");
            outputStringBufExprs(ev, cg, ar);
            cg_printf(".detach()");
        }
    }
    return;
    case T_LOGICAL_XOR:
        cg_printf("logical_xor");
        break;
    case '|':
        cg_printf("bitwise_or");
        break;
    case '&':
        cg_printf("bitwise_and");
        break;
    case '^':
        cg_printf("bitwise_xor");
        break;
    case T_IS_IDENTICAL:
        cg_printf("same");
        break;
    case T_IS_NOT_IDENTICAL:
        cg_printf("!same");
        break;
    case T_IS_EQUAL:
        cg_printf("equal");
        break;
    case T_IS_NOT_EQUAL:
        cg_printf("!equal");
        break;
    case '<':
        cg_printf("less");
        break;
    case T_IS_SMALLER_OR_EQUAL:
        cg_printf("not_more");
        break;
    case '>':
        cg_printf("more");
        break;
    case T_IS_GREATER_OR_EQUAL:
        cg_printf("not_less");
        break;
    case '/':
        cg_printf("divide");
        break;
    case '%':
        cg_printf("modulo");
        break;
    case T_INSTANCEOF:
        cg_printf("instanceOf");
        break;
    default:
        wrapped = !isUnused();
        break;
    }

    if (wrapped) cg_printf("(");

    ExpressionPtr first = m_exp1;
    ExpressionPtr second = m_exp2;

    // we could implement these functions natively on String and Array classes
    switch (m_op) {
    case '+':
    case '-':
    case '*':
    case '/':
        if (!first->outputCPPArithArg(cg, ar, m_op == '+')) {
            TypePtr argType = first->hasCPPTemp() ?
                              first->getType() : first->getActualType();
            bool flag = castIfNeeded(getActualType(), argType, cg, ar, getScope());
            first->outputCPP(cg, ar);
            if (flag) {
                cg_printf(")");
            }
        }
        break;
    case T_SL:
    case T_SR:
        ASSERT(first->getType()->is(Type::KindOfInt64));
        first->outputCPP(cg, ar);
        break;
    default:
        first->outputCPP(cg, ar);
        break;
    }

    switch (m_op) {
    case T_PLUS_EQUAL:
        cg_printf(" += ");
        break;
    case T_MINUS_EQUAL:
        cg_printf(" -= ");
        break;
    case T_MUL_EQUAL:
        cg_printf(" *= ");
        break;
    case T_DIV_EQUAL:
        cg_printf(" /= ");
        break;
    case T_MOD_EQUAL:
        cg_printf(" %%= ");
        break;
    case T_AND_EQUAL:
        cg_printf(" &= ");
        break;
    case T_OR_EQUAL:
        cg_printf(" |= ");
        break;
    case T_XOR_EQUAL:
        cg_printf(" ^= ");
        break;
    case T_SL_EQUAL:
        cg_printf(" <<= ");
        break;
    case T_SR_EQUAL:
        cg_printf(" >>= ");
        break;
    case T_BOOLEAN_OR:
        cg_printf(" || ");
        break;
    case T_BOOLEAN_AND:
        cg_printf(" && ");
        break;
    case T_LOGICAL_OR:
        cg_printf(" || ");
        break;
    case T_LOGICAL_AND:
        cg_printf(" && ");
        break;
    default:
        switch (m_op) {
        case '+':
            cg_printf(" + ");
            break;
        case '-':
            cg_printf(" - ");
            break;
        case '*':
            cg_printf(" * ");
            break;
        case T_SL:
            cg_printf(" << ");
            break;
        case T_SR:
            cg_printf(" >> ");
            break;
        default:
            cg_printf(", ");
            break;
        }
        break;
    }

    switch (m_op) {
    case '+':
    case '-':
    case '*':
    case '/':
        if (!second->outputCPPArithArg(cg, ar, m_op == '+')) {
            TypePtr argType = second->hasCPPTemp() ?
                              second->getType() : second->getActualType();
            bool flag = castIfNeeded(getActualType(), argType, cg, ar, getScope());
            second->outputCPP(cg, ar);
            if (flag) {
                cg_printf(")");
            }
        }
        break;
    case T_INSTANCEOF:
    {
        if (second->isScalar()) {
            ScalarExpressionPtr scalar =
                dynamic_pointer_cast<ScalarExpression>(second);
            bool notQuoted = scalar && !scalar->isQuoted();
            std::string s = second->getLiteralString();
            if (s == "static" && notQuoted) {
                cg_printf("FrameInjection::GetStaticClassName(fi.getThreadInfo())");
            } else if (s != "") {
                if (s == "self" && notQuoted) {
                    ClassScopeRawPtr cls = getOriginalClass();
                    if (cls) {
                        s = cls->getOriginalName();
                    }
                } else if (s == "parent" && notQuoted) {
                    ClassScopeRawPtr cls = getOriginalClass();
                    if (cls && !cls->getParent().empty()) {
                        s = cls->getParent();
                    }
                }
                cg_printString(s, ar, shared_from_this());
            } else {
                second->outputCPP(cg, ar);
            }
        } else {
            second->outputCPP(cg, ar);
        }
        break;
    }
    case T_PLUS_EQUAL:
    case T_MINUS_EQUAL:
    case T_MUL_EQUAL:
    {
        TypePtr t1 = first->getCPPType();
        TypePtr t2 = second->getType();
        if (t1 && !t1->is(Type::KindOfArray) &&
                t2 && Type::IsCastNeeded(ar, t2, t1)) {
            t1->outputCPPCast(cg, ar, getScope());
            cg_printf("(");
            second->outputCPP(cg, ar);
            cg_printf(")");
        } else {
            second->outputCPP(cg, ar);
        }
        break;
    }
    case T_BOOLEAN_OR:
    case T_BOOLEAN_AND:
    case T_LOGICAL_AND:
    case T_LOGICAL_OR:
        if (isUnused()) {
            cg_printf("(");
            if (second->outputCPPUnneeded(cg, ar)) {
                cg_printf(",");
            }
            cg_printf("false)");
        } else {
            second->outputCPP(cg, ar);
        }
        break;
    default:
        second->outputCPP(cg, ar);
    }

    if (wrapped) cg_printf(")");
}
Exemplo n.º 25
0
	ExpressionPtr buildPtrOperation(BasicGenerator::Operator op, const ExpressionPtr& lhs, const ExpressionPtr& rhs) {
		auto& basic = lhs->getNodeManager().getLangBasic();
		auto& pExt = lhs->getNodeManager().getLangExtension<PointerExtension>();
		IRBuilder builder(lhs->getNodeManager());

		auto assertPtr = [&](const ExpressionPtr& exp) {
			assert_pred1(isPointer, exp) << "Trying to build a ptr operation from non-ptr:"
				<< "\n lhs: " << *lhs << "\n  - of type: " << *lhs->getType() 
				<< "\n rhs: " << *rhs << "\n  - of type: " << *rhs->getType()
				<< "\n op: " << op;
		};
		auto assertInt = [&](const ExpressionPtr& exp) {
			assert_pred1(basic.isInt, exp->getType()) << "Trying to build a ptr add/sub with non-int"
				<< "\n lhs: " << *lhs << "\n  - of type: " << *lhs->getType() 
				<< "\n rhs: " << *rhs << "\n  - of type: " << *rhs->getType()
				<< "\n op: " << op;
		};
		auto buildInt8Cast = [&](const ExpressionPtr& exp) {
			if(!core::types::isSubTypeOf(exp->getType(), basic.getInt8())) {
				return builder.numericCast(exp, basic.getInt8());
			}
			return exp;
		};

		// arithmetic operations
		switch(op) {
		case BasicGenerator::Operator::Add: {
			if(!isPointer(lhs)) {
				assertPtr(rhs);
				assertInt(lhs);
				return builder.callExpr(pExt.getPtrAdd(), rhs, buildInt8Cast(lhs));
			}
			assertPtr(lhs);
			assertInt(rhs);
			return builder.callExpr(pExt.getPtrAdd(), lhs, buildInt8Cast(rhs));
		}
		case BasicGenerator::Operator::Sub: { // minus is only supported with ptr on the lhs
			assertPtr(lhs);
			if(!isPointer(rhs)) {
				assertInt(rhs);
				return builder.callExpr(pExt.getPtrSub(), lhs, buildInt8Cast(rhs));
			} else {
				return builder.callExpr(pExt.getPtrDiff(), lhs, rhs);
			}
		}
		default: break;
		}

		// comparison operations
		assertPtr(lhs);
		assertPtr(rhs);
		switch(op) {
		case BasicGenerator::Operator::Eq: return builder.callExpr(pExt.getPtrEqual(), lhs, rhs);
		case BasicGenerator::Operator::Ne: return builder.callExpr(pExt.getPtrNotEqual(), lhs, rhs);
		case BasicGenerator::Operator::Le: return builder.callExpr(pExt.getPtrLessEqual(), lhs, rhs);
		case BasicGenerator::Operator::Lt: return builder.callExpr(pExt.getPtrLessThan(), lhs, rhs);
		case BasicGenerator::Operator::Ge: return builder.callExpr(pExt.getPtrGreaterEqual(), lhs, rhs);
		case BasicGenerator::Operator::Gt: return builder.callExpr(pExt.getPtrGreaterThan(), lhs, rhs);
		default: break;
		}

		assert_fail() << "Unsupported binary pointer operation " << op;
		return ExpressionPtr();
	}
Exemplo n.º 26
0
	DataPath DataPath::element(const ExpressionPtr& element) const {
		auto& mgr = path.getNodeManager();
		auto& ext = mgr.getLangExtension<lang::DatapathExtension>();
		assert_true(mgr.getLangBasic().isSignedInt(element->getType())) << "Index has to be a signed integer!";
		return DataPath(IRBuilder(mgr).callExpr(ext.getDataPathElement(), path, element));
	}
Exemplo n.º 27
0
void BinaryOpExpression::outputCPPImpl(CodeGenerator &cg,
                                       AnalysisResultPtr ar) {

  if (isOpEqual() && outputCPPImplOpEqual(cg, ar)) return;

  bool wrapped = true;
  switch (m_op) {
  case T_CONCAT_EQUAL:
    if (const char *prefix = stringBufferPrefix(cg, ar, m_exp1)) {
      SimpleVariablePtr sv = static_pointer_cast<SimpleVariable>(m_exp1);
      ExpressionPtrVec ev;
      bool hasVoid = false;
      getConcatList(ev, m_exp2, hasVoid);
      cg_printf("%s", stringBufferName(Option::TempPrefix, prefix,
                                       sv->getName().c_str()).c_str());
      outputStringBufExprs(ev, cg, ar);
      return;
    }
    cg_printf("concat_assign");
    break;
  case '.':
    {
      ExpressionPtr self = static_pointer_cast<Expression>(shared_from_this());
      ExpressionPtrVec ev;
      bool hasVoid = false;
      int num = getConcatList(ev, self, hasVoid);
      assert(!hasVoid);
      if ((num <= MAX_CONCAT_ARGS ||
           (Option::GenConcat &&
            cg.getOutput() != CodeGenerator::SystemCPP))) {
        assert(num >= 2);
        if (num == 2) {
          cg_printf("concat(");
        } else {
          if (num > MAX_CONCAT_ARGS) ar->m_concatLengths.insert(num);
          cg_printf("concat%d(", num);
        }
        for (size_t i = 0; i < ev.size(); i++) {
          ExpressionPtr exp = ev[i];
          if (i) cg_printf(", ");
          outputStringExpr(cg, ar, exp, false);
        }
        cg_printf(")");
      } else {
        cg_printf("StringBuffer()");
        outputStringBufExprs(ev, cg, ar);
        cg_printf(".detach()");
      }
    }
    return;
  case T_LOGICAL_XOR:         cg_printf("logical_xor");   break;
  case '|':                   cg_printf("bitwise_or");    break;
  case '&':                   cg_printf("bitwise_and");   break;
  case '^':                   cg_printf("bitwise_xor");   break;
  case T_IS_IDENTICAL:        cg_printf("same");          break;
  case T_IS_NOT_IDENTICAL:    cg_printf("!same");         break;
  case T_IS_EQUAL:            cg_printf("equal");         break;
  case T_IS_NOT_EQUAL:        cg_printf("!equal");        break;
  case '<':                   cg_printf("less");          break;
  case T_IS_SMALLER_OR_EQUAL: cg_printf("not_more");      break;
  case '>':                   cg_printf("more");          break;
  case T_IS_GREATER_OR_EQUAL: cg_printf("not_less");      break;
  case '/':                   cg_printf("divide");        break;
  case '%':                   cg_printf("modulo");        break;
  case T_INSTANCEOF:          cg_printf("instanceOf");    break;
  default:
    wrapped = !isUnused();
    break;
  }

  if (wrapped) cg_printf("(");

  ExpressionPtr first = m_exp1;
  ExpressionPtr second = m_exp2;

  // we could implement these functions natively on String and Array classes
  switch (m_op) {
  case '+':
  case '-':
  case '*':
  case '/': {
    TypePtr actualType = first->getActualType();

    if (actualType &&
        (actualType->is(Type::KindOfString) ||
         (m_op != '+' && actualType->is(Type::KindOfArray)))) {
      cg_printf("(Variant)(");
      first->outputCPP(cg, ar);
      cg_printf(")");
    } else {
      bool flag = castIfNeeded(getActualType(), actualType, cg, ar, getScope());
      first->outputCPP(cg, ar);
      if (flag) {
        cg_printf(")");
      }
    }
    break;
  }
  case T_SL:
  case T_SR:
    cg_printf("toInt64(");
    first->outputCPP(cg, ar);
    cg_printf(")");
    break;
  default:
    first->outputCPP(cg, ar);
    break;
  }

  switch (m_op) {
  case T_PLUS_EQUAL:          cg_printf(" += ");   break;
  case T_MINUS_EQUAL:         cg_printf(" -= ");   break;
  case T_MUL_EQUAL:           cg_printf(" *= ");   break;
  case T_DIV_EQUAL:           cg_printf(" /= ");   break;
  case T_MOD_EQUAL:           cg_printf(" %%= ");  break;
  case T_AND_EQUAL:           cg_printf(" &= ");   break;
  case T_OR_EQUAL:            cg_printf(" |= ");   break;
  case T_XOR_EQUAL:           cg_printf(" ^= ");   break;
  case T_SL_EQUAL:            cg_printf(" <<= ");  break;
  case T_SR_EQUAL:            cg_printf(" >>= ");  break;
  case T_BOOLEAN_OR:          cg_printf(" || ");   break;
  case T_BOOLEAN_AND:         cg_printf(" && ");   break;
  case T_LOGICAL_OR:          cg_printf(" || ");   break;
  case T_LOGICAL_AND:         cg_printf(" && ");   break;
  default:
    switch (m_op) {
    case '+':                   cg_printf(" + ");    break;
    case '-':                   cg_printf(" - ");    break;
    case '*':                   cg_printf(" * ");    break;
    case T_SL:                  cg_printf(" << ");   break;
    case T_SR:                  cg_printf(" >> ");   break;
    default:
      cg_printf(", ");
      break;
    }
    break;
  }

  switch (m_op) {
  case '+':
  case '-':
  case '*':
  case '/': {
    TypePtr actualType = second->getActualType();

    if (actualType &&
        (actualType->is(Type::KindOfString) ||
         (m_op != '+' && actualType->is(Type::KindOfArray)))) {
      cg_printf("(Variant)(");
      second->outputCPP(cg, ar);
      cg_printf(")");
    } else {
      bool flag = castIfNeeded(getActualType(), actualType, cg, ar, getScope());
      second->outputCPP(cg, ar);
      if (flag) {
        cg_printf(")");
      }
    }
    break;
  }
  case T_INSTANCEOF:
    {
      if (second->isScalar()) {
        std::string s = second->getLiteralString();
        std::string sLower = Util::toLower(s);
        if (sLower != "") {
          cg_printString(sLower, ar, shared_from_this());
        } else {
          second->outputCPP(cg, ar);
        }
      } else {
        second->outputCPP(cg, ar);
      }
      break;
    }
  case T_PLUS_EQUAL:
  case T_MINUS_EQUAL:
  case T_MUL_EQUAL:
    {
      TypePtr t1 = first->getCPPType();
      TypePtr t2 = second->getType();
      if (t1 && !t1->is(Type::KindOfArray) &&
          t2 && Type::IsCastNeeded(ar, t2, t1)) {
        t1->outputCPPCast(cg, ar, getScope());
        cg_printf("(");
        second->outputCPP(cg, ar);
        cg_printf(")");
      } else {
        second->outputCPP(cg, ar);
      }
      break;
    }
  case T_BOOLEAN_OR:
  case T_BOOLEAN_AND:
  case T_LOGICAL_AND:
  case T_LOGICAL_OR:
    if (isUnused()) {
      cg_printf("(");
      if (second->outputCPPUnneeded(cg, ar)) {
        cg_printf(",");
      }
      cg_printf("false)");
    } else {
      second->outputCPP(cg, ar);
    }
    break;
  default:
    second->outputCPP(cg, ar);
  }

  if (wrapped) cg_printf(")");
}