view graal/com.oracle.max.asmdis/src/com/sun/max/asm/Label.java @ 4142:bc8527f3071c

Adjust code base to new level of warnings.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Sun, 18 Dec 2011 05:24:06 +0100
parents e233f5660da4
children
line wrap: on
line source

/*
 * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.max.asm;

import com.sun.max.program.*;

/**
 * Assembler labels for symbolic addressing.
 *
 * This class provides combined functionality for both 32-bit and 64-bit address spaces.
 * The respective assembler narrows the usable interface to either.
 *
 * @see Assembler32
 * @see Assembler64
 */
public final class Label implements Argument {

    public enum State {
        UNASSIGNED, BOUND, FIXED_32, FIXED_64;
    }

    protected State state = State.UNASSIGNED;

    public static Label createBoundLabel(int position) {
        final Label label = new Label();
        label.bind(position);
        return label;
    }

    public Label() {
    }

    public State state() {
        return state;
    }

    private int position;

    /**
     * Must only be called when the label is bound!
     */
    public int position() throws AssemblyException {
        if (state != State.BOUND) {
            throw new AssemblyException("unassigned or unbound label");
        }
        return position;
    }

    /**
     * Binds this label to a position in the assembler's instruction stream that represents the start of an instruction.
     * The assembler may update the position if any emitted instructions change lengths, so that this label keeps
     * denoting the same logical instruction.
     *
     * Only to be called by {@link Assembler#bindLabel(Label)}.
     *
     * @param pos
     *            an instruction's position in the assembler's instruction stream
     *
     * @see Assembler#bindLabel(Label)
     */
    void bind(int pos) {
        this.position = pos;
        state = State.BOUND;
    }

    void adjust(int delta) {
        assert state == State.BOUND;
        position += delta;
    }

    private int address32;
    private long address64;

    /**
     * Assigns a fixed, absolute 32-bit address to this label.
     * If used in a 64-bit assembler,
     * the effective address value would be unsigned-extended.
     *
     * @param address an absolute memory location
     *
     * @see Assembler#bindLabel(Label)
     */
    void fix32(int addr32) {
        this.address32 = addr32;
        state = State.FIXED_32;
    }

    /**
     * Assigns a fixed, absolute 64-bit address to this label.
     *
     * @param address an absolute memory location
     *
     * @see Assembler#bindLabel(Label)
     */
    void fix64(long addr64) {
        this.address64 = addr64;
        state = State.FIXED_64;
    }

    /**
     * Must only be called if this label has been {@link #fix32 fixed}.
     */
    public int address32() throws AssemblyException {
        switch (state) {
            case FIXED_32: {
                return address32;
            }
            case FIXED_64: {
                throw ProgramError.unexpected("64-bit address in 32-bit assembler");
            }
            default: {
                throw new AssemblyException("unassigned or unfixed label");
            }
        }
    }

    /**
     * Must only be called if this label has been {@link #fix64 fixed}.
     */
    public long address64() throws AssemblyException {
        switch (state) {
            case FIXED_64: {
                return address64;
            }
            case FIXED_32: {
                throw ProgramError.unexpected("32-bit address in 64-bit assembler");
            }
            default: {
                throw new AssemblyException("unassigned or unfixed label");
            }
        }
    }

    public String externalValue() {
        throw ProgramError.unexpected();
    }

    public String disassembledValue() {
        throw ProgramError.unexpected();
    }

    public long asLong() {
        throw ProgramError.unexpected("unimplemented");
    }

    @Override
    public boolean equals(Object other) {
        if (other instanceof Label) {
            final Label label = (Label) other;
            if (state != label.state) {
                return false;
            }
            switch (state) {
                case UNASSIGNED:
                    return this == label;
                case BOUND:
                    return position == label.position;
                case FIXED_32:
                    return address32 == label.address32;
                case FIXED_64:
                    return address64 == label.address64;
                default:
                    throw ProgramError.unexpected();
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        switch (state) {
            case BOUND:
                return position;
            case FIXED_32:
                return address32;
            case FIXED_64:
                return (int) (address64 ^ (address64 >> 32));
            default:
                return super.hashCode();
        }
    }

    @Override
    public String toString() {
        switch (state) {
            case UNASSIGNED:
                return "<unassigned>";
            case BOUND:
                return position >= 0 ? "+" + position : String.valueOf(position);
            case FIXED_32:
                return String.valueOf(address32);
            case FIXED_64:
                return String.valueOf(address64);
            default:
                throw ProgramError.unexpected();
        }
    }
}