Search in sources :

Example 1 with FmoduleDefinition

use of claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition in project claw-compiler by C2SM-RCM.

the class ScaForward method transformStd.

/**
 * Do the standard transformation for the forward directive. This transformation
 * adapt the function call and replicates any necessary changes to the
 * containing subroutine.
 *
 * @param xcodeml    Current XcodeML file unit.
 * @param translator Current translator.
 * @throws Exception If something goes wrong.
 */
private void transformStd(XcodeProgram xcodeml, Translator translator) throws Exception {
    ClawTranslator trans = (ClawTranslator) translator;
    final Context context = trans.context();
    final Configuration cfg = trans.cfg();
    FfunctionDefinition fDef = _claw.getPragma().findParentFunction();
    if (fDef == null) {
        throw new IllegalTransformationException("SCA directive is not " + "nested in a function/subroutine.", _claw.getPragma().lineNo());
    }
    FfunctionType parentFctType = xcodeml.getTypeTable().getFunctionType(fDef);
    if (_fctType.isElemental() || _fctType.getBooleanAttribute(Xattr.WAS_ELEMENTAL)) {
        _flatten = true;
    }
    List<Xnode> params = _fctType.getParameters();
    /*
         * Compute the position of the first new arguments. In the case of a type-bound
         * procedure call, the first parameter declared in the procedure is not actually
         * passed as an argument. In this case, we add an offset of one to the starting
         * arguments. TODO the check might be change to fit with the XcodeML/F2008
         * specs. The TODO cont: attribute data_ref will probably be gone and replaced
         * by a TODO cont: FmemberRef element
         */
    int argOffset = 0;
    if (!params.isEmpty() && FortranType.STRUCT.isOfType(params.get(0).getType()) && _fCall.isTbpCall()) {
        argOffset = 1;
    }
    // 1. Adapt function call with potential new arguments
    for (int i = 0; i < params.size(); i++) {
        Xnode p = params.get(i);
        String varId = p.value();
        String type;
        FbasicType paramType = xcodeml.getTypeTable().getBasicType(p);
        if (!p.getBooleanAttribute(Xattr.IS_INSERTED)) {
            continue;
        }
        if (!fDef.getSymbolTable().contains(varId)) {
            if (_flatten && !paramType.getBooleanAttribute(Xattr.IS_OPTIONAL)) {
                throw new IllegalTransformationException("Variable " + varId + " must be locally defined where the last call to one_column " + "is made.", _claw.getPragma().lineNo());
            }
            // Size variable have to be declared
            FbasicType bt = xcodeml.createBasicType(FortranType.INTEGER, Intent.IN);
            xcodeml.getTypeTable().add(bt);
            xcodeml.createIdAndDecl(varId, bt.getType(), XstorageClass.F_PARAM, fDef, DeclarationPosition.FIRST);
            type = bt.getType();
            Xnode param = xcodeml.createAndAddParam(varId, type, parentFctType);
            param.setBooleanAttribute(Xattr.IS_INSERTED, true);
        } else {
            // Var exists already. Add to the parameters if not here.
            type = fDef.getSymbolTable().get(varId).getType();
            /*
                 * If flatten mode, we do not add extra parameters to the function definition.
                 */
            if (!_flatten && !fDef.getSymbolTable().contains(varId)) {
                Xnode param = xcodeml.createAndAddParamIfNotExists(varId, type, parentFctType);
                if (param != null) {
                    param.setBooleanAttribute(Xattr.IS_INSERTED, true);
                }
            }
        }
        // Add variable in the function call before the optional parameters
        Xnode arg = xcodeml.createNamedValue(varId);
        arg.append(xcodeml.createVar(type, varId, Xscope.LOCAL));
        Xnode hook = _fCall.arguments().get((i - 1) - argOffset);
        if (hook != null) {
            hook.insertAfter(arg);
        } else {
            _fCall.addArguments(arg);
        }
    }
    // In flatten mode, arguments are demoted if needed.
    if (_flatten) {
        for (Xnode arg : _fCall.arguments()) {
            if (arg.is(Xcode.F_ARRAY_REF) && arg.matchDirectDescendant(Arrays.asList(Xcode.INDEX_RANGE, Xcode.ARRAY_INDEX)) != null) {
                List<Xnode> arrayIndexes = arg.matchAll(Xcode.ARRAY_INDEX);
                for (Xnode n : arrayIndexes) {
                    if (_doStatements != null && XnodeUtil.isInductionIndex(n, _doStatements.getInductionVariables())) {
                        n.insertAfter(xcodeml.createEmptyAssumedShaped());
                        XnodeUtil.safeDelete(n);
                    }
                }
            }
        }
    } else {
        // 2. Adapt function/subroutine in which the function call is nested
        for (Xnode pBase : _fctType.getParameters()) {
            String originalParam = pBase.value();
            if (_fctCallMapping.containsKey(originalParam)) {
                originalParam = _fctCallMapping.get(originalParam);
            }
            Xnode pUpdate = null;
            for (Xnode param : parentFctType.getParameters()) {
                if (originalParam.equals(param.value())) {
                    pUpdate = param;
                }
            }
            if (pUpdate == null) {
                // field is not a parameter but maybe out field
                Xnode d = fDef.getDeclarationTable().get(originalParam);
                if (d != null) {
                    pUpdate = d.matchSeq(Xcode.NAME);
                }
            }
            if (pUpdate != null) {
                if (pUpdate.getType() == null || FortranType.isBuiltInType(pUpdate.getType())) {
                    continue;
                }
                FbasicType typeBase = (_localFct) ? xcodeml.getTypeTable().getBasicType(pBase) : _mod.getTypeTable().getBasicType(pBase);
                FbasicType typeToUpdate = xcodeml.getTypeTable().getBasicType(pUpdate);
                int targetDim = typeBase.getDimensions();
                int baseDim = typeToUpdate.getDimensions();
                // Types have different dimensions
                if (typeBase.getDimensions() > typeToUpdate.getDimensions()) {
                    PromotionInfo promotionInfo = new PromotionInfo(originalParam);
                    promotionInfo.readDimensionsFromString(pBase.getAttribute(Xattr.PROMOTION_INFO));
                    FbasicType type = _localFct ? Type.duplicateWithDimension(typeBase, typeToUpdate, xcodeml, xcodeml, promotionInfo.getDimensions()) : Type.duplicateWithDimension(typeBase, typeToUpdate, _mod, xcodeml, promotionInfo.getDimensions());
                    pUpdate.setType(type);
                    Xid id = fDef.getSymbolTable().get(originalParam);
                    if (id != null) {
                        id.setType(type);
                    }
                    Xnode varDecl = fDef.getDeclarationTable().get(originalParam);
                    if (varDecl != null) {
                        varDecl.matchSeq(Xcode.NAME).setType(type);
                    }
                    promotionInfo.setBaseDimension(baseDim);
                    promotionInfo.setTargetDimension(targetDim);
                    promotionInfo.setTargetType(type);
                    _promotions.put(originalParam, promotionInfo);
                    _promotedVar.add(originalParam);
                    pBase.copyAttribute(pUpdate, Xattr.PROMOTION_INFO);
                }
            }
        }
        if (!parentFctType.getBooleanAttribute(Xattr.IS_PRIVATE)) {
            // 3. Replicate the change in a potential module file
            FmoduleDefinition modDef = fDef.findParentModule();
            if (modDef != null) {
                Xmod.updateSignature(modDef.getName(), xcodeml, fDef, parentFctType, false);
            }
        } else if (_fCall.matchSeq(Xcode.NAME).hasAttribute(Xattr.DATA_REF)) {
            /*
                 * The function/subroutine is private but accessible through the type as a
                 * type-bound procedure. In this case, the function is not in the type table of
                 * the .xmod file. We need to insert it first and then we can update it.
                 */
            FmoduleDefinition modDef = fDef.findParentModule();
            if (modDef != null) {
                Xmod.updateSignature(modDef.getName(), xcodeml, fDef, parentFctType, true);
            }
        }
    }
    updateResultVar(xcodeml);
    propagatePromotion(xcodeml, (ClawTranslator) translator);
    Xnode fctCallAncestor = _fCall.matchAncestor(Xcode.EXPR_STATEMENT);
    if (fctCallAncestor == null) {
        fctCallAncestor = _fCall.matchAncestor(Xcode.F_ASSIGN_STATEMENT);
    }
    if (_claw.hasClause(ClawClause.CREATE) && context.isTarget(Target.GPU)) {
        List<String> creates = _fCall.gatherArguments(xcodeml, _fctType, _mod, Intent.INOUT, true, false);
        if (_fctType.isFunction()) {
            String returnValue = XnodeUtil.gatherReturnValue(xcodeml, _fCall);
            if (returnValue != null) {
                creates.add(returnValue);
            }
        }
        Xblock fctCallBlock = new Xblock(fctCallAncestor);
        Directive.generateDataRegionClause(xcodeml, Collections.emptyList(), creates, fctCallBlock);
    }
    // Serialization input
    if (_claw.hasClause(ClawClause.SAVEPOINT)) {
        List<String> inFields = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.IN, true, false);
        Serialization.insertImports(cfg, xcodeml, _fCall.findParentFunction());
        if (context.isTarget(Target.CPU)) {
            Serialization.generateWriteSavepoint(cfg, xcodeml, fctCallAncestor, _claw.getMetadataMap(), inFields, _claw.value(ClawClause.SAVEPOINT), SerializationStep.SER_IN);
        } else {
            Serialization.generateReadSavepoint(cfg, xcodeml, fctCallAncestor, _claw.getMetadataMap(), inFields, _claw.value(ClawClause.SAVEPOINT), SerializationStep.SER_IN);
        }
    }
    Xnode postHook = fctCallAncestor;
    if (_claw.hasClause(ClawClause.UPDATE) && context.isTarget(Target.GPU) && cfg.getBooleanParameter(Configuration.SCA_FORWARD_UPDATE_ENABLED)) {
        // Generate update from HOST TO DEVICE
        if ((_claw.getUpdateClauseValue() == DataMovement.TWO_WAY || _claw.getUpdateClauseValue() == DataMovement.HOST_TO_DEVICE) && cfg.updateAtInput()) {
            List<String> in = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.IN, true, false);
            Directive.generateUpdate(xcodeml, fctCallAncestor, in, DataMovement.HOST_TO_DEVICE);
        }
        // Generate update from DEVICE to HOST
        if ((_claw.getUpdateClauseValue() == DataMovement.TWO_WAY || _claw.getUpdateClauseValue() == DataMovement.DEVICE_TO_HOST) && cfg.updateAtOutput()) {
            List<String> out = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.OUT, true, false);
            if (_fctType.isFunction()) {
                String returnValue = XnodeUtil.gatherReturnValue(xcodeml, _fCall);
                if (returnValue != null) {
                    out.add(returnValue);
                }
            }
            postHook = Directive.generateUpdate(xcodeml, fctCallAncestor, out, DataMovement.DEVICE_TO_HOST);
        }
    }
    if (_claw.hasClause(ClawClause.PARALLEL) && context.isTarget(Target.GPU)) {
        Directive.generateParallelRegion(xcodeml, fctCallAncestor, fctCallAncestor);
    }
    // Serialization output
    if (_claw.hasClause(ClawClause.SAVEPOINT)) {
        List<String> outFields = _fCall.gatherArguments(xcodeml, _fctType, _mod != null ? _mod : xcodeml, Intent.OUT, true, false);
        Serialization.insertImports(cfg, xcodeml, _fCall.findParentFunction());
        Serialization.generateWriteSavepoint(cfg, xcodeml, postHook, _claw.getMetadataMap(), outFields, _claw.value(ClawClause.SAVEPOINT), SerializationStep.SER_OUT);
    }
}
Also used : Context(claw.tatsu.common.Context) Configuration(claw.wani.x2t.configuration.Configuration) FfunctionType(claw.tatsu.xcodeml.xnode.fortran.FfunctionType) PromotionInfo(claw.tatsu.xcodeml.abstraction.PromotionInfo) FbasicType(claw.tatsu.xcodeml.xnode.fortran.FbasicType) Xnode(claw.tatsu.xcodeml.xnode.common.Xnode) Xid(claw.tatsu.xcodeml.xnode.common.Xid) FfunctionDefinition(claw.tatsu.xcodeml.xnode.fortran.FfunctionDefinition) IllegalTransformationException(claw.tatsu.xcodeml.exception.IllegalTransformationException) Xblock(claw.tatsu.xcodeml.abstraction.Xblock) FmoduleDefinition(claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition) ClawTranslator(claw.wani.x2t.translator.ClawTranslator)

Example 2 with FmoduleDefinition

use of claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition in project claw-compiler by C2SM-RCM.

the class XglobalDeclTable method readTable.

/**
 * Read the declaration table
 */
private void readTable() {
    Xnode crt = firstChild();
    while (crt != null) {
        if (crt.is(Xcode.F_FUNCTION_DEFINITION)) {
            FfunctionDefinition fctDef = new FfunctionDefinition(crt);
            _table.put(fctDef.getName(), fctDef);
        } else if (crt.is(Xcode.F_MODULE_DEFINITION)) {
            FmoduleDefinition moduleDef = new FmoduleDefinition(crt);
            _table.put(moduleDef.getName(), moduleDef);
        }
        crt = crt.nextSibling();
    }
}
Also used : FfunctionDefinition(claw.tatsu.xcodeml.xnode.fortran.FfunctionDefinition) FmoduleDefinition(claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition)

Example 3 with FmoduleDefinition

use of claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition in project claw-compiler by C2SM-RCM.

the class ScaGPU method transformElemental.

/**
 * Apply transformation on ELEMENTAL function/subroutine.
 *
 * @param xcodeml    Current translation unit.
 * @param translator Current translator.
 * @throws IllegalTransformationException If transformation fails.
 */
private void transformElemental(XcodeProgram xcodeml, ClawTranslator translator) throws Exception {
    /*
         * SCA in ELEMENTAL function. Only flag the function and leave the actual
         * transformation until having information on the calling site from another
         * translation unit.
         */
    if (_fctType.isElemental()) {
        _fctType.setBooleanAttribute(Xattr.WAS_ELEMENTAL, true);
        if (_fctType.isFunction() && !_fctType.hasAttribute(Xattr.RESULT_NAME)) {
            _arrayFieldsInOut.add(_fctDef.getName());
        }
        if (translator.cfg().getBooleanParameter(Configuration.SCA_ELEMENTAL_PROMOTION_ASSUMED)) {
            forceAssumedShapedArrayPromotion = _fctType.isSubroutine() || !(_arrayFieldsInOut.contains(_fctType.getResultName()) || _arrayFieldsInOut.contains(_fctDef.getName()));
        }
        // SCA ELEMENTAL
        FmoduleDefinition modDef = _fctDef.findParentModule();
        if (modDef == null) {
            throw new IllegalTransformationException("SCA in ELEMENTAL function " + "transformation requires module encapsulation.");
        }
        transformReturnStatement(xcodeml);
        // Apply the common transformation
        super.transform(xcodeml, translator, null);
        // Remove ELEMENTAL and PURE attributes if present.
        removeAttributesWithWaring(xcodeml, _fctType, Xattr.IS_ELEMENTAL);
        removeAttributesWithWaring(xcodeml, _fctType, Xattr.IS_PURE);
        // Apply specific steps for GPU
        applySpecificTransformation(translator.cfg(), xcodeml);
        // Finalize the common steps
        super.finalizeTransformation(xcodeml);
    }
}
Also used : IllegalTransformationException(claw.tatsu.xcodeml.exception.IllegalTransformationException) FmoduleDefinition(claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition)

Example 4 with FmoduleDefinition

use of claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition in project claw-compiler by C2SM-RCM.

the class ArrayToFctCall method analyze.

@Override
public boolean analyze(XcodeProgram xcodeml, Translator translator) {
    FfunctionDefinition fctDef = _claw.getPragma().findParentFunction();
    if (fctDef == null) {
        xcodeml.addError("Cannot locate function definition.", _claw.getPragma().lineNo());
        return false;
    }
    if (!fctDef.getDeclarationTable().contains(_claw.value(ClawClause.ARRAY_NAME))) {
        xcodeml.addError(_claw.value(ClawClause.ARRAY_NAME) + " is not declared in current function/subroutine.", _claw.getPragma().lineNo());
        return false;
    }
    _replaceFct = xcodeml.getGlobalDeclarationsTable().getFunctionDefinition(_claw.value(ClawClause.FCT_NAME));
    if (_replaceFct == null) {
        FmoduleDefinition parentModule = _claw.getPragma().findParentModule();
        Optional<FfunctionDefinition> replaceFct = parentModule.getFunctionDefinition(_claw.value(ClawClause.FCT_NAME));
        if (!replaceFct.isPresent()) {
            xcodeml.addError("Function " + _claw.value(ClawClause.FCT_NAME) + " not found in current file.", _claw.getPragma().lineNo());
            return false;
        }
        _replaceFct = replaceFct.get();
    }
    // skeleton
    return true;
}
Also used : FfunctionDefinition(claw.tatsu.xcodeml.xnode.fortran.FfunctionDefinition) FmoduleDefinition(claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition)

Example 5 with FmoduleDefinition

use of claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition in project claw-compiler by C2SM-RCM.

the class ScaForward method analyzeForward.

/**
 * Analyze the directive when it is used just before a function call.
 *
 * @param xcodeml Current XcodeML file unit.
 * @return True if the analysis succeed. False otherwise.
 */
private boolean analyzeForward(XcodeProgram xcodeml) {
    final Context context = xcodeml.context();
    if (_fCall == null) {
        xcodeml.addError("Directive is not followed by a fct call.", _claw.getPragma());
        return false;
    }
    detectParameterMapping(context, _fCall);
    _calledFctName = _fCall.getFctName();
    FfunctionDefinition fctDef = xcodeml.getGlobalDeclarationsTable().getFunctionDefinition(_calledFctName);
    FfunctionDefinition parentFctDef = _claw.getPragma().findParentFunction();
    if (parentFctDef == null) {
        xcodeml.addError("SCA directive is not nested in a " + "function/subroutine.", _claw.getPragma());
        return false;
    }
    FmoduleDefinition parentModule = parentFctDef.findParentModule();
    if (_fCall.isTbpCall()) {
        /*
             * If type is a FbasicType element for a type-bound procedure, we have to
             * matchSeq the correct function in the typeTable. TODO if there is a rename.
             * TODO generic call
             */
        Xid id = parentModule.getSymbolTable().get(_calledFctName);
        if (id == null) {
            List<Xnode> uses = parentFctDef.getDeclarationTable().uses();
            uses.addAll(parentModule.getDeclarationTable().uses());
            if (!findInModule(context, uses)) {
                xcodeml.addError("Function definition not found in module ", _claw.getPragma());
                return false;
            }
        } else {
            _fctType = xcodeml.getTypeTable().getFunctionType(id);
        }
    } else {
        if (xcodeml.getTypeTable().isFunctionType(_fCall)) {
            _fctType = xcodeml.getTypeTable().getFunctionType(_fCall);
        } else {
            xcodeml.addError("Unsupported type of XcodeML/F element for the function " + _calledFctName, _claw.getPragma());
            return false;
        }
    }
    /*
         * Workaround for a bug in OMNI Compiler. Look at test case claw/abstraction10.
         * In this test case, the XcodeML/F intermediate representation for the function
         * call points to a FfunctionType element with no parameters. Thus, we have to
         * matchSeq the correct FfunctionType for the same function/subroutine with the
         * same name in the module symbol table.
         */
    if (_fctType.getParameters().isEmpty()) {
        /*
             * If not, try to matchSeq the correct FfunctionType in the module definitions
             */
        Xid id = (parentModule == null) ? null : parentModule.getSymbolTable().get(_calledFctName);
        if (id == null) {
            // Function is not located in the current module.
            List<Xnode> uses = parentFctDef.getDeclarationTable().uses();
            if (parentModule != null) {
                uses.addAll(parentModule.getDeclarationTable().uses());
            }
            if (!findInModule(context, uses)) {
                xcodeml.addError(String.format("Function definition %s not found in module.", _calledFctName), _claw.getPragma());
                return false;
            }
        } else {
            _fctType = xcodeml.getTypeTable().getFunctionType(id);
            if (_fctType == null) {
                xcodeml.addError("Called function cannot be found in the same module ", _claw.getPragma());
                return false;
            }
        }
    }
    // end of workaround
    _callingFctName = parentFctDef.getName();
    if (_fctType != null && fctDef != null) {
        _localFct = true;
    } else {
        // Has been found already
        if (_fctType != null && _calledFctName == null) {
            return true;
        }
        // Get all the use statements in the fct and module definitions
        List<Xnode> uses = parentFctDef.getDeclarationTable().uses();
        if (parentModule != null) {
            uses.addAll(parentModule.getDeclarationTable().uses());
        }
        // Try to locate the fct in the modules defined in use statements
        if (findInModule(context, uses)) {
            return true;
        }
        xcodeml.addError("Function signature not found in the current module.", _claw.getPragma());
        return false;
    }
    return true;
}
Also used : Context(claw.tatsu.common.Context) Xnode(claw.tatsu.xcodeml.xnode.common.Xnode) Xid(claw.tatsu.xcodeml.xnode.common.Xid) FfunctionDefinition(claw.tatsu.xcodeml.xnode.fortran.FfunctionDefinition) FmoduleDefinition(claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition)

Aggregations

FmoduleDefinition (claw.tatsu.xcodeml.xnode.fortran.FmoduleDefinition)7 FfunctionDefinition (claw.tatsu.xcodeml.xnode.fortran.FfunctionDefinition)6 Context (claw.tatsu.common.Context)3 IllegalTransformationException (claw.tatsu.xcodeml.exception.IllegalTransformationException)2 Xid (claw.tatsu.xcodeml.xnode.common.Xid)2 Xnode (claw.tatsu.xcodeml.xnode.common.Xnode)2 Test (org.junit.Test)2 PromotionInfo (claw.tatsu.xcodeml.abstraction.PromotionInfo)1 Xblock (claw.tatsu.xcodeml.abstraction.Xblock)1 FbasicType (claw.tatsu.xcodeml.xnode.fortran.FbasicType)1 FfunctionType (claw.tatsu.xcodeml.xnode.fortran.FfunctionType)1 Configuration (claw.wani.x2t.configuration.Configuration)1 ClawTranslator (claw.wani.x2t.translator.ClawTranslator)1 TestContext (helper.Utils.TestContext)1