private void CompileExternMethod(CppMethodCodeNode methodCodeNodeNeedingCode, string importName) { MethodDesc method = methodCodeNodeNeedingCode.Method; MethodSignature methodSignature = method.Signature; bool slotCastRequired = false; MethodSignature externCSignature; if (_externCSignatureMap.TryGetValue(importName, out externCSignature)) { slotCastRequired = !externCSignature.Equals(methodSignature); } else { _externCSignatureMap.Add(importName, methodSignature); externCSignature = methodSignature; } var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); if (slotCastRequired) { AppendSlotTypeDef(sb, method); } sb.AppendLine(); if (!method.Signature.ReturnType.IsVoid) { sb.Append("return "); } if (slotCastRequired) { sb.Append("((__slot__" + GetCppMethodName(method) + ")"); } sb.Append("::"); sb.Append(importName); if (slotCastRequired) { sb.Append(")"); } sb.Append("("); AppendCppMethodCallParamList(sb, method); sb.Append(");"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty <Object>()); }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Log.WriteLine("Compiling " + method.ToString()); SpecialMethodKind kind = method.DetectSpecialMethodKind(); if (kind != SpecialMethodKind.Unknown) { string specialMethodCode = CompileSpecialMethod(method, kind); methodCodeNodeNeedingCode.SetCode(specialMethodCode, Array.Empty <Object>()); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } try { var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; if (!_compilation.Options.NoLineNumbers) { IEnumerable <ILSequencePoint> sequencePoints = typeSystemContext.GetSequencePointsForMethod(method); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <ILLocalVariable> localVariables = typeSystemContext.GetLocalVariableNamesForMethod(method); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = typeSystemContext.GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Log.WriteLine(e.Message + " (" + method + ")"); var builder = new CppGenerationBuffer(); builder.AppendLine(); builder.Append(GetCppMethodDeclaration(method, true)); builder.AppendLine(); builder.Append("{"); builder.Indent(); builder.AppendLine(); builder.Append("throw 0xC000C000;"); builder.Exdent(); builder.AppendLine(); builder.Append("}"); methodCodeNodeNeedingCode.SetCode(builder.ToString(), Array.Empty <Object>()); } }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Logger.Writer.WriteLine("Compiling " + method.ToString()); if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")) { CompileExternMethod(methodCodeNodeNeedingCode, ((EcmaMethod)method).GetRuntimeImportName()); return; } if (method.IsRawPInvoke()) { CompileExternMethod(methodCodeNodeNeedingCode, method.GetPInvokeMethodMetadata().Name ?? method.Name); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) return; // TODO: Remove this code once CppCodegen is able to generate code for the reflection startup path. // The startup path runs before any user code is executed. // For now we replace the startup path with a simple "ret". Reflection won't work, but // programs not using reflection will. if (method.Name == ".cctor") { MetadataType owningType = method.OwningType as MetadataType; if (owningType != null && owningType.Name == "ReflectionExecution" && owningType.Namespace == "Internal.Reflection.Execution") { methodIL = new Internal.IL.Stubs.ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ret }, Array.Empty<LocalVariableDefinition>(), null); } } try { // TODO: hacky special-case if (method.Name == "_ecvt_s") throw new NotImplementedException(); var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL); if (!_compilation.Options.HasOption(CppCodegenConfigProvider.NoLineNumbersString)) { IEnumerable<ILSequencePoint> sequencePoints = debugInfo.GetSequencePoints(); if (sequencePoints != null) ilImporter.SetSequencePoints(sequencePoints); } IEnumerable<ILLocalVariable> localVariables = debugInfo.GetLocalVariables(); if (localVariables != null) ilImporter.SetLocalVariables(localVariables); IEnumerable<string> parameters = GetParameterNamesForMethod(method); if (parameters != null) ilImporter.SetParameterNames(parameters); ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Logger.Writer.WriteLine(e.Message + " (" + method + ")"); var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("throw 0xC000C000;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty<Object>()); } }
private void CompileExternMethod(CppMethodCodeNode methodCodeNodeNeedingCode, string importName) { MethodDesc method = methodCodeNodeNeedingCode.Method; MethodSignature methodSignature = method.Signature; bool slotCastRequired = false; MethodSignature externCSignature; if (_externCSignatureMap.TryGetValue(importName, out externCSignature)) { slotCastRequired = !externCSignature.Equals(methodSignature); } else { _externCSignatureMap.Add(importName, methodSignature); externCSignature = methodSignature; } var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); if (slotCastRequired) { AppendSlotTypeDef(sb, method); } sb.AppendLine(); if (!method.Signature.ReturnType.IsVoid) { sb.Append("return "); } if (slotCastRequired) sb.Append("((__slot__" + GetCppMethodName(method) + ")"); sb.Append("::"); sb.Append(importName); if (slotCastRequired) sb.Append(")"); sb.Append("("); AppendCppMethodCallParamList(sb, method); sb.Append(");"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty<Object>()); }
public void Compile(CppMethodCodeNode methodCodeNodeNeedingCode) { FindBasicBlocks(); ImportBasicBlocks(); if (_sequencePoints != null && _sequencePoints[0].Document != null) { var sequencePoint = _sequencePoints[0]; ForceAppendEmptyLine(); Append("#line "); Append(sequencePoint.LineNumber.ToStringInvariant()); Append(" \""); Append(sequencePoint.Document.Replace("\\", "\\\\")); Append("\""); } ForceAppendEmptyLine(); Append(_writer.GetCppMethodDeclaration(_method, true)); AppendLine(); Append("{"); Indent(); bool initLocals = _methodIL.GetInitLocals(); for (int i = 0; i < _locals.Length; i++) { AppendLine(); Append(_writer.GetCppSignatureTypeName(_locals[i].Type)); Append(" "); Append(GetVarName(i, false)); if (initLocals) { TypeDesc localType = _locals[i].Type; if (localType.IsValueType && !localType.IsPrimitive && !localType.IsEnum) { AppendSemicolon(); AppendLine(); Append("memset(&"); Append(GetVarName(i, false)); Append(",0,sizeof("); Append(_writer.GetCppSignatureTypeName(localType)); Append("))"); } else { Append(" = 0"); } } AppendSemicolon(); } if (_spillSlots != null) { for (int i = 0; i < _spillSlots.Count; i++) { SpillSlot spillSlot = _spillSlots[i]; AppendLine(); Append(GetStackValueKindCPPTypeName(spillSlot.Kind, spillSlot.Type)); Append(" "); Append(spillSlot.Name); AppendSemicolon(); } } for (int i = 0; i < _exceptionRegions.Length; i++) { var r = _exceptionRegions[i]; if (r.ReturnLabels != 0) { AppendLine(); Append("int __finallyReturn"); Append(i.ToStringInvariant()); Append(" = 0"); AppendSemicolon(); } } // Temporary the indentation while printing blocks. // We want block to start on the first character of the line Exdent(); for (int i = 0; i < _basicBlocks.Length; i++) { BasicBlock basicBlock = _basicBlocks[i]; if (basicBlock != null) { AppendEmptyLine(); AppendLine(); Append("_bb"); Append(i.ToStringInvariant()); Append(": {"); ForceAppendEmptyLine(); Append(basicBlock.Code); AppendLine(); Append("}"); } } for (int i = 0; i < _exceptionRegions.Length; i++) { var r = _exceptionRegions[i]; if (r.ReturnLabels != 0) { AppendEmptyLine(); AppendLine(); Append("__endFinally" + i.ToStringInvariant() + ":"); Indent(); AppendLine(); Append("switch(__finallyReturn" + i.ToStringInvariant() + ") {"); Indent(); for (int j = 1; j <= r.ReturnLabels; j++) { AppendLine(); Append("case " + j.ToStringInvariant() + ": goto __returnFromFinally" + i.ToStringInvariant() + "_" + j.ToStringInvariant() + ";"); } AppendLine(); Append("default: CORERT_UNREACHABLE;"); Exdent(); AppendLine(); Append("}"); Exdent(); } } AppendEmptyLine(); Append("}"); methodCodeNodeNeedingCode.SetCode(_builder.ToString(), _dependencies.ToArray()); }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Log.WriteLine("Compiling " + method.ToString()); SpecialMethodKind kind = method.DetectSpecialMethodKind(); if (kind != SpecialMethodKind.Unknown) { string specialMethodCode = CompileSpecialMethod(method, kind); methodCodeNodeNeedingCode.SetCode(specialMethodCode, Array.Empty<Object>()); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) return; string methodCode; try { var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; if (!_compilation.Options.NoLineNumbers) { IEnumerable<ILSequencePoint> sequencePoints = typeSystemContext.GetSequencePointsForMethod(method); if (sequencePoints != null) ilImporter.SetSequencePoints(sequencePoints); } IEnumerable<ILLocalVariable> localVariables = typeSystemContext.GetLocalVariableNamesForMethod(method); if (localVariables != null) ilImporter.SetLocalVariables(localVariables); IEnumerable<string> parameters = typeSystemContext.GetParameterNamesForMethod(method); if (parameters != null) ilImporter.SetParameterNames(parameters); ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Log.WriteLine(e.Message + " (" + method + ")"); methodCode = GetCppMethodDeclaration(method, true) + " { throw 0xC000C000; }" + Environment.NewLine; methodCodeNodeNeedingCode.SetCode(methodCode, Array.Empty<Object>()); } }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Logger.Writer.WriteLine("Compiling " + method.ToString()); if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")) { CompileExternMethod(methodCodeNodeNeedingCode, ((EcmaMethod)method).GetRuntimeImportName()); return; } if (method.IsRawPInvoke()) { CompileExternMethod(methodCodeNodeNeedingCode, method.GetPInvokeMethodMetadata().Name ?? method.Name); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } try { // TODO: hacky special-case if (method.Name == "_ecvt_s") { throw new NotImplementedException(); } var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL); if (!_compilation.Options.HasOption(CppCodegenConfigProvider.NoLineNumbersString)) { IEnumerable <ILSequencePoint> sequencePoints = debugInfo.GetSequencePoints(); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <ILLocalVariable> localVariables = debugInfo.GetLocalVariables(); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Logger.Writer.WriteLine(e.Message + " (" + method + ")"); var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("throw 0xC000C000;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty <Object>()); } }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Log.WriteLine("Compiling " + method.ToString()); if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")) { CompileExternMethod(methodCodeNodeNeedingCode, ((EcmaMethod)method).GetRuntimeImportName()); return; } if (method.IsRawPInvoke()) { CompileExternMethod(methodCodeNodeNeedingCode, method.GetPInvokeMethodMetadata().Name ?? method.Name); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) return; try { var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL); if (!_compilation.Options.NoLineNumbers) { IEnumerable<ILSequencePoint> sequencePoints = debugInfo.GetSequencePoints(); if (sequencePoints != null) ilImporter.SetSequencePoints(sequencePoints); } IEnumerable<ILLocalVariable> localVariables = debugInfo.GetLocalVariables(); if (localVariables != null) ilImporter.SetLocalVariables(localVariables); IEnumerable<string> parameters = GetParameterNamesForMethod(method); if (parameters != null) ilImporter.SetParameterNames(parameters); ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Log.WriteLine(e.Message + " (" + method + ")"); var builder = new CppGenerationBuffer(); builder.AppendLine(); builder.Append(GetCppMethodDeclaration(method, true)); builder.AppendLine(); builder.Append("{"); builder.Indent(); builder.AppendLine(); builder.Append("throw 0xC000C000;"); builder.Exdent(); builder.AppendLine(); builder.Append("}"); methodCodeNodeNeedingCode.SetCode(builder.ToString(), Array.Empty<Object>()); } }
public void Compile(CppMethodCodeNode methodCodeNodeNeedingCode) { FindBasicBlocks(); ImportBasicBlocks(); if (_sequencePoints != null && _sequencePoints[0].Document != null) { var sequencePoint = _sequencePoints[0]; Append("#line "); Append(IntToString(sequencePoint.LineNumber)); Append(" \""); Append(sequencePoint.Document.Replace("\\", "\\\\")); Append("\""); _builder.AppendLine(); } Append(_writer.GetCppMethodDeclaration(_method, true)); _builder.Append("{"); bool initLocals = _methodIL.GetInitLocals(); for (int i = 0; i < _locals.Length; i++) { Append(_writer.GetCppSignatureTypeName(_locals[i].Type)); Append(" "); Append(GetVarName(i, false)); if (initLocals) { TypeDesc localType = _locals[i].Type; if (localType.IsValueType && !localType.IsPrimitive && !localType.IsEnum) { Finish(); Append("memset(&"); Append(GetVarName(i, false)); Append(",0,sizeof("); Append(_writer.GetCppSignatureTypeName(localType)); Append("))"); } else { Append("=0"); } } Finish(); } if (_spillSlots != null) { for (int i = 0; i < _spillSlots.Count; i++) { SpillSlot spillSlot = _spillSlots[i]; Append(GetStackValueKindCPPTypeName(spillSlot.Kind, spillSlot.Type)); Append(" "); Append(spillSlot.Name); Finish(); } } for (int i = 0; i < _exceptionRegions.Length; i++) { var r = _exceptionRegions[i]; if (r.ReturnLabels != 0) { _builder.Append("int __finallyReturn"); _builder.Append(IntToString(i)); _builder.Append("=0;"); } } for (int i = 0; i < _basicBlocks.Length; i++) { BasicBlock basicBlock = _basicBlocks[i]; if (basicBlock != null) { _builder.Append("_bb"); _builder.Append(IntToString(i)); _builder.AppendLine(": {"); _builder.Append(basicBlock.Code); // _builder.AppendLine("}"); _builder.Append("} "); } } for (int i = 0; i < _exceptionRegions.Length; i++) { var r = _exceptionRegions[i]; if (r.ReturnLabels != 0) { _builder.AppendLine("__endFinally" + IntToString(i) + ": switch(__finallyReturn" + IntToString(i) + ") {"); for (int j = 1; j <= r.ReturnLabels; j++) _builder.AppendLine("case " + IntToString(j) + ": goto __returnFromFinally" + IntToString(i) + "_" + IntToString(j) + ";"); _builder.AppendLine("default: " + (_msvc ? "__assume(0)" : "__builtin_unreachable()") + "; }"); } } _builder.AppendLine("}"); methodCodeNodeNeedingCode.SetCode(_builder.ToString(), _dependencies.ToArray()); }
public void CompileMethod(CppMethodCodeNode methodCodeNodeNeedingCode) { MethodDesc method = methodCodeNodeNeedingCode.Method; _compilation.Logger.Writer.WriteLine("Compiling " + method.ToString()); if (method.HasCustomAttribute("System.Runtime", "RuntimeImportAttribute")) { CompileExternMethod(methodCodeNodeNeedingCode, ((EcmaMethod)method).GetRuntimeImportName()); return; } if (method.IsRawPInvoke()) { CompileExternMethod(methodCodeNodeNeedingCode, method.GetPInvokeMethodMetadata().Name ?? method.Name); return; } var methodIL = _compilation.GetMethodIL(method); if (methodIL == null) { return; } // TODO: Remove this code once CppCodegen is able to generate code for the reflection startup path. // The startup path runs before any user code is executed. // For now we replace the startup path with a simple "ret". Reflection won't work, but // programs not using reflection will. if (method.Name == ".cctor") { MetadataType owningType = method.OwningType as MetadataType; if (owningType != null && owningType.Name == "ReflectionExecution" && owningType.Namespace == "Internal.Reflection.Execution") { methodIL = new Internal.IL.Stubs.ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null); } } try { // TODO: hacky special-case if (method.Name == "_ecvt_s") { throw new NotImplementedException(); } var ilImporter = new ILImporter(_compilation, this, method, methodIL); CompilerTypeSystemContext typeSystemContext = _compilation.TypeSystemContext; MethodDebugInformation debugInfo = _compilation.GetDebugInfo(methodIL); if (!_compilation.Options.HasOption(CppCodegenConfigProvider.NoLineNumbersString)) { IEnumerable <ILSequencePoint> sequencePoints = debugInfo.GetSequencePoints(); if (sequencePoints != null) { ilImporter.SetSequencePoints(sequencePoints); } } IEnumerable <ILLocalVariable> localVariables = debugInfo.GetLocalVariables(); if (localVariables != null) { ilImporter.SetLocalVariables(localVariables); } IEnumerable <string> parameters = GetParameterNamesForMethod(method); if (parameters != null) { ilImporter.SetParameterNames(parameters); } ilImporter.Compile(methodCodeNodeNeedingCode); } catch (Exception e) { _compilation.Logger.Writer.WriteLine(e.Message + " (" + method + ")"); var sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, method, true); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("throw 0xC000C000;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); methodCodeNodeNeedingCode.SetCode(sb.ToString(), Array.Empty <Object>()); } }