duke@435: /* kvn@3882: * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA trims@1907: * or visit www.oracle.com if you need additional information or have any trims@1907: * questions. duke@435: * duke@435: */ duke@435: duke@435: // FORMS.CPP - Definitions for ADL Parser Forms Classes duke@435: #include "adlc.hpp" duke@435: duke@435: //==============================Register Allocation============================ duke@435: int RegisterForm::_reg_ctr = 0; duke@435: duke@435: //------------------------------RegisterForm----------------------------------- duke@435: // Constructor duke@435: RegisterForm::RegisterForm() duke@435: : _regDef(cmpstr,hashstr, Form::arena), duke@435: _regClass(cmpstr,hashstr, Form::arena), duke@435: _allocClass(cmpstr,hashstr, Form::arena) { duke@435: } duke@435: RegisterForm::~RegisterForm() { duke@435: } duke@435: duke@435: // record a new register definition duke@435: void RegisterForm::addRegDef(char *name, char *callingConv, char *c_conv, duke@435: char *idealtype, char *encoding, char* concrete) { duke@435: RegDef *regDef = new RegDef(name, callingConv, c_conv, idealtype, encoding, concrete); duke@435: _rdefs.addName(name); duke@435: _regDef.Insert(name,regDef); duke@435: } duke@435: duke@435: // record a new register class duke@435: RegClass *RegisterForm::addRegClass(const char *className) { duke@435: RegClass *regClass = new RegClass(className); duke@435: _rclasses.addName(className); duke@435: _regClass.Insert(className,regClass); duke@435: return regClass; duke@435: } duke@435: duke@435: // record a new register class duke@435: AllocClass *RegisterForm::addAllocClass(char *className) { duke@435: AllocClass *allocClass = new AllocClass(className); duke@435: _aclasses.addName(className); duke@435: _allocClass.Insert(className,allocClass); duke@435: return allocClass; duke@435: } duke@435: duke@435: // Called after parsing the Register block. Record the register class duke@435: // for spill-slots/regs. duke@435: void RegisterForm::addSpillRegClass() { duke@435: // Stack slots start at the next available even register number. kvn@3882: _reg_ctr = (_reg_ctr+7) & ~7; duke@435: const char *rc_name = "stack_slots"; duke@435: RegClass *reg_class = new RegClass(rc_name); duke@435: reg_class->_stack_or_reg = true; duke@435: _rclasses.addName(rc_name); duke@435: _regClass.Insert(rc_name,reg_class); duke@435: } duke@435: duke@435: duke@435: // Provide iteration over all register definitions duke@435: // in the order used by the register allocator duke@435: void RegisterForm::reset_RegDefs() { duke@435: _current_ac = NULL; duke@435: _aclasses.reset(); duke@435: } duke@435: duke@435: RegDef *RegisterForm::iter_RegDefs() { duke@435: // Check if we need to get the next AllocClass duke@435: if ( _current_ac == NULL ) { duke@435: const char *ac_name = _aclasses.iter(); duke@435: if( ac_name == NULL ) return NULL; // No more allocation classes duke@435: _current_ac = (AllocClass*)_allocClass[ac_name]; duke@435: _current_ac->_regDefs.reset(); duke@435: assert( _current_ac != NULL, "Name must match an allocation class"); duke@435: } duke@435: duke@435: const char *rd_name = _current_ac->_regDefs.iter(); duke@435: if( rd_name == NULL ) { duke@435: // At end of this allocation class, check the next duke@435: _current_ac = NULL; duke@435: return iter_RegDefs(); duke@435: } duke@435: RegDef *reg_def = (RegDef*)_current_ac->_regDef[rd_name]; duke@435: assert( reg_def != NULL, "Name must match a register definition"); duke@435: return reg_def; duke@435: } duke@435: duke@435: // return the register definition with name 'regName' duke@435: RegDef *RegisterForm::getRegDef(const char *regName) { duke@435: RegDef *regDef = (RegDef*)_regDef[regName]; duke@435: return regDef; duke@435: } duke@435: duke@435: // return the register class with name 'className' duke@435: RegClass *RegisterForm::getRegClass(const char *className) { duke@435: RegClass *regClass = (RegClass*)_regClass[className]; duke@435: return regClass; duke@435: } duke@435: duke@435: duke@435: // Check that register classes are compatible with chunks duke@435: bool RegisterForm::verify() { duke@435: bool valid = true; duke@435: duke@435: // Verify Register Classes duke@435: // check that each register class contains registers from one chunk duke@435: const char *rc_name = NULL; duke@435: _rclasses.reset(); duke@435: while ( (rc_name = _rclasses.iter()) != NULL ) { duke@435: // Check the chunk value for all registers in this class duke@435: RegClass *reg_class = getRegClass(rc_name); duke@435: assert( reg_class != NULL, "InternalError() no matching register class"); duke@435: } // end of RegClasses duke@435: duke@435: // Verify that every register has been placed into an allocation class duke@435: RegDef *reg_def = NULL; duke@435: reset_RegDefs(); duke@435: uint num_register_zero = 0; duke@435: while ( (reg_def = iter_RegDefs()) != NULL ) { duke@435: if( reg_def->register_num() == 0 ) ++num_register_zero; duke@435: } duke@435: if( num_register_zero > 1 ) { duke@435: fprintf(stderr, duke@435: "ERROR: More than one register has been assigned register-number 0.\n" duke@435: "Probably because a register has not been entered into an allocation class.\n"); duke@435: } duke@435: duke@435: return valid; duke@435: } duke@435: duke@435: // Compute RegMask size duke@435: int RegisterForm::RegMask_Size() { duke@435: // Need at least this many words duke@435: int words_for_regs = (_reg_ctr + 31)>>5; kvn@3882: // The array of Register Mask bits should be large enough to cover kvn@3882: // all the machine registers and all parameters that need to be passed kvn@3882: // on the stack (stack registers) up to some interesting limit. Methods kvn@3882: // that need more parameters will NOT be compiled. On Intel, the limit kvn@3882: // is something like 90+ parameters. kvn@3882: // Add a few (3 words == 96 bits) for incoming & outgoing arguments to calls. duke@435: // Round up to the next doubleword size. kvn@3882: return (words_for_regs + 3 + 1) & ~1; duke@435: } duke@435: duke@435: void RegisterForm::dump() { // Debug printer duke@435: output(stderr); duke@435: } duke@435: duke@435: void RegisterForm::output(FILE *fp) { // Write info to output files duke@435: const char *name; duke@435: fprintf(fp,"\n"); duke@435: fprintf(fp,"-------------------- Dump RegisterForm --------------------\n"); duke@435: for(_rdefs.reset(); (name = _rdefs.iter()) != NULL;) { duke@435: ((RegDef*)_regDef[name])->output(fp); duke@435: } duke@435: fprintf(fp,"\n"); duke@435: for (_rclasses.reset(); (name = _rclasses.iter()) != NULL;) { duke@435: ((RegClass*)_regClass[name])->output(fp); duke@435: } duke@435: fprintf(fp,"\n"); duke@435: for (_aclasses.reset(); (name = _aclasses.iter()) != NULL;) { duke@435: ((AllocClass*)_allocClass[name])->output(fp); duke@435: } duke@435: fprintf(fp,"-------------------- end RegisterForm --------------------\n"); duke@435: } duke@435: duke@435: //------------------------------RegDef----------------------------------------- duke@435: // Constructor duke@435: RegDef::RegDef(char *regname, char *callconv, char *c_conv, char * idealtype, char * encode, char * concrete) duke@435: : _regname(regname), _callconv(callconv), _c_conv(c_conv), duke@435: _idealtype(idealtype), duke@435: _register_encode(encode), duke@435: _concrete(concrete), duke@435: _register_num(0) { duke@435: duke@435: // Chunk and register mask are determined by the register number duke@435: // _register_num is set when registers are added to an allocation class duke@435: } duke@435: RegDef::~RegDef() { // Destructor duke@435: } duke@435: duke@435: void RegDef::set_register_num(uint32 register_num) { duke@435: _register_num = register_num; duke@435: } duke@435: duke@435: // Bit pattern used for generating machine code duke@435: const char* RegDef::register_encode() const { duke@435: return _register_encode; duke@435: } duke@435: duke@435: // Register number used in machine-independent code duke@435: uint32 RegDef::register_num() const { duke@435: return _register_num; duke@435: } duke@435: duke@435: void RegDef::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void RegDef::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"RegDef: %s (%s) encode as %s using number %d\n", duke@435: _regname, (_callconv?_callconv:""), _register_encode, _register_num); duke@435: fprintf(fp,"\n"); duke@435: } duke@435: duke@435: duke@435: //------------------------------RegClass--------------------------------------- duke@435: // Construct a register class into which registers will be inserted roland@3317: RegClass::RegClass(const char *classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr,hashstr, Form::arena), roland@3317: _user_defined(NULL) roland@3317: { duke@435: } duke@435: duke@435: // record a register in this class duke@435: void RegClass::addReg(RegDef *regDef) { duke@435: _regDefs.addName(regDef->_regname); duke@435: _regDef.Insert((void*)regDef->_regname, regDef); duke@435: } duke@435: duke@435: // Number of registers in class duke@435: uint RegClass::size() const { duke@435: return _regDef.Size(); duke@435: } duke@435: duke@435: const RegDef *RegClass::get_RegDef(const char *rd_name) const { duke@435: return (const RegDef*)_regDef[rd_name]; duke@435: } duke@435: duke@435: void RegClass::reset() { duke@435: _regDefs.reset(); duke@435: } duke@435: duke@435: const char *RegClass::rd_name_iter() { duke@435: return _regDefs.iter(); duke@435: } duke@435: duke@435: RegDef *RegClass::RegDef_iter() { duke@435: const char *rd_name = rd_name_iter(); duke@435: RegDef *reg_def = rd_name ? (RegDef*)_regDef[rd_name] : NULL; duke@435: return reg_def; duke@435: } duke@435: duke@435: const RegDef* RegClass::find_first_elem() { duke@435: const RegDef* first = NULL; duke@435: const RegDef* def = NULL; duke@435: duke@435: reset(); duke@435: while ((def = RegDef_iter()) != NULL) { duke@435: if (first == NULL || def->register_num() < first->register_num()) { duke@435: first = def; duke@435: } duke@435: } duke@435: duke@435: assert(first != NULL, "empty mask?"); duke@435: return first;; duke@435: } duke@435: duke@435: // Collect all the registers in this register-word. One bit per register. duke@435: int RegClass::regs_in_word( int wordnum, bool stack_also ) { duke@435: int word = 0; duke@435: const char *name; duke@435: for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { duke@435: int rnum = ((RegDef*)_regDef[name])->register_num(); duke@435: if( (rnum >> 5) == wordnum ) twisti@1038: word |= (1 << (rnum & 31)); duke@435: } duke@435: if( stack_also ) { duke@435: // Now also collect stack bits duke@435: for( int i = 0; i < 32; i++ ) duke@435: if( wordnum*32+i >= RegisterForm::_reg_ctr ) twisti@1038: word |= (1 << i); duke@435: } duke@435: duke@435: return word; duke@435: } duke@435: duke@435: void RegClass::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void RegClass::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"RegClass: %s\n",_classid); duke@435: const char *name; duke@435: for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { duke@435: ((RegDef*)_regDef[name])->output(fp); duke@435: } duke@435: fprintf(fp,"--- done with entries for reg_class %s\n\n",_classid); duke@435: } duke@435: duke@435: duke@435: //------------------------------AllocClass------------------------------------- duke@435: AllocClass::AllocClass(char *classid) : _classid(classid), _regDef(cmpstr,hashstr, Form::arena) { duke@435: } duke@435: duke@435: // record a register in this class duke@435: void AllocClass::addReg(RegDef *regDef) { duke@435: assert( regDef != NULL, "Can not add a NULL to an allocation class"); duke@435: regDef->set_register_num( RegisterForm::_reg_ctr++ ); duke@435: // Add regDef to this allocation class duke@435: _regDefs.addName(regDef->_regname); duke@435: _regDef.Insert((void*)regDef->_regname, regDef); duke@435: } duke@435: duke@435: void AllocClass::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void AllocClass::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"AllocClass: %s \n",_classid); duke@435: const char *name; duke@435: for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { duke@435: ((RegDef*)_regDef[name])->output(fp); duke@435: } duke@435: fprintf(fp,"--- done with entries for alloc_class %s\n\n",_classid); duke@435: } duke@435: duke@435: //==============================Frame Handling================================= duke@435: //------------------------------FrameForm-------------------------------------- duke@435: FrameForm::FrameForm() { duke@435: _frame_pointer = NULL; duke@435: _c_frame_pointer = NULL; duke@435: _alignment = NULL; duke@435: _return_addr = NULL; duke@435: _c_return_addr = NULL; duke@435: _in_preserve_slots = NULL; duke@435: _varargs_C_out_slots_killed = NULL; duke@435: _calling_convention = NULL; duke@435: _c_calling_convention = NULL; duke@435: _return_value = NULL; duke@435: _c_return_value = NULL; duke@435: _interpreter_frame_pointer_reg = NULL; duke@435: } duke@435: duke@435: FrameForm::~FrameForm() { duke@435: } duke@435: duke@435: void FrameForm::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void FrameForm::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"\nFrame:\n"); duke@435: } duke@435: duke@435: //==============================Scheduling===================================== duke@435: //------------------------------PipelineForm----------------------------------- duke@435: PipelineForm::PipelineForm() duke@435: : _reslist () duke@435: , _resdict (cmpstr, hashstr, Form::arena) duke@435: , _classdict (cmpstr, hashstr, Form::arena) duke@435: , _rescount (0) duke@435: , _maxcycleused (0) duke@435: , _stages () duke@435: , _stagecnt (0) duke@435: , _classlist () duke@435: , _classcnt (0) duke@435: , _noplist () duke@435: , _nopcnt (0) duke@435: , _variableSizeInstrs (false) duke@435: , _branchHasDelaySlot (false) duke@435: , _maxInstrsPerBundle (0) duke@435: , _maxBundlesPerCycle (1) duke@435: , _instrUnitSize (0) duke@435: , _bundleUnitSize (0) duke@435: , _instrFetchUnitSize (0) duke@435: , _instrFetchUnits (0) { duke@435: } duke@435: PipelineForm::~PipelineForm() { duke@435: } duke@435: duke@435: void PipelineForm::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PipelineForm::output(FILE *fp) { // Write info to output files duke@435: const char *res; duke@435: const char *stage; duke@435: const char *cls; duke@435: const char *nop; duke@435: int count = 0; duke@435: duke@435: fprintf(fp,"\nPipeline:"); duke@435: if (_variableSizeInstrs) duke@435: if (_instrUnitSize > 0) duke@435: fprintf(fp," variable-sized instructions in %d byte units", _instrUnitSize); duke@435: else duke@435: fprintf(fp," variable-sized instructions"); duke@435: else duke@435: if (_instrUnitSize > 0) duke@435: fprintf(fp," fixed-sized instructions of %d bytes", _instrUnitSize); duke@435: else if (_bundleUnitSize > 0) duke@435: fprintf(fp," fixed-sized bundles of %d bytes", _bundleUnitSize); duke@435: else duke@435: fprintf(fp," fixed-sized instructions"); duke@435: if (_branchHasDelaySlot) duke@435: fprintf(fp,", branch has delay slot"); duke@435: if (_maxInstrsPerBundle > 0) duke@435: fprintf(fp,", max of %d instruction%s in parallel", duke@435: _maxInstrsPerBundle, _maxInstrsPerBundle > 1 ? "s" : ""); duke@435: if (_maxBundlesPerCycle > 0) duke@435: fprintf(fp,", max of %d bundle%s in parallel", duke@435: _maxBundlesPerCycle, _maxBundlesPerCycle > 1 ? "s" : ""); duke@435: if (_instrFetchUnitSize > 0 && _instrFetchUnits) duke@435: fprintf(fp, ", fetch %d x % d bytes per cycle", _instrFetchUnits, _instrFetchUnitSize); duke@435: duke@435: fprintf(fp,"\nResource:"); duke@435: for ( _reslist.reset(); (res = _reslist.iter()) != NULL; ) duke@435: fprintf(fp," %s(0x%08x)", res, _resdict[res]->is_resource()->mask()); duke@435: fprintf(fp,"\n"); duke@435: duke@435: fprintf(fp,"\nDescription:\n"); duke@435: for ( _stages.reset(); (stage = _stages.iter()) != NULL; ) duke@435: fprintf(fp," %s(%d)", stage, count++); duke@435: fprintf(fp,"\n"); duke@435: duke@435: fprintf(fp,"\nClasses:\n"); duke@435: for ( _classlist.reset(); (cls = _classlist.iter()) != NULL; ) duke@435: _classdict[cls]->is_pipeclass()->output(fp); duke@435: duke@435: fprintf(fp,"\nNop Instructions:"); duke@435: for ( _noplist.reset(); (nop = _noplist.iter()) != NULL; ) duke@435: fprintf(fp, " \"%s\"", nop); duke@435: fprintf(fp,"\n"); duke@435: } duke@435: duke@435: duke@435: //------------------------------ResourceForm----------------------------------- duke@435: ResourceForm::ResourceForm(unsigned resmask) duke@435: : _resmask(resmask) { duke@435: } duke@435: ResourceForm::~ResourceForm() { duke@435: } duke@435: duke@435: ResourceForm *ResourceForm::is_resource() const { duke@435: return (ResourceForm *)(this); duke@435: } duke@435: duke@435: void ResourceForm::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void ResourceForm::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp, "resource: 0x%08x;\n", mask()); duke@435: } duke@435: duke@435: duke@435: //------------------------------PipeClassOperandForm---------------------------------- duke@435: duke@435: void PipeClassOperandForm::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PipeClassOperandForm::output(FILE *fp) { // Write info to output files duke@435: fprintf(stderr,"PipeClassOperandForm: %s", _stage); duke@435: fflush(stderr); duke@435: if (_more_instrs > 0) duke@435: fprintf(stderr,"+%d", _more_instrs); duke@435: fprintf(stderr," (%s)\n", _iswrite ? "write" : "read"); duke@435: fflush(stderr); duke@435: fprintf(fp,"PipeClassOperandForm: %s", _stage); duke@435: if (_more_instrs > 0) duke@435: fprintf(fp,"+%d", _more_instrs); duke@435: fprintf(fp," (%s)\n", _iswrite ? "write" : "read"); duke@435: } duke@435: duke@435: duke@435: //------------------------------PipeClassResourceForm---------------------------------- duke@435: duke@435: void PipeClassResourceForm::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PipeClassResourceForm::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"PipeClassResourceForm: %s at stage %s for %d cycles\n", duke@435: _resource, _stage, _cycles); duke@435: } duke@435: duke@435: duke@435: //------------------------------PipeClassForm---------------------------------- duke@435: PipeClassForm::PipeClassForm(const char *id, int num) duke@435: : _ident(id) duke@435: , _num(num) duke@435: , _localNames(cmpstr, hashstr, Form::arena) duke@435: , _localUsage(cmpstr, hashstr, Form::arena) duke@435: , _has_fixed_latency(0) duke@435: , _fixed_latency(0) duke@435: , _instruction_count(0) duke@435: , _has_multiple_bundles(false) duke@435: , _has_branch_delay_slot(false) duke@435: , _force_serialization(false) duke@435: , _may_have_no_code(false) { duke@435: } duke@435: duke@435: PipeClassForm::~PipeClassForm() { duke@435: } duke@435: duke@435: PipeClassForm *PipeClassForm::is_pipeclass() const { duke@435: return (PipeClassForm *)(this); duke@435: } duke@435: duke@435: void PipeClassForm::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PipeClassForm::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"PipeClassForm: #%03d", _num); duke@435: if (_ident) duke@435: fprintf(fp," \"%s\":", _ident); duke@435: if (_has_fixed_latency) duke@435: fprintf(fp," latency %d", _fixed_latency); duke@435: if (_force_serialization) duke@435: fprintf(fp, ", force serialization"); duke@435: if (_may_have_no_code) duke@435: fprintf(fp, ", may have no code"); duke@435: fprintf(fp, ", %d instruction%s\n", InstructionCount(), InstructionCount() != 1 ? "s" : ""); duke@435: } duke@435: duke@435: duke@435: //==============================Peephole Optimization========================== duke@435: int Peephole::_peephole_counter = 0; duke@435: //------------------------------Peephole--------------------------------------- duke@435: Peephole::Peephole() : _match(NULL), _constraint(NULL), _replace(NULL), _next(NULL) { duke@435: _peephole_number = _peephole_counter++; duke@435: } duke@435: Peephole::~Peephole() { duke@435: } duke@435: duke@435: // Append a peephole rule with the same root instruction duke@435: void Peephole::append_peephole(Peephole *next_peephole) { duke@435: if( _next == NULL ) { duke@435: _next = next_peephole; duke@435: } else { duke@435: _next->append_peephole( next_peephole ); duke@435: } duke@435: } duke@435: duke@435: // Store the components of this peephole rule duke@435: void Peephole::add_match(PeepMatch *match) { duke@435: assert( _match == NULL, "fatal()" ); duke@435: _match = match; duke@435: } duke@435: duke@435: void Peephole::append_constraint(PeepConstraint *next_constraint) { duke@435: if( _constraint == NULL ) { duke@435: _constraint = next_constraint; duke@435: } else { duke@435: _constraint->append( next_constraint ); duke@435: } duke@435: } duke@435: duke@435: void Peephole::add_replace(PeepReplace *replace) { duke@435: assert( _replace == NULL, "fatal()" ); duke@435: _replace = replace; duke@435: } duke@435: duke@435: // class Peephole accessor methods are in the declaration. duke@435: duke@435: duke@435: void Peephole::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void Peephole::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"Peephole:\n"); duke@435: if( _match != NULL ) _match->output(fp); duke@435: if( _constraint != NULL ) _constraint->output(fp); duke@435: if( _replace != NULL ) _replace->output(fp); duke@435: // Output the next entry duke@435: if( _next ) _next->output(fp); duke@435: } duke@435: duke@435: //------------------------------PeepMatch-------------------------------------- duke@435: PeepMatch::PeepMatch(char *rule) : _max_position(0), _rule(rule) { duke@435: } duke@435: PeepMatch::~PeepMatch() { duke@435: } duke@435: duke@435: duke@435: // Insert info into the match-rule duke@435: void PeepMatch::add_instruction(int parent, int position, const char *name, duke@435: int input) { duke@435: if( position > _max_position ) _max_position = position; duke@435: twisti@1038: _parent.addName((char*) (intptr_t) parent); twisti@1038: _position.addName((char*) (intptr_t) position); duke@435: _instrs.addName(name); twisti@1038: _input.addName((char*) (intptr_t) input); duke@435: } duke@435: duke@435: // Access info about instructions in the peep-match rule duke@435: int PeepMatch::max_position() { duke@435: return _max_position; duke@435: } duke@435: twisti@1038: const char *PeepMatch::instruction_name(int position) { duke@435: return _instrs.name(position); duke@435: } duke@435: duke@435: // Iterate through all info on matched instructions duke@435: void PeepMatch::reset() { duke@435: _parent.reset(); duke@435: _position.reset(); duke@435: _instrs.reset(); duke@435: _input.reset(); duke@435: } duke@435: twisti@1038: void PeepMatch::next_instruction(int &parent, int &position, const char* &name, int &input) { twisti@1038: parent = (int) (intptr_t) _parent.iter(); twisti@1038: position = (int) (intptr_t) _position.iter(); duke@435: name = _instrs.iter(); twisti@1038: input = (int) (intptr_t) _input.iter(); duke@435: } duke@435: duke@435: // 'true' if current position in iteration is a placeholder, not matched. duke@435: bool PeepMatch::is_placeholder() { duke@435: return _instrs.current_is_signal(); duke@435: } duke@435: duke@435: duke@435: void PeepMatch::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PeepMatch::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"PeepMatch:\n"); duke@435: } duke@435: duke@435: //------------------------------PeepConstraint--------------------------------- twisti@1038: PeepConstraint::PeepConstraint(int left_inst, char* left_op, char* relation, twisti@1038: int right_inst, char* right_op) duke@435: : _left_inst(left_inst), _left_op(left_op), _relation(relation), duke@435: _right_inst(right_inst), _right_op(right_op), _next(NULL) {} duke@435: PeepConstraint::~PeepConstraint() { duke@435: } duke@435: duke@435: // Check if constraints use instruction at position twisti@1038: bool PeepConstraint::constrains_instruction(int position) { duke@435: // Check local instruction constraints duke@435: if( _left_inst == position ) return true; duke@435: if( _right_inst == position ) return true; duke@435: duke@435: // Check remaining constraints in list duke@435: if( _next == NULL ) return false; duke@435: else return _next->constrains_instruction(position); duke@435: } duke@435: duke@435: // Add another constraint duke@435: void PeepConstraint::append(PeepConstraint *next_constraint) { duke@435: if( _next == NULL ) { duke@435: _next = next_constraint; duke@435: } else { duke@435: _next->append( next_constraint ); duke@435: } duke@435: } duke@435: duke@435: // Access the next constraint in the list duke@435: PeepConstraint *PeepConstraint::next() { duke@435: return _next; duke@435: } duke@435: duke@435: duke@435: void PeepConstraint::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PeepConstraint::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"PeepConstraint:\n"); duke@435: } duke@435: duke@435: //------------------------------PeepReplace------------------------------------ duke@435: PeepReplace::PeepReplace(char *rule) : _rule(rule) { duke@435: } duke@435: PeepReplace::~PeepReplace() { duke@435: } duke@435: duke@435: // Add contents of peepreplace duke@435: void PeepReplace::add_instruction(char *root) { duke@435: _instruction.addName(root); duke@435: _operand_inst_num.add_signal(); duke@435: _operand_op_name.add_signal(); duke@435: } duke@435: void PeepReplace::add_operand( int inst_num, char *inst_operand ) { duke@435: _instruction.add_signal(); twisti@1038: _operand_inst_num.addName((char*) (intptr_t) inst_num); duke@435: _operand_op_name.addName(inst_operand); duke@435: } duke@435: duke@435: // Access contents of peepreplace duke@435: void PeepReplace::reset() { duke@435: _instruction.reset(); duke@435: _operand_inst_num.reset(); duke@435: _operand_op_name.reset(); duke@435: } twisti@1038: void PeepReplace::next_instruction(const char* &inst){ duke@435: inst = _instruction.iter(); twisti@1038: int inst_num = (int) (intptr_t) _operand_inst_num.iter(); twisti@1038: const char* inst_operand = _operand_op_name.iter(); duke@435: } twisti@1038: void PeepReplace::next_operand(int &inst_num, const char* &inst_operand) { twisti@1038: const char* inst = _instruction.iter(); twisti@1038: inst_num = (int) (intptr_t) _operand_inst_num.iter(); twisti@1038: inst_operand = _operand_op_name.iter(); duke@435: } duke@435: duke@435: duke@435: duke@435: void PeepReplace::dump() { duke@435: output(stderr); duke@435: } duke@435: duke@435: void PeepReplace::output(FILE *fp) { // Write info to output files duke@435: fprintf(fp,"PeepReplace:\n"); duke@435: }