Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/adlc/archDesc.cpp
32285 views
//1// Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3//4// This code is free software; you can redistribute it and/or modify it5// under the terms of the GNU General Public License version 2 only, as6// published by the Free Software Foundation.7//8// This code is distributed in the hope that it will be useful, but WITHOUT9// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11// version 2 for more details (a copy is included in the LICENSE file that12// accompanied this code).13//14// You should have received a copy of the GNU General Public License version15// 2 along with this work; if not, write to the Free Software Foundation,16// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17//18// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19// or visit www.oracle.com if you need additional information or have any20// questions.21//22//232425// archDesc.cpp - Internal format for architecture definition26#include "adlc.hpp"2728static FILE *errfile = stderr;2930//--------------------------- utility functions -----------------------------31inline char toUpper(char lower) {32return (('a' <= lower && lower <= 'z') ? ((char) (lower + ('A'-'a'))) : lower);33}34char *toUpper(const char *str) {35char *upper = new char[strlen(str)+1];36char *result = upper;37const char *end = str + strlen(str);38for (; str < end; ++str, ++upper) {39*upper = toUpper(*str);40}41*upper = '\0';42return result;43}4445//---------------------------ChainList Methods-------------------------------46ChainList::ChainList() {47}4849void ChainList::insert(const char *name, const char *cost, const char *rule) {50_name.addName(name);51_cost.addName(cost);52_rule.addName(rule);53}5455bool ChainList::search(const char *name) {56return _name.search(name);57}5859void ChainList::reset() {60_name.reset();61_cost.reset();62_rule.reset();63}6465bool ChainList::iter(const char * &name, const char * &cost, const char * &rule) {66bool notDone = false;67const char *n = _name.iter();68const char *c = _cost.iter();69const char *r = _rule.iter();7071if (n && c && r) {72notDone = true;73name = n;74cost = c;75rule = r;76}7778return notDone;79}8081void ChainList::dump() {82output(stderr);83}8485void ChainList::output(FILE *fp) {86fprintf(fp, "\nChain Rules: output resets iterator\n");87const char *cost = NULL;88const char *name = NULL;89const char *rule = NULL;90bool chains_exist = false;91for(reset(); (iter(name,cost,rule)) == true; ) {92fprintf(fp, "Chain to <%s> at cost #%s using %s_rule\n",name, cost ? cost : "0", rule);93// // Check for transitive chain rules94// Form *form = (Form *)_globalNames[rule];95// if (form->is_instruction()) {96// // chain_rule(fp, indent, name, cost, rule);97// chain_rule(fp, indent, name, cost, rule);98// }99}100reset();101if( ! chains_exist ) {102fprintf(fp, "No entries in this ChainList\n");103}104}105106107//---------------------------MatchList Methods-------------------------------108bool MatchList::search(const char *opc, const char *res, const char *lch,109const char *rch, Predicate *pr) {110bool tmp = false;111if ((res == _resultStr) || (res && _resultStr && !strcmp(res, _resultStr))) {112if ((lch == _lchild) || (lch && _lchild && !strcmp(lch, _lchild))) {113if ((rch == _rchild) || (rch && _rchild && !strcmp(rch, _rchild))) {114char * predStr = get_pred();115char * prStr = pr?pr->_pred:NULL;116if (ADLParser::equivalent_expressions(prStr, predStr)) {117return true;118}119}120}121}122if (_next) {123tmp = _next->search(opc, res, lch, rch, pr);124}125return tmp;126}127128129void MatchList::dump() {130output(stderr);131}132133void MatchList::output(FILE *fp) {134fprintf(fp, "\nMatchList output is Unimplemented();\n");135}136137138//---------------------------ArchDesc Constructor and Destructor-------------139140ArchDesc::ArchDesc()141: _globalNames(cmpstr,hashstr, Form::arena),142_globalDefs(cmpstr,hashstr, Form::arena),143_preproc_table(cmpstr,hashstr, Form::arena),144_idealIndex(cmpstr,hashstr, Form::arena),145_internalOps(cmpstr,hashstr, Form::arena),146_internalMatch(cmpstr,hashstr, Form::arena),147_chainRules(cmpstr,hashstr, Form::arena),148_cisc_spill_operand(NULL),149_needs_clone_jvms(false) {150151// Initialize the opcode to MatchList table with NULLs152for( int i=0; i<_last_opcode; ++i ) {153_mlistab[i] = NULL;154}155156// Set-up the global tables157initKeywords(_globalNames); // Initialize the Name Table with keywords158159// Prime user-defined types with predefined types: Set, RegI, RegF, ...160initBaseOpTypes();161162// Initialize flags & counters163_TotalLines = 0;164_no_output = 0;165_quiet_mode = 0;166_disable_warnings = 0;167_dfa_debug = 0;168_dfa_small = 0;169_adl_debug = 0;170_adlocation_debug = 0;171_internalOpCounter = 0;172_cisc_spill_debug = false;173_short_branch_debug = false;174175// Initialize match rule flags176for (int i = 0; i < _last_opcode; i++) {177_has_match_rule[i] = false;178}179180// Error/Warning Counts181_syntax_errs = 0;182_semantic_errs = 0;183_warnings = 0;184_internal_errs = 0;185186// Initialize I/O Files187_ADL_file._name = NULL; _ADL_file._fp = NULL;188// Machine dependent output files189_DFA_file._name = NULL; _DFA_file._fp = NULL;190_HPP_file._name = NULL; _HPP_file._fp = NULL;191_CPP_file._name = NULL; _CPP_file._fp = NULL;192_bug_file._name = "bugs.out"; _bug_file._fp = NULL;193194// Initialize Register & Pipeline Form Pointers195_register = NULL;196_encode = NULL;197_pipeline = NULL;198_frame = NULL;199}200201ArchDesc::~ArchDesc() {202// Clean-up and quit203204}205206//---------------------------ArchDesc methods: Public ----------------------207// Store forms according to type208void ArchDesc::addForm(PreHeaderForm *ptr) { _pre_header.addForm(ptr); };209void ArchDesc::addForm(HeaderForm *ptr) { _header.addForm(ptr); };210void ArchDesc::addForm(SourceForm *ptr) { _source.addForm(ptr); };211void ArchDesc::addForm(EncodeForm *ptr) { _encode = ptr; };212void ArchDesc::addForm(InstructForm *ptr) { _instructions.addForm(ptr); };213void ArchDesc::addForm(MachNodeForm *ptr) { _machnodes.addForm(ptr); };214void ArchDesc::addForm(OperandForm *ptr) { _operands.addForm(ptr); };215void ArchDesc::addForm(OpClassForm *ptr) { _opclass.addForm(ptr); };216void ArchDesc::addForm(AttributeForm *ptr) { _attributes.addForm(ptr); };217void ArchDesc::addForm(RegisterForm *ptr) { _register = ptr; };218void ArchDesc::addForm(FrameForm *ptr) { _frame = ptr; };219void ArchDesc::addForm(PipelineForm *ptr) { _pipeline = ptr; };220221// Build MatchList array and construct MatchLists222void ArchDesc::generateMatchLists() {223// Call inspection routines to populate array224inspectOperands();225inspectInstructions();226}227228// Build MatchList structures for operands229void ArchDesc::inspectOperands() {230231// Iterate through all operands232_operands.reset();233OperandForm *op;234for( ; (op = (OperandForm*)_operands.iter()) != NULL;) {235// Construct list of top-level operands (components)236op->build_components();237238// Ensure that match field is defined.239if ( op->_matrule == NULL ) continue;240241// Type check match rules242check_optype(op->_matrule);243244// Construct chain rules245build_chain_rule(op);246247MatchRule &mrule = *op->_matrule;248Predicate *pred = op->_predicate;249250// Grab the machine type of the operand251const char *rootOp = op->_ident;252mrule._machType = rootOp;253254// Check for special cases255if (strcmp(rootOp,"Universe")==0) continue;256if (strcmp(rootOp,"label")==0) continue;257// !!!!! !!!!!258assert( strcmp(rootOp,"sReg") != 0, "Disable untyped 'sReg'");259if (strcmp(rootOp,"sRegI")==0) continue;260if (strcmp(rootOp,"sRegP")==0) continue;261if (strcmp(rootOp,"sRegF")==0) continue;262if (strcmp(rootOp,"sRegD")==0) continue;263if (strcmp(rootOp,"sRegL")==0) continue;264265// Cost for this match266const char *costStr = op->cost();267const char *defaultCost =268((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef;269const char *cost = costStr? costStr : defaultCost;270271// Find result type for match.272const char *result = op->reduce_result();273bool has_root = false;274275// Construct a MatchList for this entry276buildMatchList(op->_matrule, result, rootOp, pred, cost);277}278}279280// Build MatchList structures for instructions281void ArchDesc::inspectInstructions() {282283// Iterate through all instructions284_instructions.reset();285InstructForm *instr;286for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {287// Construct list of top-level operands (components)288instr->build_components();289290// Ensure that match field is defined.291if ( instr->_matrule == NULL ) continue;292293MatchRule &mrule = *instr->_matrule;294Predicate *pred = instr->build_predicate();295296// Grab the machine type of the operand297const char *rootOp = instr->_ident;298mrule._machType = rootOp;299300// Cost for this match301const char *costStr = instr->cost();302const char *defaultCost =303((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;304const char *cost = costStr? costStr : defaultCost;305306// Find result type for match307const char *result = instr->reduce_result();308309if ( instr->is_ideal_branch() && instr->label_position() == -1 ||310!instr->is_ideal_branch() && instr->label_position() != -1) {311syntax_err(instr->_linenum, "%s: Only branches to a label are supported\n", rootOp);312}313314Attribute *attr = instr->_attribs;315while (attr != NULL) {316if (strcmp(attr->_ident,"ins_short_branch") == 0 &&317attr->int_val(*this) != 0) {318if (!instr->is_ideal_branch() || instr->label_position() == -1) {319syntax_err(instr->_linenum, "%s: Only short branch to a label is supported\n", rootOp);320}321instr->set_short_branch(true);322} else if (strcmp(attr->_ident,"ins_alignment") == 0 &&323attr->int_val(*this) != 0) {324instr->set_alignment(attr->int_val(*this));325}326attr = (Attribute *)attr->_next;327}328329if (!instr->is_short_branch()) {330buildMatchList(instr->_matrule, result, mrule._machType, pred, cost);331}332}333}334335static int setsResult(MatchRule &mrule) {336if (strcmp(mrule._name,"Set") == 0) return 1;337return 0;338}339340const char *ArchDesc::getMatchListIndex(MatchRule &mrule) {341if (setsResult(mrule)) {342// right child343return mrule._rChild->_opType;344} else {345// first entry346return mrule._opType;347}348}349350351//------------------------------result of reduction----------------------------352353354//------------------------------left reduction---------------------------------355// Return the left reduction associated with an internal name356const char *ArchDesc::reduceLeft(char *internalName) {357const char *left = NULL;358MatchNode *mnode = (MatchNode*)_internalMatch[internalName];359if (mnode->_lChild) {360mnode = mnode->_lChild;361left = mnode->_internalop ? mnode->_internalop : mnode->_opType;362}363return left;364}365366367//------------------------------right reduction--------------------------------368const char *ArchDesc::reduceRight(char *internalName) {369const char *right = NULL;370MatchNode *mnode = (MatchNode*)_internalMatch[internalName];371if (mnode->_rChild) {372mnode = mnode->_rChild;373right = mnode->_internalop ? mnode->_internalop : mnode->_opType;374}375return right;376}377378379//------------------------------check_optype-----------------------------------380void ArchDesc::check_optype(MatchRule *mrule) {381MatchRule *rule = mrule;382383// !!!!!384// // Cycle through the list of match rules385// while(mrule) {386// // Check for a filled in type field387// if (mrule->_opType == NULL) {388// const Form *form = operands[_result];389// OpClassForm *opcForm = form ? form->is_opclass() : NULL;390// assert(opcForm != NULL, "Match Rule contains invalid operand name.");391// }392// char *opType = opcForm->_ident;393// }394}395396//------------------------------add_chain_rule_entry--------------------------397void ArchDesc::add_chain_rule_entry(const char *src, const char *cost,398const char *result) {399// Look-up the operation in chain rule table400ChainList *lst = (ChainList *)_chainRules[src];401if (lst == NULL) {402lst = new ChainList();403_chainRules.Insert(src, lst);404}405if (!lst->search(result)) {406if (cost == NULL) {407cost = ((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef;408}409lst->insert(result, cost, result);410}411}412413//------------------------------build_chain_rule-------------------------------414void ArchDesc::build_chain_rule(OperandForm *oper) {415MatchRule *rule;416417// Check for chain rules here418// If this is only a chain rule419if ((oper->_matrule) && (oper->_matrule->_lChild == NULL) &&420(oper->_matrule->_rChild == NULL)) {421422{423const Form *form = _globalNames[oper->_matrule->_opType];424if ((form) && form->is_operand() &&425(form->ideal_only() == false)) {426add_chain_rule_entry(oper->_matrule->_opType, oper->cost(), oper->_ident);427}428}429// Check for additional chain rules430if (oper->_matrule->_next) {431rule = oper->_matrule;432do {433rule = rule->_next;434// Any extra match rules after the first must be chain rules435const Form *form = _globalNames[rule->_opType];436if ((form) && form->is_operand() &&437(form->ideal_only() == false)) {438add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident);439}440} while(rule->_next != NULL);441}442}443else if ((oper->_matrule) && (oper->_matrule->_next)) {444// Regardles of whether the first matchrule is a chain rule, check the list445rule = oper->_matrule;446do {447rule = rule->_next;448// Any extra match rules after the first must be chain rules449const Form *form = _globalNames[rule->_opType];450if ((form) && form->is_operand() &&451(form->ideal_only() == false)) {452assert( oper->cost(), "This case expects NULL cost, not default cost");453add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident);454}455} while(rule->_next != NULL);456}457458}459460//------------------------------buildMatchList---------------------------------461// operands and instructions provide the result462void ArchDesc::buildMatchList(MatchRule *mrule, const char *resultStr,463const char *rootOp, Predicate *pred,464const char *cost) {465const char *leftstr, *rightstr;466MatchNode *mnode;467468leftstr = rightstr = NULL;469// Check for chain rule, and do not generate a match list for it470if ( mrule->is_chain_rule(_globalNames) ) {471return;472}473474// Identify index position among ideal operands475intptr_t index = _last_opcode;476const char *indexStr = getMatchListIndex(*mrule);477index = (intptr_t)_idealIndex[indexStr];478if (index == 0) {479fprintf(stderr, "Ideal node missing: %s\n", indexStr);480assert(index != 0, "Failed lookup of ideal node\n");481}482483// Check that this will be placed appropriately in the DFA484if (index >= _last_opcode) {485fprintf(stderr, "Invalid match rule %s <-- ( %s )\n",486resultStr ? resultStr : " ",487rootOp ? rootOp : " ");488assert(index < _last_opcode, "Matching item not in ideal graph\n");489return;490}491492493// Walk the MatchRule, generating MatchList entries for each level494// of the rule (each nesting of parentheses)495// Check for "Set"496if (!strcmp(mrule->_opType, "Set")) {497mnode = mrule->_rChild;498buildMList(mnode, rootOp, resultStr, pred, cost);499return;500}501// Build MatchLists for children502// Check each child for an internal operand name, and use that name503// for the parent's matchlist entry if it exists504mnode = mrule->_lChild;505if (mnode) {506buildMList(mnode, NULL, NULL, NULL, NULL);507leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;508}509mnode = mrule->_rChild;510if (mnode) {511buildMList(mnode, NULL, NULL, NULL, NULL);512rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;513}514// Search for an identical matchlist entry already on the list515if ((_mlistab[index] == NULL) ||516(_mlistab[index] &&517!_mlistab[index]->search(rootOp, resultStr, leftstr, rightstr, pred))) {518// Place this match rule at front of list519MatchList *mList =520new MatchList(_mlistab[index], pred, cost,521rootOp, resultStr, leftstr, rightstr);522_mlistab[index] = mList;523}524}525526// Recursive call for construction of match lists527void ArchDesc::buildMList(MatchNode *node, const char *rootOp,528const char *resultOp, Predicate *pred,529const char *cost) {530const char *leftstr, *rightstr;531const char *resultop;532const char *opcode;533MatchNode *mnode;534Form *form;535536leftstr = rightstr = NULL;537// Do not process leaves of the Match Tree if they are not ideal538if ((node) && (node->_lChild == NULL) && (node->_rChild == NULL) &&539((form = (Form *)_globalNames[node->_opType]) != NULL) &&540(!form->ideal_only())) {541return;542}543544// Identify index position among ideal operands545intptr_t index = _last_opcode;546const char *indexStr = node ? node->_opType : (char *) " ";547index = (intptr_t)_idealIndex[indexStr];548if (index == 0) {549fprintf(stderr, "error: operand \"%s\" not found\n", indexStr);550assert(0, "fatal error");551}552553// Build MatchLists for children554// Check each child for an internal operand name, and use that name555// for the parent's matchlist entry if it exists556mnode = node->_lChild;557if (mnode) {558buildMList(mnode, NULL, NULL, NULL, NULL);559leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;560}561mnode = node->_rChild;562if (mnode) {563buildMList(mnode, NULL, NULL, NULL, NULL);564rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;565}566// Grab the string for the opcode of this list entry567if (rootOp == NULL) {568opcode = (node->_internalop) ? node->_internalop : node->_opType;569} else {570opcode = rootOp;571}572// Grab the string for the result of this list entry573if (resultOp == NULL) {574resultop = (node->_internalop) ? node->_internalop : node->_opType;575}576else resultop = resultOp;577// Search for an identical matchlist entry already on the list578if ((_mlistab[index] == NULL) || (_mlistab[index] &&579!_mlistab[index]->search(opcode, resultop, leftstr, rightstr, pred))) {580// Place this match rule at front of list581MatchList *mList =582new MatchList(_mlistab[index],pred,cost,583opcode, resultop, leftstr, rightstr);584_mlistab[index] = mList;585}586}587588// Count number of OperandForms defined589int ArchDesc::operandFormCount() {590// Only interested in ones with non-NULL match rule591int count = 0; _operands.reset();592OperandForm *cur;593for( ; (cur = (OperandForm*)_operands.iter()) != NULL; ) {594if (cur->_matrule != NULL) ++count;595};596return count;597}598599// Count number of OpClassForms defined600int ArchDesc::opclassFormCount() {601// Only interested in ones with non-NULL match rule602int count = 0; _operands.reset();603OpClassForm *cur;604for( ; (cur = (OpClassForm*)_opclass.iter()) != NULL; ) {605++count;606};607return count;608}609610// Count number of InstructForms defined611int ArchDesc::instructFormCount() {612// Only interested in ones with non-NULL match rule613int count = 0; _instructions.reset();614InstructForm *cur;615for( ; (cur = (InstructForm*)_instructions.iter()) != NULL; ) {616if (cur->_matrule != NULL) ++count;617};618return count;619}620621622//------------------------------get_preproc_def--------------------------------623// Return the textual binding for a given CPP flag name.624// Return NULL if there is no binding, or it has been #undef-ed.625char* ArchDesc::get_preproc_def(const char* flag) {626// In case of syntax errors, flag may take the value NULL.627SourceForm* deff = NULL;628if (flag != NULL)629deff = (SourceForm*) _preproc_table[flag];630return (deff == NULL) ? NULL : deff->_code;631}632633634//------------------------------set_preproc_def--------------------------------635// Change or create a textual binding for a given CPP flag name.636// Giving NULL means the flag name is to be #undef-ed.637// In any case, _preproc_list collects all names either #defined or #undef-ed.638void ArchDesc::set_preproc_def(const char* flag, const char* def) {639SourceForm* deff = (SourceForm*) _preproc_table[flag];640if (deff == NULL) {641deff = new SourceForm(NULL);642_preproc_table.Insert(flag, deff);643_preproc_list.addName(flag); // this supports iteration644}645deff->_code = (char*) def;646}647648649bool ArchDesc::verify() {650651if (_register)652assert( _register->verify(), "Register declarations failed verification");653if (!_quiet_mode)654fprintf(stderr,"\n");655// fprintf(stderr,"---------------------------- Verify Operands ---------------\n");656// _operands.verify();657// fprintf(stderr,"\n");658// fprintf(stderr,"---------------------------- Verify Operand Classes --------\n");659// _opclass.verify();660// fprintf(stderr,"\n");661// fprintf(stderr,"---------------------------- Verify Attributes ------------\n");662// _attributes.verify();663// fprintf(stderr,"\n");664if (!_quiet_mode)665fprintf(stderr,"---------------------------- Verify Instructions ----------------------------\n");666_instructions.verify();667if (!_quiet_mode)668fprintf(stderr,"\n");669// if ( _encode ) {670// fprintf(stderr,"---------------------------- Verify Encodings --------------\n");671// _encode->verify();672// }673674//if (_pipeline) _pipeline->verify();675676return true;677}678679680void ArchDesc::dump() {681_pre_header.dump();682_header.dump();683_source.dump();684if (_register) _register->dump();685fprintf(stderr,"\n");686fprintf(stderr,"------------------ Dump Operands ---------------------\n");687_operands.dump();688fprintf(stderr,"\n");689fprintf(stderr,"------------------ Dump Operand Classes --------------\n");690_opclass.dump();691fprintf(stderr,"\n");692fprintf(stderr,"------------------ Dump Attributes ------------------\n");693_attributes.dump();694fprintf(stderr,"\n");695fprintf(stderr,"------------------ Dump Instructions -----------------\n");696_instructions.dump();697if ( _encode ) {698fprintf(stderr,"------------------ Dump Encodings --------------------\n");699_encode->dump();700}701if (_pipeline) _pipeline->dump();702}703704705//------------------------------init_keywords----------------------------------706// Load the kewords into the global name table707void ArchDesc::initKeywords(FormDict& names) {708// Insert keyword strings into Global Name Table. Keywords have a NULL value709// field for quick easy identification when checking identifiers.710names.Insert("instruct", NULL);711names.Insert("operand", NULL);712names.Insert("attribute", NULL);713names.Insert("source", NULL);714names.Insert("register", NULL);715names.Insert("pipeline", NULL);716names.Insert("constraint", NULL);717names.Insert("predicate", NULL);718names.Insert("encode", NULL);719names.Insert("enc_class", NULL);720names.Insert("interface", NULL);721names.Insert("opcode", NULL);722names.Insert("ins_encode", NULL);723names.Insert("match", NULL);724names.Insert("effect", NULL);725names.Insert("expand", NULL);726names.Insert("rewrite", NULL);727names.Insert("reg_def", NULL);728names.Insert("reg_class", NULL);729names.Insert("alloc_class", NULL);730names.Insert("resource", NULL);731names.Insert("pipe_class", NULL);732names.Insert("pipe_desc", NULL);733}734735736//------------------------------internal_err----------------------------------737// Issue a parser error message, and skip to the end of the current line738void ArchDesc::internal_err(const char *fmt, ...) {739va_list args;740741va_start(args, fmt);742_internal_errs += emit_msg(0, INTERNAL_ERR, 0, fmt, args);743va_end(args);744745_no_output = 1;746}747748//------------------------------syntax_err----------------------------------749// Issue a parser error message, and skip to the end of the current line750void ArchDesc::syntax_err(int lineno, const char *fmt, ...) {751va_list args;752753va_start(args, fmt);754_internal_errs += emit_msg(0, SYNERR, lineno, fmt, args);755va_end(args);756757_no_output = 1;758}759760//------------------------------emit_msg---------------------------------------761// Emit a user message, typically a warning or error762int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt,763va_list args) {764static int last_lineno = -1;765int i;766const char *pref;767768switch(flag) {769case 0: pref = "Warning: "; break;770case 1: pref = "Syntax Error: "; break;771case 2: pref = "Semantic Error: "; break;772case 3: pref = "Internal Error: "; break;773default: assert(0, ""); break;774}775776if (line == last_lineno) return 0;777last_lineno = line;778779if (!quiet) { /* no output if in quiet mode */780i = fprintf(errfile, "%s(%d) ", _ADL_file._name, line);781while (i++ <= 15) fputc(' ', errfile);782fprintf(errfile, "%-8s:", pref);783vfprintf(errfile, fmt, args);784fprintf(errfile, "\n");785fflush(errfile);786}787return 1;788}789790791// ---------------------------------------------------------------------------792//--------Utilities to build mappings for machine registers ------------------793// ---------------------------------------------------------------------------794795// Construct the name of the register mask.796static const char *getRegMask(const char *reg_class_name) {797if( reg_class_name == NULL ) return "RegMask::Empty";798799if (strcmp(reg_class_name,"Universe")==0) {800return "RegMask::Empty";801} else if (strcmp(reg_class_name,"stack_slots")==0) {802return "(Compile::current()->FIRST_STACK_mask())";803} else {804char *rc_name = toUpper(reg_class_name);805const char *mask = "_mask";806int length = (int)strlen(rc_name) + (int)strlen(mask) + 5;807char *regMask = new char[length];808sprintf(regMask,"%s%s()", rc_name, mask);809delete[] rc_name;810return regMask;811}812}813814// Convert a register class name to its register mask.815const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) {816const char *reg_mask = "RegMask::Empty";817818if( _register ) {819RegClass *reg_class = _register->getRegClass(rc_name);820if (reg_class == NULL) {821syntax_err(0, "Use of an undefined register class %s", rc_name);822return reg_mask;823}824825// Construct the name of the register mask.826reg_mask = getRegMask(rc_name);827}828829return reg_mask;830}831832833// Obtain the name of the RegMask for an OperandForm834const char *ArchDesc::reg_mask(OperandForm &opForm) {835const char *regMask = "RegMask::Empty";836837// Check constraints on result's register class838const char *result_class = opForm.constrained_reg_class();839if (result_class == NULL) {840opForm.dump();841syntax_err(opForm._linenum,842"Use of an undefined result class for operand: %s",843opForm._ident);844abort();845}846847regMask = reg_class_to_reg_mask( result_class );848849return regMask;850}851852// Obtain the name of the RegMask for an InstructForm853const char *ArchDesc::reg_mask(InstructForm &inForm) {854const char *result = inForm.reduce_result();855856if (result == NULL) {857syntax_err(inForm._linenum,858"Did not find result operand or RegMask"859" for this instruction: %s",860inForm._ident);861abort();862}863864// Instructions producing 'Universe' use RegMask::Empty865if( strcmp(result,"Universe")==0 ) {866return "RegMask::Empty";867}868869// Lookup this result operand and get its register class870Form *form = (Form*)_globalNames[result];871if (form == NULL) {872syntax_err(inForm._linenum,873"Did not find result operand for result: %s", result);874abort();875}876OperandForm *oper = form->is_operand();877if (oper == NULL) {878syntax_err(inForm._linenum, "Form is not an OperandForm:");879form->dump();880abort();881}882return reg_mask( *oper );883}884885886// Obtain the STACK_OR_reg_mask name for an OperandForm887char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) {888// name of cisc_spillable version889const char *reg_mask_name = reg_mask(opForm);890891if (reg_mask_name == NULL) {892syntax_err(opForm._linenum,893"Did not find reg_mask for opForm: %s",894opForm._ident);895abort();896}897898const char *stack_or = "STACK_OR_";899int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1;900char *result = new char[length];901sprintf(result,"%s%s", stack_or, reg_mask_name);902903return result;904}905906// Record that the register class must generate a stack_or_reg_mask907void ArchDesc::set_stack_or_reg(const char *reg_class_name) {908if( _register ) {909RegClass *reg_class = _register->getRegClass(reg_class_name);910reg_class->set_stack_version(true);911}912}913914915// Return the type signature for the ideal operation916const char *ArchDesc::getIdealType(const char *idealOp) {917// Find last character in idealOp, it specifies the type918char last_char = 0;919const char *ptr = idealOp;920for (; *ptr != '\0'; ++ptr) {921last_char = *ptr;922}923924// Match Vector types.925if (strncmp(idealOp, "Vec",3)==0) {926switch(last_char) {927case 'S': return "TypeVect::VECTS";928case 'D': return "TypeVect::VECTD";929case 'X': return "TypeVect::VECTX";930case 'Y': return "TypeVect::VECTY";931default:932internal_err("Vector type %s with unrecognized type\n",idealOp);933}934}935936// !!!!!937switch(last_char) {938case 'I': return "TypeInt::INT";939case 'P': return "TypePtr::BOTTOM";940case 'N': return "TypeNarrowOop::BOTTOM";941case 'F': return "Type::FLOAT";942case 'D': return "Type::DOUBLE";943case 'L': return "TypeLong::LONG";944case 's': return "TypeInt::CC /*flags*/";945default:946return NULL;947// !!!!!948// internal_err("Ideal type %s with unrecognized type\n",idealOp);949break;950}951952return NULL;953}954955956957OperandForm *ArchDesc::constructOperand(const char *ident,958bool ideal_only) {959OperandForm *opForm = new OperandForm(ident, ideal_only);960_globalNames.Insert(ident, opForm);961addForm(opForm);962963return opForm;964}965966967// Import predefined base types: Set = 1, RegI, RegP, ...968void ArchDesc::initBaseOpTypes() {969// Create OperandForm and assign type for each opcode.970for (int i = 1; i < _last_machine_leaf; ++i) {971char *ident = (char *)NodeClassNames[i];972constructOperand(ident, true);973}974// Create InstructForm and assign type for each ideal instruction.975for ( int j = _last_machine_leaf+1; j < _last_opcode; ++j) {976char *ident = (char *)NodeClassNames[j];977if(!strcmp(ident, "ConI") || !strcmp(ident, "ConP") ||978!strcmp(ident, "ConN") || !strcmp(ident, "ConNKlass") ||979!strcmp(ident, "ConF") || !strcmp(ident, "ConD") ||980!strcmp(ident, "ConL") || !strcmp(ident, "Con" ) ||981!strcmp(ident, "Bool") ) {982constructOperand(ident, true);983}984else {985InstructForm *insForm = new InstructForm(ident, true);986// insForm->_opcode = nextUserOpType(ident);987_globalNames.Insert(ident,insForm);988addForm(insForm);989}990}991992{ OperandForm *opForm;993// Create operand type "Universe" for return instructions.994const char *ident = "Universe";995opForm = constructOperand(ident, false);996997// Create operand type "label" for branch targets998ident = "label";999opForm = constructOperand(ident, false);10001001// !!!!! Update - when adding a new sReg/stackSlot type1002// Create operand types "sReg[IPFDL]" for stack slot registers1003opForm = constructOperand("sRegI", false);1004opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1005opForm = constructOperand("sRegP", false);1006opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1007opForm = constructOperand("sRegF", false);1008opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1009opForm = constructOperand("sRegD", false);1010opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1011opForm = constructOperand("sRegL", false);1012opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");10131014// Create operand type "method" for call targets1015ident = "method";1016opForm = constructOperand(ident, false);1017}10181019// Create Effect Forms for each of the legal effects1020// USE, DEF, USE_DEF, KILL, USE_KILL1021{1022const char *ident = "USE";1023Effect *eForm = new Effect(ident);1024_globalNames.Insert(ident, eForm);1025ident = "DEF";1026eForm = new Effect(ident);1027_globalNames.Insert(ident, eForm);1028ident = "USE_DEF";1029eForm = new Effect(ident);1030_globalNames.Insert(ident, eForm);1031ident = "KILL";1032eForm = new Effect(ident);1033_globalNames.Insert(ident, eForm);1034ident = "USE_KILL";1035eForm = new Effect(ident);1036_globalNames.Insert(ident, eForm);1037ident = "TEMP";1038eForm = new Effect(ident);1039_globalNames.Insert(ident, eForm);1040ident = "CALL";1041eForm = new Effect(ident);1042_globalNames.Insert(ident, eForm);1043}10441045//1046// Build mapping from ideal names to ideal indices1047int idealIndex = 0;1048for (idealIndex = 1; idealIndex < _last_machine_leaf; ++idealIndex) {1049const char *idealName = NodeClassNames[idealIndex];1050_idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex);1051}1052for ( idealIndex = _last_machine_leaf+1;1053idealIndex < _last_opcode; ++idealIndex) {1054const char *idealName = NodeClassNames[idealIndex];1055_idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex);1056}10571058}105910601061//---------------------------addSUNcopyright-------------------------------1062// output SUN copyright info1063void ArchDesc::addSunCopyright(char* legal, int size, FILE *fp) {1064size_t count = fwrite(legal, 1, size, fp);1065assert(count == (size_t) size, "copyright info truncated");1066fprintf(fp,"\n");1067fprintf(fp,"// Machine Generated File. Do Not Edit!\n");1068fprintf(fp,"\n");1069}107010711072//---------------------------addIncludeGuardStart--------------------------1073// output the start of an include guard.1074void ArchDesc::addIncludeGuardStart(ADLFILE &adlfile, const char* guardString) {1075// Build #include lines1076fprintf(adlfile._fp, "\n");1077fprintf(adlfile._fp, "#ifndef %s\n", guardString);1078fprintf(adlfile._fp, "#define %s\n", guardString);1079fprintf(adlfile._fp, "\n");10801081}10821083//---------------------------addIncludeGuardEnd--------------------------1084// output the end of an include guard.1085void ArchDesc::addIncludeGuardEnd(ADLFILE &adlfile, const char* guardString) {1086// Build #include lines1087fprintf(adlfile._fp, "\n");1088fprintf(adlfile._fp, "#endif // %s\n", guardString);10891090}10911092//---------------------------addInclude--------------------------1093// output the #include line for this file.1094void ArchDesc::addInclude(ADLFILE &adlfile, const char* fileName) {1095fprintf(adlfile._fp, "#include \"%s\"\n", fileName);10961097}10981099void ArchDesc::addInclude(ADLFILE &adlfile, const char* includeDir, const char* fileName) {1100fprintf(adlfile._fp, "#include \"%s/%s\"\n", includeDir, fileName);11011102}11031104//---------------------------addPreprocessorChecks-----------------------------1105// Output C preprocessor code to verify the backend compilation environment.1106// The idea is to force code produced by "adlc -DHS64" to be compiled by a1107// command of the form "CC ... -DHS64 ...", so that any #ifdefs in the source1108// blocks select C code that is consistent with adlc's selections of AD code.1109void ArchDesc::addPreprocessorChecks(FILE *fp) {1110const char* flag;1111_preproc_list.reset();1112if (_preproc_list.count() > 0 && !_preproc_list.current_is_signal()) {1113fprintf(fp, "// Check consistency of C++ compilation with ADLC options:\n");1114}1115for (_preproc_list.reset(); (flag = _preproc_list.iter()) != NULL; ) {1116if (_preproc_list.current_is_signal()) break;1117char* def = get_preproc_def(flag);1118fprintf(fp, "// Check adlc ");1119if (def)1120fprintf(fp, "-D%s=%s\n", flag, def);1121else fprintf(fp, "-U%s\n", flag);1122fprintf(fp, "#%s %s\n",1123def ? "ifndef" : "ifdef", flag);1124fprintf(fp, "# error \"%s %s be defined\"\n",1125flag, def ? "must" : "must not");1126fprintf(fp, "#endif // %s\n", flag);1127}1128}112911301131// Convert operand name into enum name1132const char *ArchDesc::machOperEnum(const char *opName) {1133return ArchDesc::getMachOperEnum(opName);1134}11351136// Convert operand name into enum name1137const char *ArchDesc::getMachOperEnum(const char *opName) {1138return (opName ? toUpper(opName) : opName);1139}11401141//---------------------------buildMustCloneMap-----------------------------1142// Flag cases when machine needs cloned values or instructions1143void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) {1144// Build external declarations for mappings1145fprintf(fp_hpp, "// Mapping from machine-independent opcode to boolean\n");1146fprintf(fp_hpp, "// Flag cases where machine needs cloned values or instructions\n");1147fprintf(fp_hpp, "extern const char must_clone[];\n");1148fprintf(fp_hpp, "\n");11491150// Build mapping from ideal names to ideal indices1151fprintf(fp_cpp, "\n");1152fprintf(fp_cpp, "// Mapping from machine-independent opcode to boolean\n");1153fprintf(fp_cpp, "const char must_clone[] = {\n");1154for (int idealIndex = 0; idealIndex < _last_opcode; ++idealIndex) {1155int must_clone = 0;1156const char *idealName = NodeClassNames[idealIndex];1157// Previously selected constants for cloning1158// !!!!!1159// These are the current machine-dependent clones1160if ( strcmp(idealName,"CmpI") == 01161|| strcmp(idealName,"CmpU") == 01162|| strcmp(idealName,"CmpP") == 01163|| strcmp(idealName,"CmpN") == 01164|| strcmp(idealName,"CmpL") == 01165|| strcmp(idealName,"CmpUL") == 01166|| strcmp(idealName,"CmpD") == 01167|| strcmp(idealName,"CmpF") == 01168|| strcmp(idealName,"FastLock") == 01169|| strcmp(idealName,"FastUnlock") == 01170|| strcmp(idealName,"OverflowAddI") == 01171|| strcmp(idealName,"OverflowAddL") == 01172|| strcmp(idealName,"OverflowSubI") == 01173|| strcmp(idealName,"OverflowSubL") == 01174|| strcmp(idealName,"OverflowMulI") == 01175|| strcmp(idealName,"OverflowMulL") == 01176|| strcmp(idealName,"Bool") == 01177|| strcmp(idealName,"Binary") == 0 ) {1178// Removed ConI from the must_clone list. CPUs that cannot use1179// large constants as immediates manifest the constant as an1180// instruction. The must_clone flag prevents the constant from1181// floating up out of loops.1182must_clone = 1;1183}1184fprintf(fp_cpp, " %d%s // %s: %d\n", must_clone,1185(idealIndex != (_last_opcode - 1)) ? "," : " // no trailing comma",1186idealName, idealIndex);1187}1188// Finish defining table1189fprintf(fp_cpp, "};\n");1190}119111921193