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

org.robovm.compiler.llvm.DataLayout Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2013 RoboVM AB
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.robovm.compiler.llvm;

import org.robovm.llvm.Context;
import org.robovm.llvm.Module;
import org.robovm.llvm.Target;
import org.robovm.llvm.TargetMachine;

/**
 *
 * @version $Id$
 */
public class DataLayout {
    
    private final String triple;
    private final Target target;
    
    public DataLayout(String triple) {
        this.triple = triple;
        this.target = Target.lookupTarget(triple);
    }
    
    private  T runTypeQuery(Type type, TypeCallback cb) {
        Context context = null;
        Module module = null;
        TargetMachine targetMachine = null;
        try {
            String definition;
            if (type instanceof PrimitiveType) {
                definition = "{" + ((PrimitiveType) type).getName() + "}";
            } else if (type instanceof VectorStructureType) {
                // if it is vector of primitive (E.g. VectorFloat2) it will return
                // <2 x float> like definition  and it will not go to
                // LLVM types that will cause a crash later, so wrap it into struct
                // And if it is vector of another structs (E.g. MatrixFloat2x2) it
                // will be wrapped into struct and nothing to be done
                VectorStructureType st = (VectorStructureType) type;
                if (!st.isVectorArray())
                    definition = "{" + ((StructureType) type).getDefinition() + "}";
                else
                    definition = ((StructureType) type).getDefinition();
            } else if (type instanceof StructureType) {
                definition = ((StructureType) type).getDefinition();
            } else {
                definition = "{" + ((UserType) type).getDefinition() + "}";
            }
            context = new Context();
            module = Module.parseIR(context, "%t = type " + definition, null);
            targetMachine = target.createTargetMachine(triple);
            return cb.doWithType(targetMachine, module.getTypeByName("t"));
        } finally {
            if (targetMachine != null) {
                targetMachine.dispose();
            }
            if (module != null) {
                module.dispose();
            }
            if (context != null) {
                context.dispose();
            }
        }
    }
    
    public int getAllocSize(Type type) {
        return runTypeQuery(type, new TypeCallback() {
            Integer doWithType(TargetMachine targetMachine, org.robovm.llvm.Type type) {
                return (int) targetMachine.getDataLayout().getTypeAllocSize(type);
            }
        });
    }

    public int getAlignment(Type type) {
        return runTypeQuery(type, new TypeCallback() {
            Integer doWithType(TargetMachine targetMachine, org.robovm.llvm.Type type) {
                return targetMachine.getDataLayout().getABITypeAlignment(type);
            }
        });
    }
    
    public int getStoreSize(Type type) {
        return runTypeQuery(type, new TypeCallback() {
            Integer doWithType(TargetMachine targetMachine, org.robovm.llvm.Type type) {
                return (int) targetMachine.getDataLayout().getTypeStoreSize(type);
            }
        });
    }

    public int getOffsetOfElement(StructureType type, int idx) {
        if (type instanceof VectorStructureType) {
            // special case handling for simple vector arrays like VectorFloat2 that has llvm signature as <2 x float>
            // wrapping it into {<2 x float>} will fail on getting offset at index 1+ as there is only one element in
            // the list
            if (type.getOwnMembersOffset() != 0)
                throw new IllegalArgumentException("Failed to process Vectorized struct. Probably it inherits another struct!");

            // in this case just get storage size and multiply
            return getStoreSize(type.getTypeAt(0)) * idx;
        } else {
            return runTypeQuery(type, new TypeCallback() {
                Integer doWithType(TargetMachine targetMachine, org.robovm.llvm.Type type) {
                    return (int) targetMachine.getDataLayout().getOffsetOfElement(type, idx);
                }
            });
        }
    }

    private static abstract class TypeCallback {
        abstract T doWithType(TargetMachine targetMachine, org.robovm.llvm.Type type);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy