/* * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// FORMS.CPP - Definitions for ADL Parser Forms Classes #include"adlc.hpp"
//==============================Register Allocation============================ int RegisterForm::_reg_ctr = 0;
// record a new register definition void RegisterForm::addRegDef(char *name, char *callingConv, char *c_conv, char *idealtype, char *encoding, char* concrete) {
RegDef *regDef = new RegDef(name, callingConv, c_conv, idealtype, encoding, concrete);
_rdefs.addName(name);
_regDef.Insert(name,regDef);
}
// record a new register class template <typename T>
T* RegisterForm::addRegClass(constchar* className) {
T* regClass = new T(className);
_rclasses.addName(className);
_regClass.Insert(className, regClass); return regClass;
}
// Explicit instantiation for all supported register classes. template RegClass* RegisterForm::addRegClass<RegClass>(constchar* className); template CodeSnippetRegClass* RegisterForm::addRegClass<CodeSnippetRegClass>(constchar* className); template ConditionalRegClass* RegisterForm::addRegClass<ConditionalRegClass>(constchar* className);
// record a new register class
AllocClass *RegisterForm::addAllocClass(char *className) {
AllocClass *allocClass = new AllocClass(className);
_aclasses.addName(className);
_allocClass.Insert(className,allocClass); return allocClass;
}
// Called after parsing the Register block. Record the register class // for spill-slots/regs. void RegisterForm::addSpillRegClass() { // Stack slots start at the next available even register number.
_reg_ctr = (_reg_ctr+7) & ~7; constchar *rc_name = "stack_slots";
RegClass* reg_class = new RegClass(rc_name);
reg_class->set_stack_version(true);
_rclasses.addName(rc_name);
_regClass.Insert(rc_name,reg_class);
}
// Called after parsing the Register block. Record the register class // for operands which are overwritten after matching. void RegisterForm::addDynamicRegClass() { constchar *rc_name = "dynamic";
RegClass* reg_class = new RegClass(rc_name);
reg_class->set_stack_version(false);
_rclasses.addName(rc_name);
_regClass.Insert(rc_name,reg_class);
}
// Provide iteration over all register definitions // in the order used by the register allocator void RegisterForm::reset_RegDefs() {
_current_ac = NULL;
_aclasses.reset();
}
RegDef *RegisterForm::iter_RegDefs() { // Check if we need to get the next AllocClass if ( _current_ac == NULL ) { constchar *ac_name = _aclasses.iter(); if( ac_name == NULL ) return NULL; // No more allocation classes
_current_ac = (AllocClass*)_allocClass[ac_name];
_current_ac->_regDefs.reset();
assert( _current_ac != NULL, "Name must match an allocation class");
}
constchar *rd_name = _current_ac->_regDefs.iter(); if( rd_name == NULL ) { // At end of this allocation class, check the next
_current_ac = NULL; return iter_RegDefs();
}
RegDef *reg_def = (RegDef*)_current_ac->_regDef[rd_name];
assert( reg_def != NULL, "Name must match a register definition"); return reg_def;
}
// return the register definition with name 'regName'
RegDef *RegisterForm::getRegDef(constchar *regName) {
RegDef *regDef = (RegDef*)_regDef[regName]; return regDef;
}
// return the register class with name 'className'
RegClass *RegisterForm::getRegClass(constchar *className) {
RegClass *regClass = (RegClass*)_regClass[className]; return regClass;
}
// Check that register classes are compatible with chunks bool RegisterForm::verify() { bool valid = true;
// Verify Register Classes // check that each register class contains registers from one chunk constchar *rc_name = NULL;
_rclasses.reset(); while ( (rc_name = _rclasses.iter()) != NULL ) { // Check the chunk value for all registers in this class
RegClass *reg_class = getRegClass(rc_name);
assert( reg_class != NULL, "InternalError() no matching register class");
} // end of RegClasses
// Verify that every register has been placed into an allocation class
RegDef *reg_def = NULL;
reset_RegDefs();
uint num_register_zero = 0; while ( (reg_def = iter_RegDefs()) != NULL ) { if( reg_def->register_num() == 0 ) ++num_register_zero;
} if( num_register_zero > 1 ) {
fprintf(stderr, "ERROR: More than one register has been assigned register-number 0.\n" "Probably because a register has not been entered into an allocation class.\n");
}
return valid;
}
// Compute RegMask size int RegisterForm::RegMask_Size() { // Need at least this many words int words_for_regs = (_reg_ctr + 31)>>5; // The array of Register Mask bits should be large enough to cover // all the machine registers and all parameters that need to be passed // on the stack (stack registers) up to some interesting limit. Methods // that need more parameters will NOT be compiled. On Intel, the limit // is something like 90+ parameters. // Add a few (3 words == 96 bits) for incoming & outgoing arguments to calls. // Round up to the next doubleword size. return (words_for_regs + 3 + 1) & ~1;
}
// AdlChunk and register mask are determined by the register number // _register_num is set when registers are added to an allocation class
}
RegDef::~RegDef() { // Destructor
}
// Bit pattern used for generating machine code constchar* RegDef::register_encode() const { return _register_encode;
}
// Register number used in machine-independent code
uint32 RegDef::register_num() const { return _register_num;
}
void RegDef::dump() {
output(stderr);
}
void RegDef::output(FILE *fp) { // Write info to output files
fprintf(fp,"RegDef: %s (%s) encode as %s using number %d\n",
_regname, (_callconv?_callconv:""), _register_encode, _register_num);
fprintf(fp,"\n");
}
//------------------------------RegClass--------------------------------------- // Construct a register class into which registers will be inserted
RegClass::RegClass(constchar* classid) : _stack_or_reg(false), _classid(classid), _regDef(cmpstr, hashstr, Form::arena) {
}
RegClass::~RegClass() {
}
// record a register in this class void RegClass::addReg(RegDef *regDef) {
_regDefs.addName(regDef->_regname);
_regDef.Insert((void*)regDef->_regname, regDef);
}
// Number of registers in class
uint RegClass::size() const { return _regDef.Size();
}
// Collect all the registers in this register-word. One bit per register. int RegClass::regs_in_word( int wordnum, bool stack_also ) { int word = 0; constchar *name; for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) { int rnum = ((RegDef*)_regDef[name])->register_num(); if( (rnum >> 5) == wordnum )
word |= (1 << (rnum & 31));
} if( stack_also ) { // Now also collect stack bits for( int i = 0; i < 32; i++ ) if( wordnum*32+i >= RegisterForm::_reg_ctr )
word |= (1 << i);
}
return word;
}
void RegClass::dump() {
output(stderr);
}
void RegClass::output(FILE *fp) { // Write info to output files
fprintf(fp,"RegClass: %s\n",_classid); constchar *name; for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) {
((RegDef*)_regDef[name])->output(fp);
}
fprintf(fp,"--- done with entries for reg_class %s\n\n",_classid);
}
// record a register in this class void AllocClass::addReg(RegDef *regDef) {
assert( regDef != NULL, "Can not add a NULL to an allocation class");
regDef->set_register_num( RegisterForm::_reg_ctr++ ); // Add regDef to this allocation class
_regDefs.addName(regDef->_regname);
_regDef.Insert((void*)regDef->_regname, regDef);
}
void AllocClass::dump() {
output(stderr);
}
void AllocClass::output(FILE *fp) { // Write info to output files
fprintf(fp,"AllocClass: %s \n",_classid); constchar *name; for(_regDefs.reset(); (name = _regDefs.iter()) != NULL;) {
((RegDef*)_regDef[name])->output(fp);
}
fprintf(fp,"--- done with entries for alloc_class %s\n\n",_classid);
}
// Insert info into the match-rule void PeepMatch::add_instruction(int parent, int position, constchar *name, int input) { if( position > _max_position ) _max_position = position;
// Check if constraints use instruction at position bool PeepConstraint::constrains_instruction(int position) { // Check local instruction constraints if( _left_inst == position ) returntrue; if( _right_inst == position ) returntrue;
// Check remaining constraints in list if( _next == NULL ) returnfalse; elsereturn _next->constrains_instruction(position);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.