use of org.robovm.compiler.llvm.GlobalRef in project robovm by robovm.
the class MethodCompiler method assign.
private void assign(DefinitionStmt stmt) {
/*
* leftOp is either a Local, an ArrayRef or a FieldRef
* rightOp is either a Local, a Ref, or an Expr
*/
soot.Value rightOp = stmt.getRightOp();
Value result;
if (rightOp instanceof Immediate) {
Immediate immediate = (Immediate) rightOp;
result = immediate(stmt, immediate);
} else if (rightOp instanceof ThisRef) {
result = function.getParameterRef(1);
} else if (rightOp instanceof ParameterRef) {
ParameterRef ref = (ParameterRef) rightOp;
int index = (sootMethod.isStatic() ? 1 : 2) + ref.getIndex();
Value p = new VariableRef("p" + index, getType(ref.getType()));
result = widenToI32Value(stmt, p, isUnsigned(ref.getType()));
} else if (rightOp instanceof CaughtExceptionRef) {
result = call(stmt, BC_EXCEPTION_CLEAR, env);
} else if (rightOp instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) rightOp;
VariableRef base = (VariableRef) immediate(stmt, (Immediate) ref.getBase());
if (ref.getType() instanceof NullType) {
// The base value is always null. Do a null check which will
// always throw NPE.
checkNull(stmt, base);
return;
} else {
Value index = immediate(stmt, (Immediate) ref.getIndex());
checkNull(stmt, base);
checkBounds(stmt, base, index);
result = call(stmt, getArrayLoad(ref.getType()), base, index);
result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
}
} else if (rightOp instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) rightOp;
Value base = immediate(stmt, (Immediate) ref.getBase());
checkNull(stmt, base);
FunctionRef fn = null;
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.getterSymbol(ref.getFieldRef()), new FunctionType(getType(ref.getType()), ENV_PTR, OBJECT_PTR));
} else {
soot.Type runtimeType = ref.getBase().getType();
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
Trampoline trampoline = new GetField(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
result = call(stmt, fn, env, base);
result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
} else if (rightOp instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) rightOp;
FunctionRef fn = config.isDebug() ? null : Intrinsics.getIntrinsic(sootMethod, stmt);
if (fn == null) {
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.getterSymbol(ref.getFieldRef()), new FunctionType(getType(ref.getType()), ENV_PTR));
} else {
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
Trampoline trampoline = new GetStatic(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
}
result = call(stmt, fn, env);
result = widenToI32Value(stmt, result, isUnsigned(ref.getType()));
} else if (rightOp instanceof Expr) {
if (rightOp instanceof BinopExpr) {
BinopExpr expr = (BinopExpr) rightOp;
Type rightType = getLocalType(expr.getType());
Variable resultVar = function.newVariable(rightType);
result = resultVar.ref();
Value op1 = immediate(stmt, (Immediate) expr.getOp1());
Value op2 = immediate(stmt, (Immediate) expr.getOp2());
if (rightOp instanceof AddExpr) {
if (rightType instanceof IntegerType) {
function.add(new Add(resultVar, op1, op2)).attach(stmt);
} else {
function.add(new Fadd(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof AndExpr) {
function.add(new And(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof CmpExpr) {
Variable t1 = function.newVariable(I1);
Variable t2 = function.newVariable(I1);
Variable t3 = function.newVariable(resultVar.getType());
Variable t4 = function.newVariable(resultVar.getType());
function.add(new Icmp(t1, Condition.slt, op1, op2)).attach(stmt);
function.add(new Icmp(t2, Condition.sgt, op1, op2)).attach(stmt);
function.add(new Zext(t3, new VariableRef(t1), resultVar.getType())).attach(stmt);
function.add(new Zext(t4, new VariableRef(t2), resultVar.getType())).attach(stmt);
function.add(new Sub(resultVar, new VariableRef(t4), new VariableRef(t3))).attach(stmt);
} else if (rightOp instanceof DivExpr) {
if (rightType instanceof IntegerType) {
FunctionRef f = rightType == I64 ? LDIV : IDIV;
result = call(stmt, f, env, op1, op2);
} else {
// float or double
function.add(new Fdiv(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof MulExpr) {
if (rightType instanceof IntegerType) {
function.add(new Mul(resultVar, op1, op2)).attach(stmt);
} else {
function.add(new Fmul(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof OrExpr) {
function.add(new Or(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof RemExpr) {
if (rightType instanceof IntegerType) {
FunctionRef f = rightType == I64 ? LREM : IREM;
result = call(stmt, f, env, op1, op2);
} else {
FunctionRef f = rightType == DOUBLE ? DREM : FREM;
result = call(stmt, f, env, op1, op2);
}
} else if (rightOp instanceof ShlExpr || rightOp instanceof ShrExpr || rightOp instanceof UshrExpr) {
IntegerType type = (IntegerType) op1.getType();
int bits = type.getBits();
Variable t = function.newVariable(op2.getType());
function.add(new And(t, op2, new IntegerConstant(bits - 1, (IntegerType) op2.getType()))).attach(stmt);
Value shift = t.ref();
if (((IntegerType) shift.getType()).getBits() < bits) {
Variable tmp = function.newVariable(type);
function.add(new Zext(tmp, shift, type)).attach(stmt);
shift = tmp.ref();
}
if (rightOp instanceof ShlExpr) {
function.add(new Shl(resultVar, op1, shift)).attach(stmt);
} else if (rightOp instanceof ShrExpr) {
function.add(new Ashr(resultVar, op1, shift)).attach(stmt);
} else {
function.add(new Lshr(resultVar, op1, shift)).attach(stmt);
}
} else if (rightOp instanceof SubExpr) {
if (rightType instanceof IntegerType) {
function.add(new Sub(resultVar, op1, op2)).attach(stmt);
} else {
function.add(new Fsub(resultVar, op1, op2)).attach(stmt);
}
} else if (rightOp instanceof XorExpr) {
function.add(new Xor(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof XorExpr) {
function.add(new Xor(resultVar, op1, op2)).attach(stmt);
} else if (rightOp instanceof CmplExpr) {
FunctionRef f = op1.getType() == FLOAT ? FCMPL : DCMPL;
function.add(new Call(resultVar, f, op1, op2)).attach(stmt);
} else if (rightOp instanceof CmpgExpr) {
FunctionRef f = op1.getType() == FLOAT ? FCMPG : DCMPG;
function.add(new Call(resultVar, f, op1, op2)).attach(stmt);
} else {
throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
}
} else if (rightOp instanceof CastExpr) {
Value op = immediate(stmt, (Immediate) ((CastExpr) rightOp).getOp());
soot.Type sootTargetType = ((CastExpr) rightOp).getCastType();
soot.Type sootSourceType = ((CastExpr) rightOp).getOp().getType();
if (sootTargetType instanceof PrimType) {
Type targetType = getType(sootTargetType);
Type sourceType = getType(sootSourceType);
if (targetType instanceof IntegerType && sourceType instanceof IntegerType) {
// op is at least I32 and has already been widened if source type had fewer bits then I32
IntegerType toType = (IntegerType) targetType;
IntegerType fromType = (IntegerType) op.getType();
Variable v = function.newVariable(toType);
if (fromType.getBits() < toType.getBits()) {
// Widening
if (isUnsigned(sootSourceType)) {
function.add(new Zext(v, op, toType)).attach(stmt);
} else {
function.add(new Sext(v, op, toType)).attach(stmt);
}
} else if (fromType.getBits() == toType.getBits()) {
function.add(new Bitcast(v, op, toType)).attach(stmt);
} else {
// Narrow
function.add(new Trunc(v, op, toType)).attach(stmt);
}
result = widenToI32Value(stmt, v.ref(), isUnsigned(sootTargetType));
} else if (targetType instanceof FloatingPointType && sourceType instanceof IntegerType) {
// we always to a signed conversion since if op is char it has already been zero extended to I32
Variable v = function.newVariable(targetType);
function.add(new Sitofp(v, op, targetType)).attach(stmt);
result = v.ref();
} else if (targetType instanceof FloatingPointType && sourceType instanceof FloatingPointType) {
Variable v = function.newVariable(targetType);
if (targetType == FLOAT && sourceType == DOUBLE) {
function.add(new Fptrunc(v, op, targetType)).attach(stmt);
} else if (targetType == DOUBLE && sourceType == FLOAT) {
function.add(new Fpext(v, op, targetType)).attach(stmt);
} else {
function.add(new Bitcast(v, op, targetType)).attach(stmt);
}
result = v.ref();
} else {
// F2I, F2L, D2I, D2L
FunctionRef f = null;
if (targetType == I32 && sourceType == FLOAT) {
f = F2I;
} else if (targetType == I64 && sourceType == FLOAT) {
f = F2L;
} else if (targetType == I32 && sourceType == DOUBLE) {
f = D2I;
} else if (targetType == I64 && sourceType == DOUBLE) {
f = D2L;
} else {
throw new IllegalArgumentException();
}
Variable v = function.newVariable(targetType);
function.add(new Call(v, f, op)).attach(stmt);
result = v.ref();
}
} else {
if (sootTargetType instanceof soot.ArrayType && ((soot.ArrayType) sootTargetType).getElementType() instanceof PrimType) {
soot.Type primType = ((soot.ArrayType) sootTargetType).getElementType();
GlobalRef arrayClassPtr = new GlobalRef("array_" + getDescriptor(primType), CLASS_PTR);
Variable arrayClass = function.newVariable(CLASS_PTR);
function.add(new Load(arrayClass, arrayClassPtr)).attach(stmt);
result = call(stmt, CHECKCAST_PRIM_ARRAY, env, arrayClass.ref(), op);
} else {
String targetClassName = getInternalName(sootTargetType);
Trampoline trampoline = new Checkcast(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, op);
}
}
} else if (rightOp instanceof InstanceOfExpr) {
Value op = immediate(stmt, (Immediate) ((InstanceOfExpr) rightOp).getOp());
soot.Type checkType = ((InstanceOfExpr) rightOp).getCheckType();
if (checkType instanceof soot.ArrayType && ((soot.ArrayType) checkType).getElementType() instanceof PrimType) {
soot.Type primType = ((soot.ArrayType) checkType).getElementType();
GlobalRef arrayClassPtr = new GlobalRef("array_" + getDescriptor(primType), CLASS_PTR);
Variable arrayClass = function.newVariable(CLASS_PTR);
function.add(new Load(arrayClass, arrayClassPtr)).attach(stmt);
result = call(stmt, INSTANCEOF_PRIM_ARRAY, env, arrayClass.ref(), op);
} else {
String targetClassName = getInternalName(checkType);
Trampoline trampoline = new Instanceof(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, op);
}
} else if (rightOp instanceof NewExpr) {
String targetClassName = getInternalName(((NewExpr) rightOp).getBaseType());
FunctionRef fn = null;
if (targetClassName.equals(this.className)) {
fn = FunctionBuilder.allocator(sootMethod.getDeclaringClass()).ref();
} else {
Trampoline trampoline = new New(this.className, targetClassName);
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
result = call(stmt, fn, env);
} else if (rightOp instanceof NewArrayExpr) {
NewArrayExpr expr = (NewArrayExpr) rightOp;
Value size = immediate(stmt, (Immediate) expr.getSize());
if (expr.getBaseType() instanceof PrimType) {
result = call(stmt, getNewArray(expr.getBaseType()), env, size);
} else {
String targetClassName = getInternalName(expr.getType());
Trampoline trampoline = new Anewarray(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, size);
}
} else if (rightOp instanceof NewMultiArrayExpr) {
NewMultiArrayExpr expr = (NewMultiArrayExpr) rightOp;
if (expr.getBaseType().numDimensions == 1 && expr.getBaseType().getElementType() instanceof PrimType) {
Value size = immediate(stmt, (Immediate) expr.getSize(0));
result = call(stmt, getNewArray(expr.getBaseType().getElementType()), env, size);
} else {
for (int i = 0; i < expr.getSizeCount(); i++) {
Value size = immediate(stmt, (Immediate) expr.getSize(i));
Variable ptr = function.newVariable(new PointerType(I32));
function.add(new Getelementptr(ptr, dims.ref(), 0, i)).attach(stmt);
function.add(new Store(size, ptr.ref())).attach(stmt);
}
Variable dimsI32 = function.newVariable(new PointerType(I32));
function.add(new Bitcast(dimsI32, dims.ref(), dimsI32.getType())).attach(stmt);
String targetClassName = getInternalName(expr.getType());
Trampoline trampoline = new Multianewarray(this.className, targetClassName);
trampolines.add(trampoline);
result = call(stmt, trampoline.getFunctionRef(), env, new IntegerConstant(expr.getSizeCount()), dimsI32.ref());
}
} else if (rightOp instanceof InvokeExpr) {
result = invokeExpr(stmt, (InvokeExpr) rightOp);
} else if (rightOp instanceof LengthExpr) {
Value op = immediate(stmt, (Immediate) ((LengthExpr) rightOp).getOp());
checkNull(stmt, op);
Variable v = function.newVariable(I32);
function.add(new Call(v, ARRAY_LENGTH, op)).attach(stmt);
result = v.ref();
} else if (rightOp instanceof NegExpr) {
NegExpr expr = (NegExpr) rightOp;
Value op = immediate(stmt, (Immediate) expr.getOp());
Type rightType = op.getType();
Variable v = function.newVariable(op.getType());
if (rightType instanceof IntegerType) {
function.add(new Sub(v, new IntegerConstant(0, (IntegerType) rightType), op)).attach(stmt);
} else {
function.add(new Fmul(v, new FloatingPointConstant(-1.0, (FloatingPointType) rightType), op)).attach(stmt);
}
result = v.ref();
} else {
throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
}
} else {
throw new IllegalArgumentException("Unknown type for rightOp: " + rightOp.getClass());
}
soot.Value leftOp = stmt.getLeftOp();
if (leftOp instanceof Local) {
Local local = (Local) leftOp;
VariableRef v = new VariableRef(local.getName(), new PointerType(getLocalType(leftOp.getType())));
function.add(new Store(result, v, !sootMethod.getActiveBody().getTraps().isEmpty())).attach(stmt);
} else {
Type leftType = getType(leftOp.getType());
Value narrowedResult = narrowFromI32Value(stmt, leftType, result);
if (leftOp instanceof ArrayRef) {
ArrayRef ref = (ArrayRef) leftOp;
VariableRef base = (VariableRef) immediate(stmt, (Immediate) ref.getBase());
Value index = immediate(stmt, (Immediate) ref.getIndex());
checkNull(stmt, base);
checkBounds(stmt, base, index);
if (leftOp.getType() instanceof RefLikeType) {
call(stmt, BC_SET_OBJECT_ARRAY_ELEMENT, env, base, index, narrowedResult);
} else {
call(stmt, getArrayStore(leftOp.getType()), base, index, narrowedResult);
}
} else if (leftOp instanceof InstanceFieldRef) {
InstanceFieldRef ref = (InstanceFieldRef) leftOp;
Value base = immediate(stmt, (Immediate) ref.getBase());
checkNull(stmt, base);
FunctionRef fn = null;
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.setterSymbol(ref.getFieldRef()), new FunctionType(VOID, ENV_PTR, OBJECT_PTR, getType(ref.getType())));
} else {
soot.Type runtimeType = ref.getBase().getType();
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
Trampoline trampoline = new PutField(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()), runtimeClassName);
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
call(stmt, fn, env, base, narrowedResult);
} else if (leftOp instanceof StaticFieldRef) {
StaticFieldRef ref = (StaticFieldRef) leftOp;
FunctionRef fn = null;
if (canAccessDirectly(ref)) {
fn = new FunctionRef(Symbols.setterSymbol(ref.getFieldRef()), new FunctionType(VOID, ENV_PTR, getType(ref.getType())));
} else {
String targetClassName = getInternalName(ref.getFieldRef().declaringClass());
Trampoline trampoline = new PutStatic(this.className, targetClassName, ref.getFieldRef().name(), getDescriptor(ref.getFieldRef().type()));
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
call(stmt, fn, env, narrowedResult);
} else {
throw new IllegalArgumentException("Unknown type for leftOp: " + leftOp.getClass());
}
}
}
use of org.robovm.compiler.llvm.GlobalRef in project robovm by robovm.
the class MethodCompiler method immediate.
private Value immediate(Unit unit, Immediate v) {
// v is either a soot.Local or a soot.jimple.Constant
if (v instanceof soot.Local) {
Local local = (Local) v;
Type type = getLocalType(v.getType());
VariableRef var = new VariableRef(local.getName(), new PointerType(type));
Variable tmp = function.newVariable(type);
function.add(new Load(tmp, var, !sootMethod.getActiveBody().getTraps().isEmpty())).attach(unit);
return new VariableRef(tmp);
} else if (v instanceof soot.jimple.IntConstant) {
return new IntegerConstant(((soot.jimple.IntConstant) v).value);
} else if (v instanceof soot.jimple.LongConstant) {
return new IntegerConstant(((soot.jimple.LongConstant) v).value);
} else if (v instanceof soot.jimple.FloatConstant) {
return new FloatingPointConstant(((soot.jimple.FloatConstant) v).value);
} else if (v instanceof soot.jimple.DoubleConstant) {
return new FloatingPointConstant(((soot.jimple.DoubleConstant) v).value);
} else if (v instanceof soot.jimple.NullConstant) {
return new NullConstant(OBJECT_PTR);
} else if (v instanceof soot.jimple.StringConstant) {
String s = ((soot.jimple.StringConstant) v).value;
return call(unit, ldcString(s), env);
} else if (v instanceof soot.jimple.ClassConstant) {
// ClassConstant is either the internal name of a class or the descriptor of an array
String targetClassName = ((soot.jimple.ClassConstant) v).getValue();
if (isArray(targetClassName) && isPrimitiveComponentType(targetClassName)) {
String primitiveDesc = targetClassName.substring(1);
Variable result = function.newVariable(OBJECT_PTR);
function.add(new Load(result, new ConstantBitcast(new GlobalRef("array_" + primitiveDesc, CLASS_PTR), new PointerType(OBJECT_PTR)))).attach(unit);
return result.ref();
} else {
FunctionRef fn = null;
if (targetClassName.equals(this.className)) {
fn = FunctionBuilder.ldcInternal(sootMethod.getDeclaringClass()).ref();
} else {
Trampoline trampoline = new LdcClass(className, ((soot.jimple.ClassConstant) v).getValue());
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
return call(unit, fn, env);
}
}
throw new IllegalArgumentException("Unknown Immediate type: " + v.getClass());
}
use of org.robovm.compiler.llvm.GlobalRef in project robovm by robovm.
the class BroMethodCompiler method ldcClass.
protected Value ldcClass(Function fn, String name, Value env) {
if (isArray(name) && isPrimitiveBaseType(name)) {
String primitiveDesc = name.substring(name.length() - 1);
Variable result = fn.newVariable(OBJECT_PTR);
fn.add(new Load(result, new ConstantBitcast(new GlobalRef("array_" + primitiveDesc, CLASS_PTR), new PointerType(OBJECT_PTR))));
return result.ref();
} else {
FunctionRef ldcClassFn = null;
if (name.equals(this.className)) {
ldcClassFn = FunctionBuilder.ldcInternal(this.className).ref();
} else {
Trampoline trampoline = new LdcClass(this.className, name);
trampolines.add(trampoline);
ldcClassFn = trampoline.getFunctionRef();
}
return call(fn, ldcClassFn, env);
}
}
use of org.robovm.compiler.llvm.GlobalRef in project robovm by robovm.
the class ModuleBuilder method getString.
public Constant getString(String string) {
Global g = strings.get(string);
if (g == null) {
byte[] modUtf8 = stringToModifiedUtf8Z(string);
g = new Global(getStringVarName(modUtf8), Linkage.weak, new StringConstant(modUtf8), true);
addGlobal(g);
strings.put(string, g);
}
return new ConstantGetelementptr(new GlobalRef(g), 0, 0);
}
use of org.robovm.compiler.llvm.GlobalRef in project robovm by robovm.
the class ClassCompiler method createClassInfoStruct.
private StructureConstant createClassInfoStruct() {
int flags = 0;
if (Modifier.isPublic(sootClass.getModifiers())) {
flags |= CI_PUBLIC;
}
if (Modifier.isFinal(sootClass.getModifiers())) {
flags |= CI_FINAL;
}
if (Modifier.isInterface(sootClass.getModifiers())) {
flags |= CI_INTERFACE;
}
if (Modifier.isAbstract(sootClass.getModifiers())) {
flags |= CI_ABSTRACT;
}
if ((sootClass.getModifiers() & 0x1000) > 0) {
flags |= CI_SYNTHETIC;
}
if (Modifier.isAnnotation(sootClass.getModifiers())) {
flags |= CI_ANNOTATION;
}
if (Modifier.isEnum(sootClass.getModifiers())) {
flags |= CI_ENUM;
}
if (attributesEncoder.classHasAttributes()) {
flags |= CI_ATTRIBUTES;
}
if (hasFinalizer(sootClass)) {
flags |= CI_FINALIZABLE;
}
// Create the ClassInfoHeader structure.
StructureConstantBuilder header = new StructureConstantBuilder();
// Points to the runtime Class struct
header.add(new NullConstant(I8_PTR));
header.add(new IntegerConstant(flags));
header.add(getString(getInternalName(sootClass)));
if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) {
SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v());
header.add(new FunctionRef(Symbols.methodSymbol(method), getFunctionType(method)));
} else {
header.add(new NullConstant(I8_PTR));
}
mb.addGlobal(new Global(Symbols.typeInfoSymbol(getInternalName(sootClass)), Linkage.external, I8_PTR, true));
// TypeInfo* generated by Linker
header.add(new GlobalRef(Symbols.typeInfoSymbol(getInternalName(sootClass)), I8_PTR));
if (!sootClass.isInterface()) {
header.add(createVTableStruct());
} else {
header.add(createITableStruct());
}
header.add(createITablesStruct());
header.add(sizeof(classType));
header.add(sizeof(instanceType));
if (!instanceFields.isEmpty()) {
header.add(offsetof(instanceType, 1, 1));
} else {
header.add(sizeof(instanceType));
}
header.add(new IntegerConstant((short) countReferences(classFields)));
header.add(new IntegerConstant((short) countReferences(instanceFields)));
PackedStructureConstantBuilder body = new PackedStructureConstantBuilder();
body.add(new IntegerConstant((short) sootClass.getInterfaceCount()));
body.add(new IntegerConstant((short) sootClass.getFieldCount()));
body.add(new IntegerConstant((short) sootClass.getMethodCount()));
if (!sootClass.isInterface()) {
body.add(getStringOrNull(sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null));
}
if (attributesEncoder.classHasAttributes()) {
body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR));
}
for (SootClass s : sootClass.getInterfaces()) {
body.add(getString(getInternalName(s)));
}
for (SootField f : sootClass.getFields()) {
flags = 0;
soot.Type t = f.getType();
if (t instanceof PrimType) {
if (t.equals(BooleanType.v())) {
flags |= DESC_Z;
} else if (t.equals(ByteType.v())) {
flags |= DESC_B;
} else if (t.equals(ShortType.v())) {
flags |= DESC_S;
} else if (t.equals(CharType.v())) {
flags |= DESC_C;
} else if (t.equals(IntType.v())) {
flags |= DESC_I;
} else if (t.equals(LongType.v())) {
flags |= DESC_J;
} else if (t.equals(FloatType.v())) {
flags |= DESC_F;
} else if (t.equals(DoubleType.v())) {
flags |= DESC_D;
}
flags <<= 12;
}
if (Modifier.isPublic(f.getModifiers())) {
flags |= FI_PUBLIC;
} else if (Modifier.isPrivate(f.getModifiers())) {
flags |= FI_PRIVATE;
} else if (Modifier.isProtected(f.getModifiers())) {
flags |= FI_PROTECTED;
}
if (Modifier.isStatic(f.getModifiers())) {
flags |= FI_STATIC;
}
if (Modifier.isFinal(f.getModifiers())) {
flags |= FI_FINAL;
}
if (Modifier.isVolatile(f.getModifiers())) {
flags |= FI_VOLATILE;
}
if (Modifier.isTransient(f.getModifiers())) {
flags |= FI_TRANSIENT;
}
if ((f.getModifiers() & 0x1000) > 0) {
flags |= FI_SYNTHETIC;
}
if (Modifier.isEnum(f.getModifiers())) {
flags |= FI_ENUM;
}
if (attributesEncoder.fieldHasAttributes(f)) {
flags |= FI_ATTRIBUTES;
}
body.add(new IntegerConstant((short) flags));
body.add(getString(f.getName()));
if (!(t instanceof PrimType)) {
body.add(getString(getDescriptor(f)));
}
if (f.isStatic()) {
int index = classFields.indexOf(f);
body.add(offsetof(classType, 1, index, 1));
} else {
int index = instanceFields.indexOf(f);
body.add(offsetof(instanceType, 1, 1 + index, 1));
}
if (attributesEncoder.fieldHasAttributes(f)) {
body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR));
}
}
VTable vtable = !sootClass.isInterface() ? config.getVTableCache().get(sootClass) : null;
ITable itable = sootClass.isInterface() ? config.getITableCache().get(sootClass) : null;
;
for (SootMethod m : sootClass.getMethods()) {
soot.Type t = m.getReturnType();
flags = 0;
if (Modifier.isPublic(m.getModifiers())) {
flags |= MI_PUBLIC;
} else if (Modifier.isPrivate(m.getModifiers())) {
flags |= MI_PRIVATE;
} else if (Modifier.isProtected(m.getModifiers())) {
flags |= MI_PROTECTED;
}
if (Modifier.isStatic(m.getModifiers())) {
flags |= MI_STATIC;
}
if (Modifier.isFinal(m.getModifiers())) {
flags |= MI_FINAL;
}
if (Modifier.isSynchronized(m.getModifiers())) {
flags |= MI_SYNCHRONIZED;
}
if ((m.getModifiers() & 0x0040) > 0) {
flags |= MI_BRIDGE;
}
if ((m.getModifiers() & 0x0080) > 0) {
flags |= MI_VARARGS;
}
if (Modifier.isNative(m.getModifiers())) {
if (!isStruct(sootClass) && !hasStructMemberAnnotation(m)) {
flags |= MI_NATIVE;
}
}
if (Modifier.isAbstract(m.getModifiers())) {
flags |= MI_ABSTRACT;
}
if (Modifier.isStrictFP(m.getModifiers())) {
flags |= MI_STRICT;
}
if ((m.getModifiers() & 0x1000) > 0) {
flags |= MI_SYNTHETIC;
}
if (attributesEncoder.methodHasAttributes(m)) {
flags |= MI_ATTRIBUTES;
}
if (hasBridgeAnnotation(m) || hasGlobalValueAnnotation(m)) {
flags |= MI_BRO_BRIDGE;
}
if (hasCallbackAnnotation(m)) {
flags |= MI_BRO_CALLBACK;
}
if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) {
flags |= MI_COMPACT_DESC;
}
body.add(new IntegerConstant((short) flags));
Constant viTableIndex = new IntegerConstant((short) -1);
if (vtable != null) {
VTable.Entry entry = vtable.getEntry(m);
if (entry != null) {
viTableIndex = new IntegerConstant((short) entry.getIndex());
}
} else {
ITable.Entry entry = itable.getEntry(m);
if (entry != null) {
viTableIndex = new IntegerConstant((short) entry.getIndex());
}
}
body.add(viTableIndex);
body.add(getString(m.getName()));
if ((flags & MI_COMPACT_DESC) > 0) {
int desc = 0;
if (t.equals(BooleanType.v())) {
desc = DESC_Z;
} else if (t.equals(ByteType.v())) {
desc = DESC_B;
} else if (t.equals(ShortType.v())) {
desc = DESC_S;
} else if (t.equals(CharType.v())) {
desc = DESC_C;
} else if (t.equals(IntType.v())) {
desc = DESC_I;
} else if (t.equals(LongType.v())) {
desc = DESC_J;
} else if (t.equals(FloatType.v())) {
desc = DESC_F;
} else if (t.equals(DoubleType.v())) {
desc = DESC_D;
} else if (t.equals(VoidType.v())) {
desc = DESC_V;
}
body.add(new IntegerConstant((byte) desc));
} else {
body.add(getString(getDescriptor(m)));
}
if (attributesEncoder.methodHasAttributes(m)) {
body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR));
}
if (!m.isAbstract()) {
body.add(new ConstantBitcast(new FunctionRef(Symbols.methodSymbol(m), getFunctionType(m)), I8_PTR));
// Size of function. This value will be modified later by patching the .s file.
body.add(new IntegerConstant(DUMMY_METHOD_SIZE));
if (m.isSynchronized()) {
body.add(new ConstantBitcast(new FunctionRef(Symbols.synchronizedWrapperSymbol(m), getFunctionType(m)), I8_PTR));
}
if ((flags & MI_NATIVE) == 0) {
// Cannot use m.isNative() in the condition above since methods which are native in the
// Java class file may have been changed to non-native by the RoboVM compiler
// (e.g. @StructMember methods). The native code which parses the info structs will see
// the method as non-native.
// Add a weak linetable pointer which points to a -1 value which will be interpreted as 0 linenumbers in the table
Global linetableGlobal = new Global(Symbols.linetableSymbol(m), Linkage.weak, new IntegerConstant(-1));
mb.addGlobal(linetableGlobal);
body.add(linetableGlobal.ref());
}
}
if (hasBridgeAnnotation(m)) {
if (!readBooleanElem(getAnnotation(m, BRIDGE), "dynamic", false)) {
body.add(new GlobalRef(Symbols.bridgePtrSymbol(m), I8_PTR));
} else {
body.add(new NullConstant(I8_PTR));
}
} else if (hasGlobalValueAnnotation(m)) {
body.add(new GlobalRef(Symbols.globalValuePtrSymbol(m), I8_PTR));
}
if (hasCallbackAnnotation(m)) {
body.add(new AliasRef(Symbols.callbackPtrSymbol(m), I8_PTR));
}
}
// after sizeof(ClassInfoHeader) bytes.
return new StructureConstantBuilder().add(header.build()).add(body.build()).build();
}
Aggregations