OpenADFortTk (basic)
src/xaif2whirl/XlateExpression.cxx
Go to the documentation of this file.
00001 // -*-Mode: C++;-*-
00002 // $Header: /Volumes/cvsrep/developer/OpenADFortTk/src/xaif2whirl/XlateExpression.cxx,v 1.2 2006/05/12 16:12:23 utke Exp $
00003 
00004 #include <stdlib.h> // ANSI: cstdlib // for strtol
00005 #include <string.h> // ANSI: cstring // for strcmp, etc.
00006 #include <iostream>
00007 #include <vector>
00008 #include <algorithm>
00009 
00010 #include "Open64IRInterface/Open64BasicTypes.h"
00011 #include "Open64IRInterface/Open64IRInterface.hpp"
00012 #include "Open64IRInterface/SymTab.h"
00013 #include "Open64IRInterface/wn_attr.h"
00014 #include "Open64IRInterface/stab_attr.h"
00015 
00016 #include "ScalarizedRefTab.h"
00017 #include "WhirlIDMaps.h"
00018 #include "XAIFStrings.h"
00019 #include "Diagnostics.h"
00020 
00021 #include "xaif2whirl.h"
00022 #include "Args.h"
00023 #include "XlateExpression.h"
00024 #include "XAIF_DOMFilters.h"
00025 #include "XercesStrX.h"
00026 
00027 namespace xaif2whirl { 
00028   extern TY_IDX ActiveTypeTyIdx;            // FIXME
00029   extern TY_IDX ActiveTypeInitializedTyIdx; // FIXME
00030 
00031 
00032   WN* XlateExpression::translateExpression(const DOMElement* elem, 
00033                                            PUXlationContext& ctxt) {
00034     FORTTK_ASSERT(elem, fortTkSupport::Diagnostics::UnexpectedInput);
00035     // Slurp expression into a graph (DAG) and translate it
00036     OA::OA_ptr<OA::DGraph::DGraphImplement> g = createExpressionGraph(elem);
00037     // xaif2whirl::DDumpDotGraph(g);
00038     OA::OA_ptr<OA::DGraph::NodeInterface> root = g->getExprGraphRootNode();
00039     OA::OA_ptr<MyDGNode> n = root.convert<MyDGNode>();
00040     WN* wn = xlate_Expression(g, n, ctxt);
00041     return wn;
00042   }
00043 
00044   WN* XlateExpression::translateExpressionSimple(const DOMElement* elem,
00045                                                  PUXlationContext& ctxt) {
00046     ctxt.createXlationContext(XlationContext::EXPRSIMPLE);
00047     WN* wn = translateExpression(elem, ctxt);
00048     ctxt.deleteXlationContext();
00049     return wn;
00050   }
00051 
00052   WN* XlateExpression::translateVarRef(const DOMElement* elem, 
00053                                        PUXlationContext& ctxt) {
00054     FORTTK_ASSERT(elem, fortTkSupport::Diagnostics::UnexpectedInput);
00055     // Slurp expression into a graph (DAG) and translate it
00056     ctxt.createXlationContext(XlationContext::VARREF);
00057     OA::OA_ptr<OA::DGraph::DGraphImplement> g = 
00058       createExpressionGraph(elem, true /* varRef */);
00059     // xaif2whirl::DDumpDotGraph(g);
00060     OA::OA_ptr<OA::DGraph::NodeInterface> root = g->getExprGraphRootNode();
00061     OA::OA_ptr<MyDGNode> n = root.convert<MyDGNode>();
00062     WN* wn = xlate_VarRef(g, n, ctxt);
00063     ctxt.deleteXlationContext();
00064     // If we are not already within another VarRef and we translated an
00065     // active symbol, select the appropriate portion of the active type
00066     if (!ctxt.currentXlationContext().isFlag(XlationContext::VARREF)
00067         ||
00068         ctxt.currentXlationContext().isFlag(XlationContext::ARRAYIDX)) {
00069       if (ctxt.currentXlationContext().isFlag(XlationContext::ACTIVETYPE)) { 
00070         if (ctxt.currentXlationContext().isFlag(XlationContext::VALUESELECTOR)) {
00071           wn = createValueSelector(wn); // active
00072         } else if (ctxt.currentXlationContext().isFlag(XlationContext::DERIVSELECTOR)) {
00073           wn = createDerivSelector(wn); // deriv
00074         }
00075         ctxt.currentXlationContext().unsetFlag(XlationContext::ACTIVETYPE); // halt up-inheritance
00076       }
00077     }  
00078     return wn;
00079   }
00080 
00081   std::pair<ST*, WN_OFFSET> XlateExpression::translateVarRefSimple(const DOMElement* elem, 
00082                                                                    PUXlationContext& ctxt) {
00083     FORTTK_ASSERT(elem, fortTkSupport::Diagnostics::UnexpectedInput);
00084     // This must be a plain XAIF symbol reference (a one-vertex graph)
00085     const XMLCh* nameX = elem->getNodeName();
00086     if ( !(XMLString::equals(nameX, XAIFStrings.elem_SymRef_x()) &&
00087            GetNextSiblingElement(elem) == NULL) ) {
00088       FORTTK_DIE("Expected a simple var ref but found:\n" << *elem);
00089     }
00090     ctxt.createXlationContext(XlationContext::NOFLAG);
00091     pair<ST*, WN_OFFSET> stpair = xlate_SymbolReferenceSimple(elem, ctxt);
00092     ctxt.deleteXlationContext();
00093     return stpair;
00094   }
00095 
00096   WN* XlateExpression::patchWNExpr(WN* parent, 
00097                                    INT kidno, 
00098                                    PUXlationContext& ctxt) {
00099     // Simple Base cases
00100     if (!parent) { return NULL; }
00101     WN* wn = WN_kid(parent, kidno);
00102     if (!wn) { return NULL; }
00103     OPERATOR opr = WN_operator(wn);
00104     if (!OPERATOR_is_expression(opr) && !OPERATOR_is_call(opr)) { return parent; }
00105     // Base case: a variable reference
00106     if (fortTkSupport::ScalarizedRef::isRefTranslatableToXAIF(wn)) {
00107       if (hasActiveSymbolType(wn)) {
00108         WN* newwn = createValueSelector(wn);
00109         WN_kid(parent, kidno) = newwn;
00110       }
00111     }
00112     else {
00113       // Recursive case
00114       for (INT i = 0; i < WN_kid_count(wn); ++i) {
00115         patchWNExpr(wn, i /* kid */, ctxt);
00116       }
00117     }
00118     return parent;
00119   }
00120 
00121   bool XlateExpression::hasActiveSymbolType(WN* aWNp) { 
00122     if (WN_has_sym(aWNp)) {
00123       if (WN_operator(aWNp)==OPR_IMPLICIT_BND)
00124         return false;
00125       ST* st = WN_st(aWNp);
00126       TY_IDX tyIdx = ST_type(st);
00127       if (TY_kind(tyIdx) == KIND_POINTER) {
00128         tyIdx = TY_pointed(tyIdx);
00129       } 
00130       if (TY_kind(tyIdx) == KIND_ARRAY) {
00131         tyIdx = TY_etype(tyIdx);
00132       }
00133       if (tyIdx == ActiveTypeTyIdx || tyIdx == ActiveTypeInitializedTyIdx) {
00134         return true; 
00135       }
00136     }
00137     else if( WN_operator(aWNp)==OPR_STRCTFLD) { 
00138       TY_IDX base_ty = WN_GetBaseObjType(aWNp);
00139       UINT field_id = WN_field_id(aWNp);
00140       UINT cur_field_id=0;
00141       FLD_HANDLE fld = FLD_get_to_field (base_ty, field_id, cur_field_id);
00142       TY_IDX tyIdx = FLD_type(fld);
00143       if (TY_kind(tyIdx) == KIND_POINTER) {
00144         tyIdx = TY_pointed(tyIdx);
00145       } 
00146       if (TY_kind(tyIdx) == KIND_ARRAY) {
00147         tyIdx = TY_etype(tyIdx);
00148       }
00149       if (tyIdx == ActiveTypeTyIdx || tyIdx == ActiveTypeInitializedTyIdx) {
00150         return true; 
00151       }
00152     }
00153     else { 
00154       // Recursive case
00155       for (INT i = 0; i < WN_kid_count(aWNp); ++i) {
00156         if (hasActiveSymbolType(WN_kid(aWNp, i))) 
00157           return true;
00158       }
00159     }
00160     return false; 
00161   } 
00162 
00163   WN* XlateExpression::translateConstant(const DOMElement* elem, 
00164                                          PUXlationContext& ctxt) {
00165     FORTTK_ASSERT(elem, fortTkSupport::Diagnostics::UnexpectedInput);
00166     const XMLCh* typeX = elem->getAttribute(XAIFStrings.attr_type_x());
00167     const XMLCh* fetypeX = elem->getAttribute(XAIFStrings.attr_feType_x());
00168     const XMLCh* valX = elem->getAttribute(XAIFStrings.attr_value_x());
00169     XercesStrX type = XercesStrX(typeX);
00170     XercesStrX fetype = XercesStrX(fetypeX);
00171     TYPE_ID mtype=XAIFFETypeToWHIRLMTy(fetype.c_str());
00172     XercesStrX value = XercesStrX(valX);
00173     WN* wn = NULL;
00174     if ((strcmp(type.c_str(), "real") == 0) ||
00175         (strcmp(type.c_str(), "double") == 0)) {
00176       // Floating point constant
00177       double val = strtod(value.c_str(), (char **)NULL);
00178       if (mtype==MTYPE_UNKNOWN)
00179         mtype=Args::ourDefaultMTypeReal;
00180       TCON tcon = Host_To_Targ_Float(mtype, val);
00181       wn = Make_Const(tcon);
00182     } 
00183     else if (strcmp(type.c_str(), "integer") == 0) {
00184       // Integer constant: Note that we have turned off WHIRL's
00185       // expression simplifier, which can cause problems with our code.
00186       // Also note that certain special expressions need an I4INTCONST.
00187       // E.g.: array indices, loop updates.
00188       INT64 val = strtol(value.c_str(), (char **)NULL, 10);
00189       if (ctxt.currentXlationContext().isFlag(XlationContext::ARRAYIDX) || 
00190           ctxt.currentXlationContext().isFlag(XlationContext::EXPRSIMPLE)) {
00191         wn = WN_CreateIntconst(OPC_I4INTCONST, (INT32)val);
00192       } else {
00193         if (mtype==MTYPE_UNKNOWN)
00194           mtype=Args::ourDefaultMTypeInt;
00195         OPCODE opc = OPCODE_make_op(OPR_INTCONST, mtype, MTYPE_V);
00196         wn = WN_CreateIntconst(opc, val);
00197       }
00198     } 
00199     else if (strcmp(type.c_str(), "bool") == 0) {
00200       // Boolean constant: boolean values can be true/false or 1/0.
00201       unsigned int val = 1;
00202       const char* v = value.c_str();    
00203       if ((strcmp(v, "false") == 0) || (strcmp(v, "0") == 0)) {
00204         val = 0;
00205       }
00206       wn = CreateBoolConst(val);
00207     } 
00208     else if (strcmp(type.c_str(), "char") == 0) {
00209       // Character constant. Cf. cwh_stmt.cxx:349
00210       // wn = WN_CreateIntconst(OPC_I4INTCONST, (INT64)val);
00211       FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "creation of character constant");
00212     } 
00213     else if (strcmp(type.c_str(), "string") == 0) {
00214       // String constant. A string constant reference to "S" looks like:
00215       //   U4U1ILOAD 0 T<43,.character.,1> T<175,anon_ptr.,8>
00216       //     U8LDA 0 <1,596,(1_bytes)_"S"> T<127,anon_ptr.,8>
00217       // cf. fei_pattern_con(..) in cwh_stab.cxx
00218       TY_IDX ty = MTYPE_To_TY(MTYPE_STRING);
00219       TY_IDX ty_ptr = Stab_Pointer_To(ty);
00220       UINT32 len = strlen(value.c_str());
00221       TCON tcon = Host_To_Targ_String(MTYPE_STRING, (char*)value.c_str(), len);
00222       ST* st = Gen_String_Sym(&tcon, ty, FALSE);
00223       TYPE_ID rty = TY_mtype(ty_ptr); // Pointer_Mtype
00224       WN* lda = WN_CreateLda(OPR_LDA, rty, MTYPE_V, 0, ty_ptr, st, 0);
00225       wn = WN_CreateIload(OPR_ILOAD, MTYPE_U4, MTYPE_U1, 0, ty, ty_ptr, lda, 0);
00226     }
00227     return wn;
00228   }
00229 
00230   WN* XlateExpression::xlate_Intrinsic(OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00231                                        OA::OA_ptr<MyDGNode> n, 
00232                                        PUXlationContext& ctxt) {
00233     FORTTK_ASSERT(!g.ptrEqual(NULL) && !n.ptrEqual(NULL), fortTkSupport::Diagnostics::UnexpectedInput);
00234     DOMElement* elem = n->GetElem();
00235     const XMLCh* nmX = elem->getAttribute(XAIFStrings.attr_name_x());
00236     XercesStrX nm = XercesStrX(nmX);
00237     std::string key = GetIntrinsicKey(elem);
00238     bool suppressIt=(std::string("allocated")==nm.c_str() 
00239                      || 
00240                      std::string("lbound")==nm.c_str() 
00241                      || 
00242                      std::string("ubound")==nm.c_str()
00243                      || 
00244                      std::string("size")==nm.c_str());
00245     if (suppressIt) { 
00246       ctxt.currentXlationContext().setFlag(XlationContext::SUPPRESSSELECTOR);
00247     } 
00248     WN* wn = xlate_ExprOpUsingIntrinsicTable(fortTkSupport::IntrinsicXlationTable::XAIFIntrin, 
00249                                              nm.c_str(), 
00250                                              key.c_str(), 
00251                                              g, 
00252                                              n, 
00253                                              ctxt);
00254     if (suppressIt) {
00255       ctxt.currentXlationContext().unsetFlag(XlationContext::SUPPRESSSELECTOR);
00256     }
00257     return wn;
00258   }
00259 
00260   WN* XlateExpression::xlate_Expression(OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00261                                         OA::OA_ptr<MyDGNode> n, 
00262                                         PUXlationContext& ctxt) {
00263     // Recursively translate the DAG (tree) rooted at this node
00264     DOMElement* elem = n->GetElem();
00265     const XMLCh* nameX = elem->getNodeName();
00266     XercesStrX name = XercesStrX(nameX);
00267     WN* wn = NULL;
00268     if (XMLString::equals(nameX, XAIFStrings.elem_VarRef_x())) {
00269       // VariableReference
00270       wn = xlate_VarRef(elem, ctxt);
00271     } 
00272     else if (XMLString::equals(nameX, XAIFStrings.elem_Constant_x())) {
00273       // Constant
00274       wn = translateConstant(elem, ctxt);
00275     } 
00276     else if (XMLString::equals(nameX, XAIFStrings.elem_Intrinsic_x())) {
00277       // Intrinsic
00278       wn = xlate_Intrinsic(g, n, ctxt);
00279     } 
00280     else if (XMLString::equals(nameX, XAIFStrings.elem_FuncCall_x())) {
00281       // FunctionCall
00282       wn = xlate_FunctionCall(g, n, ctxt);
00283     } 
00284     else if (XMLString::equals(nameX, XAIFStrings.elem_BoolOp_x())) {
00285       // BooleanOperation
00286       wn = xlate_BooleanOperation(g, n, ctxt);
00287     } 
00288     else {
00289       FORTTK_DIE("Unknown XAIF expression:\n" << *elem);
00290     }
00291     return wn;
00292   }
00293 
00294   WN* XlateExpression::xlate_VarRef(const DOMElement* elem, PUXlationContext& ctxt) {
00295     FORTTK_ASSERT(elem, fortTkSupport::Diagnostics::UnexpectedInput);
00296     // VariableReferenceType
00297     bool deriv = GetDerivAttr(elem);
00298     // skip the xaif:VariableReference node
00299     DOMElement* varref = GetFirstChildElement(elem);
00300     if (ctxt.currentXlationContext().isFlag(XlationContext::SUPPRESSSELECTOR)) { 
00301       ctxt.createXlationContext();
00302       // to make sure:
00303       ctxt.currentXlationContext().unsetFlag(XlationContext::DERIVSELECTOR);
00304       ctxt.currentXlationContext().unsetFlag(XlationContext::VALUESELECTOR);
00305     }  
00306     else 
00307       ctxt.createXlationContext((deriv) ? XlationContext::DERIVSELECTOR : XlationContext::VALUESELECTOR);
00308     WN* wn = translateVarRef(varref, ctxt);
00309     ctxt.deleteXlationContext();
00310     return wn;
00311   }
00312 
00313   WN* XlateExpression::xlate_VarRef(OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00314                                     OA::OA_ptr<MyDGNode> n, 
00315                                     PUXlationContext& ctxt) {
00316     FORTTK_ASSERT(!g.ptrEqual(NULL) && !n.ptrEqual(NULL), fortTkSupport::Diagnostics::UnexpectedInput);
00317     // Recursively translate the DAG (tree) rooted at this node
00318     DOMElement* elem = n->GetElem();
00319     FORTTK_ASSERT(elem, "Internal error: var-ref graph contains null DOM elem.");
00320     WN* wn = NULL;  
00321     const XMLCh* nameX = elem->getNodeName();
00322     if (XMLString::equals(nameX, XAIFStrings.elem_SymRef_x())) {
00323       // SymbolReference
00324       wn = xlate_SymbolReference(elem, ctxt);
00325     } 
00326     else if (XMLString::equals(nameX, XAIFStrings.elem_ArrayElemRef_x())) {
00327       // ArrayElementReference
00328       wn = xlate_ArrayElementReference(g, n, ctxt);
00329     } 
00330     else {
00331       FORTTK_DIE("Unknown XAIF variable reference:\n" << *elem);
00332     }
00333     return wn;
00334   }
00335 
00336   WN* XlateExpression::xlate_FunctionCall(OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00337                                           OA::OA_ptr<MyDGNode> n,
00338                                           PUXlationContext& ctxt) {
00339     FORTTK_ASSERT(!g.ptrEqual(NULL) && !n.ptrEqual(NULL), fortTkSupport::Diagnostics::UnexpectedInput);
00340     DOMElement* elem = n->GetElem();
00341     // FIXME: children are expr; find num of args (use Intrinsic function above)
00342     FORTTK_DIE(fortTkSupport::Diagnostics::Unimplemented << "xaif:FunctionCall");
00343     return NULL;
00344   }
00345 
00346   WN* XlateExpression::xlate_BooleanOperation(OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00347                                               OA::OA_ptr<MyDGNode> n,
00348                                               PUXlationContext& ctxt) {
00349     FORTTK_ASSERT(!g.ptrEqual(NULL) && !n.ptrEqual(NULL), fortTkSupport::Diagnostics::UnexpectedInput);
00350     DOMElement* elem = n->GetElem();
00351     const XMLCh* nmX = elem->getAttribute(XAIFStrings.attr_name_x());
00352     XercesStrX nm = XercesStrX(nmX);
00353     WN* wn = xlate_ExprOpUsingIntrinsicTable(fortTkSupport::IntrinsicXlationTable::XAIFBoolOp, 
00354                                              nm.c_str(), 
00355                                              NULL, 
00356                                              g, 
00357                                              n, 
00358                                              ctxt);
00359     return wn;
00360   }
00361 
00362   struct XAIFEdgePositionCompare {
00363     // return true if e1 < e2; false otherwise
00364     bool operator()(const OA::OA_ptr<MyDGEdge> e1, 
00365                     const OA::OA_ptr<MyDGEdge> e2) const {
00366       unsigned int pos1 = GetPositionAttr(e1->GetElem());
00367       unsigned int pos2 = GetPositionAttr(e2->GetElem());
00368       return (pos1 < pos2);
00369     }
00370   };
00371 
00372   bool conversionToReal(fortTkSupport::IntrinsicXlationTable::WHIRLInfo& info) { 
00373     if (info.opr==OPR_CALL) {
00374       const std::string oprName(info.name);
00375       if (
00376           oprName.compare("REAL")==0
00377           ||
00378           oprName.compare("DBLE")==0
00379           || 
00380           oprName.compare("FLOAT")==0
00381           || 
00382           oprName.compare("AIMAG")==0
00383           )
00384         return true;
00385     } 
00386     return false; 
00387   } 
00388 
00389   WN* XlateExpression::xlate_ExprOpUsingIntrinsicTable(const fortTkSupport::IntrinsicXlationTable::XAIFOpr xopr, 
00390                                                        const char* xoprNm, 
00391                                                        const char* xIntrinKey,
00392                                                        OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00393                                                        OA::OA_ptr<MyDGNode> n, 
00394                                                        PUXlationContext& ctxt) {
00395     using namespace OA::DGraph;
00396     fortTkSupport::IntrinsicXlationTable::WHIRLInfo* aWhirlInfo_p = 
00397       IntrinsicTable.findWHIRLInfo(xopr, xoprNm, xIntrinKey);
00398     // 1. Gather the operands, sorted by the "position" attribute
00399     unsigned int actualArgCount(n->num_incoming());
00400     FORTTK_ASSERT_WARN(actualArgCount<= aWhirlInfo_p->numop && actualArgCount>= aWhirlInfo_p->numop-aWhirlInfo_p->numOptional, 
00401                        "Warning: get " << actualArgCount<< " intrinsic arguments for '"
00402                        << xoprNm  << "' expect " << aWhirlInfo_p->numop << " (have " << aWhirlInfo_p->numOptional << " optional args?)");
00403     OA::OA_ptr<MyDGEdge> tmp; tmp = NULL;
00404     vector<OA::OA_ptr<MyDGEdge> > opnd_edge(actualArgCount, tmp);
00405     OA::OA_ptr<EdgesIteratorInterface> itPtr 
00406       = n->getIncomingEdgesIterator();
00407     for (int i = 0; itPtr->isValid(); ++(*itPtr), ++i) {
00408       OA::OA_ptr<OA::DGraph::EdgeInterface> etmp = itPtr->current();
00409       opnd_edge[i] = etmp.convert<MyDGEdge>();
00410     }
00411     std::sort(opnd_edge.begin(), opnd_edge.end(),XAIFEdgePositionCompare()); // ascending
00412     // 2. Translate each operand into a WHIRL expression tree
00413     vector<WN*> opnd_wn(actualArgCount, NULL); 
00414     for (unsigned i = 0; i < actualArgCount; ++i) {
00415       OA::OA_ptr<NodeInterface> ntmp = opnd_edge[i]->getSource();
00416       OA::OA_ptr<MyDGNode> opnd = ntmp.convert<MyDGNode>();
00417       opnd_wn[i] = xlate_Expression(g, opnd, ctxt);
00418     }       
00419     if (aWhirlInfo_p->opr==OPR_CALL 
00420         && 
00421         (aWhirlInfo_p->name && strcmp(aWhirlInfo_p->name,"TRANSFER")==0
00422          ||
00423          aWhirlInfo_p->name && strcmp(aWhirlInfo_p->name,"ASSOCIATED")==0
00424          ||
00425          aWhirlInfo_p->name && strcmp(aWhirlInfo_p->name,"SIZE")==0)) { 
00426       // leave transfer arguments untouched
00427       // std::cout << "XlateExpression::xlate_ExprOpUsingIntrinsicTable: skipping argument conversion for transfer" << std::endl; 
00428     }
00429     else { 
00430       // Here promote all arguments up to 8 bytes; we assume canonicalized
00431       // argument forms
00432       // FIXME: for now we promote reals to 8; demote ints to 4; we could
00433       // selectively do this...
00434       for (unsigned i = 0; i < opnd_wn.size(); ++i) {
00435         if (WN_operator(opnd_wn[i])==OPR_CALL 
00436             && 
00437             (strcmp(ST_name(WN_st(opnd_wn[i])),"TRANSFER")==0
00438              ||
00439              strcmp(ST_name(WN_st(opnd_wn[i])),"ASSOCIATED")==0
00440              ||
00441              strcmp(ST_name(WN_st(opnd_wn[i])),"SIZE")==0)) { 
00442           // leave transfer result untouched
00443           //  std::cout << "XlateExpression::xlate_ExprOpUsingIntrinsicTable: skipping result conversion for transfer" << std::endl; 
00444         }
00445         else { 
00446           // FIXME: could use rtype for operator
00447           TY_IDX ty = WN_Tree_Type(opnd_wn[i]);
00448           TYPE_ID rty = TY_mtype(ty);      
00449           // Pointers and character strings often look like integers to the
00450           // test below
00451           if (TY_Is_Pointer(ty) || TY_Is_Character_String(ty)) { continue; }
00452           TYPE_ID newrty = MTYPE_UNKNOWN;
00453           if (MTYPE_is_integral(rty)) {
00454             newrty = getMType(MTYPE_CLASS_INTEGER, 4);
00455           }
00456           else if (MTYPE_is_float(rty)) {
00457             newrty = getMType(MTYPE_CLASS_FLOAT, 8);
00458           }
00459           // WN_set_rtype(opnd_wn[i], newrty);
00460           if (newrty != MTYPE_UNKNOWN 
00461               && 
00462               newrty != rty
00463               && 
00464               ! conversionToReal(*aWhirlInfo_p)) {
00465             opnd_wn[i] = WN_Cvt(rty, newrty, opnd_wn[i]);
00466           }
00467         }
00468       }
00469     }
00470     // 3. Translate into either WHIRL OPR_CALL or a WHIRL expression operator
00471     WN* wn = NULL;
00472     switch (aWhirlInfo_p->oprcl) {
00473     case fortTkSupport::IntrinsicXlationTable::WNCall: {
00474       TYPE_ID rtype = MTYPE_F8; // FIXME
00475       wn = CreateCallToIntrin(rtype, aWhirlInfo_p->name, opnd_wn);
00476       break;
00477     }
00478     case fortTkSupport::IntrinsicXlationTable::WNIntrinCall:
00479     case fortTkSupport::IntrinsicXlationTable::WNIntrinOp: {          
00480       TYPE_ID rtype = MTYPE_F8; // FIXME
00481       TYPE_ID dtype = MTYPE_V;  // FIXME
00482       INTRINSIC intrn = getWNIntrinsic(aWhirlInfo_p->name, opnd_wn, NULL);
00483       wn = CreateIntrinsicCall(aWhirlInfo_p->opr, intrn, rtype, dtype, opnd_wn);
00484       break;
00485     }
00486     case fortTkSupport::IntrinsicXlationTable::WNExpr: {
00487       // Find the opcode for the expression
00488       OPCODE opc = getWNExprOpcode(aWhirlInfo_p->opr, opnd_wn);
00489       // Create a WHIRL expression tree for the operator and operands
00490       switch (actualArgCount) {
00491       case 1: // unary
00492         wn = WN_CreateExp1(opc, opnd_wn[0]); break;
00493       case 2: // binary
00494         wn = WN_CreateExp2(opc, opnd_wn[0], opnd_wn[1]); break;
00495       case 3: // ternary
00496         wn = WN_CreateExp3(opc, opnd_wn[0], opnd_wn[1], opnd_wn[2]); break;
00497       default:
00498         FORTTK_DIE("Incorrect number of operands for WHIRL expr: " << actualArgCount);
00499       } 
00500       break;
00501     }
00502     default:
00503       FORTTK_DIE("Invalid WNOprClass class: " << aWhirlInfo_p->oprcl);
00504     }
00505     return wn;
00506   }
00507 
00508   // helper operator
00509   struct replaceIfLocal {
00510   public:
00511     ST** mySt;
00512     ST* myStCB;
00513     ST_IDX myOwnPUIdx;
00514     replaceIfLocal(ST** st,
00515                    ST* stCB,
00516                    ST_IDX myPUIdx):
00517       mySt(st),
00518       myStCB(stCB),
00519       myOwnPUIdx(myPUIdx) {
00520     }
00521     void operator()(UINT32, ST* st) const {
00522       if (ST_sclass(st)==SCLASS_COMMON
00523           && 
00524           ST_sclass(ST_base(st))==SCLASS_COMMON
00525           && 
00526           myOwnPUIdx==ST_st_idx(ST_base(ST_base(st)))
00527           && 
00528           strcmp(ST_name(ST_base(st)),ST_name(myStCB))==0
00529           && 
00530           strcmp(ST_name(st),ST_name(*mySt))==0)
00531         *mySt=st;
00532     }
00533   };
00534 
00535   WN* XlateExpression::xlate_SymbolReference(const DOMElement* elem, 
00536                                              PUXlationContext& ctxt) {
00537     typedef std::map<ST_IDX,std::set<ST*> >  PuIdxToSTPSetMap;
00538     // this map is supposed to retain a representer common block (associated with another PU)
00539     // for references to common block variables that did not exist in the original PU
00540     static PuIdxToSTPSetMap globPUtoCBMap; 
00541     FORTTK_ASSERT(elem, fortTkSupport::Diagnostics::UnexpectedInput);
00542     // -------------------------------------------------------
00543     // 0. Setup; Possibly redirect processing
00544     // -------------------------------------------------------
00545     WN* wn = NULL;
00546     fortTkSupport::Symbol* sym = GetSymbol(elem, ctxt);
00547     if (sym->IsActive()) {
00548       ctxt.currentXlationContext().setFlag(XlationContext::ACTIVETYPE); // N.B. inherited up the ctxt stack
00549     }
00550     // redirect handling if access path was collapsed (includes scalarization)
00551     if (sym->IsPathCollapsed()) {
00552       WN* pathVorlage = ctxt.findWN(sym->GetPathVorlage(), true /* mustFind */);
00553       return xlate_SymbolReferenceCollapsedPath(elem, pathVorlage, ctxt);
00554     }
00555     ST* st = sym->GetST();
00556     // see what kind of symbol this is
00557     if (ST_sclass(st)==SCLASS_COMMON) { 
00558       // if it is a common block variable we need to 
00559       // avoid picking up duplicate common block definitions
00560       ST* stCB=ST_base(st);
00561       if (ST_sclass(stCB)!=SCLASS_COMMON) 
00562         FORTTK_DIE("Expect a common block name here");
00563       ST* stPU=ST_base(stCB);
00564       ST_IDX otherPUIdx=ST_st_idx(stPU);
00565       ST_IDX myPUIdx=Current_PU_Info->proc_sym;
00566       // std::cout << "doing " << ST_name(stPU) << "::" << ST_name(stCB) << "::" << ST_name(st) << " while in " << ST_name(St_Table[myPUIdx]) << std::endl;
00567       if (myPUIdx!=otherPUIdx) { // not the same PU
00568         // see if there is already a local equivalent to the common block variable 
00569         // used in the other PU. 
00570         ST* givenST_p=st;
00571         For_all(St_Table,GLOBAL_SYMTAB,replaceIfLocal(&st,stCB,myPUIdx));
00572         // std::cout << "tried for local CB:  " << ST_name(ST_base(ST_base(st))) << "::" << ST_name(ST_base(st)) << "::" << ST_name(st) << " while in " << ST_name(St_Table[myPUIdx]) << std::endl;
00573         // if this is replaces that means we can map it to the common block variant in this PU
00574         if (st==givenST_p) { // not replaced, meaning this common block did not previously exist in this PU
00575           PuIdxToSTPSetMap::iterator it=globPUtoCBMap.find(myPUIdx);
00576           if (it==globPUtoCBMap.end()) { // we haven't seen this common block before
00577             // add it to the map and put the CB ST* into the set
00578             (globPUtoCBMap[myPUIdx]).insert(stCB);
00579           }
00580           else {
00581             std::set<ST*>& theCBset=it->second;
00582             std::set<ST*>::iterator sIt;
00583             for (sIt=theCBset.begin();
00584                  sIt!=theCBset.end();
00585                  ++sIt) { 
00586               if (strcmp(ST_name(*sIt),ST_name(stCB))==0) {
00587                 // got the CB already in the set
00588                 For_all(St_Table,GLOBAL_SYMTAB,replaceIfLocal(&st,*sIt,ST_st_idx(ST_base(*sIt))));
00589                 // std::cout << "tried for other CB: " << ST_name(ST_base(ST_base(st))) << "::" << ST_name(ST_base(st)) << "::" << ST_name(st) << " while in " << ST_name(St_Table[myPUIdx]) << std::endl;
00590                 break;
00591               }
00592             }
00593             if (sIt==theCBset.end()) { 
00594               // wasn't in the set, add it
00595               (globPUtoCBMap[myPUIdx]).insert(stCB);
00596             } 
00597           }
00598         }
00599       }
00600     }
00601     const char* st_name = ST_name(st);
00602     TY_IDX ty = ST_type(st);
00603     TYPE_ID rty, dty;
00604     WN_OFFSET oset = 0;
00605     // -------------------------------------------------------
00606     // 1. Determine which type of load to use
00607     // -------------------------------------------------------
00608     bool create_lda = false;
00609     // Note: Order matters in these tests
00610     if (ST_class(st) != CLASS_PREG) { // never create a pointer to a preg
00611       if (ctxt.currentXlationContext().isFlag(XlationContext::ARRAY)
00612           ||
00613           TY_Is_Chararray(ty)) {
00614         // Do not load the address of symbol that is already a pointer
00615         if (TY_kind(ty) != KIND_POINTER) {
00616           create_lda = true;
00617         }
00618       } 
00619       else if (ctxt.currentXlationContext().isFlag(XlationContext::LVALUE)) {
00620         create_lda = true;
00621       } 
00622     }
00623     // -------------------------------------------------------
00624     // 2. Create the reference
00625     // -------------------------------------------------------
00626     if (create_lda) {
00627       // OPR_LDA
00628       TY_IDX ty_ptr = Stab_Pointer_To(ty);
00629       rty = TY_mtype(ty_ptr); // Pointer_Mtype
00630       wn = WN_CreateLda(OPR_LDA, rty, MTYPE_V, oset, ty_ptr, st, 0);
00631     } 
00632     else {
00633       // OPR_LDID
00634       rty = dty = TY_mtype(ty);
00635       if (TY_kind(ty) == KIND_ARRAY) { // FIXME more special cases?
00636         rty = dty = TY_mtype(TY_etype(ty));
00637       }
00638       // FIXME: take care of small integer types
00639       if (MTYPE_byte_size(dty) < 4) {
00640         if (MTYPE_is_unsigned(dty)) { rty = Args::ourDefaultMTypeUInt; }
00641         else if (MTYPE_is_signed(dty)) { rty = Args::ourDefaultMTypeInt; }
00642       }
00643       if (ST_class(st) == CLASS_PREG) {
00644         oset = GetPregId(elem);
00645       }
00646       wn = WN_CreateLdid(OPR_LDID, rty, dty, oset, st, ty, 0);
00647     } 
00648     return wn;
00649   }
00650 
00651   std::pair<ST*, WN_OFFSET> XlateExpression::xlate_SymbolReferenceSimple(const DOMElement* elem,
00652                                                                          PUXlationContext& ctxt) {
00653     fortTkSupport::Symbol* sym = GetSymbol(elem, ctxt);
00654     ST* st = sym->GetST();
00655     WN_OFFSET oset = 0;
00656     if (ST_class(st) == CLASS_PREG) {
00657       oset = GetPregId(elem);
00658     }
00659     return make_pair(st, oset);
00660   }
00661 
00662   WN* XlateExpression::xlate_SymbolReferenceCollapsedPath(const DOMElement* elem, 
00663                                                           WN* pathVorlageWN,
00664                                                           PUXlationContext& ctxt) {
00665     OPERATOR opr = WN_operator(pathVorlageWN);
00666     bool create_lda = (ctxt.currentXlationContext().isFlag(XlationContext::LVALUE)); // FIXME  
00667     WN* wn = NULL;  
00668     switch (opr) {
00669     case OPR_STID: 
00670     case OPR_STBITS: {
00671       // Create an LDID
00672       TY_IDX ty_idx = WN_GetRefObjType(pathVorlageWN);
00673       TYPE_ID rty = TY_mtype(ty_idx); // OPCODE_rtype(WN_opcode())
00674       TYPE_ID dty = TY_mtype(ty_idx); // OPCODE_dtype(WN_opcode())
00675       ST* st = WN_st(pathVorlageWN);
00676       WN_OFFSET ofst = WN_offset(pathVorlageWN);
00677       UINT fid = WN_field_id(pathVorlageWN);
00678 #if 0 // FIXME
00679       if (!TY_Is_Pointer(ty_idx)) {
00680         ty_idx = Stab_Pointer_To(ty_idx);
00681       }
00682       TYPE_ID rty = TY_mtype(ty_idx);
00683       wn = WN_CreateLda(OPR_LDA, rty, MTYPE_V, ofst, ty_idx, st, fid);
00684 #endif
00685       wn = WN_CreateLdid(OPR_LDID, rty, dty, ofst, st, ty_idx, fid);
00686       break;
00687     }
00688     case OPR_ISTORE: 
00689     case OPR_ISTBITS: {
00690       // Create an ILOAD (copy ISTORE.kid1 to ILOAD.kid0)
00691       WN* addr = WN_COPY_Tree(WN_kid1(pathVorlageWN));
00692       TY_IDX refty = WN_GetRefObjType(pathVorlageWN);
00693       TY_IDX ptrty = WN_ty(pathVorlageWN);
00694       TYPE_ID mty = TY_mtype(refty);
00695       WN_OFFSET ofst = WN_offset(pathVorlageWN); 
00696       if (OPERATOR_has_offset(WN_operator(addr))) {
00697         ofst += WN_offset(addr); // ISTORE.offset + ISTORE.kid1.offset
00698       }
00699       UINT fid = WN_field_id(pathVorlageWN);
00700       wn = WN_CreateIload(OPR_ILOAD, mty, mty, ofst, refty, ptrty, addr, fid);
00701       break;
00702     }
00703     case OPR_LDA:
00704     case OPR_LDMA:
00705     case OPR_LDID:
00706     case OPR_LDBITS: 
00707     case OPR_ILOAD: 
00708     case OPR_ILDBITS:
00709     case OPR_STRCTFLD:
00710       wn = WN_COPY_Tree(pathVorlageWN);
00711       break;
00712     default: 
00713       break; // fall through
00714     } // switch
00715     FORTTK_ASSERT(wn, fortTkSupport::Diagnostics::Unimplemented << "Unable to recreate collapsed scalarized path.");
00716     //if (!create_lda) {
00717     //}
00718     return wn;
00719   }
00720 
00721   WN* XlateExpression::xlate_ArrayElementReference(OA::OA_ptr<OA::DGraph::DGraphImplement> g, 
00722                                                    OA::OA_ptr<MyDGNode> n, 
00723                                                    PUXlationContext& ctxt) {
00724     FORTTK_ASSERT(!g.ptrEqual(NULL) && !n.ptrEqual(NULL), fortTkSupport::Diagnostics::UnexpectedInput);
00725     DOMElement* elem = n->GetElem();
00726     WN* arrWN = 0;
00727     // ----------------------------------------------------------------------------------
00728     // Translate the array symbol reference so we can query the type
00729     OA::OA_ptr<MyDGNode> n1 = GetSuccessor(n, false /* succIsOutEdge */);
00730     const XMLCh* nmX = n1->GetElem()->getNodeName();
00731     FORTTK_ASSERT(XMLString::equals(nmX, XAIFStrings.elem_SymRef_x()),
00732                   "Expected " << XAIFStrings.elem_SymRef() << "; found:\n"
00733                   << *(n1->GetElem()));
00734     const XMLCh* symNmX = n1->GetElem()->getAttribute(XAIFStrings.attr_symId_x());
00735     XercesStrX symNm = XercesStrX(symNmX);
00736     ctxt.createXlationContext(XlationContext::ARRAY);
00737     WN* arraySym = xlate_VarRef(g, n1, ctxt);
00738     ctxt.deleteXlationContext();
00739     TY_IDX ty;
00740     if (WN_operator(arraySym)==OPR_STRCTFLD) { 
00741       ty=WN_GetRefObjType(arraySym);
00742     }
00743     else if (WN_kid0(arraySym) && WN_operator(WN_kid0(arraySym))==OPR_STRCTFLD ) {
00744       ty=WN_GetRefObjType(WN_kid0(arraySym));
00745     }
00746     else{
00747       ty = ST_type(WN_st(arraySym));
00748     }
00749     if (TY_kind(ty) == KIND_POINTER) { 
00750       ty = TY_pointed(ty); 
00751     }
00752     if (TY_Is_Character_String(ty)) {
00753       // ----------------------------------------------------------------------------------
00754       // treat character arrays separately because they have a special whirl format
00755       // there is to be one child in xaif expected to be an IndexTriplet
00756       FORTTK_ASSERT(GetChildElementCount(elem)==1,"Internal error: unexpected character array with multiple indices for >" <<  symNm.c_str() << "<");
00757       unsigned int childCount = 2; // there are two whirl child nodes
00758       DOMElement* dim = GetFirstChildElement(elem); 
00759       FORTTK_ASSERT(XMLString::equals(dim->getNodeName(), XAIFStrings.elem_IndexTriplet_x()), 
00760                     "Expected " << XAIFStrings.elem_IndexTriplet() << "; found:\n"
00761                     << *dim);
00762       DOMElement* tripletElementExpr = GetFirstChildElement(dim);
00763       UINT tripletElementCounter=0;
00764       vector<WN*> triplet(3);
00765       for (; tripletElementExpr; tripletElementExpr = GetNextSiblingElement(tripletElementExpr),++tripletElementCounter) {
00766         DOMElement* firstChild=GetFirstChildElement(tripletElementExpr);
00767         if (firstChild) { 
00768           ctxt.createXlationContext(XlationContext::ARRAYIDX);
00769           WN* indexExprWN = translateExpression(firstChild, ctxt);
00770           ctxt.deleteXlationContext();
00771           const XMLCh* tripletElementnmX = tripletElementExpr->getNodeName();
00772           if (XMLString::equals(tripletElementnmX, XAIFStrings.elem_Index_x()))
00773             triplet[0]=indexExprWN;
00774           else if (XMLString::equals(tripletElementnmX, XAIFStrings.elem_Bound_x()))
00775             triplet[1]=indexExprWN;
00776           else
00777             FORTTK_DIE("unexpected element :" << *tripletElementExpr);
00778         }
00779       }
00780       FORTTK_ASSERT(tripletElementCounter==2,"Internal error: character array has to have 2 triplet elements for >" <<  symNm.c_str() << "<");
00781       // Create Whirl ARRAY node 
00782       arrWN = WN_Create(OPR_ARRAY, MTYPE_U8, MTYPE_V, 3);
00783       // kid 0 is the array's base address
00784       WN_kid0(arrWN) = arraySym;
00785       WN_kid(arrWN, 1)=triplet[1];
00786       WN_kid(arrWN, 2)=triplet[0];
00787     }
00788     else { // is not a character array
00789       // ----------------------------------------------------------------------------------
00790       // Translate the index expression for each dimension
00791       unsigned int rank = GetChildElementCount(elem);
00792       vector<WN*> indices(rank,(WN*)0); 
00793       DOMElement* dim = GetFirstChildElement(elem);
00794       for (int i = 0; dim; dim = GetNextSiblingElement(dim), ++i) {
00795         const XMLCh* nmX = dim->getNodeName();
00796         FORTTK_ASSERT(XMLString::equals(nmX, XAIFStrings.elem_IndexTriplet_x()), 
00797                       "Expected " << XAIFStrings.elem_IndexTriplet() << "; found:\n"
00798                       << *dim);
00799         DOMElement* tripletElementExpr = GetFirstChildElement(dim);
00800         UINT tripletElementCounter=0;
00801         vector<WN*> triplet(3,(WN*)0);
00802         for (; tripletElementExpr; tripletElementExpr = GetNextSiblingElement(tripletElementExpr),++tripletElementCounter) {
00803           DOMElement* firstChild=GetFirstChildElement(tripletElementExpr);
00804           if (firstChild) { 
00805             ctxt.createXlationContext(XlationContext::ARRAYIDX);
00806             WN* indexExprWN = translateExpression(firstChild, ctxt);
00807             ctxt.deleteXlationContext();
00808             const XMLCh* tripletElementnmX = tripletElementExpr->getNodeName();
00809             if (XMLString::equals(tripletElementnmX, XAIFStrings.elem_Index_x()))
00810               triplet[0]=indexExprWN;
00811             else if (XMLString::equals(tripletElementnmX, XAIFStrings.elem_Bound_x()))
00812               triplet[1]=indexExprWN;
00813             else if (XMLString::equals(tripletElementnmX, XAIFStrings.elem_Stride_x()))
00814               triplet[2]=indexExprWN;
00815             else
00816               FORTTK_DIE("unexpected element :" << *tripletElementExpr);
00817           }
00818         }
00819         if (tripletElementCounter==1 && triplet[0]) 
00820           indices[i] = WN_Type_Conversion(triplet[0],MTYPE_I4);
00821         else { 
00822           WN* theSrcTriplet_p=WN_Create(OPR_SRCTRIPLET,
00823                                         MTYPE_I8, 
00824                                         MTYPE_V,
00825                                         3);
00826           for (int j=0; j<3; ++j) {
00827             if (triplet[j]!=0) { 
00828               WN_kid(theSrcTriplet_p,j)=WN_Type_Conversion(triplet[j],MTYPE_I4);
00829             }
00830             else { 
00831               if (j!=2)
00832                 WN_kid(theSrcTriplet_p,j)=WN_Create(OPR_IMPLICIT_BND,
00833                                                     MTYPE_V, 
00834                                                     MTYPE_V,
00835                                                     0);
00836               else // the last one (stride) should default to 1
00837                 WN_kid(theSrcTriplet_p,j)=WN_CreateIntconst(OPC_I4INTCONST, 1);
00838             }
00839           }
00840           indices[i] = theSrcTriplet_p;
00841         } 
00842       }
00843       FORTTK_ASSERT(TY_AR_ndims(ty) == (INT32)rank,
00844                     "Internal error: mismatched array dimensions");
00845       // -------------------------------------------------------
00846       // Create Whirl ARRAY node (cf. wn_fio.cxx:1.3:7055)
00847       UINT nkids = (rank * 2) + 1; // 2n + 1 where (where n == rank)
00848       arrWN = WN_Create(OPR_ARRAY, MTYPE_U8, MTYPE_V, nkids);
00849       // kid 0 is the array's base address
00850       WN_kid0(arrWN) = arraySym;
00851       // kids 1 to n give size of each dimension.  We use a bogus value,
00852       // since we need to support only translation back to source code.
00853       for (unsigned i = 1; i <= rank; ++i) {
00854         WN_kid(arrWN, i) = WN_CreateIntconst(OPC_I4INTCONST, 0);
00855       }
00856       // kids n + 1 to 2n give index expressions for each dimension.  
00857       // N.B. Reverse the order of index expressions since we are
00858       // translating Fortran.  FIXME: should we change whirl2xaif and this
00859       // to not reverse the indices?
00860       for (unsigned i = 2*rank, j = 0; i >= (rank + 1); --i, ++j) {
00861         WN_kid(arrWN, i) = indices[j];
00862       }
00863       // -------------------------------------------------------
00864       // Wrap the ARRAY in an ILOAD
00865       TY_IDX ety = TY_etype(ty);
00866       TYPE_ID emty = TY_mtype(ety);
00867       TY_IDX eptrty = Stab_Pointer_To(ety);
00868       if (emty==0 && TY_Is_Chararray(ty)) {
00869         emty=MTYPE_U4;
00870       }
00871       arrWN=WN_CreateIload(OPR_ILOAD, emty, emty, 0, ety, eptrty, arrWN, 0);
00872     }
00873     return arrWN;
00874   }
00875 
00876   OA::OA_ptr<OA::DGraph::DGraphImplement> XlateExpression::createExpressionGraph(const DOMElement* elem, 
00877                                                                                 bool varRef) {
00878     using namespace OA::DGraph;
00879     MyDGNode::resetIds();
00880     OA::OA_ptr<DGraphImplement> g; g = new DGraphImplement();
00881     VertexIdToMyDGNodeMap m;
00882     // Setup variables
00883     XMLCh* edgeStr = NULL;
00884     if (varRef) {
00885       edgeStr = XAIFStrings.elem_VarRefEdge_x();
00886     } else {
00887       edgeStr = XAIFStrings.elem_ExprEdge_x();
00888     }
00889     // -------------------------------------------------------
00890     // Create the graph (only examine element nodes)
00891     // -------------------------------------------------------
00892     DOMElement* e = const_cast<DOMElement*>(elem);
00893     do {
00894       const XMLCh* name = e->getNodeName();
00895       if (XMLString::equals(name, edgeStr)) {
00896         // Add an edge to the graph.  N.B.: we ignore the 'position'
00897         // attribute during creation of the graph.
00898         // Find src and target (sink) nodes. 
00899         const XMLCh* srcX = e->getAttribute(XAIFStrings.attr_source_x());
00900         const XMLCh* targX = e->getAttribute(XAIFStrings.attr_target_x());
00901         XercesStrX src = XercesStrX(srcX);
00902         XercesStrX targ = XercesStrX(targX);
00903         OA::OA_ptr<MyDGNode> gn1 = m[std::string(src.c_str())];  // source
00904         OA::OA_ptr<MyDGNode> gn2 = m[std::string(targ.c_str())]; // target
00905         FORTTK_ASSERT(!gn1.ptrEqual(NULL) && !gn2.ptrEqual(NULL), "Invalid edge in expression graph:\n" << *e);
00906         OA::OA_ptr<MyDGEdge> ge; ge = new MyDGEdge(gn1, gn2, e); // src, targ
00907         g->addEdge(ge);
00908       } 
00909       else {
00910         // Add a vertex to the graph
00911         const XMLCh* vidX = e->getAttribute(XAIFStrings.attr_Vid_x());
00912         XercesStrX vid = XercesStrX(vidX);
00913         FORTTK_ASSERT(strlen(vid.c_str()) > 0, 
00914                       "Invalid vertex in expression graph:\n" << *e);
00915         OA::OA_ptr<MyDGNode> gn; gn = new MyDGNode(e);
00916         g->addNode(gn);
00917         m[std::string(vid.c_str())] = gn;
00918       } 
00919     } while ( (e = GetNextSiblingElement(e)) );
00920     return g;
00921   }
00922 
00923   WN* XlateExpression::createValueSelector(WN* wn) {
00924     TYPE_ID rty = getRType(wn);
00925     WN* callWN = CreateCallToIntrin(rty, "__value__", 1);
00926     WN_actual(callWN, 0) = CreateParm(wn, WN_PARM_BY_VALUE);
00927     return callWN;
00928   }
00929 
00930   WN* XlateExpression::createDerivSelector(WN* wn) {
00931     TYPE_ID rty = getRType(wn);
00932     WN* callWN = CreateCallToIntrin(rty, "__deriv__", 1);
00933     WN_actual(callWN, 0) = CreateParm(wn, WN_PARM_BY_VALUE);
00934     return callWN;
00935   }
00936 
00937   TYPE_ID XlateExpression::getRType(WN* wn) {
00938     TY_IDX ty_idx = WN_Tree_Type(wn);
00939     TYPE_ID rty = MTYPE_UNKNOWN;
00940     if (TY_kind(ty_idx) == KIND_POINTER) { 
00941       ty_idx=TY_pointed(ty_idx);
00942     }
00943     if (TY_kind(ty_idx) == KIND_ARRAY) { 
00944       rty=TY_mtype(TY_etype(ty_idx));
00945     }
00946     else if (TY_kind(ty_idx) == KIND_STRUCT) {
00947       rty = MTYPE_M;
00948     } else {
00949       rty = TY_mtype(ty_idx);
00950     }
00951     // FIXME: pointer types
00952     FORTTK_ASSERT(rty != MTYPE_UNKNOWN, "Error finding rtype of WN expr"); 
00953     return rty;
00954   }
00955 
00956   TYPE_ID XlateExpression::getRTypeFromOpands(vector<WN*>& opands) {
00957     int opands_num = opands.size();
00958     FORTTK_ASSERT(opands_num > 0, fortTkSupport::Diagnostics::UnexpectedInput);
00959     // 1. Gather types for operands
00960     vector<TY_IDX> opands_ty(opands_num);
00961     vector<TYPE_ID> opands_mty(opands_num);
00962     for (int i = 0; i < opands_num; ++i) {
00963       TY_IDX ty = WN_Tree_Type(opands[i]);
00964       opands_ty[i] = ty;
00965       if (TY_kind(ty) == KIND_ARRAY) 
00966         opands_mty[i] = TY_mtype(TY_etype(ty));
00967       else if (TY_kind(ty) == KIND_POINTER) 
00968         opands_mty[i] = TY_mtype(TY_pointed(ty));
00969       else 
00970         opands_mty[i] = TY_mtype(ty);
00971     }
00972     // 2. Find an appropriate mtype for operands
00973     TYPE_ID mty = opands_mty[0];
00974     for (int i = 1; i < opands_num; ++i) {
00975       mty = getRTypeFromOpands(mty, opands_mty[i]);
00976     }
00977     return mty;
00978   }
00979 
00980   TYPE_ID XlateExpression::getRTypeFromOpands(TYPE_ID ty1, TYPE_ID ty2) {
00981     // -------------------------------------------------------
00982     // 1. If both types are same, the answer is easy
00983     // -------------------------------------------------------
00984     if (ty1 == ty2) {
00985       return ty1;
00986     } 
00987     // -------------------------------------------------------
00988     // 2. We have different types.
00989     // -------------------------------------------------------
00990     // 2a. If we have different, but compatible classes --> class promotion
00991     unsigned int cl1 = MTYPE_type_class(ty1);
00992     unsigned int cl2 = MTYPE_type_class(ty2);
00993     unsigned int cl = 0; // the new class
00994     if (cl1 == cl2) {
00995       cl = cl1;
00996     }
00997     // (u)int, float --> float
00998     if ( ((cl1 == MTYPE_CLASS_INTEGER || cl1 == MTYPE_CLASS_UNSIGNED_INTEGER) 
00999           && (cl2 == MTYPE_CLASS_FLOAT))
01000          ||
01001          ((cl2 == MTYPE_CLASS_INTEGER || cl2 == MTYPE_CLASS_UNSIGNED_INTEGER)
01002           && (cl1 == MTYPE_CLASS_FLOAT)) ) {
01003       cl = MTYPE_CLASS_FLOAT;
01004     }
01005     // int, uint --> [error]
01006     // !complex_float, complex_float --> [error]
01007     // !str, str --> [error]
01008     if (cl == 0) {
01009       return ty1; // FIXME: what to do here?
01010     }
01011     // 2b. If we have different sizes --> size promotion (choose larger)
01012     unsigned int sz1 = MTYPE_byte_size(ty1);
01013     unsigned int sz2 = MTYPE_byte_size(ty2);
01014     unsigned int sz = MAX(sz1, sz2); // the new size
01015     // 2c. Combine class and size information. 
01016     TYPE_ID ty = getMType(cl, sz);
01017     return ty;
01018   }
01019 
01020   TYPE_ID XlateExpression::getMType(unsigned int cl, unsigned int bytesz) {
01021     TYPE_ID ty = MTYPE_UNKNOWN;
01022     for (TYPE_ID i = MTYPE_FIRST; i <= MTYPE_LAST; ++i) {
01023       if ((MTYPE_type_class(i) == cl) && (MTYPE_byte_size(i) == bytesz)) {
01024         ty = i;
01025         break;
01026       }
01027     }
01028     return ty;
01029   }
01030 
01031   OPCODE XlateExpression::getWNExprOpcode(OPERATOR opr, vector<WN*>& opands) {
01032     // 1. Find mtype suggested from operands
01033     TYPE_ID mty = getRTypeFromOpands(opands);
01034     // 2. Find a dtype (operator dependent) FIXME/FIXME
01035     TYPE_ID dty = MTYPE_V; // typical dtype for intrinsics
01036     if (opr == OPR_TRUNC || 
01037         opr == OPR_EQ || opr == OPR_NE || opr == OPR_GT || opr == OPR_GE ||
01038         opr == OPR_LT || opr == OPR_LE) {
01039       dty = mty;
01040     } 
01041     // 3. Find a rtype (operator dependent)
01042     // FIXME: we need a better way; do we need a cvt? FIXME
01043     // Is_Valid_Opcode, Is_Valid_Opcode_Parts
01044     TYPE_ID rty = mty;
01045     if (opr == OPR_SQRT && MTYPE_is_integral(rty)) {
01046       // sqrt: f, z
01047       rty = getMType(MTYPE_CLASS_FLOAT, MTYPE_byte_size(rty));
01048     } 
01049     else if (opr == OPR_TRUNC || opr == OPR_MOD || opr == OPR_REM) {
01050       // trunc, mod, rem: i
01051       rty = getMType(MTYPE_CLASS_INTEGER, MTYPE_byte_size(rty));
01052     } 
01053     else if (opr == OPR_EQ || opr == OPR_NE || opr == OPR_GT || opr == OPR_GE ||
01054              opr == OPR_LT || opr == OPR_LE || opr == OPR_LNOT ) {
01055       rty = getMType(MTYPE_CLASS_INTEGER, 4);
01056     }
01057     else if (opr == OPR_COMPLEX ) {
01058       rty = getMType(MTYPE_CLASS_COMPLEX_FLOAT,MTYPE_byte_size(mty));
01059     }
01060     OPCODE opc = OPCODE_make_op(opr, rty, dty);
01061     return opc;
01062   }
01063 
01064   INTRINSIC XlateExpression::getWNIntrinsic(const char* intrnNm, vector<WN*>& opands, TYPE_ID* dtype) {
01065     // 1. Find dtype suggested from operands
01066     TYPE_ID mty = getRTypeFromOpands(opands);
01067     // per Nathan the situation is that there is 
01068     // a method to translate the whirl intrinsic enumerations 
01069     // into a  name but whirl doesn't have a function to 
01070     // translate the name back for all of the intrinsic names
01071     // because often the intrinsic name known in 
01072     // get_intrinsic_from_name 
01073     // includes the machine type 
01074     // Because we don't include the machine type 
01075     // we hardcode the intrinsic here for the following cases.
01076     INTRINSIC intrn = INTRINSIC_INVALID;
01077     if (strcmp(intrnNm, "EXPEXPR") == 0) {
01078       intrn = INTRN_F8EXPEXPR;
01079       if (dtype) { *dtype = MTYPE_F8; }
01080     }
01081     else if (strcmp(intrnNm, "AMOD") == 0) {
01082       intrn = INTRN_F4MOD;
01083       if (dtype) { *dtype = MTYPE_F4; }
01084     }
01085     else if (strcmp(intrnNm, "DMOD") == 0) {
01086       intrn = INTRN_F4MOD;
01087       if (dtype) { *dtype = MTYPE_F8; }
01088     }
01089     else if (strcmp(intrnNm, "LEN") == 0) {
01090       intrn = INTRN_I4CLEN;
01091       if (dtype) { *dtype = MTYPE_I4; }
01092     }
01093     else { 
01094       intrn=get_intrinsic_from_name(intrnNm);
01095     }
01096     FORTTK_ASSERT(intrn != INTRINSIC_INVALID, 
01097                   "Unknown intrinsic '" << intrnNm << "'");
01098     return intrn;
01099   }
01100 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines