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 SingleInheritanceVtbls::attach_vtbl( SingleInheritanceClassType* ctype, VariableSymbol* vsym ) { VariableDefinition* vdef = get_vtbl( ctype ); vdef->set_variable_symbol( vsym ); vsym->set_definition( vdef ); // Insert reference to vsym in ClassType ctype->set_vtbl_symbol( vsym ); // Insert vdef in ClassType ctype->get_definition_block()->append_variable_definition( vdef ); // Set type of vsym DataType* vtbl_type = vdef->get_initialization()->get_type(); QualifiedType* q_vtbl_type = _tb->get_qualified_type( vtbl_type ); vsym->set_type( q_vtbl_type ); }
/* * print_var_def() -- Generates assembly language data statements. * Data objects are put into the sdata section, data section, comm * section, or the lcomm section. If the data object is global, I * also specify a .globl pseudo-op. */ void PrinterX86::print_var_def(VarSym *vsym) { int vsym_size = get_bit_size(get_type(vsym)) >> 3; // in bytes VariableDefinition *vdef = vsym->get_definition(); if (vdef == NULL || (vdef->get_initialization() == NULL) // FIXME: shouldn't be possible || is_a<UndefinedValueBlock>(vdef->get_initialization())) { // Uninitialized data item. If global symbol, append to // .comm, else static symbol to .lcomm. if (is_global(vsym) && !is_private(vsym)) fprintf(out, "\t%s\t", x86_opcode_names[COMM]); else fprintf(out, "\t%s\t", x86_opcode_names[LCOMM]); print_sym(vsym); fprintf(out, ", %d\n", vsym_size); } else { // initialized data item // Specify data section to place data in. On x86, always use // .data section. fprintf(out, "\t%s\n", x86_opcode_names[DATA]); // If global symbol, add .globl pseudo-op. Note that a variable // is considered global in SUIF if it is part of the global or // file symbol table. For X86 assembly, a datum is global only // if it is part of the global symbol table (i.e. is_private() // checks for def in file symbol table). if (is_global(vsym) && !is_private(vsym)) { fprintf(out, "\t%s\t", x86_opcode_names[GLOBL]); print_sym(vsym); fprintf(out, "\n"); } // Determine alignment and align int bit_alignment = get_bit_alignment(vdef); // If vdef's alignment is zero (shouldn't be!), use that in vsym's type if (bit_alignment == 0) bit_alignment = get_bit_alignment(get_type(vsym)); int alignment_value; switch (bit_alignment) { case 8: // byte aligned alignment_value = 0; break; case 16: // halfword aligned alignment_value = 1; break; case 32: // word aligned alignment_value = 2; break; case 64: // double word aligned alignment_value = 3; break; case 128: // quad word aligned alignment_value = 4; break; default: claim(false, "bad alignment for %s", get_name(vsym).chars()); } fprintf(out, "\t%s\t%d\n", x86_opcode_names[ALIGN], alignment_value); // Disable automatic alignment fprintf(out, "\t%s\t%d\t# %s\n", x86_opcode_names[ALIGN], 0, "disable automatic alignment"); // Write out the label print_sym(vsym); fprintf(out, ":"); // return added in process_value_block // initialize memory with values cur_opcode = opcode_null; cur_opnd_cnt = 0; process_value_block(vdef->get_initialization()); fprintf(out, "\n"); } }
bool Expression::fold(bool mustFold, bool forbidUndefined, std::vector<Definition*>& expansionStack) { // expansionStack contains a stack of all named constants that are being expanded. // This is the max size that this stack is allowed to grow. const unsigned int EXPANSION_STACK_MAX = 16; if(folded) { return true; } switch(expressionType) { case NUMBER: { folded = true; foldedValue = number->getValue(); break; } case ATTRIBUTE: { Definition* def = attribute->findDefinition(forbidUndefined); // Get the position of the attribute's first element, used for errors. SourcePosition* pos = attribute->getPieces()->getList().front()->getSourcePosition(); if(def) { switch(def->getDefinitionType()) { case Definition::CONSTANT: { ConstantDefinition* constant = (ConstantDefinition*) def; Expression* expression = constant->getConstantDeclaration()->getExpression(); expansionStack.push_back(constant); if(expansionStack.size() > EXPANSION_STACK_MAX) { std::ostringstream os; os << "too many constant expansions required (exceeded max depth " << EXPANSION_STACK_MAX << "). are there mutually-dependent constants?"; for(size_t i = 0; i < expansionStack.size(); i++) { Definition* entry = expansionStack[i]; os << std::endl << " `" << entry->getName() << "` at " << entry->getDeclarationPoint(); } error(os.str(), pos, true); } else { folded = expression->fold(mustFold, forbidUndefined, expansionStack); } expansionStack.pop_back(); foldedValue = expression->getFoldedValue(); break; } case Definition::LABEL: { LabelDefinition* label = (LabelDefinition*) def; folded = label->isLocationKnown(); foldedValue = label->getLocation(); break; } case Definition::VARIABLE: { VariableDefinition* var = (VariableDefinition*) def; folded = true; foldedValue = var->getOffset(); break; } case Definition::PACKAGE: { std::ostringstream os; os << "package `" << attribute->getName() << "` may not be directly used in a numeric expression because it's a scope, lacking any address or numeric value."; error(os.str(), pos); folded = false; forbidUndefined = true; // this line is to prevent more the general 'indeterminate value' message below. break; } } } // If there is no known value when one is expected, then error. // Another error will trigger instead if undefined attributes are // forbidden on the current compiler pass and the symbol wasn't found. if((def || !forbidUndefined) && !folded && mustFold) { std::ostringstream os; os << "attribute `" << attribute->getName() << "` has an indeterminate value."; error(os.str(), pos); } break; } case OPERATION: { operation->getLeft()->fold(mustFold, forbidUndefined, expansionStack); operation->getRight()->fold(mustFold, forbidUndefined, expansionStack); if(!operation->getLeft()->isFolded() || !operation->getRight()->isFolded()) { return false; } folded = true; unsigned int ls = operation->getLeft()->getFoldedValue(); unsigned int rs = operation->getRight()->getFoldedValue(); switch(operation->getOperationType()) { case Operation::MUL: { if(ls > MAX_VALUE / rs) { error("multiplication yields result which will overflow outside of 0..65535.", operation->getRight()->getSourcePosition()); folded = false; } else { foldedValue = ls * rs; } break; } case Operation::DIV: { if(rs == 0) { error("division by zero is undefined.", operation->getRight()->getSourcePosition()); folded = false; } else { foldedValue = ls / rs; } break; } case Operation::MOD: { if(rs == 0) { error("modulo by zero is undefined.", operation->getRight()->getSourcePosition()); folded = false; } else { foldedValue = ls / rs; } break; } case Operation::ADD: { if(ls + MAX_VALUE < rs) { error("addition yields result which will overflow outside of 0..65535.", operation->getRight()->getSourcePosition()); folded = false; } else { foldedValue = ls + rs; } break; } case Operation::SUB: { if(ls < rs) { error("subtraction yields result which will overflow outside of 0..65535.", operation->getRight()->getSourcePosition()); folded = false; } else { foldedValue = ls - rs; } break; } case Operation::SHL: { // If shifting more than N bits, or ls << rs > 2^N-1, then error. if(rs > 16 || rs > 0 && (ls & ~(1 << (16 - rs))) != 0) { error("logical shift left yields result which will overflow outside of 0..65535.", operation->getRight()->getSourcePosition()); folded = false; } else { foldedValue = ls << rs; } break; } case Operation::SHR: { foldedValue = ls >> rs; break; } case Operation::BITWISE_AND: { foldedValue = ls & rs; break; } case Operation::BITWISE_XOR: { foldedValue = ls ^ rs; break; } case Operation::BITWISE_OR: { foldedValue = ls | rs; break; } } break; } } return folded; }