UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

81 lines 2.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertCfgToBasicBlocks = convertCfgToBasicBlocks; const control_flow_graph_1 = require("./control-flow-graph"); /** if true, return the target */ function singleOutgoingFd(outgoing) { if (!outgoing || outgoing.size !== 1) { return undefined; } const next = outgoing.entries().next().value; if (next?.[1].label === 0 /* CfgEdgeType.Fd */) { return next[0]; } else { return undefined; } } /** * Take a control flow information of a graph without any basic blocks and convert it to a graph with basic blocks. */ function convertCfgToBasicBlocks(cfInfo) { const newCfg = wrapEveryVertexInBasicBlock(cfInfo.graph); if (!newCfg) { return cfInfo; } for (const [id, vtx] of newCfg.vertices(false)) { if (vtx.type !== control_flow_graph_1.CfgVertexType.Block) { continue; } const outgoing = newCfg.outgoingEdges(id); const target = singleOutgoingFd(outgoing); if (target) { const targetIn = newCfg.ingoingEdges(target); if (targetIn && targetIn.size === 1) { newCfg.mergeTwoBasicBlocks(id, target); } } const ingoing = newCfg.ingoingEdges(id); const ingoingTarget = singleOutgoingFd(ingoing); if (ingoingTarget) { const ingoingOut = newCfg.outgoingEdges(ingoingTarget); if (ingoingOut && ingoingOut.size === 1) { newCfg.mergeTwoBasicBlocks(ingoingTarget, id); } } } const findEntries = cfInfo.entryPoints.map(e => newCfg.getBasicBlock(e)?.id); const findExits = cfInfo.exitPoints.map(e => newCfg.getBasicBlock(e)?.id); if (findEntries.some(f => f === undefined) || findExits.some(f => f === undefined)) { /* something went wrong */ return cfInfo; } return { ...cfInfo, graph: newCfg, entryPoints: findEntries, exitPoints: findExits, }; } /** only returns undefined when the cfg already contains basic blocks */ function wrapEveryVertexInBasicBlock(existing) { const newGraph = new control_flow_graph_1.ControlFlowGraph(); for (const [id, vertex] of existing.vertices(false)) { if (vertex.type === control_flow_graph_1.CfgVertexType.Block) { return undefined; } newGraph.addVertex({ type: control_flow_graph_1.CfgVertexType.Block, elems: [vertex], id: 'bb-' + id, }); } // promote all edges for (const [from, outgoing] of existing.edges().entries()) { for (const [to, edge] of outgoing.entries()) { newGraph.addEdge('bb-' + from, 'bb-' + to, edge); } } return newGraph; } //# sourceMappingURL=cfg-to-basic-blocks.js.map