Path: blob/master/src/hotspot/share/adlc/archDesc.cpp
41144 views
//1// Copyright (c) 1997, 2021, 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_deep_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();273274// Construct a MatchList for this entry.275// Iterate over the list to enumerate all match cases for operands with multiple match rules.276for (; mrule != NULL; mrule = mrule->_next) {277mrule->_machType = rootOp;278buildMatchList(mrule, result, rootOp, pred, cost);279}280}281}282283// Build MatchList structures for instructions284void ArchDesc::inspectInstructions() {285286// Iterate through all instructions287_instructions.reset();288InstructForm *instr;289for( ; (instr = (InstructForm*)_instructions.iter()) != NULL; ) {290// Construct list of top-level operands (components)291instr->build_components();292293// Ensure that match field is defined.294if ( instr->_matrule == NULL ) continue;295296MatchRule &mrule = *instr->_matrule;297Predicate *pred = instr->build_predicate();298299// Grab the machine type of the operand300const char *rootOp = instr->_ident;301mrule._machType = rootOp;302303// Cost for this match304const char *costStr = instr->cost();305const char *defaultCost =306((AttributeForm*)_globalNames[AttributeForm::_ins_cost])->_attrdef;307const char *cost = costStr? costStr : defaultCost;308309// Find result type for match310const char *result = instr->reduce_result();311312if (( instr->is_ideal_branch() && instr->label_position() == -1) ||313(!instr->is_ideal_branch() && instr->label_position() != -1)) {314syntax_err(instr->_linenum, "%s: Only branches to a label are supported\n", rootOp);315}316317Attribute *attr = instr->_attribs;318while (attr != NULL) {319if (strcmp(attr->_ident,"ins_short_branch") == 0 &&320attr->int_val(*this) != 0) {321if (!instr->is_ideal_branch() || instr->label_position() == -1) {322syntax_err(instr->_linenum, "%s: Only short branch to a label is supported\n", rootOp);323}324instr->set_short_branch(true);325} else if (strcmp(attr->_ident,"ins_alignment") == 0 &&326attr->int_val(*this) != 0) {327instr->set_alignment(attr->int_val(*this));328}329attr = (Attribute *)attr->_next;330}331332if (!instr->is_short_branch()) {333buildMatchList(instr->_matrule, result, mrule._machType, pred, cost);334}335}336}337338static int setsResult(MatchRule &mrule) {339if (strcmp(mrule._name,"Set") == 0) return 1;340return 0;341}342343const char *ArchDesc::getMatchListIndex(MatchRule &mrule) {344if (setsResult(mrule)) {345// right child346return mrule._rChild->_opType;347} else {348// first entry349return mrule._opType;350}351}352353354//------------------------------result of reduction----------------------------355356357//------------------------------left reduction---------------------------------358// Return the left reduction associated with an internal name359const char *ArchDesc::reduceLeft(char *internalName) {360const char *left = NULL;361MatchNode *mnode = (MatchNode*)_internalMatch[internalName];362if (mnode->_lChild) {363mnode = mnode->_lChild;364left = mnode->_internalop ? mnode->_internalop : mnode->_opType;365}366return left;367}368369370//------------------------------right reduction--------------------------------371const char *ArchDesc::reduceRight(char *internalName) {372const char *right = NULL;373MatchNode *mnode = (MatchNode*)_internalMatch[internalName];374if (mnode->_rChild) {375mnode = mnode->_rChild;376right = mnode->_internalop ? mnode->_internalop : mnode->_opType;377}378return right;379}380381382//------------------------------check_optype-----------------------------------383void ArchDesc::check_optype(MatchRule *mrule) {384MatchRule *rule = mrule;385386// !!!!!387// // Cycle through the list of match rules388// while(mrule) {389// // Check for a filled in type field390// if (mrule->_opType == NULL) {391// const Form *form = operands[_result];392// OpClassForm *opcForm = form ? form->is_opclass() : NULL;393// assert(opcForm != NULL, "Match Rule contains invalid operand name.");394// }395// char *opType = opcForm->_ident;396// }397}398399//------------------------------add_chain_rule_entry--------------------------400void ArchDesc::add_chain_rule_entry(const char *src, const char *cost,401const char *result) {402// Look-up the operation in chain rule table403ChainList *lst = (ChainList *)_chainRules[src];404if (lst == NULL) {405lst = new ChainList();406_chainRules.Insert(src, lst);407}408if (!lst->search(result)) {409if (cost == NULL) {410cost = ((AttributeForm*)_globalNames[AttributeForm::_op_cost])->_attrdef;411}412lst->insert(result, cost, result);413}414}415416//------------------------------build_chain_rule-------------------------------417void ArchDesc::build_chain_rule(OperandForm *oper) {418MatchRule *rule;419420// Check for chain rules here421// If this is only a chain rule422if ((oper->_matrule) && (oper->_matrule->_lChild == NULL) &&423(oper->_matrule->_rChild == NULL)) {424425{426const Form *form = _globalNames[oper->_matrule->_opType];427if ((form) && form->is_operand() &&428(form->ideal_only() == false)) {429add_chain_rule_entry(oper->_matrule->_opType, oper->cost(), oper->_ident);430}431}432// Check for additional chain rules433if (oper->_matrule->_next) {434rule = oper->_matrule;435do {436rule = rule->_next;437// Any extra match rules after the first must be chain rules438const Form *form = _globalNames[rule->_opType];439if ((form) && form->is_operand() &&440(form->ideal_only() == false)) {441add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident);442}443} while(rule->_next != NULL);444}445}446else if ((oper->_matrule) && (oper->_matrule->_next)) {447// Regardles of whether the first matchrule is a chain rule, check the list448rule = oper->_matrule;449do {450rule = rule->_next;451// Any extra match rules after the first must be chain rules452const Form *form = _globalNames[rule->_opType];453if ((form) && form->is_operand() &&454(form->ideal_only() == false)) {455assert( oper->cost(), "This case expects NULL cost, not default cost");456add_chain_rule_entry(rule->_opType, oper->cost(), oper->_ident);457}458} while(rule->_next != NULL);459}460461}462463//------------------------------buildMatchList---------------------------------464// operands and instructions provide the result465void ArchDesc::buildMatchList(MatchRule *mrule, const char *resultStr,466const char *rootOp, Predicate *pred,467const char *cost) {468const char *leftstr, *rightstr;469MatchNode *mnode;470471leftstr = rightstr = NULL;472// Check for chain rule, and do not generate a match list for it473if ( mrule->is_chain_rule(_globalNames) ) {474return;475}476477// Identify index position among ideal operands478intptr_t index = _last_opcode;479const char *indexStr = getMatchListIndex(*mrule);480index = (intptr_t)_idealIndex[indexStr];481if (index == 0) {482fprintf(stderr, "Ideal node missing: %s\n", indexStr);483assert(index != 0, "Failed lookup of ideal node\n");484}485486// Check that this will be placed appropriately in the DFA487if (index >= _last_opcode) {488fprintf(stderr, "Invalid match rule %s <-- ( %s )\n",489resultStr ? resultStr : " ",490rootOp ? rootOp : " ");491assert(index < _last_opcode, "Matching item not in ideal graph\n");492return;493}494495496// Walk the MatchRule, generating MatchList entries for each level497// of the rule (each nesting of parentheses)498// Check for "Set"499if (!strcmp(mrule->_opType, "Set")) {500mnode = mrule->_rChild;501buildMList(mnode, rootOp, resultStr, pred, cost);502return;503}504// Build MatchLists for children505// Check each child for an internal operand name, and use that name506// for the parent's matchlist entry if it exists507mnode = mrule->_lChild;508if (mnode) {509buildMList(mnode, NULL, NULL, NULL, NULL);510leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;511}512mnode = mrule->_rChild;513if (mnode) {514buildMList(mnode, NULL, NULL, NULL, NULL);515rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;516}517// Search for an identical matchlist entry already on the list518if ((_mlistab[index] == NULL) ||519(_mlistab[index] &&520!_mlistab[index]->search(rootOp, resultStr, leftstr, rightstr, pred))) {521// Place this match rule at front of list522MatchList *mList =523new MatchList(_mlistab[index], pred, cost,524rootOp, resultStr, leftstr, rightstr);525_mlistab[index] = mList;526}527}528529// Recursive call for construction of match lists530void ArchDesc::buildMList(MatchNode *node, const char *rootOp,531const char *resultOp, Predicate *pred,532const char *cost) {533const char *leftstr, *rightstr;534const char *resultop;535const char *opcode;536MatchNode *mnode;537Form *form;538539leftstr = rightstr = NULL;540// Do not process leaves of the Match Tree if they are not ideal541if ((node) && (node->_lChild == NULL) && (node->_rChild == NULL) &&542((form = (Form *)_globalNames[node->_opType]) != NULL) &&543(!form->ideal_only())) {544return;545}546547// Identify index position among ideal operands548intptr_t index = _last_opcode;549const char *indexStr = node ? node->_opType : (char *) " ";550index = (intptr_t)_idealIndex[indexStr];551if (index == 0) {552fprintf(stderr, "error: operand \"%s\" not found\n", indexStr);553assert(0, "fatal error");554}555556if (node == NULL) {557fprintf(stderr, "error: node is NULL\n");558assert(0, "fatal error");559}560// Build MatchLists for children561// Check each child for an internal operand name, and use that name562// for the parent's matchlist entry if it exists563mnode = node->_lChild;564if (mnode) {565buildMList(mnode, NULL, NULL, NULL, NULL);566leftstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;567}568mnode = node->_rChild;569if (mnode) {570buildMList(mnode, NULL, NULL, NULL, NULL);571rightstr = mnode->_internalop ? mnode->_internalop : mnode->_opType;572}573// Grab the string for the opcode of this list entry574if (rootOp == NULL) {575opcode = (node->_internalop) ? node->_internalop : node->_opType;576} else {577opcode = rootOp;578}579// Grab the string for the result of this list entry580if (resultOp == NULL) {581resultop = (node->_internalop) ? node->_internalop : node->_opType;582}583else resultop = resultOp;584// Search for an identical matchlist entry already on the list585if ((_mlistab[index] == NULL) || (_mlistab[index] &&586!_mlistab[index]->search(opcode, resultop, leftstr, rightstr, pred))) {587// Place this match rule at front of list588MatchList *mList =589new MatchList(_mlistab[index],pred,cost,590opcode, resultop, leftstr, rightstr);591_mlistab[index] = mList;592}593}594595// Count number of OperandForms defined596int ArchDesc::operandFormCount() {597// Only interested in ones with non-NULL match rule598int count = 0; _operands.reset();599OperandForm *cur;600for( ; (cur = (OperandForm*)_operands.iter()) != NULL; ) {601if (cur->_matrule != NULL) ++count;602};603return count;604}605606// Count number of OpClassForms defined607int ArchDesc::opclassFormCount() {608// Only interested in ones with non-NULL match rule609int count = 0; _operands.reset();610OpClassForm *cur;611for( ; (cur = (OpClassForm*)_opclass.iter()) != NULL; ) {612++count;613};614return count;615}616617// Count number of InstructForms defined618int ArchDesc::instructFormCount() {619// Only interested in ones with non-NULL match rule620int count = 0; _instructions.reset();621InstructForm *cur;622for( ; (cur = (InstructForm*)_instructions.iter()) != NULL; ) {623if (cur->_matrule != NULL) ++count;624};625return count;626}627628629//------------------------------get_preproc_def--------------------------------630// Return the textual binding for a given CPP flag name.631// Return NULL if there is no binding, or it has been #undef-ed.632char* ArchDesc::get_preproc_def(const char* flag) {633// In case of syntax errors, flag may take the value NULL.634SourceForm* deff = NULL;635if (flag != NULL)636deff = (SourceForm*) _preproc_table[flag];637return (deff == NULL) ? NULL : deff->_code;638}639640641//------------------------------set_preproc_def--------------------------------642// Change or create a textual binding for a given CPP flag name.643// Giving NULL means the flag name is to be #undef-ed.644// In any case, _preproc_list collects all names either #defined or #undef-ed.645void ArchDesc::set_preproc_def(const char* flag, const char* def) {646SourceForm* deff = (SourceForm*) _preproc_table[flag];647if (deff == NULL) {648deff = new SourceForm(NULL);649_preproc_table.Insert(flag, deff);650_preproc_list.addName(flag); // this supports iteration651}652deff->_code = (char*) def;653}654655656bool ArchDesc::verify() {657658if (_register)659assert( _register->verify(), "Register declarations failed verification");660if (!_quiet_mode)661fprintf(stderr,"\n");662// fprintf(stderr,"---------------------------- Verify Operands ---------------\n");663// _operands.verify();664// fprintf(stderr,"\n");665// fprintf(stderr,"---------------------------- Verify Operand Classes --------\n");666// _opclass.verify();667// fprintf(stderr,"\n");668// fprintf(stderr,"---------------------------- Verify Attributes ------------\n");669// _attributes.verify();670// fprintf(stderr,"\n");671if (!_quiet_mode)672fprintf(stderr,"---------------------------- Verify Instructions ----------------------------\n");673_instructions.verify();674if (!_quiet_mode)675fprintf(stderr,"\n");676// if ( _encode ) {677// fprintf(stderr,"---------------------------- Verify Encodings --------------\n");678// _encode->verify();679// }680681//if (_pipeline) _pipeline->verify();682683return true;684}685686687void ArchDesc::dump() {688_pre_header.dump();689_header.dump();690_source.dump();691if (_register) _register->dump();692fprintf(stderr,"\n");693fprintf(stderr,"------------------ Dump Operands ---------------------\n");694_operands.dump();695fprintf(stderr,"\n");696fprintf(stderr,"------------------ Dump Operand Classes --------------\n");697_opclass.dump();698fprintf(stderr,"\n");699fprintf(stderr,"------------------ Dump Attributes ------------------\n");700_attributes.dump();701fprintf(stderr,"\n");702fprintf(stderr,"------------------ Dump Instructions -----------------\n");703_instructions.dump();704if ( _encode ) {705fprintf(stderr,"------------------ Dump Encodings --------------------\n");706_encode->dump();707}708if (_pipeline) _pipeline->dump();709}710711712//------------------------------init_keywords----------------------------------713// Load the kewords into the global name table714void ArchDesc::initKeywords(FormDict& names) {715// Insert keyword strings into Global Name Table. Keywords have a NULL value716// field for quick easy identification when checking identifiers.717names.Insert("instruct", NULL);718names.Insert("operand", NULL);719names.Insert("attribute", NULL);720names.Insert("source", NULL);721names.Insert("register", NULL);722names.Insert("pipeline", NULL);723names.Insert("constraint", NULL);724names.Insert("predicate", NULL);725names.Insert("encode", NULL);726names.Insert("enc_class", NULL);727names.Insert("interface", NULL);728names.Insert("opcode", NULL);729names.Insert("ins_encode", NULL);730names.Insert("match", NULL);731names.Insert("effect", NULL);732names.Insert("expand", NULL);733names.Insert("rewrite", NULL);734names.Insert("reg_def", NULL);735names.Insert("reg_class", NULL);736names.Insert("alloc_class", NULL);737names.Insert("resource", NULL);738names.Insert("pipe_class", NULL);739names.Insert("pipe_desc", NULL);740}741742743//------------------------------internal_err----------------------------------744// Issue a parser error message, and skip to the end of the current line745void ArchDesc::internal_err(const char *fmt, ...) {746va_list args;747748va_start(args, fmt);749_internal_errs += emit_msg(0, INTERNAL_ERR, 0, fmt, args);750va_end(args);751752_no_output = 1;753}754755//------------------------------syntax_err----------------------------------756// Issue a parser error message, and skip to the end of the current line757void ArchDesc::syntax_err(int lineno, const char *fmt, ...) {758va_list args;759760va_start(args, fmt);761_internal_errs += emit_msg(0, SYNERR, lineno, fmt, args);762va_end(args);763764_no_output = 1;765}766767//------------------------------emit_msg---------------------------------------768// Emit a user message, typically a warning or error769int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt,770va_list args) {771static int last_lineno = -1;772int i;773const char *pref;774775switch(flag) {776case 0: pref = "Warning: "; break;777case 1: pref = "Syntax Error: "; break;778case 2: pref = "Semantic Error: "; break;779case 3: pref = "Internal Error: "; break;780default: assert(0, ""); break;781}782783if (line == last_lineno) return 0;784last_lineno = line;785786if (!quiet) { /* no output if in quiet mode */787i = fprintf(errfile, "%s(%d) ", _ADL_file._name, line);788while (i++ <= 15) fputc(' ', errfile);789fprintf(errfile, "%-8s:", pref);790vfprintf(errfile, fmt, args);791fprintf(errfile, "\n");792fflush(errfile);793}794return 1;795}796797798// ---------------------------------------------------------------------------799//--------Utilities to build mappings for machine registers ------------------800// ---------------------------------------------------------------------------801802// Construct the name of the register mask.803static const char *getRegMask(const char *reg_class_name) {804if( reg_class_name == NULL ) return "RegMask::Empty";805806if (strcmp(reg_class_name,"Universe")==0) {807return "RegMask::Empty";808} else if (strcmp(reg_class_name,"stack_slots")==0) {809return "(Compile::current()->FIRST_STACK_mask())";810} else if (strcmp(reg_class_name, "dynamic")==0) {811return "*_opnds[0]->in_RegMask(0)";812} else {813char *rc_name = toUpper(reg_class_name);814const char *mask = "_mask";815int length = (int)strlen(rc_name) + (int)strlen(mask) + 5;816char *regMask = new char[length];817sprintf(regMask,"%s%s()", rc_name, mask);818delete[] rc_name;819return regMask;820}821}822823// Convert a register class name to its register mask.824const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) {825const char *reg_mask = "RegMask::Empty";826827if( _register ) {828RegClass *reg_class = _register->getRegClass(rc_name);829if (reg_class == NULL) {830syntax_err(0, "Use of an undefined register class %s", rc_name);831return reg_mask;832}833834// Construct the name of the register mask.835reg_mask = getRegMask(rc_name);836}837838return reg_mask;839}840841842// Obtain the name of the RegMask for an OperandForm843const char *ArchDesc::reg_mask(OperandForm &opForm) {844const char *regMask = "RegMask::Empty";845846// Check constraints on result's register class847const char *result_class = opForm.constrained_reg_class();848if (result_class == NULL) {849opForm.dump();850syntax_err(opForm._linenum,851"Use of an undefined result class for operand: %s",852opForm._ident);853abort();854}855856regMask = reg_class_to_reg_mask( result_class );857858return regMask;859}860861// Obtain the name of the RegMask for an InstructForm862const char *ArchDesc::reg_mask(InstructForm &inForm) {863const char *result = inForm.reduce_result();864865if (result == NULL) {866syntax_err(inForm._linenum,867"Did not find result operand or RegMask"868" for this instruction: %s",869inForm._ident);870abort();871}872873// Instructions producing 'Universe' use RegMask::Empty874if (strcmp(result,"Universe") == 0) {875return "RegMask::Empty";876}877878// Lookup this result operand and get its register class879Form *form = (Form*)_globalNames[result];880if (form == NULL) {881syntax_err(inForm._linenum,882"Did not find result operand for result: %s", result);883abort();884}885OperandForm *oper = form->is_operand();886if (oper == NULL) {887syntax_err(inForm._linenum, "Form is not an OperandForm:");888form->dump();889abort();890}891return reg_mask( *oper );892}893894895// Obtain the STACK_OR_reg_mask name for an OperandForm896char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) {897// name of cisc_spillable version898const char *reg_mask_name = reg_mask(opForm);899900if (reg_mask_name == NULL) {901syntax_err(opForm._linenum,902"Did not find reg_mask for opForm: %s",903opForm._ident);904abort();905}906907const char *stack_or = "STACK_OR_";908int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1;909char *result = new char[length];910sprintf(result,"%s%s", stack_or, reg_mask_name);911912return result;913}914915// Record that the register class must generate a stack_or_reg_mask916void ArchDesc::set_stack_or_reg(const char *reg_class_name) {917if( _register ) {918RegClass *reg_class = _register->getRegClass(reg_class_name);919reg_class->set_stack_version(true);920}921}922923924// Return the type signature for the ideal operation925const char *ArchDesc::getIdealType(const char *idealOp) {926// Find last character in idealOp, it specifies the type927char last_char = 0;928const char *ptr = idealOp;929for (; *ptr != '\0'; ++ptr) {930last_char = *ptr;931}932933// Match Vector types.934if (strncmp(idealOp, "Vec",3)==0) {935switch(last_char) {936case 'A': return "TypeVect::VECTA";937case 'S': return "TypeVect::VECTS";938case 'D': return "TypeVect::VECTD";939case 'X': return "TypeVect::VECTX";940case 'Y': return "TypeVect::VECTY";941case 'Z': return "TypeVect::VECTZ";942default:943internal_err("Vector type %s with unrecognized type\n",idealOp);944}945}946947if (strncmp(idealOp, "RegVectMask", 8) == 0) {948return "TypeVect::VECTMASK";949}950951// !!!!!952switch(last_char) {953case 'I': return "TypeInt::INT";954case 'P': return "TypePtr::BOTTOM";955case 'N': return "TypeNarrowOop::BOTTOM";956case 'F': return "Type::FLOAT";957case 'D': return "Type::DOUBLE";958case 'L': return "TypeLong::LONG";959case 's': return "TypeInt::CC /*flags*/";960default:961return NULL;962// !!!!!963// internal_err("Ideal type %s with unrecognized type\n",idealOp);964break;965}966967return NULL;968}969970971972OperandForm *ArchDesc::constructOperand(const char *ident,973bool ideal_only) {974OperandForm *opForm = new OperandForm(ident, ideal_only);975_globalNames.Insert(ident, opForm);976addForm(opForm);977978return opForm;979}980981982// Import predefined base types: Set = 1, RegI, RegP, ...983void ArchDesc::initBaseOpTypes() {984// Create OperandForm and assign type for each opcode.985for (int i = 1; i < _last_machine_leaf; ++i) {986char *ident = (char *)NodeClassNames[i];987constructOperand(ident, true);988}989// Create InstructForm and assign type for each ideal instruction.990for (int j = _last_machine_leaf+1; j < _last_opcode; ++j) {991char *ident = (char *)NodeClassNames[j];992if (!strcmp(ident, "ConI") || !strcmp(ident, "ConP") ||993!strcmp(ident, "ConN") || !strcmp(ident, "ConNKlass") ||994!strcmp(ident, "ConF") || !strcmp(ident, "ConD") ||995!strcmp(ident, "ConL") || !strcmp(ident, "Con" ) ||996!strcmp(ident, "Bool")) {997constructOperand(ident, true);998} else {999InstructForm *insForm = new InstructForm(ident, true);1000// insForm->_opcode = nextUserOpType(ident);1001_globalNames.Insert(ident, insForm);1002addForm(insForm);1003}1004}10051006{ OperandForm *opForm;1007// Create operand type "Universe" for return instructions.1008const char *ident = "Universe";1009opForm = constructOperand(ident, false);10101011// Create operand type "label" for branch targets1012ident = "label";1013opForm = constructOperand(ident, false);10141015// !!!!! Update - when adding a new sReg/stackSlot type1016// Create operand types "sReg[IPFDL]" for stack slot registers1017opForm = constructOperand("sRegI", false);1018opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1019opForm = constructOperand("sRegP", false);1020opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1021opForm = constructOperand("sRegF", false);1022opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1023opForm = constructOperand("sRegD", false);1024opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");1025opForm = constructOperand("sRegL", false);1026opForm->_constraint = new Constraint("ALLOC_IN_RC", "stack_slots");10271028// Create operand type "method" for call targets1029ident = "method";1030opForm = constructOperand(ident, false);1031}10321033// Create Effect Forms for each of the legal effects1034// USE, DEF, USE_DEF, KILL, USE_KILL1035{1036const char *ident = "USE";1037Effect *eForm = new Effect(ident);1038_globalNames.Insert(ident, eForm);1039ident = "DEF";1040eForm = new Effect(ident);1041_globalNames.Insert(ident, eForm);1042ident = "USE_DEF";1043eForm = new Effect(ident);1044_globalNames.Insert(ident, eForm);1045ident = "KILL";1046eForm = new Effect(ident);1047_globalNames.Insert(ident, eForm);1048ident = "USE_KILL";1049eForm = new Effect(ident);1050_globalNames.Insert(ident, eForm);1051ident = "TEMP";1052eForm = new Effect(ident);1053_globalNames.Insert(ident, eForm);1054ident = "TEMP_DEF";1055eForm = new Effect(ident);1056_globalNames.Insert(ident, eForm);1057ident = "CALL";1058eForm = new Effect(ident);1059_globalNames.Insert(ident, eForm);1060}10611062//1063// Build mapping from ideal names to ideal indices1064int idealIndex = 0;1065for (idealIndex = 1; idealIndex < _last_machine_leaf; ++idealIndex) {1066const char *idealName = NodeClassNames[idealIndex];1067_idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex);1068}1069for (idealIndex = _last_machine_leaf+1;1070idealIndex < _last_opcode; ++idealIndex) {1071const char *idealName = NodeClassNames[idealIndex];1072_idealIndex.Insert((void*) idealName, (void*) (intptr_t) idealIndex);1073}10741075}107610771078//---------------------------addSUNcopyright-------------------------------1079// output SUN copyright info1080void ArchDesc::addSunCopyright(char* legal, int size, FILE *fp) {1081size_t count = fwrite(legal, 1, size, fp);1082assert(count == (size_t) size, "copyright info truncated");1083fprintf(fp,"\n");1084fprintf(fp,"// Machine Generated File. Do Not Edit!\n");1085fprintf(fp,"\n");1086}108710881089//---------------------------addIncludeGuardStart--------------------------1090// output the start of an include guard.1091void ArchDesc::addIncludeGuardStart(ADLFILE &adlfile, const char* guardString) {1092// Build #include lines1093fprintf(adlfile._fp, "\n");1094fprintf(adlfile._fp, "#ifndef %s\n", guardString);1095fprintf(adlfile._fp, "#define %s\n", guardString);1096fprintf(adlfile._fp, "\n");10971098}10991100//---------------------------addIncludeGuardEnd--------------------------1101// output the end of an include guard.1102void ArchDesc::addIncludeGuardEnd(ADLFILE &adlfile, const char* guardString) {1103// Build #include lines1104fprintf(adlfile._fp, "\n");1105fprintf(adlfile._fp, "#endif // %s\n", guardString);11061107}11081109//---------------------------addInclude--------------------------1110// output the #include line for this file.1111void ArchDesc::addInclude(ADLFILE &adlfile, const char* fileName) {1112fprintf(adlfile._fp, "#include \"%s\"\n", fileName);11131114}11151116void ArchDesc::addInclude(ADLFILE &adlfile, const char* includeDir, const char* fileName) {1117fprintf(adlfile._fp, "#include \"%s/%s\"\n", includeDir, fileName);11181119}11201121//---------------------------addPreprocessorChecks-----------------------------1122// Output C preprocessor code to verify the backend compilation environment.1123// The idea is to force code produced by "adlc -DHS64" to be compiled by a1124// command of the form "CC ... -DHS64 ...", so that any #ifdefs in the source1125// blocks select C code that is consistent with adlc's selections of AD code.1126void ArchDesc::addPreprocessorChecks(FILE *fp) {1127const char* flag;1128_preproc_list.reset();1129if (_preproc_list.count() > 0 && !_preproc_list.current_is_signal()) {1130fprintf(fp, "// Check consistency of C++ compilation with ADLC options:\n");1131}1132for (_preproc_list.reset(); (flag = _preproc_list.iter()) != NULL; ) {1133if (_preproc_list.current_is_signal()) break;1134char* def = get_preproc_def(flag);1135fprintf(fp, "// Check adlc ");1136if (def)1137fprintf(fp, "-D%s=%s\n", flag, def);1138else fprintf(fp, "-U%s\n", flag);1139fprintf(fp, "#%s %s\n",1140def ? "ifndef" : "ifdef", flag);1141fprintf(fp, "# error \"%s %s be defined\"\n",1142flag, def ? "must" : "must not");1143fprintf(fp, "#endif // %s\n", flag);1144}1145}114611471148// Convert operand name into enum name1149const char *ArchDesc::machOperEnum(const char *opName) {1150return ArchDesc::getMachOperEnum(opName);1151}11521153// Convert operand name into enum name1154const char *ArchDesc::getMachOperEnum(const char *opName) {1155return (opName ? toUpper(opName) : opName);1156}11571158//---------------------------buildMustCloneMap-----------------------------1159// Flag cases when machine needs cloned values or instructions1160void ArchDesc::buildMustCloneMap(FILE *fp_hpp, FILE *fp_cpp) {1161// Build external declarations for mappings1162fprintf(fp_hpp, "// Mapping from machine-independent opcode to boolean\n");1163fprintf(fp_hpp, "// Flag cases where machine needs cloned values or instructions\n");1164fprintf(fp_hpp, "extern const char must_clone[];\n");1165fprintf(fp_hpp, "\n");11661167// Build mapping from ideal names to ideal indices1168fprintf(fp_cpp, "\n");1169fprintf(fp_cpp, "// Mapping from machine-independent opcode to boolean\n");1170fprintf(fp_cpp, "const char must_clone[] = {\n");1171for (int idealIndex = 0; idealIndex < _last_opcode; ++idealIndex) {1172int must_clone = 0;1173const char *idealName = NodeClassNames[idealIndex];1174// Previously selected constants for cloning1175// !!!!!1176// These are the current machine-dependent clones1177if ( strcmp(idealName,"CmpI") == 01178|| strcmp(idealName,"CmpU") == 01179|| strcmp(idealName,"CmpP") == 01180|| strcmp(idealName,"CmpN") == 01181|| strcmp(idealName,"CmpL") == 01182|| strcmp(idealName,"CmpUL") == 01183|| strcmp(idealName,"CmpD") == 01184|| strcmp(idealName,"CmpF") == 01185|| strcmp(idealName,"FastLock") == 01186|| strcmp(idealName,"FastUnlock") == 01187|| strcmp(idealName,"OverflowAddI") == 01188|| strcmp(idealName,"OverflowAddL") == 01189|| strcmp(idealName,"OverflowSubI") == 01190|| strcmp(idealName,"OverflowSubL") == 01191|| strcmp(idealName,"OverflowMulI") == 01192|| strcmp(idealName,"OverflowMulL") == 01193|| strcmp(idealName,"Bool") == 01194|| strcmp(idealName,"Binary") == 0 ) {1195// Removed ConI from the must_clone list. CPUs that cannot use1196// large constants as immediates manifest the constant as an1197// instruction. The must_clone flag prevents the constant from1198// floating up out of loops.1199must_clone = 1;1200}1201fprintf(fp_cpp, " %d%s // %s: %d\n", must_clone,1202(idealIndex != (_last_opcode - 1)) ? "," : " // no trailing comma",1203idealName, idealIndex);1204}1205// Finish defining table1206fprintf(fp_cpp, "};\n");1207}120812091210