diff options
Diffstat (limited to 'src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala')
-rw-r--r-- | src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala | 860 |
1 files changed, 0 insertions, 860 deletions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala deleted file mode 100644 index 413b08ddd8..0000000000 --- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala +++ /dev/null @@ -1,860 +0,0 @@ -/* - * System.Reflection.Emit-like API for writing .NET assemblies in MSIL - */ - - -package ch.epfl.lamp.compiler.msil.emit - -import java.io.File -import java.io.FileWriter -import java.io.BufferedWriter -import java.io.PrintWriter -import java.io.IOException -import java.util.Comparator - -import ch.epfl.lamp.compiler.msil._ -import ch.epfl.lamp.compiler.msil.util.Table - -/** - * The MSIL printer Visitor. It prints a complete - * assembly in a single or multiple files. Then this file can be compiled by ilasm. - * - * @author Nikolay Mihaylov - * @version 1.0 - */ -abstract class ILPrinterVisitor extends Visitor { - - import ILPrinterVisitor._ - import OpCode._ - - //########################################################################## - - protected final val assemblyNameComparator = - new scala.math.Ordering[Assembly]() { - override def compare(o1: Assembly, o2: Assembly): Int = { - val a1 = o1.asInstanceOf[Assembly] - val a2 = o2.asInstanceOf[Assembly] - return a1.GetName().Name.compareTo(a2.GetName().Name) - } - } - - // the output file writer - protected var out: PrintWriter = null - - // the left margin - private var lmargin = 0 - - // indicate a newline - private var newline = true - - // print types without or with members? - protected var nomembers: Boolean = false - - // external assemblies - protected var as: Array[Assembly] = null - - private def align() { - if (newline) - padding = lmargin - printPadding() - newline = false - } - private def indent() { - lmargin += TAB - } - private def undent() { - lmargin -= TAB - assert(lmargin >= 0) - } - - private var padding = 0 - private def pad(n: Int) { - assert(n >= 0, "negative padding: " + n) - padding += n - } - private def printPadding() { - if (padding <= 0) - return - while (padding > SPACES_LEN) { - out.print(SPACES) - padding -= SPACES_LEN - } - out.print(SPACES.substring(0, padding)) - padding = 0 - } - - // methods to print code - protected def print(s: String) { align(); out.print(s)} - protected def print(o: Object) { align(); out.print(o) } - protected def print(c: Char) { align(); out.print(c) } - protected def print(`val`: Int) { align(); out.print(`val`)} - protected def print(`val`: Long){ align(); out.print(`val`)} - protected def println() { out.println(); newline = true; padding = 0 } - protected def println(c: Char) { print(c); println() } - protected def println(i: Int) { print(i); println() } - protected def println(l: Long) { print(l); println() } - protected def println(s: String){ print(s); println() } - protected def println(o: Object){ print(o); println() } - protected def printName(name: String) { - val ch = name.charAt(0) - //if (Character.isLetter(ch) && Character.isLowerCase(ch)) { - if ((ch != '.') && (ch != '!')) { - print('\''); print(name); print('\'') - } else - print(name) - } - - protected def printAssemblyBoilerplate() { - // print all the external assemblies - for (j <- 0 until as.length) { - printAssemblySignature(as(j), true) - } - // print assembly declaration - printAssemblySignature(currAssembly, false) - } - - // the entrypoint method - protected var entryPoint: MethodInfo = null - - // current opcode argument - protected var argument: Object = null - - /***/ - @throws(classOf[IOException]) - protected def print(vAble: Visitable) { - if (vAble != null) - vAble.apply(this) - } - - /** - * Visit an AssemblyBuilder - */ - @throws(classOf[IOException]) - def caseAssemblyBuilder(assemblyBuilder: AssemblyBuilder) - - protected var currentModule: Module = null - /** - * Visit a ModuleBuilder - */ - @throws(classOf[IOException]) - def caseModuleBuilder(module: ModuleBuilder) - - protected var currentType: Type = null - - def printTypeParams(sortedTVars : Array[GenericParamAndConstraints]) { - - def constraintFlags(tVar : GenericParamAndConstraints) = { - val varianceDirective = (if (tVar.isCovariant) "+ " else (if (tVar.isContravariant) "- " else "")) - val typeKindDirective = (if (tVar.isReferenceType) "class " else (if (tVar.isValueType) "valuetype " else "")) - val dfltConstrDirective = (if (tVar.hasDefaultConstructor) ".ctor " else "") - varianceDirective + typeKindDirective + dfltConstrDirective - } - - def tparamName(tVar : GenericParamAndConstraints) = { - /* TODO Type-params in referenced assemblies may lack a name (those in a TypeBuilder or MethodBuilder shouldn't). - Given that we need not list (in ilasm syntax) the original type-params' names when - providing type arguments to it, the only type-param-names we'll serialize into a .msil file - are those for type-params in a TypeBuilder or MethodBuilder. Still, more details on this - appear in Sec. 4.5 "Faulty metadata in XMLReaderFactory" of - http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/Libs4Lib.pdf - - To avoid name clashes when choosing a param name, - first collect all existing tparam-names from a type (and its nested types). - Not that those names are needed (ordinal positions can be used instead) - but will look better when disassembling with ildasm. */ - assert(tVar.Name != null) - tVar.Name - } - - if(sortedTVars.length == 0) { return } - print('<') - val lastIdx = sortedTVars.length - 1 - for (it <- 0 until sortedTVars.length) { - val tVar = sortedTVars(it) - print(constraintFlags(tVar)) - if(tVar.Constraints.length > 0) { - print('(') - for (ic <- 0 until tVar.Constraints.length) { - val cnstrt = tVar.Constraints(ic) - printReference(cnstrt) - if (ic < lastIdx) { print(", ") } - } - print(')') - } - print(" " + tparamName(tVar)) - if (it < lastIdx) { print(", ") } - } - print('>') - } - - /** - * Visit a TypeBuilder - */ - @throws(classOf[IOException]) - def caseTypeBuilder(`type`: TypeBuilder) { - currentType = `type` - if (!`type`.Namespace.equals("") && `type`.DeclaringType == null) { - print(".namespace \'" ); print(`type`.Namespace); println("\'") - println("{"); indent() - } - print(".class ") - // <classHead> ::= - // <classAttr>* <id> - // [extends <typeReference>] - // [implements <typeReference> [, <typeReference>]*] - print(TypeAttributes.toString(`type`.Attributes)) - print(" \'"); print(`type`.Name); print("\'") - printTypeParams(`type`.getSortedTVars()) - if (`type`.BaseType() != null) { - println() - print(" extends ") - printReference(`type`.BaseType()) - } - val ifaces: Array[Type] = `type`.getInterfaces() - if (ifaces.length > 0) { - println() - print(" implements ") - for (i <- 0 until ifaces.length) { - if (i > 0) { - println(",") - print(" ") - } - printReference(ifaces(i)) - } - } - println() - println("{") - indent() - if (!nomembers && `type`.sourceFilename != null) - println(".line " + `type`.sourceLine - + " '" + `type`.sourceFilename + "'") - if (!nomembers) { - printAttributes(`type`) - } - // print nested classes - val nested = `type`.nestedTypeBuilders.iterator - while(nested.hasNext) - print(nested.next().asInstanceOf[TypeBuilder]) - - // print each field - val fields = `type`.fieldBuilders.iterator - while(fields.hasNext) - print(fields.next().asInstanceOf[FieldBuilder]) - - // print each constructor - val constrs = `type`.constructorBuilders.iterator - while (constrs.hasNext) - print(constrs.next().asInstanceOf[ConstructorBuilder]) - - // print each method - val methods = `type`.methodBuilders.iterator - while (methods.hasNext) { - val method = methods.next().asInstanceOf[MethodBuilder] - assert(method.DeclaringType == `type`) - print(method) - } - - undent(); println("}") - if (!`type`.Namespace.equals("") && `type`.DeclaringType == null) { - undent(); println("}") - } - currentType = null - } - - /** - * Visit a FieldBuilder - */ - @throws(classOf[IOException]) - def caseFieldBuilder(field: FieldBuilder) { - if (nomembers) return - // [[int32]] <fieldAttr>* <type> <id> [= <fieldInit> | at <dataLabel>] - print(".field ") - print(FieldAttributes.toString(field.Attributes)) - print(" "); printSignature(field.FieldType, field.cmods) - print(" \'"); print(field.Name); print("\'") - if (field.IsLiteral()) { - print(" = ") - val value = field.getValue() - if (value == null) { - print("nullref") - } else if (value.isInstanceOf[String]) { - print(msilString(value.asInstanceOf[String])) - } else if (value.isInstanceOf[Boolean]) { - print("bool (") - print(if((value.asInstanceOf[Boolean]).booleanValue()) { "true" } else { "false" }) - print(")") - } else if (value.isInstanceOf[Byte]) { - print("int8 (") - print(value) - print(")") - } else if (value.isInstanceOf[java.lang.Short]) { - print("int16 (") - print(value) - print(")") - } else if (value.isInstanceOf[Character]) { - print("char (") - print((value.asInstanceOf[Character]).charValue()) - print(")") - } else if (value.isInstanceOf[Integer]) { - print("int32 (") - print((value.asInstanceOf[Integer]).intValue()) - print(")") - } else if (value.isInstanceOf[Long]) { - print("int64 (") - print((value.asInstanceOf[Long]).longValue()) - print(")") - } else if (value.isInstanceOf[Float]) { - print(msilSyntaxFloat(value.asInstanceOf[Float])) - } else if (value.isInstanceOf[Double]) { - print(msilSyntaxDouble(value.asInstanceOf[Double])) - } else { - throw new Error("ILPrinterVisitor: Illegal default value: " - + value.getClass()) - } - } - println() - printAttributes(field) - } - - def msilSyntaxFloat(valFlo: java.lang.Float) : String = { - // !!! check if encoding is correct - val bits = java.lang.Float.floatToRawIntBits(valFlo.floatValue()) - /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */ - /* Note: no value is equal to Nan, including NaN. Thus, x == Float.NaN always evaluates to false. */ - val res = if (valFlo.isNaN) "0xFFC00000 /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */ - else if (java.lang.Float.NEGATIVE_INFINITY == valFlo.floatValue) "0xFF800000 /* NEGATIVE_INFINITY */ " - else if (java.lang.Float.POSITIVE_INFINITY == valFlo.floatValue) "0x7F800000 /* POSITIVE_INFINITY */ " - else bits - "float32 (" + res + ")" - } - - def msilSyntaxDouble(valDou: java.lang.Double) : String = { - // !!! check if encoding is correct - val bits = java.lang.Double.doubleToRawLongBits(valDou.doubleValue()) - /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */ - /* Note: no value is equal to Nan, including NaN. Thus, x == Double.NaN always evaluates to false. */ - val res = if (valDou.isNaN) "0xffffffffffffffff /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */ - else if (java.lang.Double.NEGATIVE_INFINITY == valDou.doubleValue) "0xfff0000000000000 /* NEGATIVE_INFINITY */ " - else if (java.lang.Double.POSITIVE_INFINITY == valDou.doubleValue) "0x7ff0000000000000 /* POSITIVE_INFINITY */ " - else bits - // float64(float64(...)) != float64(...) - "float64 (" + res + ")" - } - - /** - * Visit a ConstructorBuilder - */ - @throws(classOf[IOException]) - def caseConstructorBuilder(constr: ConstructorBuilder) { - if (nomembers) return - print(".method "); printHeader(constr, VOID) - println(); println("{"); indent() - printAttributes(constr) - try { - print(constr.GetILGenerator()) - } catch { - case e : RuntimeException => { - System.err.println("In method " + constr) - e.printStackTrace() - } - } - undent(); println("}") - } - - /** - * Visit a MethodBuilder - */ - @throws(classOf[IOException]) - def caseMethodBuilder(method: MethodBuilder) { - if (nomembers) return - print(".method "); printHeader(method, method.ReturnType) - if (method.IsAbstract() - || (method.DeclaringType != null - && method.DeclaringType.IsInterface() - && !method.IsStatic())) - { - println(" {"); indent() - printAttributes(method) - undent(); println("}") - } else { - println(); println("{"); indent() - printAttributes(method) - if (method == entryPoint) - println(".entrypoint") - try { - print(method.GetILGenerator()) - } catch { - case e: RuntimeException => - System.err.println("In method " + method) - e.printStackTrace() - } - undent(); println("}") - } - } - - /** - * Visit a ParameterBuilder - */ - @throws(classOf[IOException]) - def caseParameterBuilder(param: ParameterBuilder) { - print(ParameterAttributes.toString(param.Attributes)) - printSignature(param.ParameterType) - //print(' ') print(marshal) - print(' '); printName(param.Name) - } - - var locals: Array[LocalBuilder] = null - /** - * Visit an ILGenerator - */ - @throws(classOf[IOException]) - def caseILGenerator(code: ILGenerator) { - // print maxstack - println(".maxstack " + code.getMaxStacksize()) - // get the local variables - locals = code.getLocals() - if (locals.length > 0) { - println(".locals init (") - indent() - for (i <- 0 until locals.length) { - if (i > 0) println(",") - print(locals(i)) - } // end while - undent() - println(")") - } - // get 3 iterators for the 3 lists - val itL = code.getLabelIterator() - val itO = code.getOpcodeIterator() - val itA = code.getArgumentIterator() - // iterate over each opcode - while (itO.hasNext) { - // first print label - val label = itL.next - val oOpt = code.lineNums.get(label) - if (oOpt.isDefined) { - println(".line " + oOpt.get) - } - argument = itA.next.asInstanceOf[Object] - printLabel(label) - val o2 = itO.next - if (o2 != null) { - print(" ") - print(o2.asInstanceOf[OpCode]) - } - println() - } // end while - } - - /** - * visit an OpCode - */ - @throws(classOf[IOException]) - def caseOpCode(opCode: OpCode) { - val opString = opCode.toString() - print(opString) - pad(14 - opString.length()) - - // switch opcode - if (opCode == OpCode.Ldstr) { - print(msilString(argument.toString())) - } else if(opCode == OpCode.Switch) { - // switch ( <labels> ) - print("(") - val targets = argument.asInstanceOf[Array[Label]] - val m = targets.length - for (i <- 0 until m) { - if (i != 0) print(", ") - print(targets(i)) - } // end for - print(")") - } else if(opCode == OpCode.Call || opCode == OpCode.Callvirt || opCode == OpCode.Jmp || opCode == OpCode.Ldftn || opCode == OpCode.Ldvirtftn) { - // call | callvirt | jmp | ldftn | ldvirtftn - // <instr_method> <callConv> <type> [ <typeSpec> :: ] <methodName> - printSignature(argument.asInstanceOf[MethodBase]) - } else if (opCode == OpCode.Newobj) { - printSignature(argument.asInstanceOf[ConstructorInfo]) - // ldfld | ldflda | ldsfld | ldsflda | stfld | stsfld - } else if (opCode == OpCode.Ldfld || opCode == OpCode.Ldflda || opCode == OpCode.Ldsfld || opCode == OpCode.Ldsflda || opCode == OpCode.Stfld || opCode == OpCode.Stsfld) { - printSignature(argument.asInstanceOf[FieldInfo]) - } else if (opCode == OpCode.Castclass || opCode == OpCode.Isinst || opCode == OpCode.Ldobj || opCode == OpCode.Newarr) { - printSignature(argument.asInstanceOf[Type]) - } else if (opCode == OpCode.Box || opCode == OpCode.Unbox || opCode == OpCode.Ldtoken || opCode == OpCode.Initobj) { - printReference(argument.asInstanceOf[Type]) - } else if (opCode == OpCode.Ldloc || opCode == OpCode.Ldloc_S || opCode == OpCode.Ldloca || opCode == OpCode.Ldloca_S || opCode == OpCode.Stloc || opCode == OpCode.Stloc_S) { - val loc = argument.asInstanceOf[LocalBuilder] - print(loc.slot); print("\t// "); printSignature(loc.LocalType) - print(" \'"); print(loc.name); print("\'") - //print("'") print(((LocalBuilder)argument).name) print("'") - } else if (opCode == OpCode.Ldloc_0 || opCode == OpCode.Ldloc_1 || opCode == OpCode.Ldloc_2 || opCode == OpCode.Ldloc_3 ) { - val loc = locals(opCode.CEE_opcode - OpCode.CEE_LDLOC_0) - print("\t// "); printSignature(loc.LocalType) - print(" \'"); print(loc.name); print("\'") - } else if (opCode == OpCode.Stloc_0 || opCode == OpCode.Stloc_1 || opCode == OpCode.Stloc_2 || opCode == OpCode.Stloc_3 ) { - val loc = locals(opCode.CEE_opcode - OpCode.CEE_STLOC_0) - print("\t// "); printSignature(loc.LocalType) - print(" \'"); print(loc.name); print("\'") - } else if (opCode == OpCode.Readonly) { - // nothing to do - } else if (opCode == OpCode.Constrained) { - printReference(argument.asInstanceOf[Type]) - } else if (opCode == OpCode.Ldelema) { - printReference(argument.asInstanceOf[Type]) - } else { - // by default print toString argument if any - if (argument != null) { - val strArgument = java.lang.String.valueOf(argument) - if ( argument.isInstanceOf[java.lang.Float] - && ( strArgument.equals("NaN") - || strArgument.equals("-Infinity") - || strArgument.equals("Infinity"))) - print(msilSyntaxFloat(argument.asInstanceOf[java.lang.Float])) - else if ( argument.isInstanceOf[java.lang.Double] - && ( strArgument.equals("NaN") - || strArgument.equals("-Infinity") - || strArgument.equals("Infinity"))) - print(msilSyntaxDouble(argument.asInstanceOf[java.lang.Double])) - else print(strArgument) - } - - } // end switch - } - - /** - * Visit a Label - */ - def printLabel(label: Label) { - val kind = label.getKind() - if (kind == Label.Kind.Normal) { - print(label+ ": ") - } else if (kind == Label.Kind.NewScope) { - print("{"); indent() - } else if (kind == Label.Kind.EndScope) { - undent(); print("}") - } else if (kind == Label.Kind.Try) { - print(".try {"); indent() - } else if (kind == Label.Kind.Catch) { - undent() - println("}") - print("catch ") - printReference(argument.asInstanceOf[Type]) - print(" {") - indent() - } else if (kind == Label.Kind.Filter) { - undent() - println("}") - print("filter {") - indent() - } else if (kind == Label.Kind.EndFilter) { - print("endfilter") - undent() - println("}") - } else if (kind == Label.Kind.Finally) { - undent() - println("}") - print("finally {") - indent() - } else if (kind == Label.Kind.EndTry) { - undent() - print("}") - } - } - - /** - * Visit a LocalBuilder - */ - @throws(classOf[IOException]) - def caseLocalBuilder(localBuilder: LocalBuilder) { - // print type - printSignature(localBuilder.LocalType) - // space - print(" \'") - // print name - print(localBuilder.name) - print("\'") - } - - - //########################################################################## - - def printAssemblySignature(assem: Assembly, extern: Boolean) { - print(".assembly ") - if (extern) - print("extern ") - val an = assem.GetName() - printName(an.Name); println() - println("{") - if (!extern) - printAttributes(assem) - val v = an.Version - if (v != null) { - print(" .ver "); print(v.Major); print(':'); print(v.Minor) - print(':'); print(v.Build); print(':') - print(v.Revision); println() - } - var key = an.GetPublicKeyToken() - if (key != null) { - print(" .publickeytoken = ("); print(PEFile.bytes2hex(key)) - println(")") - } else { - key = an.GetPublicKey() - if (key != null) { - print(" .publickey = ("); print(PEFile.bytes2hex(key)) - println(")") - } - } - println("}") - } - - - def printSignature(field: FieldInfo) { - printSignature(field.FieldType, field.cmods) - //print(' ') print(owner) - print(' ') - //if (field.IsStatic && field.DeclaringType != currentType) { - printReference(field.DeclaringType) - print("::") - //} - printName(field.Name) - } - - // print method head - @throws(classOf[IOException]) - def printHeader(method: MethodBase, returnType: Type) { - print(MethodAttributes.toString(method.Attributes)) - print(' '); print(CallingConventions.toString(method.CallingConvention)) - print(' '); printSignature(returnType) - //print(' ') print(marshal) - print(' '); printName(method.Name) - if(method.isInstanceOf[MethodInfo]) { - val mthdInfo = method.asInstanceOf[MethodInfo] - printTypeParams(mthdInfo.getSortedMVars()) - } - val params = method.GetParameters() - print('(') - for (i <- 0 until params.length) { - if (i > 0) print(", ") - print(params(i).asInstanceOf[ParameterBuilder]) - } - print(") ") - - print(MethodImplAttributes - .toString(method.GetMethodImplementationFlags())) - } - - - def printSignature(method: MethodBase) { - var returnType: Type = null - if (method.isInstanceOf[MethodInfo]) - returnType = (method.asInstanceOf[MethodInfo]).ReturnType - else if (method.isInstanceOf[ConstructorInfo]) - returnType = VOID - else - throw new RuntimeException() - - val s = CallingConventions.toString(method.CallingConvention) - print(s) - if (s.length() > 0) print(' ') - printSignature(returnType) - //print(' ') print(owner) - print(' '); printReference(method.DeclaringType) - print("::"); printName(method.Name) - - val params = method.GetParameters() - print("(") - for (i <- 0 until params.length) { - if (i > 0) print(", ") - printSignature(params(i).ParameterType) - } - print(")") - } - - def printSignature(marked: Type, cmods: Array[CustomModifier]) { - printSignature(marked) - if( (cmods != null) && !cmods.isEmpty ) { - print(" ") - for(cm <- cmods) { - print(if (cm.isReqd) "modreq( " else "modopt( ") - printReference(cm.marker) - print(" ) ") - } - } - } - - def printSignature(`type`: Type) { - val sigOpt = primitive.get(`type`) - if (sigOpt.isDefined) { - print(sigOpt.get) - return - } - if (`type`.HasElementType()) { - printSignature(`type`.GetElementType()) - if (`type`.IsArray()) - print("[]") - else if (`type`.IsPointer()) - print('*') - else if (`type`.IsByRef()) - print('&') - } else { - val preref = if (`type`.isInstanceOf[Type.TMVarUsage]) "" - else if(`type`.IsValueType()) "valuetype " - else "class " - print(preref) - printReference(`type`) - } - } - - def printReference(`type`: Type) { - if (`type`.Module != null) { // i.e. not PrimitiveType and not TMVarUsage - if (`type`.Assembly() != currentModule.Assembly) { - print('['); print(`type`.Assembly().GetName().Name); print("]") - } else if (`type`.Module != currentModule) { - print("[.module "); print(`type`.Module.Name); print("]") - } - } - printTypeName(`type`) - } - - def printTypeName(`type`: Type) { - if (`type`.isInstanceOf[ConstructedType]) { - val ct = `type`.asInstanceOf[ConstructedType] - printTypeName(ct.instantiatedType) - print("<") - var i = 0 - while (i < ct.typeArgs.length) { - val ta = ct.typeArgs(i) - val sigOpt = primitive.get(ta) - if (sigOpt.isDefined) print(sigOpt.get) - else printTypeName(ta); /* should be printSignature, but don't want `class` or `valuetype` - appearing before a type param usage. */ - i = i + 1; - if (i < ct.typeArgs.length) { - print(", ") - } - } - print(">") - } else if (`type`.DeclaringType != null) { - printTypeName(`type`.DeclaringType) - print('/') - printName(`type`.Name) - } else { - printName(`type`.FullName) - } - } - - def printAttributes(icap: ICustomAttributeProvider) { - val attrs = icap.GetCustomAttributes(false) - for (i <- 0 until attrs.length) { - print(".custom ") - printSignature((attrs(i).asInstanceOf[Attribute]).getConstructor()) - print(" = (") - print(PEFile.bytes2hex((attrs(i).asInstanceOf[Attribute]).getValue())) - println(")") - } - } - - //########################################################################## - -} // class ILPrinterVisitor - -object ILPrinterVisitor { - final val VOID: Type = Type.GetType("System.Void") - protected final val TAB = 4 - - protected final val SPACES = " " - protected final val SPACES_LEN = SPACES.length() - - def hasControlChars(str: String): Boolean = { - for(i <- 0 until str.length()) { - val ch = str.charAt(i) - ch match { - case '\b' => - case '\t' => - case '\n' => - case '\f' => - case '\r' => - case _ => if(Character.isISOControl(ch)) return true - } - } - return false - } - - final val EMPTY: String = "" - def msilString(s: String): String = { - if (hasControlChars(s)) { - try { - return "bytearray (" + PEFile.bytes2hex(s.getBytes("UTF-16LE")) + ")" - } catch { - case e : java.io.UnsupportedEncodingException => throw new RuntimeException(e) - } - } - val str = new StringBuffer(s) - var ss = EMPTY - var i = 0 - while(i < str.length()) { - ss = EMPTY - val c = str.charAt(i) - c match { - case '\b' => ss = "\\b" - case '\t' => ss = "\\t" - case '\n' => ss = "\\n" - case '\f' => ss = "\\f" - case '\r' => ss = "\\r" - case '\"' => ss = "\\\"" - case '\'' => ss = "\\\'" - case '\\' => ss = "\\\\" - case _ => if (Character.isISOControl(c)) - ss = "\\u" + PEFile.int2hex(Character.getNumericValue(c)) - } - if (ss != EMPTY) { - str.replace(i, i + 1, ss) - i = i + ss.length() - 1 - } - i = i + 1 - } - return "\"" + str.toString() + "\"" - } - - /** - * the main printer method - */ - @throws(classOf[IOException]) - def printAssembly(assemblyBuilder: AssemblyBuilder, fileName: String) { - assemblyBuilder.apply(new SingleFileILPrinterVisitor(fileName)) - } - - @throws(classOf[IOException]) - def printAssembly(assemblyBuilder: AssemblyBuilder, destPath: String, sourceFilesPath: String) { - assemblyBuilder.apply(new MultipleFilesILPrinterVisitor(destPath, sourceFilesPath)) - } - - /** The current assembly */ - var currAssembly: Assembly = _ - - final var primitive = scala.collection.mutable.Map.empty[Type, String] - def addPrimitive(name: String, sig: String) { - val `type` = - Type.GetType(name) - assert(`type` != null, "Cannot lookup primitive type " + `type`) - primitive.put(`type`, sig) - } - - addPrimitive("System.Object", "object") - addPrimitive("System.String", "string") - addPrimitive("System.Void", "void") - addPrimitive("System.Boolean", "bool") - addPrimitive("System.Char", "char") - addPrimitive("System.SByte", "int8") - addPrimitive("System.Byte", "unsigned int8") - addPrimitive("System.Int16", "int16") - addPrimitive("System.UInt16", "unsigned int16") - addPrimitive("System.Int32", "int32") - addPrimitive("System.UInt32", "unsigned int32") - addPrimitive("System.Int64", "int64") - addPrimitive("System.UInt64", "unsigned int64") - addPrimitive("System.IntPtr", "native int") - addPrimitive("System.UIntPtr", "unsigned native int") - addPrimitive("System.Single", "float32") - addPrimitive("System.Double", "float64") - addPrimitive("System.TypedReference", "typedref") -} |