// 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) ; } }
static String handle_static_variable_symbol(CPrintStyleModule *map, const SuifObject *obj) { VariableSymbol *var = to<VariableSymbol>(obj); // I'd like to figure out what procedure and BLOCK scope this // is in... return(String(var->get_name())); }
void ConstantArrayPropagationPass::CollectInitializations() { if (!initializations.empty()) { initializations.clear() ; } DefinitionBlock* procDefBlock = procDef->get_definition_block() ; assert(procDefBlock != NULL) ; Iter<VariableDefinition*> varDefIter = procDefBlock->get_variable_definition_iterator() ; while (varDefIter.is_valid()) { VariableDefinition* varDef = varDefIter.current() ; assert(varDef != NULL) ; VariableSymbol* varSym = varDef->get_variable_symbol() ; ValueBlock* valBlock = varDef->get_initialization() ; assert(varSym != NULL) ; assert(valBlock != NULL) ; if (ValidSymbol(varSym)) { initializations[varSym] = valBlock ; varSym->append_annote(create_brick_annote(theEnv, "ConstPropArray")) ; } varDefIter.next() ; } }
void LUTDetectionPass::do_procedure_definition(ProcedureDefinition* p) { procDef = p ; assert(procDef != NULL) ; OutputInformation("LUT Detection Pass begins") ; // LUTs can only exist in New Style Systems or Modules if (isLegacy(procDef)) { OutputInformation("Legacy code - No LUTs supported") ; return ; } // LUTs are defined to be arrays that are not parameter symbols SymbolTable* symTab = procDef->get_symbol_table() ; for (int i = 0 ; i < symTab->get_symbol_table_object_count() ; ++i) { SymbolTableObject* currentObject = symTab->get_symbol_table_object(i) ; VariableSymbol* currentVar = dynamic_cast<VariableSymbol*>(currentObject) ; ParameterSymbol* currentParam = dynamic_cast<ParameterSymbol*>(currentObject) ; if (currentVar != NULL && dynamic_cast<ArrayType*>(currentVar->get_type()->get_base_type()) != NULL && currentParam == NULL && currentVar->lookup_annote_by_name("ConstPropArray") == NULL) { // Found one! Let's mark it! currentObject->append_annote(create_brick_annote(theEnv, "LUT")) ; } } OutputInformation("LUT Detection Pass ends") ; }
void CopyPropagationPass2::Initialize() { // I don't want to delete any of the statements, but I must clear // out the list I was using to contain the statements if (!toBeRemoved.empty()) { while (toBeRemoved.begin() != toBeRemoved.end()) { toBeRemoved.pop_front() ; } } assert(procDef != NULL) ; InitializeMap() ; // Also, collect all of the feedback variables for later SymbolTable* procSymTable = procDef->get_symbol_table() ; assert(procSymTable != NULL) ; for (int i = 0 ; i < procSymTable->get_symbol_table_object_count() ; ++i) { if(dynamic_cast<VariableSymbol*>(procSymTable->get_symbol_table_object(i)) != NULL) { VariableSymbol* nextSymbol = dynamic_cast<VariableSymbol*>(procSymTable->get_symbol_table_object(i)); if (nextSymbol->lookup_annote_by_name("FeedbackVariable") != NULL) { feedbackVariables.push_back(nextSymbol) ; } } } }
std::shared_ptr<ExpressionNode> VariableNode::evaluate(Environment* e) { VariableSymbol* vs = 0; if ((vs = e->getVariable(name))) { // double parantheses because return vs->getValue()->evaluate(e); // compiler is a smartass otherwise } else return shared_from_this(); }
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) ; }
// This is a vastly simpler way to setup annotations that doesn't worry // or assume that all feedbacks come from a single store variable statement void SolveFeedbackVariablesPass3::SetupAnnotations() { assert(theEnv != NULL) ; // Go through the list of all feedback instances we have discovered. list<PossibleFeedbackPair>::iterator feedbackIter = actualFeedbacks.begin(); while (feedbackIter != actualFeedbacks.end()) { // For every feedback, we need to create a two variables // The first one is a replacement for the original use. // The second one is the variable used for feedback. LString replacementName = (*feedbackIter).varSym->get_name() ; replacementName = replacementName + "_replacementTmp" ; VariableSymbol* replacementVariable = create_variable_symbol(theEnv, (*feedbackIter).varSym->get_type(), TempName(replacementName)) ; procDef->get_symbol_table()->append_symbol_table_object(replacementVariable); VariableSymbol* feedbackVariable = create_variable_symbol(theEnv, (*feedbackIter).varSym->get_type(), TempName(LString("feedbackTmp"))) ; procDef->get_symbol_table()->append_symbol_table_object(feedbackVariable) ; // Replace the use with this new feedback variable (*feedbackIter).use->set_source(replacementVariable) ; // I am looking for the variable that originally defined me and // the variable that will replace me. Statement* definition = (*feedbackIter).definition ; VariableSymbol* definitionVariable = GetDefinedVariable(definition, (*feedbackIter).definitionLocation) ; assert(definitionVariable != NULL) ; // Finally, annotate the feedback variable SetupAnnotations(feedbackVariable, definitionVariable, replacementVariable) ; replacementVariable->append_annote(create_brick_annote(theEnv, "NonInputScalar")); ++feedbackIter ; } }
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) ; } } } }
VarDecl * NameResolver::HandleVarDecl(NameToken name, TypeSpecifier &spec, Expression *init) { Scope *scope = getOrCreateScope(); // :TODO: set variadic info VarDecl *var = new (pool_) VarDecl(name, init); // Note: the parser has already bound |var->init()| at this point, meaning // that aside from globals it should be impossible to self-initialize like: // int x = x; // // :TODO: do check this for globals. VariableSymbol *sym = new (pool_) VariableSymbol(var, scope, var->name()); registerSymbol(sym); var->setSymbol(sym); // Set this before we evaluate the type, since it determines whether or not // a const on a parameter is meaningless. if (spec.isByRef()) { assert(scope->kind() == Scope::Argument && sym->isArgument()); sym->storage_flags() |= StorageFlags::byref; } // See the comment in TypeResolver::visitVarDecl for why we do not want to // infer sizes from literals for arguments. if (init && !scope->isArgument() && ((init->isArrayLiteral() && init->asArrayLiteral()->isFixedArrayLiteral()) || (init->isStringLiteral()))) { // Wait until the type resolution pass to figure this out. We still have // to precompute the base though. if (Type *type = resolveBase(spec)) spec.setResolvedBaseType(type); var->te() = TypeExpr(new (pool_) TypeSpecifier(spec)); } else { VarDeclSpecHelper helper(var, nullptr); var->te() = resolve(spec, &helper); } if (var->te().resolved()) { sym->setType(var->te().resolved()); // We need to check this both here and in lazy resolution, which is gross, // but I don't see any obvious way to simplify it yet. if (spec.isByRef() && sym->type()->passesByReference()) { cc_.report(spec.byRefLoc(), rmsg::type_cannot_be_ref) << sym->type(); } } // Even if we were able to resolve the type, if we have to resolve a constant // value, we'll have to add it to the resolver queue. if (!var->te().resolved() || sym->canUseInConstExpr()) tr_.addPending(var); return var; }
void SemanticAnalysis::visitNameProxy(NameProxy *proxy) { Symbol *sym = proxy->sym(); VariableSymbol *var = sym->asVariable(); // If we see that a symbol is a function literal, then we bypass the scope // chain operations entirely and hardcode the function literal. if (sym->isFunction()) { assert(sym->scope()->kind() == Scope::Global); hir_ = new (pool_) HFunction(proxy, sym->asFunction()); return; } if (value_context_ == kLValue) { // Egads! We're being asked to construct an l-value instead of an r-value. *outp_ = LValue(var); return; } Scope *in = sym->scope(); switch (in->kind()) { case Scope::Global: hir_ = new (pool_) HGlobal(proxy, var); return; case Scope::Function: { assert(var->storage() == VariableSymbol::Arg); // Since we're in an r-value context, we need to strip the reference type. Type *type = var->type(); if (type->isReference()) type = type->toReference()->contained(); hir_ = new (pool_) HLocal(proxy, type, var); return; } default: assert(in->kind() == Scope::Block); assert(var->storage() == VariableSymbol::Local); hir_ = new (pool_) HLocal(proxy, var->type(), var); return; } }
bool VarDeclSpecHelper::receiveConstQualifier(CompileContext &cc, const SourceLocation &constLoc, Type *type) { VariableSymbol *sym = decl_->sym(); if (sym->isArgument()) { if (!!(sym->storage_flags() & StorageFlags::byref)) { cc.report(constLoc, rmsg::const_ref_has_no_meaning) << type; return true; } if (!type->passesByReference()) { cc.report(constLoc, rmsg::const_has_no_meaning) << type; return true; } } else if (TypeSupportsCompileTimeInterning(type)) { sym->storage_flags() |= StorageFlags::constval; } sym->storage_flags() |= StorageFlags::readonly; return true; }
void CleanupRedundantVotes::ProcessCall(CallStatement* c) { assert(c != NULL) ; SymbolAddressExpression* symAddress = dynamic_cast<SymbolAddressExpression*>(c->get_callee_address()) ; assert(symAddress != NULL) ; Symbol* sym = symAddress->get_addressed_symbol() ; assert(sym != NULL) ; if (sym->get_name() == LString("ROCCCTripleVote") || sym->get_name() == LString("ROCCCDoubleVote") ) { LoadVariableExpression* errorVariableExpression = dynamic_cast<LoadVariableExpression*>(c->get_argument(0)) ; assert(errorVariableExpression != NULL) ; VariableSymbol* currentError = errorVariableExpression->get_source() ; assert(currentError != NULL) ; if (InList(currentError)) { // Create a new variable VariableSymbol* errorDupe = create_variable_symbol(theEnv, currentError->get_type(), TempName(LString("UnrolledRedundantError"))) ; errorDupe->append_annote(create_brick_annote(theEnv, "DebugRegister")) ; procDef->get_symbol_table()->append_symbol_table_object(errorDupe) ; usedVariables.push_back(errorDupe) ; errorVariableExpression->set_source(errorDupe) ; } else { usedVariables.push_back(currentError) ; } } }
void ScalarReplacementPass2::ProcessLoad(LoadExpression* e) { assert(e != NULL) ; Expression* innerExp = e->get_source_address() ; ArrayReferenceExpression* innerRef = dynamic_cast<ArrayReferenceExpression*>(innerExp) ; if (innerRef == NULL) { return ; } // Again, don't process lookup tables if (IsLookupTable(GetArrayVariable(innerRef))) { return ; } VariableSymbol* replacement = NULL ; list<std::pair<Expression*, VariableSymbol*> >::iterator identIter = Identified.begin() ; while (identIter != Identified.end()) { if (EquivalentExpressions((*identIter).first, innerRef)) { replacement = (*identIter).second ; break ; } ++identIter ; } assert(replacement != NULL) ; LoadVariableExpression* loadVar = create_load_variable_expression(theEnv, replacement->get_type()->get_base_type(), replacement) ; e->get_parent()->replace(e, loadVar) ; }
void TransformUnrolledArraysPass::TransformNDIntoNMinusOneD(int N) { // Get all unique N-dimensional arrays CollectArrays(N) ; // For every array access that has a constant as one of its offsets, // we have to create a new array list<VariableSymbol*> arraysToRemove ; list<EquivalentReferences*>::iterator refIter = currentReferences.begin() ; while (refIter != currentReferences.end()) { VariableSymbol* originalSymbol = GetArrayVariable((*refIter)->original) ; // Lookup tables should not be transformed if (originalSymbol->lookup_annote_by_name("LUT") == NULL) { bool replaced = ReplaceNDReference(*refIter) ; if (replaced) { if (!InList(arraysToRemove, originalSymbol)) { arraysToRemove.push_back(originalSymbol) ; } } } ++refIter ; } // Remove all of the arrays that need to be removed list<VariableSymbol*>::iterator arrayIter = arraysToRemove.begin() ; while (arrayIter != arraysToRemove.end()) { procDef->get_symbol_table()->remove_symbol_table_object(*arrayIter) ; ++arrayIter ; } }
std::shared_ptr<ExpressionNode> AssignmentNode::evaluate(Environment* e) { std::shared_ptr<ExpressionNode> newValue = b->evaluate(e); std::shared_ptr<VariableNode> var = std::dynamic_pointer_cast<VariableNode> (a); if (var.get()->equals(newValue.get())) return shared_from_this(); if (var) { const std::string varName = var->getString(); VariableSymbol* vs = e->getVariable(varName); if (vs) vs->setValue(newValue); else e->addSymbol(new VariableSymbol(var->getString(), newValue)); } else { throw ArithmeticException("left side of assignment must be a variable"); } return std::make_shared<AssignmentNode> (a, newValue); }
void One2MultiArrayExpressionPass::do_procedure_definition(ProcedureDefinition* proc_def) { bool kill_all = !(_preserve_one_dim->is_set()); // access all array type declarations and create corresponding multi array types SuifEnv* suif_env = proc_def->get_suif_env(); TypeBuilder* tb = (TypeBuilder*)suif_env-> get_object_factory(TypeBuilder::get_class_name()); (void) tb; // avoid warning #ifdef CONVERT_TYPES for (Iter<ArrayType> at_iter = object_iterator<ArrayType>(proc_def); at_iter.is_valid();at_iter.next()) { MultiDimArrayType* multi_type = converter->array_type2multi_array_type(&at_iter.current()); } #endif //CONVERT_TYPES // collect tops of array access chains into this list list<ArrayReferenceExpression*> ref_exprs; for (Iter<ArrayReferenceExpression> are_iter = object_iterator<ArrayReferenceExpression>(proc_def); are_iter.is_valid(); are_iter.next()) { // itself an array and parent is *not* an array ArrayReferenceExpression* are = &are_iter.current(); if((kill_all || is_kind_of<ArrayReferenceExpression>(are->get_base_array_address())) && !is_kind_of<ArrayReferenceExpression>(are->get_parent())) { //printf("%p \t", are);are->print_to_default(); ref_exprs.push_back(are); } } // for top all expressions, convert them to multi-exprs for(list<ArrayReferenceExpression*>::iterator ref_iter = ref_exprs.begin(); ref_iter != ref_exprs.end(); ref_iter++) { ArrayReferenceExpression* top_array = *ref_iter; converter->convert_array_expr2multi_array_expr(top_array); } #ifdef CONVERT_TYPES // replace the types of all array variables for (Iter<VariableSymbol> iter = object_iterator<VariableSymbol>(proc_def); iter.is_valid();iter.next()) { VariableSymbol* vd = &iter.current(); DataType *vtype = tb->unqualify_data_type(vd->get_type()); if (is_kind_of<ArrayType>(vtype)) { MultiDimArrayType* multi_type = converter->array_type2multi_array_type(to<ArrayType>(vtype)); vd->replace(vd->get_type(), tb->get_qualified_type(multi_type)); } } // remove the remaining one-dim array types converter->remove_all_one_dim_array_types(); #endif //CONVERT_TYPES // make sure no traces of single-dim arrays are left if(kill_all){ {for(Iter<ArrayReferenceExpression> iter = object_iterator<ArrayReferenceExpression>(proc_def); iter.is_valid(); iter.next()) { // ArrayReferenceExpression* are = &iter.current(); //are->print_to_default(); printf("at %p \t", are); suif_assert_message(false, ("ARE not eliminated")); } } #ifdef CONVERT_TYPES {for(Iter<ArrayType> iter = object_iterator<ArrayType>(proc_def); iter.is_valid(); iter.next()) {suif_assert_message(false, ("ArrayType not eliminated"));}} #endif } }
void ScalarReplacementPass2::CollectArrayReferences() { assert(procDef != NULL) ; list<ArrayReferenceExpression*>* allRefs = collect_objects<ArrayReferenceExpression>(procDef->get_body()) ; list<ArrayReferenceExpression*>::iterator refIter = allRefs->begin() ; while (refIter != allRefs->end()) { // If this is not the topmost array reference, skip it. if (dynamic_cast<ArrayReferenceExpression*>((*refIter)->get_parent()) != NULL) { ++refIter ; continue ; } // Also, skip lookup tables if (IsLookupTable(GetArrayVariable(*refIter))) { ++refIter ; continue ; } bool found = false ; std::pair<Expression*, VariableSymbol*> toAdd ; list<std::pair<Expression*, VariableSymbol*> >::iterator identIter = Identified.begin() ; while (identIter != Identified.end()) { if (EquivalentExpressions((*identIter).first, *refIter)) { found = true ; toAdd = (*identIter) ; break ; } ++identIter ; } if (!found) { VariableSymbol* replacement = create_variable_symbol(theEnv, GetQualifiedTypeOfElement(*refIter), TempName(LString("suifTmp"))) ; replacement->append_annote(create_brick_annote(theEnv, "ScalarReplacedVariable")) ; procDef->get_symbol_table()->append_symbol_table_object(replacement) ; toAdd.first = (*refIter) ; toAdd.second = replacement ; Identified.push_back(toAdd) ; } if (dynamic_cast<LoadExpression*>((*refIter)->get_parent()) != NULL) { found = false ; identIter = IdentifiedLoads.begin() ; while (identIter != IdentifiedLoads.end()) { if (EquivalentExpressions((*identIter).first, *refIter)) { found = true ; break ; } ++identIter ; } if (!found) { IdentifiedLoads.push_back(toAdd) ; } } else if (dynamic_cast<StoreStatement*>((*refIter)->get_parent()) != NULL) { found = false ; identIter = IdentifiedStores.begin() ; while (identIter != IdentifiedStores.end()) { if (EquivalentExpressions((*identIter).first, *refIter)) { found = true ; break ; } ++identIter ; } if (!found) { IdentifiedStores.push_back(toAdd) ; } } else { assert(0 && "Improperly formatted array reference!") ; } ++refIter ; } delete allRefs ; }
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()) ; }
void EliminateArrayConvertsPass::do_procedure_definition(ProcedureDefinition* proc_def){ suif_hash_map<ParameterSymbol*, Type*> params; TypeBuilder *tb = (TypeBuilder*) get_suif_env()->get_object_factory(TypeBuilder::get_class_name()); // collect all procedure parameters of pointer type into params list for(Iter<ParameterSymbol*> iter = proc_def->get_formal_parameter_iterator(); iter.is_valid(); iter.next()) { ParameterSymbol* par_sym = iter.current(); Type* par_type = tb->unqualify_type(par_sym->get_type()); if(is_kind_of<PointerType>(par_type)){ // put NULLs into the map at first, // they will later be overwritten params[par_sym] = NULL; } } if(params.size()==0) return; // nothing to do // walk thru all AREs and look for arrays that are in the param list {for(Iter<ArrayReferenceExpression> iter = object_iterator<ArrayReferenceExpression>(proc_def); iter.is_valid(); iter.next()) { ArrayReferenceExpression* are = &iter.current(); if(is_kind_of<UnaryExpression>(are->get_base_array_address())){ UnaryExpression* ue = to<UnaryExpression>(are->get_base_array_address()); if(ue->get_opcode() == k_convert){ if(is_kind_of<LoadVariableExpression>(ue->get_source())){ LoadVariableExpression* lve = to<LoadVariableExpression>(ue->get_source()); VariableSymbol* array = lve->get_source(); for(suif_hash_map<ParameterSymbol*, Type*>::iterator iter = params.begin(); iter!=params.end();iter++) { ParameterSymbol* par_sym = (*iter).first; if(par_sym == array){ // match! Type* array_type; suif_hash_map<ParameterSymbol*, Type*>::iterator iter = params.find(par_sym); if(iter==params.end() || (*iter).second==NULL){ //array_type = to<PointerType>(ue->get_result_type())->get_reference_type(); array_type = tb->get_qualified_type(ue->get_result_type()); params[par_sym] = array_type; //printf("%s has type ",par_sym->get_name().c_str()); //array_type->print_to_default(); }else{ array_type = params[par_sym].second; suif_assert(is_kind_of<QualifiedType>(array_type)); } array->replace(array->get_type(), array_type); remove_suif_object(ue); remove_suif_object(lve); lve->replace(lve->get_result_type(), tb->unqualify_type(array_type)); // put the LoadVar directly under ARE are->set_base_array_address(lve); //are->print_to_default(); } } } else { suif_warning(ue->get_source(), ("Expecting a LoadVariableExpression here")); } } else { suif_warning(ue, ("Disallow converts in AREs for " "things other than procedure parameters")); } } } } }
// 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 ; }
Statement *for_statement_walker::dismantle_for_statement(ForStatement *the_for){ StatementList *replacement = create_statement_list(the_for->get_suif_env()); VariableSymbol* index = the_for->get_index(); DataType *type = unqualify_data_type(index->get_type()); Expression *lower = the_for->get_lower_bound(); Expression *upper = the_for->get_upper_bound(); Expression *step = the_for->get_step(); LString compare_op = the_for->get_comparison_opcode(); Statement* body = the_for->get_body(); Statement* pre_pad = the_for->get_pre_pad(); // Statement* post_pad = the_for->get_post_pad(); CodeLabelSymbol* break_lab = the_for->get_break_label(); CodeLabelSymbol* continue_lab = the_for->get_continue_label(); the_for->set_index(0); remove_suif_object(lower); remove_suif_object(upper); remove_suif_object(step); remove_suif_object(body); remove_suif_object(pre_pad); // the_for->set_post_pad(0); // remove_suif_object(post_pad); the_for->set_break_label(0); the_for->set_continue_label(0); // I am guessing what pre-pad and post-pad do if(pre_pad != 0)replacement->append_statement(pre_pad); // initialize the index. Is this right? should we ever initialize to upper, for -ve steps? // Is index guaranteed not to be changed? Should we be creating a temporary? replacement->append_statement(create_store_variable_statement(body->get_suif_env(),index,lower)); replacement->append_statement(create_label_location_statement(body->get_suif_env(), continue_lab)); if (body != 0) replacement->append_statement(body); // increment the counter Expression *index_expr = create_load_variable_expression(body->get_suif_env(), unqualify_data_type(index->get_type()), index); Expression *increment = create_binary_expression(body->get_suif_env(),type,k_add, index_expr,step); replacement->append_statement(create_store_variable_statement(body->get_suif_env(),index,increment)); // and loop if not out of range Expression *compare = create_binary_expression(body->get_suif_env(),type, compare_op, deep_suif_clone<Expression>(index_expr), deep_suif_clone<Expression>(step)); replacement->append_statement(create_branch_statement(body->get_suif_env(),compare,continue_lab)); // end of loop replacement->append_statement(create_label_location_statement(body->get_suif_env(),break_lab)); // if(post_pad != 0)replacement->append_statement(post_pad); the_for->get_parent()->replace(the_for,replacement); return replacement; }
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 ; }
void TransformSystemsToModules::HandleFeedback() { assert(procDef != NULL) ; list<VariableSymbol*> toReplace ; // This function needs to find all variables that are both input and // output scalars (they used to be feedbacks, but now there is no loop) SymbolTable* procSymTab = procDef->get_symbol_table() ; 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 && nextObject->lookup_annote_by_name("OutputVariable") != NULL) { VariableSymbol* var = dynamic_cast<VariableSymbol*>(nextObject) ; assert(var != NULL) ; toReplace.push_back(var) ; } } // Now, go through all of the different values that need to be replaced and // find all of the uses and definitions and replace them... list<VariableSymbol*>::iterator replaceIter = toReplace.begin() ; while (replaceIter != toReplace.end()) { LString inputName = (*replaceIter)->get_name() ; inputName = inputName + LString("_in") ; LString outputName = (*replaceIter)->get_name() ; outputName = outputName + LString("_out") ; // Create two variables, one for input and one for output VariableSymbol* inputReplacement = create_variable_symbol(theEnv, (*replaceIter)->get_type(), inputName) ; VariableSymbol* outputReplacement = create_variable_symbol(theEnv, (*replaceIter)->get_type(), outputName) ; procDef->get_symbol_table()->append_symbol_table_object(inputReplacement) ; procDef->get_symbol_table()->append_symbol_table_object(outputReplacement); inputReplacement->append_annote(create_brick_annote(theEnv, "InputScalar")) ; outputReplacement->append_annote(create_brick_annote(theEnv, "OutputVariable")) ; // Find all uses before the first definition and replace them with the // input variable. ReplaceUses((*replaceIter), inputReplacement) ; // Find the last definition and replace it with the output variable. ReplaceDefinition((*replaceIter), outputReplacement) ; // Remove the annotes that started the whole thing delete (*replaceIter)->remove_annote_by_name("InputScalar") ; delete (*replaceIter)->remove_annote_by_name("OutputVariable") ; ++replaceIter ; } }
void TypeResolver::visitVarDecl(VarDecl *node) { VariableSymbol *sym = node->sym(); assert(!sym->type()); Type* type; if (TypeSpecifier *spec = node->te().spec()) { // We always infer sizes for postdims in variable scope. In argument // scope, we don't want something like: // // f(x[] = {}), or // // To infer as int[0]. However, this should be illegal: // // f(int x[] = {}) // // So we simply never infer dimensions for arguments. // // Note: we should not be able to recurse from inside this block. If it // could, we'd have to mark spec as resolving earlier. Vector<int> literal_dims; if (Expression *init = node->initialization()) { if (spec->hasPostDims() && !sym->isArgument()) { // Compute the dimensions of initializers in case the declaration type // requires inference. if (ArrayLiteral *lit = init->asArrayLiteral()) { literal_dims = fixedArrayLiteralDimensions(spec, lit); } else if (StringLiteral *lit = init->asStringLiteral()) { literal_dims.append(lit->arrayLength()); } } } VarDeclSpecHelper helper(node, &literal_dims); type = resolveType(node->te(), &helper); } else { type = node->te().resolved(); } if (!assignTypeToSymbol(sym, type)) return; if (sym->isConstExpr() || !sym->canUseInConstExpr()) return; // If we're currently trying to resolve this variable's constant // expression, report an error. if (sym->isResolvingConstExpr()) { cc_.report(node->loc(), rmsg::recursive_constexpr) << sym->name(); // Pawn requires that const variables have constexprs, so we just set a // default one to quell as many other errors as we can. In the future we // may want to lax this restriction. sym->setConstExpr(DefaultValueForPlainType(sym->type())); return; } // We got a constexpr with no initialization. Just assume it's 0, but // report an error as SP1 does. if (!node->initialization()) { cc_.report(node->loc(), rmsg::constant_var_needs_constexpr) << sym->name(); sym->setConstExpr(DefaultValueForPlainType(sym->type())); return; } sym->setResolvingConstExpr(); // In Pawn, a const var *must* be a constexpr. We only care about this for // ints/floats since constexprs aren't really relevant yet otherwise. BoxedValue box; ConstantEvaluator ceval(cc_, this, ConstantEvaluator::Required); switch (ceval.Evaluate(node->initialization(), &box)) { case ConstantEvaluator::Ok: break; case ConstantEvaluator::NotConstant: cc_.report(node->loc(), rmsg::constant_var_needs_constexpr) << sym->name(); // FALLTHROUGH. case ConstantEvaluator::TypeError: // Error has already been reported. box = DefaultValueForPlainType(sym->type()); break; default: assert(false); } // :TODO: type check box sym->setConstExpr(box); }