All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.qbicc.graph.BasicBlock Maven / Gradle / Ivy

There is a newer version: 0.77.0
Show newest version
package org.qbicc.graph;

import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import io.smallrye.common.constraint.Assert;

/**
 *
 */
public final class BasicBlock {
    private final BlockEntry blockEntry;
    private final Terminator terminator;
    private BlockLabel myLabel;
    private boolean reachable;
    // set by scheduler
    private Set incoming = Set.of();
    private Set loops = Set.of();
    private int index;
    private Set liveOuts;
    private List instructions;
    private Map usedParameters;

    BasicBlock(final BlockEntry blockEntry, final Terminator terminator) {
        this.blockEntry = blockEntry;
        this.terminator = terminator;
    }

    public BlockEntry getBlockEntry() {
        return blockEntry;
    }

    public Terminator getTerminator() {
        return terminator;
    }

    // nodes contain links to handles, not to nodes
    BlockLabel getHandle() {
        BlockLabel myHandle = this.myLabel;
        if (myHandle == null) {
            myHandle = this.myLabel = new BlockLabel();
            myHandle.setTarget(this);
        }
        return myHandle;
    }

    BlockLabel getHandleIfExists() {
        return myLabel;
    }

    void setHandle(BlockLabel newHandle) {
        assert myLabel == null;
        myLabel = newHandle;
    }

    /**
     * Get the sequence of instructions for this block.
     *
     * @return the instruction list (not {@code null})
     */
    public List getInstructions() {
        List instructions = this.instructions;
        if (instructions == null) {
            throw new IllegalStateException("Scheduling is not yet complete");
        }
        return instructions;
    }

    public void setInstructions(List instructions) {
        // only call from scheduler...
        this.instructions = instructions;
    }

    /**
     * Get the block parameter for the given slot, if any.
     *
     * @param slot the slot (must not be {@code null})
     * @return the block parameter, or {@code null} if there is none for {@code slot} or there is but it was never used
     */
    public BlockParameter getBlockParameter(Slot slot) {
        Map usedParameters = this.usedParameters;
        if (usedParameters == null) {
            throw new IllegalStateException("Scheduling is not yet complete");
        }
        return usedParameters.get(slot);
    }

    public Set getUsedParameterSlots() {
        Map usedParameters = this.usedParameters;
        if (usedParameters == null) {
            throw new IllegalStateException("Scheduling is not yet complete");
        }
        return usedParameters.keySet();
    }

    public void setUsedParameters(Map usedParameters) {
        // only call from scheduler...
        this.usedParameters = usedParameters;
    }

    /**
     * Get the set of loops that this block is a part of.
     *
     * @return the set of loops that this block is a part of
     */
    public Set getLoops() {
        return loops;
    }

    void setLoops(Set loops) {
        this.loops = loops;
    }

    public boolean isReachable() {
        return reachable;
    }

    public boolean setReachableFrom(BasicBlock from) {
        if (from != null && ! incoming.contains(from)) {
            if (incoming.isEmpty()) {
                incoming = Set.of(from);
            } else if (incoming.size() == 1) {
                incoming = Set.of(from, incoming.iterator().next());
            } else if (incoming.size() == 2) {
                Set old = this.incoming;
                incoming = new LinkedHashSet<>();
                incoming.addAll(old);
                incoming.add(from);
            } else {
                incoming.add(from);
            }
        }
        boolean old = this.reachable;
        if (old) {
            return false;
        }
        this.reachable = true;
        return true;
    }

    public Set getIncoming() {
        return incoming;
    }

    public boolean isSucceededBy(final BasicBlock block) {
        int cnt = terminator.getSuccessorCount();
        for (int i = 0; i < cnt; i ++) {
            if (block.equals(terminator.getSuccessor(i))) {
                return true;
            }
        }
        return false;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }

    /**
     * Get the set of reference-typed values that must be alive when this block exits.
     *
     * @return the (possibly empty) set of live values
     */
    public Set getLiveOuts() {
        return liveOuts;
    }

    /**
     * For use by the scheduler.
     *
     * @param liveOuts the live outs to add
     */
    public void setLiveOuts(Set liveOuts) {
        this.liveOuts = liveOuts;
    }

    public StringBuilder toString(StringBuilder b) {
        return b.append("bb").append(index);
    }

    @Override
    public String toString() {
        return toString(new StringBuilder()).toString();
    }

    public static final class Loop {
        private final BasicBlock startBlock;
        private final BasicBlock endBlock;

        public Loop(BasicBlock startBlock, BasicBlock endBlock) {
            this.startBlock = Assert.checkNotNullParam("startBlock", startBlock);
            this.endBlock = Assert.checkNotNullParam("endBlock", endBlock);
        }

        public BasicBlock getStartBlock() {
            return startBlock;
        }

        public BasicBlock getEndBlock() {
            return endBlock;
        }

        @Override
        public int hashCode() {
            return Objects.hash(startBlock, endBlock);
        }

        @Override
        public boolean equals(Object obj) {
            return obj instanceof Loop && equals((Loop) obj);
        }

        public boolean equals(Loop obj) {
            return this == obj || obj != null && startBlock == obj.startBlock && endBlock == obj.endBlock;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy