void ExportPass::AddSymbols()
{
  assert(repository != NULL) ;
  assert(constructedType != NULL) ;
  assert(constructedSymbol != NULL) ;

  // By this point, the repository has been read in and the symbol table
  //  has been completely overwritten.

  SymbolTable* symTab = repository->get_external_symbol_table() ;
  assert(symTab != NULL) ;

  DataType* resultType = constructedType->get_result_type() ;
  bool resultReplaced = false ;
  for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j)
  {
    DataType* existingType = 
      dynamic_cast<DataType*>(symTab->get_symbol_table_object(j)) ;
    if (existingType != NULL && EquivalentTypes(resultType, existingType))
    {
      constructedType->set_result_type(existingType) ;
      resultReplaced = true ;
      delete resultType ;
      break ;
    }
  }
  if (!resultReplaced)
  {
    symTab->append_symbol_table_object(resultType) ;
  }
  
  // Go through all of the arguments and replace them with appropriate types
  //  if they already exist in the symbol table.
  for (int i = 0 ; i < constructedType->get_argument_count() ; ++i)
  {
    QualifiedType* currentArg = constructedType->get_argument(i) ;
    assert(currentArg != NULL) ;
    bool replaced = false ;
    for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j)
    {
      QualifiedType* existingType = 
	dynamic_cast<QualifiedType*>(symTab->get_symbol_table_object(j)) ;
      if (existingType != NULL && EquivalentTypes(currentArg, existingType) &&
	  existingType->get_annote_count() == currentArg->get_annote_count())
      {
	constructedType->replace_argument(i, existingType) ;
	replaced = true ;
	break ;
      }
    }    
    if (replaced == false)
    {
      symTab->append_symbol_table_object(currentArg) ;
      symTab->append_symbol_table_object(currentArg->get_base_type()) ;
    }
  }

  symTab->append_symbol_table_object(constructedType) ;
  symTab->append_symbol_table_object(constructedSymbol) ;
}
Exemple #2
0
bool SpCandidate::isMoreSpecific(const SpCandidate * other) const {
  const Template * tm = def_->templateSignature();
  const Template * otm = other->def_->templateSignature();

  if (tm->typeParams()->size() != otm->typeParams()->size()) {
    return false;
  }

  bool same = true;
  size_t numParams = tm->typeParams()->size();
  for (size_t i = 0; i < numParams; ++i) {
    QualifiedType param = tm->typeParam(i);
    QualifiedType oparam = otm->typeParam(i);

    if (!TypeRelation::isEqual(param, oparam)) {
      same = false;
      if (!TypeRelation::isSubtype(param, oparam)) {
        if (oparam->typeClass() != Type::TypeVar) {
          return false;
        }

        // TODO: CanBind check here...
      }
    }
  }

  if (same) {
    // TODO A temporary kludge.
    if (!def_->hasUnboundTypeParams() && other->def_->hasUnboundTypeParams()) {
      return true;
    }
  }

  return !same;
}
Exemple #3
0
static QualifiedType
returnInfoFirstDeref(CallExpr* call) {
  QualifiedType tmp = call->get(1)->qualType();
  Type* type = tmp.type()->getValType();
  // if it's a tuple, also remove references in the elements
  if (type->symbol->hasFlag(FLAG_TUPLE)) {
    type = computeNonRefTuple(type);
  }
  return QualifiedType(type, QUAL_VAL);
}
QualifiedType AmbiguousTypeParamType::forType(QualifiedType base, const Type * match,
    unsigned paramIndex) {
  base = dealias(base);
  match = dealias(match);
  switch (base->typeClass()) {
    case Type::Class:
    case Type::Struct:
    case Type::Interface:
    case Type::Protocol: {
      const CompositeType * ctBase = static_cast<const CompositeType *>(base.type());
      if (const CompositeType * ctMatch = dyn_cast_or_null<CompositeType>(match)) {
        if (ctMatch != NULL) {
          base = ctBase->findBaseSpecializing(ctMatch);
          if (!base) {
            return QualifiedType();
          }
        }
        if (paramIndex >= base->numTypeParams()) {
          return QualifiedType();
        } else {
          return base->typeParam(paramIndex);
        }
      }
      return QualifiedType();
    }

    case Type::NAddress:
    case Type::NArray:
    case Type::FlexibleArray: {
      if (paramIndex == 0 && (match == NULL || base->typeClass() == match->typeClass())) {
        return base->typeParam(0);
      }
      return QualifiedType();
    }

    case Type::Tuple: {
      if (match != NULL || paramIndex >= base->numTypeParams()) {
        return QualifiedType();
      } else {
        return base->typeParam(paramIndex);
      }
    }

    case Type::AmbiguousParameter:
    case Type::AmbiguousResult:
    case Type::AmbiguousTypeParam:
    case Type::AmbiguousPhi:
    case Type::Assignment: {
      QualifiedTypeSet expansion;
      base.expand(expansion);
      if (expansion.size() == 1) {
        return forType(*expansion.begin(), match, paramIndex);
      }
      return new AmbiguousTypeParamType(base, match, paramIndex);
    }

    default:
      return QualifiedType();
  }
}
Exemple #5
0
bool TypeSetConstraint::isReferenceType() const {
  QualifiedTypeSet expansion;
  expandImpl(expansion, 0);
  for (QualifiedTypeSet::iterator it = expansion.begin(); it != expansion.end(); ++it) {
    QualifiedType ty = *it;
    if (!ty->isReferenceType()) {
      return false;
    }
  }

  return true;
}
void AmbiguousTypeParamType::expandImpl(QualifiedTypeSet & out, unsigned qualifiers) const {
  QualifiedTypeSet baseExpansion;
  base_.expand(baseExpansion);
  for (QualifiedTypeSet::iterator it = baseExpansion.begin(); it != baseExpansion.end(); ++it) {
    QualifiedType ty = forType(*it, match_, paramIndex_);
    if (ty) {
      ty.expand(out, qualifiers);
    } else {
      out.insert(&BadType::instance);
    }
  }
}
void ExportPass::ConstructModuleSymbols()
{
  CProcedureType* originalType = dynamic_cast<CProcedureType*>(originalProcedure->get_procedure_symbol()->get_type()) ;
  assert(originalType != NULL) ;

  // The original type takes and returns a struct.  We need to change this
  //  to a list of arguments.

  VoidType* newReturnType = create_void_type(theEnv, IInteger(0), 0) ;
  constructedType = create_c_procedure_type(theEnv,
					    newReturnType,
					    false, // has varargs
					    true, // arguments_known
					    0, // bit alignment
					    LString("ConstructedType")) ;

  StructType* returnType = 
    dynamic_cast<StructType*>(originalType->get_result_type()) ;
  assert(returnType != NULL) ;

  SymbolTable* structSymTab = returnType->get_group_symbol_table() ;
  assert(structSymTab != NULL) ;

  for (int i = 0 ; i < structSymTab->get_symbol_table_object_count() ; ++i)
  {
    VariableSymbol* nextVariable = 
      dynamic_cast<VariableSymbol*>(structSymTab->get_symbol_table_object(i));
    if (nextVariable != NULL)
    {
      // Check to see if this is an output or not
      QualifiedType* cloneType ;
      DataType* cloneBase = 
	dynamic_cast<DataType*>(nextVariable->get_type()->get_base_type()->deep_clone()) ;
      assert(cloneBase != NULL) ;
      cloneType = create_qualified_type(theEnv, cloneBase) ;
 
      if (nextVariable->lookup_annote_by_name("Output") != NULL)
      {
	cloneType->append_annote(create_brick_annote(theEnv, "Output")) ;
	// Why doesn't this stick around?
      }
      constructedType->append_argument(cloneType) ;
    }
  }

  constructedSymbol = create_procedure_symbol(theEnv,
					      constructedType,
					      originalProcedure->get_procedure_symbol()->get_name()) ;
  constructedSymbol->set_definition(NULL) ;

}
Exemple #8
0
GenRet ArgSymbol::codegen() {
  GenInfo* info = gGenInfo;
  FILE* outfile = info->cfile;
  GenRet ret;

  if( outfile ) {
    QualifiedType qt = qualType();
    ret.c = '&';
    ret.c += cname;
    ret.isLVPtr = GEN_PTR;
    if (qt.isRef() && !qt.isRefType())
      ret.chplType = getOrMakeRefTypeDuringCodegen(typeInfo());
    else if (qt.isWideRef() && !qt.isWideRefType()) {
      Type* refType = getOrMakeRefTypeDuringCodegen(typeInfo());
      ret.chplType = getOrMakeWideTypeDuringCodegen(refType);
    }
    /*
    // BHARSH TODO: Is this still necessary?
    if (q.isRef() && !q.isRefType()) {
      ret.c = cname;
      ret.isLVPtr = GEN_PTR;
    } else if(q.isWideRef() && !q.isWideRefType()) {
      ret.c = cname;
      ret.isLVPtr = GEN_WIDE_PTR;
    } else {
      ret.c = '&';
      ret.c += cname;
      ret.isLVPtr = GEN_PTR;
    }
    */
  } else {
#ifdef HAVE_LLVM
    ret = info->lvt->getValue(cname);
#endif
  }

  // BHARSH TODO: Is this still necessary?
  //if( requiresCPtr() ) {
  //  // Don't try to use chplType.
  //  ret.chplType = NULL;
  //  ret = codegenLocalDeref(ret);
  //}

  //ret.chplType = this->type;

  return ret;
}
Exemple #9
0
ConversionRank CallCandidate::updateConversionRank() {
  conversionRank_ = IdenticalTypes;
  conversionCount_ = 0;

  size_t argCount = callExpr_->argCount();
  for (size_t argIndex = 0; argIndex < argCount; ++argIndex) {
    Expr * argExpr = callExpr_->arg(argIndex);
    QualifiedType paramType = this->paramType(argIndex);
    combineConversionRanks(TypeConversion::check(argExpr, paramType, TypeConversion::COERCE));
  }

  QualifiedType expectedReturnType = callExpr_->expectedReturnType();
  if (!expectedReturnType.isNull() && callExpr_->exprType() != Expr::Construct) {
    AnalyzerBase::analyzeType(resultType_, Task_PrepTypeComparison);
    combineConversionRanks(
        TypeConversion::check(resultType_, expectedReturnType, TypeConversion::COERCE));
  }

  // If there are explicit specializations, then check those too.
  // Note that these must be an exact match.
  if (spCandidate_ != NULL) {
    combineConversionRanks(spCandidate_->updateConversionRank());
  }

  if (method_ != NULL && !method_->checkMutableSelf(base_)) {
    combineConversionRanks(QualifierLoss);
  }

#if 0
  if (typeArgs_ != NULL) {
    size_t typeArgCount = typeArgs_->size();
    for (size_t i = 0; i < typeArgCount; ++i) {
      const Type * typeArg = (*typeArgs_)[i];
      const Type * typeParam = (*typeParams_)[i];
      ConversionRank rank = typeParam->canConvert(typeArg);
      if (rank < IdenticalTypes) {
        conversionRank_ = Incompatible;
        break;
      }
    }
  }
#endif

  return conversionRank_;
}
void ReferenceCleanupPass::CleanupCall(CallStatement* c)
{
  assert(procDef != NULL) ;
  assert(c != NULL) ;

  // We only need to clean up module calls.  If they are built in
  //  functions, like boolsel, we don't want to do this.
  if (IsBuiltIn(c))
  {
    return ;
  }
  
  // Go through the arguments and see if any of them are load variable
  //  expressions to a reference typed variable, and replace those with
  //  symbol address expressions
  for (unsigned int i = 0 ; i < c->get_argument_count() ; ++i)
  {
    Expression* currentArg = c->get_argument(i) ;
    LoadVariableExpression* currentLoadVar = 
      dynamic_cast<LoadVariableExpression*>(currentArg) ;
    if (currentLoadVar != NULL)
    {
      VariableSymbol* currentVar = currentLoadVar->get_source() ;
      DataType* varType = currentVar->get_type()->get_base_type() ;
      ReferenceType* refType = dynamic_cast<ReferenceType*>(varType) ;
      if (refType != NULL)
      {
	QualifiedType* internalType = 
	  dynamic_cast<QualifiedType*>(refType->get_reference_type()) ;
	assert(internalType != NULL) ;
	//	currentVar->set_type(internalType) ;
	SymbolAddressExpression* symAddrExp = 
	  create_symbol_address_expression(theEnv, 
					   internalType->get_base_type(),
					   currentVar) ;
	if (currentLoadVar->lookup_annote_by_name("UndefinedPath") != NULL)
	{
	  symAddrExp->append_annote(create_brick_annote(theEnv, "UndefinedPath")) ;
	}
	currentLoadVar->get_parent()->replace(currentLoadVar, symAddrExp) ;
      }
    }
  }
}
Exemple #11
0
void CallCandidate::reportConversionErrors() {
  diag.info(method_) << Format_Type << method_ << " [" << conversionRank_ << "]";

  size_t argCount = callExpr_->argCount();
  for (size_t argIndex = 0; argIndex < argCount; ++argIndex) {
    Expr * argExpr = callExpr_->arg(argIndex);
    QualifiedType paramType = this->paramType(argIndex);
    ConversionRank rank = TypeConversion::check(argExpr, paramType, TypeConversion::COERCE);
    if (isConversionWarning(rank)) {
      diag.indent();
      diag.info(callExpr_) << compatibilityError(rank) << Format_Dealias << " converting argument " <<
          argIndex << " from '" << argExpr->type() << "' to '" << paramType << "'.";
      diag.unindent();
    }
  }

  QualifiedType expectedReturnType = callExpr_->expectedReturnType();
  if (!expectedReturnType.isNull() && callExpr_->exprType() != Expr::Construct) {
    AnalyzerBase::analyzeType(resultType_, Task_PrepTypeComparison);
    ConversionRank rank = TypeConversion::check(
        resultType_, expectedReturnType, TypeConversion::COERCE);
    if (isConversionWarning(rank)) {
      diag.indent();
      diag.info(callExpr_) << compatibilityError(rank) << Format_Dealias <<
          " converting return value from '" << resultType_ << "' to '" <<
          expectedReturnType << "'.";
      diag.unindent();
    }
  }

  // If there are explicit specializations, then check those too.
  // Note that these must be an exact match.
  if (spCandidate_ != NULL) {
    spCandidate_->reportConversionErrors();
  }

  if (method_ != NULL && !method_->checkMutableSelf(base_)) {
    diag.indent();
    diag.info(callExpr_) << "Non-readonly method with a readonly 'self' argument";
    diag.unindent();
  }
}
// Turn an reference pointer into an array reference expression
void ReferenceCleanupPass::CleanupArrayStore(StoreStatement* s)
{
  assert(s != NULL) ;
  
  // Check to see if the destination is a reference variable
  Expression* destination = s->get_destination_address() ;

  VariableSymbol* storedVariable = FindVariable(destination) ;

  if (storedVariable == NULL)
  {
    return ;
  }

  if (dynamic_cast<ReferenceType*>(storedVariable->get_type()->get_base_type()))
  {
    // Can I just change the type?  Pointer conversion should take care of it
    //  then, but I'll have to annotate it
    ReferenceType* refType = 
      dynamic_cast<ReferenceType*>(storedVariable->get_type()->get_base_type()) ;
    QualifiedType* internalType = 
      dynamic_cast<QualifiedType*>(refType->get_reference_type()) ;
    assert(internalType != NULL) ;

    DataType* internalType2 = internalType->get_base_type() ;
    QualifiedType* qualType = storedVariable->get_type() ;
    qualType->set_base_type(NULL) ;
    refType->set_parent(NULL) ;
    internalType->set_parent(NULL) ;
    refType->set_reference_type(NULL) ;
    qualType->set_base_type(internalType2) ;
  }
}
bool ConstantArrayPropagationPass::ValidSymbol(VariableSymbol* var)
{
  assert(var != NULL) ;
  // The variable should be an array type and have the const qualifier.
  if (dynamic_cast<ArrayType*>(var->get_type()->get_base_type()) == NULL)
  {
    return false ;
  }
  QualifiedType* qualType = var->get_type() ;
  while (dynamic_cast<ArrayType*>(qualType->get_base_type()) != NULL)
  {
    ArrayType* array = dynamic_cast<ArrayType*>(qualType->get_base_type()) ;
    qualType = array->get_element_type() ;
  }
  assert(qualType != NULL) ;
  for (int i = 0 ; i < qualType->get_qualification_count(); ++i)
  {
    if (qualType->get_qualification(i) == LString("const"))
    {
      return true ;
    }
  }
  return false ;
}
Exemple #14
0
static Type* getArgSymbolCodegenType(ArgSymbol* arg) {
  QualifiedType q = arg->qualType();
  Type* useType = q.type();

  if (q.isRef() && !q.isRefType())
    useType = getOrMakeRefTypeDuringCodegen(useType);

  if (q.isWideRef() && !q.isWideRefType()) {
    Type* refType = getOrMakeRefTypeDuringCodegen(useType);
    useType = getOrMakeWideTypeDuringCodegen(refType);
  }
  return useType;
}
Exemple #15
0
int LexicalTypeOrdering::compare(const QualifiedType & t0, const QualifiedType & t1) {
  int result = compare(t0.unqualified(), t1.unqualified());
  if (result != 0) {
    return result;
  }

  if (t0.qualifiers() < t1.qualifiers()) {
    return -1;
  } else if (t0.qualifiers() > t1.qualifiers()) {
    return 1;
  } else {
    return 0;
  }
}
Exemple #16
0
DataType* ExportPass::CloneDataType(DataType* t)
{
  assert(t != NULL) ;
  PointerType* pointerClone = dynamic_cast<PointerType*>(t) ;
  ReferenceType* referenceClone = dynamic_cast<ReferenceType*>(t) ;
  ArrayType* arrayClone = dynamic_cast<ArrayType*>(t) ;
  if (pointerClone != NULL)
  {
    QualifiedType* refType = 
      dynamic_cast<QualifiedType*>(pointerClone->get_reference_type()) ;
    assert(refType != NULL) ;
    DataType* cloneType = CloneDataType(refType->get_base_type()) ;
    assert(cloneType != NULL) ;

    return create_pointer_type(theEnv, 
			       IInteger(32),
			       0,
			       create_qualified_type(theEnv, cloneType)) ;
  }
  if (referenceClone != NULL)
  {
    QualifiedType* refType = 
      dynamic_cast<QualifiedType*>(referenceClone->get_reference_type()) ;
    assert(refType != NULL) ;
    DataType* clonedType = CloneDataType(refType->get_base_type()) ;
    
    return create_reference_type(theEnv,
				 IInteger(32),
				 0,
				 create_qualified_type(theEnv, clonedType)) ;
  }
  if (arrayClone != NULL)
  {
    QualifiedType* elementType = arrayClone->get_element_type() ;
    DataType* internalType = CloneDataType(elementType->get_base_type()) ;
    QualifiedType* finalQual = create_qualified_type(theEnv, internalType) ;
    return create_pointer_type(theEnv,
			       IInteger(32),
			       0, 
			       finalQual) ;    
  }
  return dynamic_cast<DataType*>(t->deep_clone()) ;
}
void DismantleStructuredReturns::do_file_set_block( FileSetBlock* file_set_block ) {
    suif_map<CProcedureType *,QualifiedType *> type_map;
    list<ArrayReferenceExpression*> ref_exprs;
    SuifEnv *env = 0;
    TypeBuilder *tb = 0;
    VoidType *vt = 0;
    for (Iter<ProcedureSymbol> iter =
                object_iterator<ProcedureSymbol>(file_set_block);
	iter.is_valid();
	iter.next()) {
	ProcedureSymbol *sym = &iter.current();
	Type *type = sym->get_type();
	if (!is_kind_of<CProcedureType>(type))
	    continue;
	CProcedureType *cp_type = to<CProcedureType>(type);
	type = cp_type->get_result_type();
	if (!env) {
	    env = type->get_suif_env();
	    tb = (TypeBuilder*)
                env->get_object_factory(TypeBuilder::get_class_name());
	    vt = tb->get_void_type();
	    }
	suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type);

	QualifiedType *qtype;
	
 	if (t_iter == type_map.end()) {
	    if (!is_kind_of<GroupType>(type) && !is_kind_of<ArrayType>(type))
                continue;
	    qtype = tb->get_qualified_type(
                        tb->get_pointer_type(to<DataType>(type)));

	    cp_type->set_result_type(vt);
	    
	    cp_type->insert_argument(0,qtype);
	    type_map.enter_value(cp_type,qtype);
	    }
	else {
	    qtype = (*t_iter).second;
	    }
	ProcedureDefinition *def = sym->get_definition();
	if (!def) 
	    continue;
	ParameterSymbol *par = create_parameter_symbol(env,qtype);
	def->get_symbol_table()->append_symbol_table_object(par);
        def->insert_formal_parameter(0,par);
	//	Convert all returns into assigned and returns
	for (Iter<ReturnStatement> ret_iter = object_iterator<ReturnStatement>(def->get_body());
        	ret_iter.is_valid();
        	ret_iter.next()) {
	    ReturnStatement *ret = &ret_iter.current();
	    Expression *retval = ret->get_return_value();
	    ret->set_return_value(0);
	    retval->set_parent(0);
	    insert_statement_before(ret,
			create_store_statement(env,retval,create_var_use(par)));
	    }
	}
    //	Change all calls to the new form
    for (Iter<CallStatement> cs_iter =
                object_iterator<CallStatement>(file_set_block);
        cs_iter.is_valid();
        cs_iter.next()) {
        CallStatement *call = &cs_iter.current();
	Type *type = call->get_callee_address()->get_result_type();
	Type *p_type = tb->unqualify_type(to<PointerType>(type)->get_reference_type());
        if (!is_kind_of<PointerType>(p_type))
            continue;
        p_type = tb->unqualify_type(to<PointerType>(p_type)->get_reference_type());

	if (!is_kind_of<CProcedureType>(p_type))
	    continue;
	CProcedureType *cp_type = to<CProcedureType>(p_type);
	
	suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type);
	if (t_iter == type_map.end())
	    continue;
	QualifiedType *qtype = (*t_iter).second;
	DataType *var_type = to<DataType>(tb->unqualify_type(to<PointerType>(qtype->get_base_type())
		->get_reference_type()));
	VariableSymbol *var =
      	    new_anonymous_variable(env,call,tb->get_qualified_type(var_type));
	Expression *exp = create_symbol_address_expression(
		env,
		tb->get_pointer_type(var_type),
		var);
        call->insert_argument(0,exp);
        call->set_destination(0);
	}

    for (Iter<CallExpression> ce_iter =
                object_iterator<CallExpression>(file_set_block);
        ce_iter.is_valid();
        ce_iter.next()) {
        CallExpression *call = &ce_iter.current();
        Type *type = call->get_callee_address()->get_result_type();
        Type *p_type = tb->unqualify_type(to<PointerType>(type)->get_reference_type());
	if (!is_kind_of<PointerType>(p_type))
            continue;
	p_type = tb->unqualify_type(to<PointerType>(p_type)->get_reference_type());
        if (!is_kind_of<CProcedureType>(p_type))
            continue;
        CProcedureType *cp_type = to<CProcedureType>(p_type);
;
        suif_map<CProcedureType *,QualifiedType *>::iterator t_iter = type_map.find(cp_type);
        if (t_iter == type_map.end())
            continue;
        QualifiedType *qtype = (*t_iter).second;
        DataType *var_type = to<DataType>(tb->unqualify_type(to<PointerType>(qtype->get_base_type())
                ->get_reference_type()));
        VariableSymbol *var =
            new_anonymous_variable(env,call,tb->get_qualified_type(var_type));
        Expression *exp = create_symbol_address_expression(
                env,
                tb->get_pointer_type(var_type),
                var);
        call->insert_argument(0,exp);

	Statement *loc = get_expression_owner(call);
	call->get_parent()->replace(call,create_var_use(var));
	call->set_parent(0);
        suif_assert(vt != 0);
        call->set_result_type(vt);

	EvalStatement *es = create_eval_statement(env);
	insert_statement_before(loc,es);
	// Would be better to turn this into a call statement
	es->append_expression(call);
        }
    }
Exemple #18
0
static QualifiedType
returnInfoArrayIndex(CallExpr* call) {
  QualifiedType tmp = returnInfoArrayIndexValue(call);
  return QualifiedType(tmp.type()->refType, QUAL_REF);
}
Exemple #19
0
static QualifiedType
returnInfoFirstDeref(CallExpr* call) {
  QualifiedType tmp = call->get(1)->qualType();
  Type* type = tmp.type()->getValType();
  return QualifiedType(type, QUAL_VAL);
}
Exemple #20
0
void ExportPass::ConstructSystemSymbols()
{
  ProcedureSymbol* originalSymbol = originalProcedure->get_procedure_symbol() ;
  assert(originalSymbol != NULL) ;
  CProcedureType* originalType = 
    dynamic_cast<CProcedureType*>(originalSymbol->get_type()) ;
  assert(originalType != NULL) ;

  constructedType = create_c_procedure_type(theEnv,
    dynamic_cast<DataType*>(originalType->get_result_type()->deep_clone()),
					    false, // has variable arguments
					    false, // arguments known
					    0) ; // bit alignment

  // The system has been written in one of two ways, either the old
  //  way where there are no arguments, or the new way where everything
  //  is put into the arguments.
  
  if (originalType->get_argument_count() > 0)
  {
    for (int i = 0 ; i < originalType->get_argument_count() ; ++i)
    {
      QualifiedType* originalArgument = originalType->get_argument(i) ;
      DataType* originalBase = originalArgument->get_base_type() ;
      DataType* constructedBase = CloneDataType(originalBase) ;
      QualifiedType* constructedArgument = 
	create_qualified_type(theEnv, constructedBase) ;
      constructedType->append_argument(constructedArgument) ;

      // Go through the symbol table and find the parameter symbol 
      //  that matches the parameter number, and check to see if it
      //  is an output or not...
      SymbolTable* symTab = originalProcedure->get_symbol_table() ;
      ParameterSymbol* correspondingSymbol = NULL ;
      for (int j = 0 ; j < symTab->get_symbol_table_object_count() ; ++j)
      {
	ParameterSymbol* currentSym = 
	  dynamic_cast<ParameterSymbol*>(symTab->get_symbol_table_object(j)) ;
	if (currentSym != NULL)
	{
	  BrickAnnote* orderAnnote = dynamic_cast<BrickAnnote*>(currentSym->lookup_annote_by_name("ParameterOrder")) ;
	  assert(orderAnnote != NULL) ;
	  IntegerBrick* orderBrick = 
	    dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ;
	  assert(orderBrick != NULL) ;
	  if (orderBrick->get_value().c_int() == i)
	  {
	    correspondingSymbol = currentSym ;
	    break ;
	  }
	}
      }
      if (correspondingSymbol != NULL)
      {
        if (correspondingSymbol->lookup_annote_by_name("OutputScalar") != NULL ||
	    correspondingSymbol->lookup_annote_by_name("OutputVariable") != NULL ||
	    correspondingSymbol->lookup_annote_by_name("OutputFifo") != NULL)
        {
	  constructedArgument->append_annote(create_brick_annote(theEnv,
								 "Output")) ;
        }
      }
      //      if (dynamic_cast<ReferenceType*>(originalBase) != NULL)
      //{
      //	constructedArgument->append_annote(create_brick_annote(theEnv,
      //						       "Output")) ;
      //      }
    }
  }
  else
  {   
    SymbolTable* symTab = originalProcedure->get_symbol_table() ;
    assert(symTab != NULL) ;
    list<VariableSymbol*> inputScalars ;
    list<VariableSymbol*> inputFifos ; 
    list<VariableSymbol*> outputScalars ;
    list<VariableSymbol*> outputFifos ;

    for (int i = 0 ; i < symTab->get_symbol_table_object_count() ; ++i)
    {
      VariableSymbol* currentVar = 
	dynamic_cast<VariableSymbol*>(symTab->get_symbol_table_object(i)) ;
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("InputScalar") != NULL &&
	  currentVar->lookup_annote_by_name("TemporalFeedback") == NULL &&
	  currentVar->lookup_annote_by_name("NormalFeedback") == NULL &&
	  currentVar->lookup_annote_by_name("DebugRegister") == NULL)
      {
	inputScalars.push_back(currentVar) ;
      }
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("InputFifo") != NULL)
      {
	inputFifos.push_back(currentVar) ;
      }
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("OutputVariable") != NULL &&
	  currentVar->lookup_annote_by_name("Dummy") == NULL &&
	  currentVar->lookup_annote_by_name("FeedbackSource") == NULL)
      {
	outputScalars.push_back(currentVar) ;
      }
      if (currentVar != NULL &&
	  currentVar->lookup_annote_by_name("OutputFifo") != NULL)
      {
	outputFifos.push_back(currentVar) ;
      }
    }
    // Add the types of the input scalars, then the input fifos, 
    //  then the output scalars, and finally the output fifos.
    list<VariableSymbol*>::iterator varIter = inputScalars.begin() ;
    while (varIter != inputScalars.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      assert(originalQual != NULL) ;
      DataType* originalBase = originalQual->get_base_type() ;
      assert(originalBase != NULL) ;
      DataType* constructedBase = 
	dynamic_cast<DataType*>(originalBase->deep_clone()) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    varIter = inputFifos.begin() ;
    while (varIter != inputFifos.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      assert(originalQual != NULL) ;
      DataType* originalBase = originalQual->get_base_type() ;
      assert(originalBase != NULL) ;
      // Fifos will have pointer types or reference types.  A 
      //  simple deep clone will not suffice, I need to build up a
      //  new type from the bottom up.
      DataType* constructedBase = CloneDataType(originalBase) ;
      assert(constructedBase != NULL) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      assert(constructedBase != NULL) ;
      assert(constructedType != NULL) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    varIter = outputScalars.begin() ;
    while (varIter != outputScalars.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      DataType* originalBase = originalQual->get_base_type() ;
      DataType* constructedBase = CloneDataType(originalBase) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      constructedQual->append_annote(create_brick_annote(theEnv, "Output")) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    varIter = outputFifos.begin() ;
    while (varIter != outputFifos.end())
    {
      QualifiedType* originalQual = (*varIter)->get_type() ;
      assert(originalQual != NULL) ;
      DataType* originalBase = originalQual->get_base_type() ;
      assert(originalBase != NULL) ;
      DataType* constructedBase = CloneDataType(originalBase) ;
      assert(constructedBase != NULL) ;
      QualifiedType* constructedQual = 
	create_qualified_type(theEnv, constructedBase) ;
      assert(constructedQual != NULL) ;
      constructedQual->append_annote(create_brick_annote(theEnv, "Output")) ;
      assert(constructedType != NULL) ;
      constructedType->append_argument(constructedQual) ;
      ++varIter ;
    }
    
  }
  constructedSymbol = create_procedure_symbol(theEnv, constructedType,
					      originalProcedure->get_procedure_symbol()->get_name()) ;
}
// All of the array references expressions in the passed in the struct are
//  equivalent, so we can determine types of the original and use that
//  to create a new expression with which to replace everything.
bool TransformUnrolledArraysPass::ReplaceNDReference(EquivalentReferences* a)
{
  assert(a != NULL) ;
  assert(a->original != NULL) ;

  // Check to see if the reference at this stage is a constant or not
  IntConstant* constantIndex = 
    dynamic_cast<IntConstant*>(a->original->get_index()) ;
  
  if (constantIndex == NULL)
  {
    // There was no replacement made
    return false ;
  }

  Expression* baseAddress = a->original->get_base_array_address() ;
  assert(baseAddress != NULL) ;
  assert(constantIndex != NULL) ;

  // Create a replacement expression for this value.  This will either
  //  be another array reference expression or a single variable.
  Expression* replacementExp = NULL ;
  //  QualifiedType* elementType = GetQualifiedTypeOfElement(a->original) ;
  VariableSymbol* originalSymbol = GetArrayVariable(a->original) ;
  assert(originalSymbol != NULL) ;
  LString replacementName = 
    GetReplacementName(originalSymbol->get_name(), 
		       constantIndex->get_value().c_int()) ;
  int dimensionality = GetDimensionality(a->original) ;
  
  QualifiedType* elementType = originalSymbol->get_type() ;
  while (dynamic_cast<ArrayType*>(elementType->get_base_type()) != NULL)
  {
    elementType = dynamic_cast<ArrayType*>(elementType->get_base_type())->get_element_type() ;
  }
  
  // There is a special case for one dimensional arrays as opposed to all
  //  other dimensional arrays.  It only should happen if we are truly
  //  replacing an array with a one dimensional array.
  if (dimensionality == 1 && 
      dynamic_cast<ArrayReferenceExpression*>(a->original->get_parent())==NULL)
  {

    VariableSymbol* replacementVar = 
      create_variable_symbol(theEnv,
			     GetQualifiedTypeOfElement(a->original),
			     TempName(replacementName)) ;
    procDef->get_symbol_table()->append_symbol_table_object(replacementVar) ;
    
    replacementExp = 
      create_load_variable_expression(theEnv,
				      elementType->get_base_type(),
				      replacementVar) ;
  }
  else
  {
    // Create a new array with one less dimension.  This requires a new
    //  array type.
    ArrayType* varType = 
      dynamic_cast<ArrayType*>(originalSymbol->get_type()->get_base_type()) ;
    assert(varType != NULL) ;
   
    ArrayType* replacementArrayType =
      create_array_type(theEnv,
	varType->get_element_type()->get_base_type()->get_bit_size(),
	0, // bit alignment
	OneLessDimension(originalSymbol->get_type(), dimensionality),
	dynamic_cast<Expression*>(varType->get_lower_bound()->deep_clone()),
	dynamic_cast<Expression*>(varType->get_upper_bound()->deep_clone()),
	TempName(varType->get_name())) ;

    procDef->get_symbol_table()->append_symbol_table_object(replacementArrayType) ;

    VariableSymbol* replacementArraySymbol = 
      create_variable_symbol(theEnv,
			     create_qualified_type(theEnv,
						   replacementArrayType,
						   TempName(LString("qualType"))),
			     TempName(replacementName)) ;

    procDef->get_symbol_table()->append_symbol_table_object(replacementArraySymbol) ;

    // Create a new symbol address expression for this variable symbol
    SymbolAddressExpression* replacementAddrExp =
      create_symbol_address_expression(theEnv,
				       replacementArrayType,
				       replacementArraySymbol) ;

    // Now, replace the symbol address expression in the base
    //  array address with this symbol.
    ReplaceSymbol(a->original, replacementAddrExp) ;
    
    // And replace this reference with the base array address.
    replacementExp = a->original->get_base_array_address() ;
    a->original->set_base_array_address(NULL) ;
    replacementExp->set_parent(NULL) ;
  }

  // Replace all of the equivalent expressions with the newly generated
  //  replacement expression.
  assert(replacementExp != NULL) ;
  a->original->get_parent()->replace(a->original, replacementExp) ;
   
  //  ReplaceChildExpression(a->original->get_parent(),
  //			 a->original,
  //			 replacementExp) ;

  list<ArrayReferenceExpression*>::iterator equivIter = 
    a->allEquivalent.begin() ;
  while (equivIter != a->allEquivalent.end()) 
  {
    (*equivIter)->get_parent()->replace((*equivIter),
					dynamic_cast<Expression*>(replacementExp->deep_clone())) ;
    //    ReplaceChildExpression((*equivIter)->get_parent(),
    //			   (*equivIter),
    //			   dynamic_cast<Expression*>(replacementExp->deep_clone())) ;
    ++equivIter ;
  }

  return true ;
}
// Do a sort of garbage collection.  Take all of the types that we want to
//  delete and collect them.  If there are no uses of them after this function
//  has finished, then remove them.
void RemoveModulePass::RemoveProcedure(ProcedureSymbol* p)
{
    assert(repository != NULL) ;
    list<Type*> usedTypes ;

    if (p == NULL)
    {
        return ;
    }

    // There should be no definition, but just in case remove it
    ProcedureDefinition* defToRemove = p->get_definition() ;
    p->set_definition(NULL) ;
    if (defToRemove != NULL)
    {
        delete defToRemove ;
    }

    // Clear out all of the values associated with the procedure type
    CProcedureType* procType =
        dynamic_cast<CProcedureType*>(p->get_type()) ;
    assert(procType != NULL) ;

    DataType* returnTypeToRemove = procType->get_result_type() ;
    procType->set_result_type(NULL) ;
    if (returnTypeToRemove != NULL)
    {
        usedTypes.push_back(returnTypeToRemove) ;
    }

    while (procType->get_argument_count() > 0)
    {
        QualifiedType* currentArg = procType->get_argument(0) ;
        procType->remove_argument(0) ;
        if (!InList(usedTypes, currentArg))
        {
            usedTypes.push_back(currentArg) ;
        }
    }
    SymbolTable* symTab = repository->get_external_symbol_table() ;
    p->set_type(NULL) ;
    symTab->remove_symbol_table_object(procType) ;
    delete procType ;
    symTab->remove_symbol_table_object(p) ;
    delete p ;

    // Now, go through each used type and see if it is used anywhere
    list<Type*>::iterator typeIter = usedTypes.begin() ;
    while (typeIter != usedTypes.end())
    {
        bool removeMe = true ;
        for (int i = 0 ; i < symTab->get_symbol_table_object_count() ; ++i)
        {
            CProcedureType* currentType =
                dynamic_cast<CProcedureType*>(symTab->get_symbol_table_object(i)) ;
            if (currentType != NULL)
            {
                if (IsUsed(*typeIter, currentType))
                {
                    removeMe = false ;
                    break ;
                }
            }
        }
        if (removeMe)
        {
            if ((*typeIter)->lookup_annote_by_name("Output") != NULL)
            {
                delete (*typeIter)->remove_annote_by_name("Output") ;
            }
            QualifiedType* q = dynamic_cast<QualifiedType*>(*typeIter) ;
            DataType* d = dynamic_cast<DataType*>(*typeIter) ;
            if (q != NULL)
            {
                DataType* internalD = q->get_base_type() ;
                q->set_base_type(NULL) ;
                symTab->remove_symbol_table_object(internalD) ;
                symTab->remove_symbol_table_object(q) ;
                delete internalD ;
                delete q ;
            }
            else if (d != NULL)
            {
                symTab->remove_symbol_table_object(d) ;
                delete d ;
            }
            else
            {
                assert(0 && "Trying to remove something weird...") ;
            }

        }
        ++typeIter ;
    }

}
Exemple #23
0
bool FunctionMergePass::areTypesCompatible(QualifiedType from, QualifiedType to) {
  return areTypesCompatible(from.unqualified(), to.unqualified());
}
void TransformSystemsToModules::Transform()
{
  assert(procDef != NULL) ;

  // Collect all the input scalars and output scalars
  list<VariableSymbol*> ports ;
  
  SymbolTable* procSymTab = procDef->get_symbol_table() ;
  bool foundInputs = false ;
  bool foundOutputs = false ;
 
  for (int i = 0 ; i < procSymTab->get_symbol_table_object_count() ; ++i)
  {
    SymbolTableObject* nextObject = procSymTab->get_symbol_table_object(i) ;

    if (nextObject->lookup_annote_by_name("InputScalar") != NULL)
    {
      VariableSymbol* toConvert = 
	dynamic_cast<VariableSymbol*>(nextObject) ;
      assert(toConvert != NULL) ;
      LString inputName = toConvert->get_name() ;
      inputName = inputName + "_in" ;
      toConvert->set_name(inputName) ;
      ports.push_back(toConvert) ;
      foundInputs = true ;
    }
    if (nextObject->lookup_annote_by_name("OutputVariable") != NULL)
    {
      VariableSymbol* toConvert = 
	dynamic_cast<VariableSymbol*>(nextObject) ;
      assert(toConvert != NULL) ;
      LString outputName = toConvert->get_name() ;
      outputName = outputName + "_out" ;
      toConvert->set_name(outputName) ;
      ports.push_back(toConvert) ;
      foundOutputs = true ;
    }
  }
  assert(foundInputs && 
	 "Could not identify inputs.  Were they removed via optimizations?") ;
  assert(foundOutputs && 
	 "Could not identify outputs.  Were they removed via optimizations?") ;

  // Determine the bit size and add everything to a new symbol table
  int bitSize = 0 ;
  GroupSymbolTable* structTable = 
    create_group_symbol_table(theEnv,
			      procDef->get_symbol_table()) ;

  std::map<VariableSymbol*, FieldSymbol*> replacementFields ;

  bool portsRemoved = false ;
  // If this was actually a new style module, we should make sure to
  //  put these in the correct order.
  if (isModule(procDef))
  {
    // Go through the original symbol table and remove any parameter 
    //  symbols that originally existed
    SymbolTable* originalSymTab = procDef->get_symbol_table() ;
    Iter<SymbolTableObject*> originalIter = 
      originalSymTab->get_symbol_table_object_iterator() ;
    while (originalIter.is_valid())
    {
      SymbolTableObject* currentObj = originalIter.current() ;
      originalIter.next() ;
      if (dynamic_cast<ParameterSymbol*>(currentObj) != NULL)
      {
	originalSymTab->remove_symbol_table_object(currentObj) ;
      }
    }
    portsRemoved = true ;

    // Sort the variable symbols in parameter order.  This is just an 
    //  insertion sort, so it could be done faster.
    list<VariableSymbol*> sortedPorts ;
    for (int i = 0 ; i < ports.size() ; ++i)
    {
      list<VariableSymbol*>::iterator portIter = ports.begin() ;
      while (portIter != ports.end())
      {
	BrickAnnote* orderAnnote = 
	  dynamic_cast<BrickAnnote*>((*portIter)->
				     lookup_annote_by_name("ParameterOrder")) ;
	if (orderAnnote == NULL)
	{
	  ++portIter ;
	  continue ;
	}
	IntegerBrick* orderBrick = 
	  dynamic_cast<IntegerBrick*>(orderAnnote->get_brick(0)) ;
	assert(orderBrick != NULL) ;
	if (orderBrick->get_value().c_int() == i)
	{
	  sortedPorts.push_back(*portIter) ;
	  break ;
	}
	++portIter ;
      }
    }
    if (sortedPorts.size() != ports.size())
    {
      OutputWarning("Warning! Analysis detected some input scalars not in"
		    " the parameter list") ;
    }
    // Replace ports with sortedPorts
    ports = sortedPorts ;
  }

  list<VariableSymbol*>::iterator portIter = ports.begin() ;  
  while (portIter != ports.end()) 
  {
    bitSize += 
      (*portIter)->get_type()->get_base_type()->get_bit_size().c_int() ;

    LString dupeName = (*portIter)->get_name() ;

    // Create offset expression:
    IntConstant* offset = 
      create_int_constant(theEnv,
			  create_data_type(theEnv,
					   IInteger(32),
					   0),
			  IInteger(bitSize)) ;


    QualifiedType* dupeType = (*portIter)->get_type() ;
    // Deal with the case where reference types were passed in
    ReferenceType* refType = 
      dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ;
    while (refType != NULL)
    {
      dupeType = dynamic_cast<QualifiedType*>(refType->get_reference_type()) ;
      assert(dupeType != NULL) ;
      refType = dynamic_cast<ReferenceType*>(dupeType->get_base_type()) ;
    }

    // Create a new variable symbol clone
    FieldSymbol* dupe = 
      create_field_symbol(theEnv,
			  dupeType,
			  offset,
			  dupeName) ;
        
    structTable->append_symbol_table_object(dupe) ;

    // Make the connection with the duplicated symbol
    replacementFields[(*portIter)] = dupe ;

    // Remove the original variable symbol from the procedure definition
    //  symbol table.
    if (!portsRemoved)
    {
      procDef->get_symbol_table()->remove_symbol_table_object(*portIter) ;
    }
    
    ++portIter ;
  }
  assert(bitSize != 0);

  StructType* moduleStruct = 
    create_struct_type(theEnv,
		       IInteger(bitSize),
		       0, // bit_alignment
		       TempName(procDef->get_procedure_symbol()->get_name()),
		       0, // is_complete
		       structTable) ;

  
  Iter<FileBlock*> fBlocks = 
    theEnv->get_file_set_block()->get_file_block_iterator() ;
  
  assert(fBlocks.is_valid()) ;
  (fBlocks.current())->get_symbol_table()->append_symbol_table_object(moduleStruct) ;
  
  // This is commented out because it is in the file state block
  //procDef->get_symbol_table()->append_symbol_table_object(moduleStruct) ;

  QualifiedType* qualifiedModuleStruct =
    create_qualified_type(theEnv,
			  moduleStruct,
			  TempName(LString("qualifiedModuleStruct"))) ;
  
  procDef->get_symbol_table()->append_symbol_table_object(qualifiedModuleStruct) ;

  // Create an instance of this type and add it to the symbol table.
  ParameterSymbol* structInstance = 
    create_parameter_symbol(theEnv,
			   qualifiedModuleStruct,
			   TempName(LString("structInstance"))) ;

  procDef->get_symbol_table()->append_symbol_table_object(structInstance) ;

  // Now, set up the procedure symbol to take the struct and return the 
  //  struct.
  assert(procDef != NULL) ;
  ProcedureSymbol* procSym = procDef->get_procedure_symbol() ;
  assert(procSym != NULL) ;
  ProcedureType* procType = procSym->get_type() ;
  assert(procType != NULL) ;
  CProcedureType* cProcType = dynamic_cast<CProcedureType*>(procType) ;
  assert(cProcType != NULL) ;

  // Instead of appending the struct argument, we need to replace all of the 
  //  arguments with the struct.

  while (cProcType->get_argument_count() > 0)
  {
    cProcType->remove_argument(0) ;
  }

  cProcType->set_result_type(moduleStruct) ;
  cProcType->append_argument(qualifiedModuleStruct) ;

  // Now go through all load variable expressions and replace them all with
  //  field symbol values if appropriate
  
  list<LoadVariableExpression*>* allLoads = 
    collect_objects<LoadVariableExpression>(procDef->get_body()) ;

  list<LoadVariableExpression*>::iterator loadIter = allLoads->begin() ;
  while (loadIter != allLoads->end())
  {
    VariableSymbol* currentVariable = (*loadIter)->get_source() ;
    if (replacementFields.find(currentVariable) != replacementFields.end())
    {
      (*loadIter)->set_source(replacementFields[currentVariable]) ;
    }
    ++loadIter ;
  }
  delete allLoads ;

  // Also replace all of the definitions with the field symbol
  list<StoreVariableStatement*>* allStoreVars = 
    collect_objects<StoreVariableStatement>(procDef->get_body()) ;
  list<StoreVariableStatement*>::iterator storeVarIter = allStoreVars->begin();
  while (storeVarIter != allStoreVars->end())
  {
    VariableSymbol* currentDest = (*storeVarIter)->get_destination() ;
    if (replacementFields.find(currentDest) != replacementFields.end())
    {
      (*storeVarIter)->set_destination(replacementFields[currentDest]) ;
    }
    ++storeVarIter ;
  }
  delete allStoreVars ;

  list<SymbolAddressExpression*>* allSymAddr = 
    collect_objects<SymbolAddressExpression>(procDef->get_body()) ;
  list<SymbolAddressExpression*>::iterator symAddrIter = allSymAddr->begin() ;
  while (symAddrIter != allSymAddr->end())
  {
    VariableSymbol* currentVar = 
      dynamic_cast<VariableSymbol*>((*symAddrIter)->get_addressed_symbol()) ;
    if (currentVar != NULL &&
	replacementFields.find(currentVar) != replacementFields.end())
    {
      (*symAddrIter)->set_addressed_symbol(replacementFields[currentVar]) ;
    }
    ++symAddrIter ;
  }
  delete allSymAddr ;
  // One final for bool selects
  list<CallStatement*>* allCalls = 
    collect_objects<CallStatement>(procDef->get_body()) ;
  list<CallStatement*>::iterator callIter = allCalls->begin() ;
  while(callIter != allCalls->end())
  {
    VariableSymbol* currentVar = (*callIter)->get_destination() ;
    if (currentVar != NULL &&
	replacementFields.find(currentVar) != replacementFields.end())
    {
      (*callIter)->set_destination(replacementFields[currentVar]) ;
    }
    ++callIter ;
  }
  delete allCalls ;
}
Exemple #25
0
void VarSymbol::codegenDefC(bool global, bool isHeader) {
  GenInfo* info = gGenInfo;
  if (this->hasFlag(FLAG_EXTERN))
    return;

  if (type == dtVoid)
    return;

  AggregateType* ct = toAggregateType(type);
  QualifiedType qt = qualType();

  if (qt.isRef() && !qt.isRefType()) {
    Type* refType = getOrMakeRefTypeDuringCodegen(type);
    ct = toAggregateType(refType);
  }
  if (qt.isWideRef() && !qt.isWideRefType()) {
    Type* refType = getOrMakeRefTypeDuringCodegen(type);
    Type* wideType = getOrMakeWideTypeDuringCodegen(refType);
    ct = toAggregateType(wideType);
  }

  Type* useType = type;
  if (ct) useType = ct;

  std::string typestr =  (this->hasFlag(FLAG_SUPER_CLASS) ?
                          std::string(toAggregateType(useType)->classStructName(true)) :
                          useType->codegen().c);

  //
  // a variable can be codegen'd as static if it is global and neither
  // exported nor external.
  //
  std::string str;

  if(fIncrementalCompilation) {
    bool addExtern =  global && isHeader;
    str = (addExtern ? "extern " : "") + typestr + " " + cname;
  } else {
    bool isStatic =  global && !hasFlag(FLAG_EXPORT) && !hasFlag(FLAG_EXTERN);
    str = (isStatic ? "static " : "") + typestr + " " + cname;
  }

  if (ct) {
    if (ct->isClass()) {
      if (isFnSymbol(defPoint->parentSymbol)) {
        str += " = NULL";
      }
    } else if (ct->symbol->hasFlag(FLAG_WIDE_REF) ||
               ct->symbol->hasFlag(FLAG_WIDE_CLASS)) {
      if (isFnSymbol(defPoint->parentSymbol)) {
        if (widePointersStruct) {
          //
          // CHPL_LOCALEID_T_INIT is #defined in the chpl-locale-model.h
          // file in the runtime, for the selected locale model.
          //
          str += " = {CHPL_LOCALEID_T_INIT, NULL}";
        } else {
          str += " = ((wide_ptr_t) NULL)";
        }
      }
    }
  }

  if (fGenIDS)
    str = idCommentTemp(this) + str;
  if (printCppLineno && !isHeader && !isTypeSymbol(defPoint->parentSymbol))
    str = zlineToString(this) + str;

  info->cLocalDecls.push_back(str);
}
Exemple #26
0
GenRet VarSymbol::codegenVarSymbol(bool lhsInSetReference) {
  GenInfo* info = gGenInfo;
  FILE* outfile = info->cfile;
  GenRet ret;
  ret.chplType = typeInfo();

  if( outfile ) {
    // dtString immediates don't actually codegen as immediates, we just use
    // them for param string functionality.
    if (immediate && ret.chplType != dtString) {
      ret.isLVPtr = GEN_VAL;
      if (immediate->const_kind == CONST_KIND_STRING) {
        ret.c += '"';
        ret.c += immediate->v_string;
        ret.c += '"';
      } else if (immediate->const_kind == NUM_KIND_BOOL) {
        std::string bstring = (immediate->bool_value())?"true":"false";
        const char* castString = "(";
        switch (immediate->num_index) {
        case BOOL_SIZE_1:
        case BOOL_SIZE_SYS:
        case BOOL_SIZE_8:
          castString = "UINT8(";
          break;
        case BOOL_SIZE_16:
          castString = "UINT16(";
          break;
        case BOOL_SIZE_32:
          castString = "UINT32(";
          break;
        case BOOL_SIZE_64:
          castString = "UINT64(";
          break;
        default:
          INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index);
        }
        ret.c = castString + bstring + ")";
      } else if (immediate->const_kind == NUM_KIND_INT) {
        int64_t iconst = immediate->int_value();
        if (iconst == (1ll<<63)) {
          ret.c = "-INT64(9223372036854775807) - INT64(1)";
        } else if (iconst <= -2147483648ll || iconst >= 2147483647ll) {
          ret.c = "INT64(" + int64_to_string(iconst) + ")";
        } else {
          const char* castString = "(";
          switch (immediate->num_index) {
          case INT_SIZE_8:
            castString = "INT8(";
            break;
          case INT_SIZE_16:
            castString = "INT16(";
            break;
          case INT_SIZE_32:
            castString = "INT32(";
            break;
          case INT_SIZE_64:
            castString = "INT64(";
            break;
          default:
            INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index);
          }

          ret.c = castString + int64_to_string(iconst) + ")";
        }
      } else if (immediate->const_kind == NUM_KIND_UINT) {
        uint64_t uconst = immediate->uint_value();
        if( uconst <= (uint64_t) INT32_MAX ) {
          const char* castString = "(";
          switch (immediate->num_index) {
          case INT_SIZE_8:
            castString = "UINT8(";
            break;
          case INT_SIZE_16:
            castString = "UINT16(";
            break;
          case INT_SIZE_32:
            castString = "UINT32(";
            break;
          case INT_SIZE_64:
            castString = "UINT64(";
            break;
          default:
            INT_FATAL("Unexpected immediate->num_index: %d\n", immediate->num_index);
          }
          ret.c = castString + uint64_to_string(uconst) + ")";
        } else {
          ret.c = "UINT64(" + uint64_to_string(uconst) + ")";
        }
      } else {
        ret.c = cname; // in C, all floating point literals are (double)
      }
    } else {
      // not immediate
      // is it a constant extern? If it is, it might be for example
      // an enum or #define'd value, in which case taking the address
      // of it is simply nonsense. Therefore, we code generate
      // extern const symbols as GEN_VAL (ie not an lvalue).
      if( hasFlag(FLAG_CONST) && hasFlag(FLAG_EXTERN) ) {
        ret.isLVPtr = GEN_VAL;
        ret.c = cname;
      } else {
        QualifiedType qt = qualType();
        if (lhsInSetReference) {
          ret.c = '&';
          ret.c += cname;
          ret.isLVPtr = GEN_PTR;
          if (qt.isRef() && !qt.isRefType())
            ret.chplType = getOrMakeRefTypeDuringCodegen(typeInfo());
          else if (qt.isWideRef() && !qt.isWideRefType()) {
            Type* refType = getOrMakeRefTypeDuringCodegen(typeInfo());
            ret.chplType = getOrMakeWideTypeDuringCodegen(refType);
          }
        } else {
          if (qt.isRef() && !qt.isRefType()) {
            ret.c = cname;
            ret.isLVPtr = GEN_PTR;
          } else if(qt.isWideRef() && !qt.isWideRefType()) {
            ret.c = cname;
            ret.isLVPtr = GEN_WIDE_PTR;
          } else {
            ret.c = '&';
            ret.c += cname;
            ret.isLVPtr = GEN_PTR;
          }
        }
      }
      // Print string contents in a comment if developer mode
      // and savec is set.
      if (developer &&
          0 != strcmp(saveCDir, "") &&
          immediate &&
          ret.chplType == dtString &&
          immediate->const_kind == CONST_KIND_STRING) {
        if (strstr(immediate->v_string, "/*") ||
            strstr(immediate->v_string, "*/")) {
          // Don't emit comment b/c string contained comment character.
        } else {
          ret.c += " /* \"";
          ret.c += immediate->v_string;
          ret.c += "\" */";
        }
      }
    }
    return ret;
  } else {
#ifdef HAVE_LLVM

    // for LLVM

    // Handle extern type variables.
    if( hasFlag(FLAG_EXTERN) && isType() ) {
      // code generate the type.
      GenRet got = typeInfo();
      return got;
    }

    // for nil, generate a void pointer of chplType dtNil
    // to allow LLVM pointer cast
    // e.g. T = ( (locale) (nil) );
    //
    // We would just compare against dtNil, but in some cases
    // the code generator needs to assign e.g.
    //   _ret:dtNil = nil
    if( typeInfo() == dtNil && 0 == strcmp(cname, "nil") ) {
      GenRet voidPtr;
      voidPtr.val = llvm::Constant::getNullValue(info->builder->getInt8PtrTy());
      voidPtr.chplType = dtNil;
      return voidPtr;
    }

    if (typeInfo() == dtBool){
      // since "true" and "false" are read into the LVT during ReadMacrosAction
      // they will generate an LLVM value of type i32 instead of i8
      if (0 == strcmp(cname, "false")){
        GenRet boolVal = new_UIntSymbol(0, INT_SIZE_8)->codegen();
        return boolVal;
      }
      if (0 == strcmp(cname, "true")){
        GenRet boolVal = new_UIntSymbol(1, INT_SIZE_8)->codegen();
        return boolVal;
      }
    }

    if(!isImmediate()) {
      // check LVT for value
      GenRet got = info->lvt->getValue(cname);
      got.chplType = typeInfo();
      if( got.val ) {
        return got;
      }
    }

    if(isImmediate()) {
      ret.isLVPtr = GEN_VAL;
      if(immediate->const_kind == CONST_KIND_STRING) {
        if(llvm::Value *value = info->module->getNamedGlobal(name)) {
          ret.val = value;
          ret.isLVPtr = GEN_PTR;
          return ret;
        }
        llvm::Value *constString = codegenImmediateLLVM(immediate);
        llvm::GlobalVariable *globalValue =
          llvm::cast<llvm::GlobalVariable>(
              info->module->getOrInsertGlobal
                  (name, info->builder->getInt8PtrTy()));
        globalValue->setConstant(true);
        globalValue->setInitializer(llvm::cast<llvm::Constant>(
              info->builder->CreateConstInBoundsGEP2_32(
#if HAVE_LLVM_VER >= 37
                NULL,
#endif
                constString, 0, 0)));
        ret.val = globalValue;
        ret.isLVPtr = GEN_PTR;
      } else {
        ret.val = codegenImmediateLLVM(immediate);
      }

      return ret;
    }

    if(std::string(cname) == "0") {
      // Chapel compiler should not make these.
      INT_FATAL(" zero value BOO ");
      return ret;
    } else if (std::string(cname) == "NULL") {
      GenRet voidPtr;
      voidPtr.val = llvm::Constant::getNullValue(info->builder->getInt8PtrTy());
      voidPtr.chplType = typeInfo();
      return voidPtr;
    }
#endif
  }

  INT_FATAL("Could not code generate %s - "
            "perhaps it is a complex macro?", cname);
  return ret;
}
Exemple #27
0
Value * CodeGenerator::genCall(const tart::FnCallExpr* in) {
  const FunctionDefn * fn = in->function();
  const FunctionType * fnType = fn->functionType();
  bool saveIntermediateStackRoots = true;

  if (fn->isIntrinsic()) {
    return fn->intrinsic()->generate(*this, in);
  }

  size_t savedRootCount = rootStackSize();

  ValueList args;
  fnType->irType(); // Need to know the irType for isStructReturn.
  Value * retVal = NULL;
  if (fnType->isStructReturn()) {
    DASSERT(in->exprType() != Expr::CtorCall); // Constructors have no return.
    retVal = builder_.CreateAlloca(fnType->returnType()->irType(), NULL, "sret");
    args.push_back(retVal);
  }

  Value * selfArg = NULL;
  if (in->selfArg() != NULL) {
    Type::TypeClass selfTypeClass = in->selfArg()->type()->typeClass();
    if (selfTypeClass == Type::Struct) {
      if (in->exprType() == Expr::CtorCall) {
        selfArg = genExpr(in->selfArg());
      } else {
        selfArg = genLValueAddress(in->selfArg());
      }
    } else {
      selfArg = genArgExpr(in->selfArg(), saveIntermediateStackRoots);
    }

    DASSERT_OBJ(selfArg != NULL, in->selfArg());

    // Upcast the self argument type.
    if (fnType->selfParam() != NULL) {
      const Type * selfType = fnType->selfParam()->type().dealias().unqualified();
      selfArg = genUpCastInstr(selfArg, in->selfArg()->type().unqualified(), selfType);
    }

    if (fn->storageClass() == Storage_Instance) {
      args.push_back(selfArg);
    }
  }

  const ExprList & inArgs = in->args();
  for (ExprList::const_iterator it = inArgs.begin(); it != inArgs.end(); ++it) {
    const Expr * arg = *it;
    QualifiedType argType = arg->canonicalType();

    Value * argVal = genArgExpr(arg, saveIntermediateStackRoots);
    if (argVal == NULL) {
      return NULL;
    }

    DASSERT_TYPE_EQ(in, argType->irParameterType(), argVal->getType());
    args.push_back(argVal);
  }

  // Generate the function to call.
  Value * fnVal;
  if (in->exprType() == Expr::VTableCall) {
    DASSERT_OBJ(selfArg != NULL, in);
    const Type * classType = fnType->selfParam()->type().dealias().unqualified();
    if (classType->typeClass() == Type::Class) {
      fnVal = genVTableLookup(fn, static_cast<const CompositeType *>(classType), selfArg);
    } else if (classType->typeClass() == Type::Interface) {
      fnVal = genITableLookup(fn, static_cast<const CompositeType *>(classType), selfArg);
    } else {
      DASSERT(classType->typeClass() == Type::Struct);
      // Struct or protocol.
      fnVal = genFunctionValue(fn);
    }
  } else {
    fnVal = genCallableDefn(fn);
  }

  Value * result = genCallInstr(fnVal, args, fn->name());
  if (in->exprType() == Expr::CtorCall) {
    // Constructor call returns the 'self' argument.
    TypeShape selfTypeShape = in->selfArg()->type()->typeShape();
    // A large value type will, at this point, be a pointer.
    if (selfTypeShape == Shape_Small_LValue) {
      selfArg = builder_.CreateLoad(selfArg, "self");
    }

    result = selfArg;
  } else if (fnType->isStructReturn()) {
    result = retVal;
  }

  // Clear out all the temporary roots
  popRootStack(savedRootCount);
  return result;
}
Exemple #28
0
bool CodeGenerator::genFunction(FunctionDefn * fdef) {
  // Don't generate undefined functions.
  if (fdef->isUndefined() || fdef->isAbstract() || fdef->isInterfaceMethod()) {
    return true;
  }

  DASSERT_OBJ(fdef->isSingular(), fdef);
  DASSERT_OBJ(fdef->type(), fdef);
  DASSERT_OBJ(fdef->type()->isSingular(), fdef);

  // Don't generate intrinsic functions.
  if (fdef->isIntrinsic()) {
    return true;
  }

  // Don't generate a function if it has been merged to another function
  if (fdef->mergeTo() != NULL || fdef->isUndefined()) {
    return true;
  }

  // Create the function
  Function * f = genFunctionValue(fdef);

  if (fdef->hasBody() && f->getBasicBlockList().empty()) {
    FunctionType * ftype = fdef->functionType();

    if (fdef->isSynthetic()) {
      f->setLinkage(GlobalValue::LinkOnceODRLinkage);
    }

    if (gcEnabled_) {
      if (SsGC) {
        f->setGC("shadow-stack");
      } else {
        f->setGC("tart-gc");
      }
    }

    if (debug_) {
      dbgContext_ = genDISubprogram(fdef);
      //dbgContext_ = genLexicalBlock(fdef->location());
      dbgInlineContext_ = DIScope();
      setDebugLocation(fdef->location());
    }

    BasicBlock * prologue = BasicBlock::Create(context_, "prologue", f);

    // Create the LLVM Basic Blocks corresponding to each high level BB.
//    BlockList & blocks = fdef->blocks();
//    for (BlockList::iterator b = blocks.begin(); b != blocks.end(); ++b) {
//      Block * blk = *b;
//      blk->setIRBlock(BasicBlock::Create(context_, blk->label(), f));
//    }

    builder_.SetInsertPoint(prologue);

    // Handle the explicit parameters
    unsigned param_index = 0;
    Function::arg_iterator it = f->arg_begin();

    Value * saveStructRet = structRet_;
    if (ftype->isStructReturn()) {
      it->addAttr(llvm::Attribute::StructRet);
      structRet_ = it;
      ++it;
    }

    // Handle the 'self' parameter
    if (ftype->selfParam() != NULL) {
      ParameterDefn * selfParam = ftype->selfParam();
      const Type * selfParamType = selfParam->type().unqualified();
      DASSERT_OBJ(fdef->storageClass() == Storage_Instance ||
          fdef->storageClass() == Storage_Local, fdef);
      DASSERT_OBJ(it != f->arg_end(), ftype);

      // Check if the self param is a root.
      if (selfParamType->isReferenceType()) {
        selfParam->setFlag(ParameterDefn::LValueParam, true);
        Value * selfAlloca = builder_.CreateAlloca(
            selfParam->type()->irEmbeddedType(), 0, "self.alloca");
        builder_.CreateStore(it, selfAlloca);
        selfParam->setIRValue(selfAlloca);
        markGCRoot(selfAlloca, NULL, "self.alloca");
      } else {
        // Since selfParam is always a pointer, we don't need to mark the object pointed
        // to as a root, since the next call frame up is responsible for tracing it.
        ftype->selfParam()->setIRValue(it);
      }

      it->setName("self");
      ++it;
    }

    // If this function needs to make allocations, cache a copy of the
    // allocation context pointer for this thread, since it can on some
    // platforms be expensive to look up.
    if (fdef->flags() & FunctionDefn::MakesAllocs) {
      Function * gcGetAllocContext = genFunctionValue(gc_allocContext);
      gcAllocContext_ = builder_.CreateCall(gcGetAllocContext, "allocCtx");
    }

    for (; it != f->arg_end(); ++it, ++param_index) {

      // Set the name of the Nth parameter
      ParameterDefn * param = ftype->params()[param_index];
      DASSERT_OBJ(param != NULL, fdef);
      DASSERT_OBJ(param->storageClass() == Storage_Local, param);
      QualifiedType paramType = param->internalType();
      it->setName(param->name());
      Value * paramValue = it;

      // If the parameter is a shared reference, then create the shared ref.
      if (param->isSharedRef()) {
        genLocalVar(param, paramValue);
        genGCRoot(param->irValue(), param->sharedRefType(), param->name());
        continue;
      }

      // If the parameter type contains any reference types, then the parameter needs
      // to be a root.
      bool paramIsRoot = false;
      if (paramType->isReferenceType()) {
        param->setFlag(ParameterDefn::LValueParam, true);
        paramIsRoot = true;
      } else if (paramType->containsReferenceType()) {
        // TODO: Handle roots of various shapes
        //param->setFlag(ParameterDefn::LValueParam, true);
      }

      // See if we need to make a local copy of the param.
      if (param->isLValue()) {
        Value * paramAlloca = builder_.CreateAlloca(paramType->irEmbeddedType(), 0, param->name());
        param->setIRValue(paramAlloca);

        if (paramType->typeShape() == Shape_Large_Value) {
          paramValue = builder_.CreateLoad(paramValue);
        }

        builder_.CreateStore(paramValue, paramAlloca);
        if (paramIsRoot) {
          genGCRoot(paramAlloca, paramType.unqualified(), param->name());
        }
      } else {
        param->setIRValue(paramValue);
      }
    }

    // Generate the body
    Function * saveFn = currentFn_;
    currentFn_ = f;
#if 0
    if (fdef->isGenerator()) {
      assert(false);
    } else {
#endif
      genLocalStorage(fdef->localScopes());
      genDISubprogramStart(fdef);
      genLocalRoots(fdef->localScopes());

      BasicBlock * blkEntry = createBlock("entry");
      builder_.SetInsertPoint(blkEntry);
      genExpr(fdef->body());

      if (!atTerminator()) {
        if (fdef->returnType()->isVoidType()) {
          builder_.CreateRetVoid();
        } else {
          // TODO: Use the location from the last statement of the function.
          diag.error(fdef) << "Missing return statement at end of non-void function.";
        }
      }

      gcAllocContext_ = NULL;
#if 0
    }
#endif

    builder_.SetInsertPoint(prologue);
    builder_.CreateBr(blkEntry);

    currentFn_ = saveFn;
    structRet_ = saveStructRet;

    if (!diag.inRecovery()) {
      if (verifyFunction(*f, PrintMessageAction)) {
        f->dump();
        DFAIL("Function failed to verify");
      }
    }

    //if (debug_ && !dbgContext_.isNull() && !dbgContext_.Verify()) {
    //  dbgContext_.Verify();
    //  DFAIL("BAD DBG");
    //}

    dbgContext_ = DIScope();
    dbgInlineContext_ = DIScope();
    builder_.ClearInsertionPoint();
    builder_.SetCurrentDebugLocation(llvm::DebugLoc());
  }

  return true;
}
Exemple #29
0
bool CallCandidate::unify(CallExpr * callExpr, BindingEnv & env, FormatStream * errStrm) {
  size_t argCount = callExpr_->argCount();
  for (size_t argIndex = 0; argIndex < argCount; ++argIndex) {
    QualifiedType paramType = this->paramType(argIndex);
    AnalyzerBase::analyzeType(paramType, Task_PrepConversion);
  }

  if (!isTemplate_) {
    return true;
  }

  // Now, for each parameter attempt unification.
  SourceContext callSite(callExpr, NULL, callExpr);
  SourceContext candidateSite(method_, &callSite, method_, Format_Type);

  // Unify explicit template arguments with template parameters.
  if (spCandidate_ != NULL) {
    if (!spCandidate_->unify(&candidateSite, env)) {
      return false;
    }
  }

  //bool hasUnsizedArgs = false;
  for (size_t argIndex = 0; argIndex < argCount; ++argIndex) {
    Expr * argExpr = callExpr_->arg(argIndex);
    QualifiedType argType = argExpr->type();
    QualifiedType paramType = this->paramType(argIndex);

    // Skip unsized type integers for now, we'll bind them on the second pass.
    if (!env.unify(&candidateSite, paramType, argType, Constraint::LOWER_BOUND)) {
      if (errStrm) {
        *errStrm << "Argument #" << argIndex + 1 << " type " << paramType <<
            " failed to unify with " << argType;
      }
      return false;
    }
  }

  // Unify the return type
  QualifiedType expectedReturnType = callExpr_->expectedReturnType();
  if (!expectedReturnType.isNull()) {
    if (!env.unify(&candidateSite, resultType_, expectedReturnType, Constraint::UPPER_BOUND)) {
      if (errStrm) {
        *errStrm << "Return type " << expectedReturnType << " failed to unify with " << resultType_;
      }
      return false;
    }
  }

  // A proper unification requires that each template parameter be bound to something.
  for (Defn * def = method_; def != NULL && !def->isSingular(); def = def->parentDefn()) {
    Template * ts = def->templateSignature();
    if (ts != NULL) {
      size_t numParams = ts->typeParams()->size();
      // For each template parameter, create a TypeAssignment instance.
      for (size_t i = 0; i < numParams; ++i) {
        const TypeVariable * var = ts->patternVar(i);
        const TypeAssignment * ta = env.getAssignment(var, this);
        if (ta->constraints().empty()) {
          if (errStrm) {
            *errStrm << "No binding for template parameter " << var << " in " << env;
          }
          return false;
        }
      }
    }
  }

  return true;
}