private void OutputMainMethodStub(MethodDesc entrypoint) { var sb = new CppGenerationBuffer(); // Stub for main method sb.AppendLine(); if (_compilation.TypeSystemContext.Target.OperatingSystem == TargetOS.Windows) { sb.Append("int wmain(int argc, wchar_t * argv[]) { "); } else { sb.Append("int main(int argc, char * argv[]) {"); } sb.Indent(); sb.AppendLine(); sb.Append("if (__initialize_runtime() != 0)"); sb.Indent(); sb.AppendLine(); sb.Append("return -1;"); sb.Exdent(); sb.AppendEmptyLine(); sb.AppendLine(); sb.Append("ReversePInvokeFrame frame;"); sb.AppendLine(); sb.Append("__reverse_pinvoke(&frame);"); sb.AppendEmptyLine(); sb.AppendLine(); sb.Append("int ret = "); sb.Append(GetCppMethodDeclarationName(entrypoint.OwningType, GetCppMethodName(entrypoint))); sb.Append("(argc, (intptr_t)argv);"); sb.AppendEmptyLine(); sb.AppendLine(); sb.Append("__reverse_pinvoke_return(&frame);"); sb.AppendLine(); sb.Append("__shutdown_runtime();"); sb.AppendLine(); sb.Append("return ret;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); Out.Write(sb.ToString()); }
private void OutputType(CppGenerationBuffer sb, TypeDesc t, bool full) { _emittedTypes.Add(t); if (full) { if (!t.IsValueType) { var baseType = t.BaseType; if (baseType != null) { if (!_emittedTypes.Contains(baseType)) { OutputType(sb, baseType, full); } } } foreach (var field in t.GetFields()) { var fieldType = GetFieldTypeOrPlaceholder(field); if (fieldType.IsValueType && !fieldType.IsPrimitive && !field.IsStatic) { if (!_emittedTypes.Contains(fieldType)) { OutputType(sb, fieldType, full); } } } } string mangledName = GetCppTypeName(t); int nesting = 0; int current = 0; // Create Namespaces. If a mangledName starts with just :: we will simply ignore it. sb.AppendLine(); for (;;) { int sep = mangledName.IndexOf("::", current); if (sep < 0) { break; } if (sep != 0) { // Case of a name not starting with :: sb.Append("namespace " + mangledName.Substring(current, sep - current) + " { "); nesting++; } current = sep + 2; } if (full) { sb.Append("class " + mangledName.Substring(current)); if (!t.IsValueType) { if (t.BaseType != null) { sb.Append(" : public " + GetCppTypeName(t.BaseType)); } } sb.Append(" {"); sb.AppendLine(); sb.Append("public:"); sb.Indent(); // TODO: Enable once the dependencies are tracked for arrays // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked) if (!t.IsPointer && !t.IsByRef) { sb.AppendLine(); sb.Append("static MethodTable * __getMethodTable();"); } IReadOnlyList <MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(t).Slots; int baseSlots = 0; var baseType = t.BaseType; while (baseType != null) { IReadOnlyList <MethodDesc> baseVirtualSlots = _compilation.NodeFactory.VTable(baseType).Slots; if (baseVirtualSlots != null) { baseSlots += baseVirtualSlots.Count; } baseType = baseType.BaseType; } for (int slot = 0; slot < virtualSlots.Count; slot++) { MethodDesc virtualMethod = virtualSlots[slot]; sb.AppendLine(); sb.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot)); } if (t.IsDelegate) { sb.AppendLine(); sb.Append(GetCodeForDelegate(t)); } OutputTypeFields(sb, t); if (t.HasStaticConstructor) { _statics.AppendLine(); _statics.Append("bool __cctor_" + GetCppTypeName(t).Replace("::", "__") + ";"); } List <MethodDesc> methodList; if (_methodLists.TryGetValue(t, out methodList)) { foreach (var m in methodList) { OutputMethod(sb, m); } } sb.Exdent(); sb.AppendLine(); sb.Append("};"); } else { sb.Append("class " + mangledName.Substring(current) + ";"); } while (nesting > 0) { sb.Append("};"); nesting--; } // Make some rooms between two type definitions if (full) { sb.AppendEmptyLine(); } }
public void OutputCode(IEnumerable <DependencyNode> nodes, MethodDesc entrypoint) { BuildMethodLists(nodes); ExpandTypes(); Out.WriteLine("#include \"common.h\""); Out.WriteLine("#include \"CppCodeGen.h\""); Out.WriteLine(); Out.Write("/* Forward type definitions */"); OutputTypes(false); Out.WriteLine(); Out.WriteLine(); Out.Write("/* Type definitions */"); OutputTypes(true); var sb = new CppGenerationBuffer(); foreach (var externC in _externCSignatureMap) { string importName = externC.Key; // TODO: hacky special-case if (importName != "memmove" && importName != "malloc") // some methods are already declared by the CRT headers { sb.AppendLine(); sb.Append(GetCppMethodDeclaration(null, false, importName, externC.Value)); } } Out.Write(sb.ToString()); sb.Clear(); foreach (var t in _cppSignatureNames.Keys) { // TODO: Enable once the dependencies are tracked for arrays // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked) if (!t.IsPointer && !t.IsByRef) { sb.AppendLine(); sb.Append(GetCodeForType(t)); } List <MethodDesc> methodList; if (_methodLists.TryGetValue(t, out methodList)) { foreach (var m in methodList) { var methodCodeNode = (CppMethodCodeNode)_compilation.NodeFactory.MethodEntrypoint(m); sb.AppendLine(); sb.Append(methodCodeNode.CppCode); var alternateName = _compilation.NodeFactory.GetSymbolAlternateName(methodCodeNode); if (alternateName != null) { sb.AppendLine(); sb.Append(GetCppMethodDeclaration(m, true, alternateName)); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); if (!m.Signature.ReturnType.IsVoid) { sb.Append("return "); } sb.Append(GetCppMethodDeclarationName(m.OwningType, GetCppMethodName(m))); sb.Append("("); sb.Append(GetCppMethodCallParamList(m)); sb.Append(");"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); } } } } Out.Write(sb.ToString()); sb.Clear(); if (entrypoint != null) { // Stub for main method sb.AppendLine(); if (_compilation.TypeSystemContext.Target.OperatingSystem == TargetOS.Windows) { sb.Append("int wmain(int argc, wchar_t * argv[]) { "); } else { sb.Append("int main(int argc, char * argv[]) {"); } sb.Indent(); sb.AppendLine(); sb.Append("if (__initialize_runtime() != 0)"); sb.Indent(); sb.AppendLine(); sb.Append("return -1;"); sb.Exdent(); sb.AppendEmptyLine(); sb.AppendLine(); sb.Append("ReversePInvokeFrame frame;"); sb.AppendLine(); sb.Append("__reverse_pinvoke(&frame);"); sb.AppendEmptyLine(); sb.AppendLine(); sb.Append("int ret = "); sb.Append(GetCppMethodDeclarationName(entrypoint.OwningType, GetCppMethodName(entrypoint))); sb.Append("(argc-1, (intptr_t)(argv+1));"); sb.AppendEmptyLine(); sb.AppendLine(); sb.Append("__reverse_pinvoke_return(&frame);"); sb.AppendLine(); sb.Append("__shutdown_runtime();"); sb.AppendLine(); sb.Append("return ret;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); } Out.Write(sb.ToString()); sb.Clear(); Out.Dispose(); }
private void OutputTypeNode(IEETypeNode typeNode, NodeFactory factory, CppGenerationBuffer forwardDefinitions, CppGenerationBuffer typeDefinitions, CppGenerationBuffer methodTable) { if (_emittedTypes == null) { _emittedTypes = new HashSet <TypeDesc>(); } TypeDesc nodeType = typeNode.Type; if (_emittedTypes.Contains(nodeType)) { return; } _emittedTypes.Add(nodeType); // Create Namespaces string mangledName = _compilation.NameMangler.GetMangledTypeName(nodeType); int nesting = 0; int current = 0; forwardDefinitions.AppendLine(); for (;;) { int sep = mangledName.IndexOf("::", current); if (sep < 0) { break; } if (sep != 0) { // Case of a name not starting with :: forwardDefinitions.Append("namespace " + mangledName.Substring(current, sep - current) + " { "); typeDefinitions.Append("namespace " + mangledName.Substring(current, sep - current) + " { "); typeDefinitions.Indent(); nesting++; } current = sep + 2; } forwardDefinitions.Append("class " + mangledName.Substring(current) + ";"); // type definition typeDefinitions.Append("class " + mangledName.Substring(current)); if (!nodeType.IsValueType) { // Don't emit inheritance if base type has not been marked for emission if (nodeType.BaseType != null && _emittedTypes.Contains(nodeType.BaseType)) { typeDefinitions.Append(" : public " + GetCppTypeName(nodeType.BaseType)); } } typeDefinitions.Append(" {"); typeDefinitions.AppendLine(); typeDefinitions.Append("public:"); typeDefinitions.Indent(); // TODO: Enable once the dependencies are tracked for arrays // if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(t)).Marked) { typeDefinitions.AppendLine(); typeDefinitions.Append("static MethodTable * __getMethodTable();"); } if (typeNode is ConstructedEETypeNode) { OutputTypeFields(typeDefinitions, nodeType); IReadOnlyList <MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(nodeType).Slots; int baseSlots = 0; var baseType = nodeType.BaseType; while (baseType != null) { IReadOnlyList <MethodDesc> baseVirtualSlots = _compilation.NodeFactory.VTable(baseType).Slots; if (baseVirtualSlots != null) { baseSlots += baseVirtualSlots.Count; } baseType = baseType.BaseType; } for (int slot = 0; slot < virtualSlots.Count; slot++) { MethodDesc virtualMethod = virtualSlots[slot]; typeDefinitions.AppendLine(); typeDefinitions.Append(GetCodeForVirtualMethod(virtualMethod, baseSlots + slot)); } if (nodeType.IsDelegate) { typeDefinitions.AppendLine(); typeDefinitions.Append(GetCodeForDelegate(nodeType)); } } if (nodeType.HasStaticConstructor) { _statics.AppendLine(); _statics.Append("bool __cctor_" + GetCppTypeName(nodeType).Replace("::", "__") + ";"); } List <MethodDesc> methodList; if (_methodLists.TryGetValue(nodeType, out methodList)) { foreach (var m in methodList) { typeDefinitions.AppendLine(); AppendCppMethodDeclaration(typeDefinitions, m, false); } } typeDefinitions.AppendEmptyLine(); typeDefinitions.Append("};"); typeDefinitions.AppendEmptyLine(); typeDefinitions.Exdent(); while (nesting > 0) { forwardDefinitions.Append("};"); typeDefinitions.Append("};"); typeDefinitions.Exdent(); nesting--; } typeDefinitions.AppendEmptyLine(); // declare method table methodTable.Append(GetCodeForObjectNode(typeNode as ObjectNode, factory)); methodTable.AppendEmptyLine(); }