private String GetCodeForNodeStruct(List<NodeDataSection> nodeDataDivs, DependencyNode node) { CppGenerationBuffer nodeStructDecl = new CppGenerationBuffer(); int relocCounter = 1; int i = 0; nodeStructDecl.Indent(); for (i = 0; i < nodeDataDivs.Count; i++) { NodeDataSection section = nodeDataDivs[i]; if (section.SectionType == NodeDataSectionType.Relocation) { nodeStructDecl.Append("void* reloc"); nodeStructDecl.Append(relocCounter); nodeStructDecl.Append(";"); relocCounter++; } else { nodeStructDecl.Append("unsigned char data"); nodeStructDecl.Append((i + 1) - relocCounter); nodeStructDecl.Append("["); nodeStructDecl.Append(section.SectionSize); nodeStructDecl.Append("];"); } nodeStructDecl.AppendLine(); } nodeStructDecl.Exdent(); return nodeStructDecl.ToString(); }
public void OutputCode(IEnumerable<DependencyNode> nodes, MethodDesc entrypoint, NodeFactory factory) { var sb = new CppGenerationBuffer(); BuildMethodLists(nodes); ExpandTypes(); Out.WriteLine("#include \"common.h\""); Out.WriteLine("#include \"CppCodeGen.h\""); Out.WriteLine(); _statics = new CppGenerationBuffer(); _statics.Indent(); _gcStatics = new CppGenerationBuffer(); _gcStatics.Indent(); _threadStatics = new CppGenerationBuffer(); _threadStatics.Indent(); _gcThreadStatics = new CppGenerationBuffer(); _gcThreadStatics.Indent(); var methodImplementations = new CppGenerationBuffer(); OutputNodes(nodes, entrypoint, factory, sb, methodImplementations); Out.Write(sb.ToString()); sb.Clear(); Out.Write("struct {"); Out.Write(_statics.ToString()); Out.Write("} __statics;"); Out.Write("struct {"); Out.Write(_gcStatics.ToString()); Out.Write("} __gcStatics;"); Out.Write("struct {"); Out.Write(_gcStatics.ToString()); Out.Write("} __gcThreadStatics;"); 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(); Out.Write(methodImplementations.ToString()); methodImplementations.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, (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()); sb.Clear(); Out.Dispose(); }
private String GetCodeForDelegate(TypeDesc delegateType) { var sb = new CppGenerationBuffer(); MethodDesc method = delegateType.GetKnownMethod("Invoke", null); AppendSlotTypeDef(sb, method); sb.AppendLine(); sb.Append("static __slot__"); sb.Append(GetCppMethodName(method)); sb.Append(" __invoke__"); sb.Append(GetCppMethodName(method)); sb.Append("(void * pThis)"); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("return (__slot__"); sb.Append(GetCppMethodName(method)); sb.Append(")((("); sb.Append(GetCppSignatureTypeName(_compilation.TypeSystemContext.GetWellKnownType(WellKnownType.MulticastDelegate))); sb.Append(")pThis)->m_functionPointer);"); sb.Exdent(); sb.AppendLine(); sb.Append("};"); return sb.ToString(); }
private String GetCodeForObjectNode(ObjectNode node, NodeFactory factory) { // virtual slots var nodeData = node.GetData(factory, false); CppGenerationBuffer nodeCode = new CppGenerationBuffer(); /* Create list of byte data. Used to divide contents between reloc and byte data * First val - isReloc * Second val - size of byte data if first value of tuple is false */ List<NodeDataSection> nodeDataSections = new List<NodeDataSection>(); byte[] actualData = new byte[nodeData.Data.Length]; Relocation[] relocs = nodeData.Relocs; int nextRelocOffset = -1; int nextRelocIndex = -1; int lastByteIndex = 0; if (relocs.Length > 0) { nextRelocOffset = relocs[0].Offset; nextRelocIndex = 0; } int i = 0; int offset = 0; CppGenerationBuffer nodeDataDecl = new CppGenerationBuffer(); if (node is ISymbolNode) { offset = (node as ISymbolNode).Offset; i = offset; lastByteIndex = offset; } while (i < nodeData.Data.Length) { if (i == nextRelocOffset) { Relocation reloc = relocs[nextRelocIndex]; int size = _compilation.TypeSystemContext.Target.PointerSize; // Make sure we've gotten the correct size for the reloc System.Diagnostics.Debug.Assert(reloc.RelocType == (size == 8 ? RelocType.IMAGE_REL_BASED_DIR64 : RelocType.IMAGE_REL_BASED_HIGHLOW)); // Update nextRelocIndex/Offset if (++nextRelocIndex < relocs.Length) { nextRelocOffset = relocs[nextRelocIndex].Offset; } nodeDataSections.Add(new NodeDataSection(NodeDataSectionType.Relocation, size)); i += size; lastByteIndex = i; } else { i++; if (i + 1 == nextRelocOffset || i + 1 == nodeData.Data.Length) { nodeDataSections.Add(new NodeDataSection(NodeDataSectionType.ByteData, (i + 1) - lastByteIndex)); } } } string pointerType = node is EETypeNode ? "MethodTable * " : "void* "; nodeCode.Append(pointerType); if (node is EETypeNode) { nodeCode.Append(GetCppMethodDeclarationName((node as EETypeNode).Type, "__getMethodTable")); } else { string mangledName = ((ISymbolNode)node).GetMangledName(); // Rename generic composition and optional fields nodes to avoid name clash with types bool shouldReplaceNamespaceQualifier = node is GenericCompositionNode || node is EETypeOptionalFieldsNode; nodeCode.Append(shouldReplaceNamespaceQualifier ? mangledName.Replace("::", "_") : mangledName); } nodeCode.Append("()"); nodeCode.AppendLine(); nodeCode.Append("{"); nodeCode.Indent(); nodeCode.AppendLine(); nodeCode.Append("static struct {"); nodeCode.AppendLine(); nodeCode.Append(GetCodeForNodeStruct(nodeDataSections, node)); nodeCode.AppendLine(); nodeCode.Append("} mt = {"); nodeCode.Append(GetCodeForNodeData(nodeDataSections, relocs, nodeData.Data, node, offset, factory)); nodeCode.Append("};"); nodeCode.AppendLine(); nodeCode.Append("return ( "); nodeCode.Append(pointerType); nodeCode.Append(")&mt;"); nodeCode.Exdent(); nodeCode.AppendLine(); nodeCode.Append("}"); nodeCode.AppendLine(); return nodeCode.ToString(); }
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>()); }
private void OutputTypeFields(CppGenerationBuffer sb, TypeDesc t) { bool explicitLayout = false; ClassLayoutMetadata classLayoutMetadata = default(ClassLayoutMetadata); if (t.IsValueType) { MetadataType metadataType = (MetadataType)t; if (metadataType.IsExplicitLayout) { explicitLayout = true; classLayoutMetadata = metadataType.GetClassLayout(); } } int instanceFieldIndex = 0; if (explicitLayout) { sb.AppendLine(); sb.Append("union {"); sb.Indent(); } foreach (var field in t.GetFields()) { if (field.IsStatic) { if (field.IsLiteral) continue; TypeDesc fieldType = GetFieldTypeOrPlaceholder(field); CppGenerationBuffer builder; if (!fieldType.IsValueType) { builder = _gcStatics; } else { // TODO: Valuetype statics with GC references builder = _statics; } builder.AppendLine(); builder.Append(GetCppSignatureTypeName(fieldType)); builder.Append(" "); builder.Append(GetCppStaticFieldName(field) + ";"); } else { if (explicitLayout) { sb.AppendLine(); sb.Append("struct {"); sb.Indent(); int offset = classLayoutMetadata.Offsets[instanceFieldIndex].Offset; if (offset > 0) { sb.AppendLine(); sb.Append("char __pad" + instanceFieldIndex + "[" + offset + "];"); } } sb.AppendLine(); sb.Append(GetCppSignatureTypeName(GetFieldTypeOrPlaceholder(field)) + " " + GetCppFieldName(field) + ";"); if (explicitLayout) { sb.Exdent(); sb.AppendLine(); sb.Append("};"); } instanceFieldIndex++; } } if (explicitLayout) { sb.Exdent(); sb.AppendLine(); sb.Append("};"); } }
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>()); } }
private String GetCodeForReadyToRunHeader(ReadyToRunHeaderNode headerNode, NodeFactory factory) { CppGenerationBuffer rtrHeader = new CppGenerationBuffer(); rtrHeader.Append(GetCodeForObjectNode(headerNode, factory)); rtrHeader.AppendLine(); rtrHeader.Append("void* RtRHeaderWrapper() {"); rtrHeader.Indent(); rtrHeader.AppendLine(); rtrHeader.Append("static struct {"); rtrHeader.AppendLine(); rtrHeader.Append("unsigned char leftPadding[8];"); rtrHeader.AppendLine(); rtrHeader.Append("void* rtrHeader;"); rtrHeader.AppendLine(); rtrHeader.Append("unsigned char rightPadding[8];"); rtrHeader.AppendLine(); rtrHeader.Append("} rtrHeaderWrapper = {"); rtrHeader.Indent(); rtrHeader.AppendLine(); rtrHeader.Append("{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },"); rtrHeader.AppendLine(); rtrHeader.Append("(void*)"); rtrHeader.Append(headerNode.GetMangledName()); rtrHeader.Append("(),"); rtrHeader.AppendLine(); rtrHeader.Append("{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }"); rtrHeader.AppendLine(); rtrHeader.Append("};"); rtrHeader.Exdent(); rtrHeader.AppendLine(); rtrHeader.Append("return (void *)&rtrHeaderWrapper;"); rtrHeader.Exdent(); rtrHeader.AppendLine(); rtrHeader.Append("}"); rtrHeader.AppendLine(); return rtrHeader.ToString(); }
private void AppendVirtualSlots(CppGenerationBuffer sb, TypeDesc implType, TypeDesc declType) { var baseType = declType.BaseType; if (baseType != null) AppendVirtualSlots(sb, implType, baseType); List<MethodDesc> virtualSlots; _compilation.NodeFactory.VirtualSlots.TryGetValue(declType, out virtualSlots); if (virtualSlots != null) { for (int i = 0; i < virtualSlots.Count; i++) { MethodDesc declMethod = virtualSlots[i]; MethodDesc implMethod = VirtualFunctionResolution.FindVirtualFunctionTargetMethodOnObjectType(declMethod, implType.GetClosestMetadataType()); sb.AppendLine(); if (implMethod.IsAbstract) { sb.Append("NULL,"); } else { sb.Append("(void*)&"); sb.Append(GetCppTypeName(implMethod.OwningType)); sb.Append("::"); sb.Append(GetCppMethodName(implMethod)); sb.Append(","); } } } }
private string CompileSpecialMethod(MethodDesc method, SpecialMethodKind kind) { var builder = new CppGenerationBuffer(); switch (kind) { case SpecialMethodKind.PInvoke: case SpecialMethodKind.RuntimeImport: { EcmaMethod ecmaMethod = method as EcmaMethod; string importName = kind == SpecialMethodKind.PInvoke ? method.GetPInvokeMethodMetadata().Name : ecmaMethod.GetAttributeStringValue("System.Runtime", "RuntimeImportAttribute"); if (importName == null) importName = method.Name; MethodSignature methodSignature = method.Signature; bool slotCastRequired = false; MethodSignature externCSignature; if (_externCSignatureMap.TryGetValue(importName, out externCSignature)) { slotCastRequired = !externCSignature.Equals(method.Signature); } else { _externCSignatureMap.Add(importName, methodSignature); externCSignature = methodSignature; } builder.AppendLine(); builder.Append(GetCppMethodDeclaration(method, true)); builder.AppendLine(); builder.Append("{"); builder.Indent(); if (slotCastRequired) { AppendSlotTypeDef(builder, method); } builder.AppendLine(); if (!method.Signature.ReturnType.IsVoid) { builder.Append("return "); } if (slotCastRequired) builder.Append("((__slot__" + GetCppMethodName(method) + ")"); builder.Append("::"); builder.Append(importName); if (slotCastRequired) builder.Append(")"); builder.Append("("); builder.Append(GetCppMethodCallParamList(method)); builder.Append(");"); builder.Exdent(); builder.AppendLine(); builder.Append("}"); return builder.ToString(); } default: 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("}"); return builder.ToString(); } }
private void OutputTypes(bool full) { var sb = new CppGenerationBuffer(); if (full) { _statics = new CppGenerationBuffer(); _statics.Indent(); _gcStatics = new CppGenerationBuffer(); _gcStatics.Indent(); _threadStatics = new CppGenerationBuffer(); _threadStatics.Indent(); _gcThreadStatics = new CppGenerationBuffer(); _gcThreadStatics.Indent(); } _emittedTypes = new HashSet<TypeDesc>(); foreach (var t in _cppSignatureNames.Keys) { if (t.IsByRef || t.IsPointer) continue; // Base class types and valuetype instantance field types may be emitted out-of-order to make them // appear before they are used. if (_emittedTypes.Contains(t)) continue; OutputType(sb, t, full); } _emittedTypes = null; if (full) { sb.AppendLine(); sb.Append("struct {"); // No need to indent or add a new line as _statics is already properly indented sb.Append(_statics.ToString()); sb.AppendLine(); sb.Append("} __statics;"); // TODO: Register GC statics with GC sb.AppendLine(); sb.Append("struct {"); // No need to indent or add a new line as _gcStatics is already properly indented sb.Append(_gcStatics.ToString()); sb.AppendLine(); sb.Append("} __gcStatics;"); sb.AppendLine(); // @TODO_SDM: do for real - note: the 'extra' series are just testing the init syntax for 0-length arrays, they should be removed // TODO: preinitialized 0-length arrays are not supported in CLang sb.Append("#ifdef _MSC_VER"); sb.AppendLine(); sb.Append("StaticGcDesc __gcStaticsDescs = { 1, { { sizeof(__gcStatics), 0 }, { 123, 456 }, { 789, 101112 } } };"); sb.AppendLine(); sb.Append("#else"); sb.AppendLine(); sb.Append("StaticGcDesc __gcStaticsDescs;"); sb.AppendLine(); sb.Append("#endif"); sb.AppendLine(); sb.Append("SimpleModuleHeader __module = { &__gcStatics, &__gcStaticsDescs };"); _statics = null; _gcStatics = null; _threadStatics = null; _gcThreadStatics = null; } Out.Write(sb.ToString()); sb.Clear(); }
private void OutputMainMethodStub(MethodDesc entrypoint) { var sb = new CppGenerationBuffer(); 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("::System_Private_CoreLib::Internal::Runtime::CompilerHelpers::StartupCodeHelpers::InitializeModules((intptr_t)RtRHeaderWrapper(), 2);"); 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 String GetCodeForNodeData(List<NodeDataSection> nodeDataSections, Relocation[] relocs, byte[] byteData, DependencyNode node, int offset) { CppGenerationBuffer nodeDataDecl = new CppGenerationBuffer(); int relocCounter = 0; int divisionStartIndex = offset; nodeDataDecl.Indent(); nodeDataDecl.AppendLine(); for (int i = 0; i < nodeDataSections.Count; i++) { nodeDataDecl.Indent(); if (nodeDataSections[i].SectionType == NodeDataSectionType.Relocation) { Relocation reloc = relocs[relocCounter]; if (reloc.Target is CppMethodCodeNode) { var method = reloc.Target as CppMethodCodeNode; nodeDataDecl.Append("(void*)&"); nodeDataDecl.Append(GetCppMethodDeclarationName(method.Method.OwningType, GetCppMethodName(method.Method))); nodeDataDecl.Append(","); } else if (reloc.Target is EETypeNode && node is EETypeNode && _emittedTypes.Contains((reloc.Target as EETypeNode).Type)) { nodeDataDecl.Append(GetCppMethodDeclarationName((reloc.Target as EETypeNode).Type, "__getMethodTable")); nodeDataDecl.Append("(),"); } else { // TODO Add support for other relocs nodeDataDecl.Append("NULL,"); } relocCounter++; } else { AppendFormattedByteArray(nodeDataDecl, byteData, divisionStartIndex, divisionStartIndex + nodeDataSections[i].SectionSize); nodeDataDecl.Append(","); } divisionStartIndex += nodeDataSections[i].SectionSize; nodeDataDecl.AppendLine(); nodeDataDecl.Exdent(); } return nodeDataDecl.ToString(); }
/// <summary> /// Output C++ code for a given codeNode /// </summary> /// <param name="methodCodeNode">The code node to be output</param> /// <param name="methodImplementations">The buffer in which to write out the C++ code</param> private void OutputMethodNode(CppMethodCodeNode methodCodeNode) { Out.WriteLine(); Out.Write(methodCodeNode.CppCode); var alternateName = _compilation.NodeFactory.GetSymbolAlternateName(methodCodeNode); if (alternateName != null) { CppGenerationBuffer sb = new CppGenerationBuffer(); sb.AppendLine(); AppendCppMethodDeclaration(sb, methodCodeNode.Method, true, alternateName); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); if (!methodCodeNode.Method.Signature.ReturnType.IsVoid) { sb.Append("return "); } sb.Append(GetCppMethodDeclarationName(methodCodeNode.Method.OwningType, GetCppMethodName(methodCodeNode.Method))); sb.Append("("); AppendCppMethodCallParamList(sb, methodCodeNode.Method); sb.Append(");"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); Out.Write(sb.ToString()); } }
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, (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()); 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 (nodeType.IsPointer || nodeType.IsByRef || _emittedTypes.Contains(nodeType)) return; _emittedTypes.Add(nodeType); // Create Namespaces string mangledName = GetCppTypeName(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) if (!nodeType.IsPointer && !nodeType.IsByRef) { 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 if (!nodeType.IsPointer && !nodeType.IsByRef) { methodTable.Append(GetCodeForObjectNode(typeNode as ObjectNode, factory)); methodTable.AppendEmptyLine(); } }
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>()); } }
private void OutputExternCSignatures() { 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(); AppendCppMethodDeclaration(sb, null, false, importName, externC.Value); } } Out.Write(sb.ToString()); }
private void OutputTypes(bool full) { var sb = new CppGenerationBuffer(); if (full) { _statics = new CppGenerationBuffer(); _statics.Indent(); _gcStatics = new CppGenerationBuffer(); _gcStatics.Indent(); _threadStatics = new CppGenerationBuffer(); _threadStatics.Indent(); _gcThreadStatics = new CppGenerationBuffer(); _gcThreadStatics.Indent(); } _emittedTypes = new HashSet<TypeDesc>(); foreach (var t in _cppSignatureNames.Keys) { if (t.IsByRef || t.IsPointer) continue; // Base class types and valuetype instantance field types may be emitted out-of-order to make them // appear before they are used. if (_emittedTypes.Contains(t)) continue; OutputType(sb, t, full); } _emittedTypes = null; if (full) { sb.AppendLine(); sb.Append("struct {"); // No need to indent or add a new line as _statics is already properly indented sb.Append(_statics.ToString()); sb.AppendLine(); sb.Append("} __statics;"); // TODO: Register GC statics with GC sb.AppendLine(); sb.Append("struct {"); // No need to indent or add a new line as _gcStatics is already properly indented sb.Append(_gcStatics.ToString()); sb.AppendLine(); sb.Append("} __gcStatics;"); sb.AppendLine(); _statics = null; _gcStatics = null; _threadStatics = null; _gcThreadStatics = null; } Out.Write(sb.ToString()); sb.Clear(); }
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 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(); }
internal void AppendSignatureTypeDef(CppGenerationBuffer sb, string name, MethodSignature methodSignature, TypeDesc thisArgument) { sb.AppendLine(); sb.Append("typedef "); sb.Append(GetCppSignatureTypeName(methodSignature.ReturnType)); sb.Append("(*"); sb.Append(name); sb.Append(")("); int argCount = methodSignature.Length; if (thisArgument != null) argCount++; for (int i = 0; i < argCount; i++) { if (thisArgument != null) { if (i == 0) { sb.Append(GetCppSignatureTypeName(thisArgument)); } else { sb.Append(GetCppSignatureTypeName(methodSignature[i - 1])); } } else { sb.Append(GetCppSignatureTypeName(methodSignature[i])); } if (i != argCount - 1) sb.Append(", "); } sb.Append(");"); }
private void OutputMethod(CppGenerationBuffer sb, MethodDesc m) { sb.AppendLine(); sb.Append(GetCppMethodDeclaration(m, false)); }
private String GetCodeForVirtualMethod(MethodDesc method, int slot) { var sb = new CppGenerationBuffer(); sb.Indent(); if (method.OwningType.IsInterface) { AppendSlotTypeDef(sb, method); sb.Indent(); sb.AppendLine(); sb.Append("static uint16_t"); sb.Append(" __getslot__"); sb.Append(GetCppMethodName(method)); sb.Append("(void * pThis)"); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("return "); sb.Append(slot); sb.Append(";"); sb.AppendLine(); } else { AppendSlotTypeDef(sb, method); sb.Indent(); sb.AppendLine(); sb.Append("static __slot__"); sb.Append(GetCppMethodName(method)); sb.Append(" __getslot__"); sb.Append(GetCppMethodName(method)); sb.Append("(void * pThis)"); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append(" return (__slot__"); sb.Append(GetCppMethodName(method)); sb.Append(")*((void **)(*((RawEEType **)pThis) + 1) + "); sb.Append(slot.ToStringInvariant()); sb.Append(");"); } sb.Exdent(); sb.AppendLine(); sb.Append("};"); sb.Exdent(); return sb.ToString(); }
private void AppendVirtualSlots(CppGenerationBuffer sb, TypeDesc implType, TypeDesc declType) { var baseType = declType.BaseType; if (baseType != null) AppendVirtualSlots(sb, implType, baseType); IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(declType).Slots; for (int i = 0; i < virtualSlots.Count; i++) { MethodDesc declMethod = virtualSlots[i]; MethodDesc implMethod = implType.GetClosestMetadataType().FindVirtualFunctionTargetMethodOnObjectType(declMethod); sb.AppendLine(); if (implMethod.IsAbstract) { sb.Append("NULL,"); } else { sb.Append("(void*)&"); sb.Append(GetCppMethodDeclarationName(implMethod.OwningType, GetCppMethodName(implMethod))); sb.Append(","); } } }
private String GetCodeForNodeData(List<NodeDataSection> nodeDataSections, Relocation[] relocs, byte[] byteData, DependencyNode node, int offset, NodeFactory factory) { CppGenerationBuffer nodeDataDecl = new CppGenerationBuffer(); int relocCounter = 0; int divisionStartIndex = offset; nodeDataDecl.Indent(); nodeDataDecl.Indent(); nodeDataDecl.AppendLine(); for (int i = 0; i < nodeDataSections.Count; i++) { if (nodeDataSections[i].SectionType == NodeDataSectionType.Relocation) { Relocation reloc = relocs[relocCounter]; nodeDataDecl.Append(GetCodeForReloc(reloc, node, factory)); nodeDataDecl.Append(","); relocCounter++; } else { AppendFormattedByteArray(nodeDataDecl, byteData, divisionStartIndex, divisionStartIndex + nodeDataSections[i].SectionSize); nodeDataDecl.Append(","); } divisionStartIndex += nodeDataSections[i].SectionSize; nodeDataDecl.AppendLine(); } return nodeDataDecl.ToString(); }
private String GetCodeForType(TypeDesc type) { var sb = new CppGenerationBuffer(); int totalSlots = 0; TypeDesc t = type; while (t != null) { IReadOnlyList<MethodDesc> virtualSlots = _compilation.NodeFactory.VTable(t).Slots; totalSlots += virtualSlots.Count; t = t.BaseType; } UInt16 flags = 0; try { flags = EETypeBuilderHelpers.ComputeFlags(type); } catch { // TODO: Handling of missing dependencies flags = 0; } sb.Append("MethodTable * "); sb.Append(GetCppMethodDeclarationName(type, "__getMethodTable")); sb.Append("()"); sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("static struct {"); sb.Indent(); // sb.Append(GCDesc); sb.AppendLine(); sb.Append("RawEEType EEType;"); if (totalSlots != 0) { sb.AppendLine(); sb.Append("void * slots["); sb.Append(totalSlots); sb.Append("];"); } sb.Exdent(); sb.AppendLine(); sb.Append("} mt = {"); sb.Indent(); // gcdesc if (type.IsString) { // String has non-standard layout sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("sizeof(uint16_t),"); sb.AppendLine(); sb.Append("0x"); // EEType::_usComponentSize sb.Append(flags.ToStringInvariant("x4")); // EEType::_usFlags sb.Append(","); sb.AppendLine(); sb.Append("2 * sizeof(void*) + sizeof(int32_t) + 2,"); // EEType::_uBaseSize } else if (type.IsSzArray) { sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("sizeof("); sb.Append(GetCppSignatureTypeName(((ArrayType)type).ElementType)); // EEType::_usComponentSize sb.Append("),"); sb.AppendLine(); sb.Append("0x"); sb.Append(flags.ToStringInvariant("x4")); // EEType::_usFlags sb.Append(","); sb.AppendLine(); sb.Append("3 * sizeof(void*),"); // EEType::_uBaseSize } else if (type.IsArray) { sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("sizeof("); sb.Append(GetCppSignatureTypeName(((ArrayType)type).ElementType)); // EEType::_usComponentSize sb.Append("),"); sb.AppendLine(); sb.Append("0x"); sb.Append(flags.ToStringInvariant("x4")); // EEType::_usFlags sb.Append(","); sb.AppendLine(); sb.Append("3 * sizeof(void*) + "); // EEType::_uBaseSize sb.Append(((ArrayType)type).Rank.ToStringInvariant()); sb.Append("* sizeof(int32_t) * 2,"); } else { // sizeof(void*) == size of object header sb.AppendLine(); sb.Append("{"); sb.Indent(); sb.AppendLine(); sb.Append("0,"); sb.AppendLine(); sb.Append("0x"); // EEType::_usComponentSize sb.Append(flags.ToStringInvariant("x")); // EEType::_usFlags sb.Append(","); sb.AppendLine(); sb.Append("AlignBaseSize(sizeof(void*)+sizeof("); // EEType::_uBaseSize sb.Append(GetCppTypeName(type)); sb.Append(")),"); } sb.AppendLine(); // base type if (type.IsArray) { sb.Append(GetCppMethodDeclarationName(((ArrayType)type).ElementType, "__getMethodTable")); sb.Append("()"); } else { var baseType = type.BaseType; if (baseType != null) { sb.Append(GetCppMethodDeclarationName(type.BaseType, "__getMethodTable")); sb.Append("()"); } else { sb.Append("NULL"); } } sb.Exdent(); sb.AppendLine(); sb.Append("},"); // virtual slots if (((DependencyNode)_compilation.NodeFactory.ConstructedTypeSymbol(type)).Marked) AppendVirtualSlots(sb, type, type); sb.Exdent(); sb.AppendLine(); sb.Append("};"); sb.AppendLine(); sb.Append("return (MethodTable *)&mt.EEType;"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); return sb.ToString(); }
/// <summary> /// Output C++ code via a given dependency graph /// </summary> /// <param name="nodes">A set of dependency nodes</param> /// <param name="entrypoint">Code entrypoint</param> /// <param name="factory">Associated NodeFactory instance</param> /// <param name="definitions">Text buffer in which the type and method definitions will be written</param> /// <param name="implementation">Text buffer in which the method implementations will be written</param> public void OutputNodes(IEnumerable<DependencyNode> nodes, NodeFactory factory) { CppGenerationBuffer dispatchPointers = new CppGenerationBuffer(); CppGenerationBuffer forwardDefinitions = new CppGenerationBuffer(); CppGenerationBuffer typeDefinitions = new CppGenerationBuffer(); CppGenerationBuffer methodTables = new CppGenerationBuffer(); CppGenerationBuffer additionalNodes = new CppGenerationBuffer(); DependencyNodeIterator nodeIterator = new DependencyNodeIterator(nodes); // Number of InterfaceDispatchMapNodes needs to be declared explicitly for Ubuntu and OSX int dispatchMapCount = 0; dispatchPointers.AppendLine(); dispatchPointers.Indent(); //RTR header needs to be declared after all modules have already been output string rtrHeader = string.Empty; // Iterate through nodes foreach (var node in nodeIterator.GetNodes()) { if (node is EETypeNode) OutputTypeNode(node as EETypeNode, factory, forwardDefinitions, typeDefinitions, methodTables); else if ((node is EETypeOptionalFieldsNode || node is TypeManagerIndirectionNode || node is GenericCompositionNode) && !(node as ObjectNode).ShouldSkipEmittingObjectNode(factory)) additionalNodes.Append(GetCodeForObjectNode(node as ObjectNode, factory)); else if (node is InterfaceDispatchMapNode) { dispatchPointers.Append("(void *)"); dispatchPointers.Append(((ISymbolNode)node).GetMangledName()); dispatchPointers.Append("(),"); dispatchPointers.AppendLine(); dispatchMapCount++; additionalNodes.Append(GetCodeForObjectNode(node as ObjectNode, factory)); } else if (node is ReadyToRunHeaderNode) rtrHeader = GetCodeForReadyToRunHeader(node as ReadyToRunHeaderNode, factory); } dispatchPointers.AppendLine(); dispatchPointers.Exdent(); Out.Write(forwardDefinitions.ToString()); Out.Write(typeDefinitions.ToString()); Out.Write(additionalNodes.ToString()); Out.Write(methodTables.ToString()); // Emit pointers to dispatch map nodes, to be used in interface dispatch Out.Write("void * dispatchMapModule["); Out.Write(dispatchMapCount); Out.Write("] = {"); Out.Write(dispatchPointers.ToString()); Out.Write("};"); Out.Write(rtrHeader); }
/// <summary> /// Output C++ code for a given codeNode /// </summary> /// <param name="methodCodeNode">The code node to be output</param> /// <param name="methodImplementations">The buffer in which to write out the C++ code</param> private void OutputMethodNode(CppMethodCodeNode methodCodeNode, CppGenerationBuffer methodImplementations) { methodImplementations.AppendLine(); methodImplementations.Append(methodCodeNode.CppCode); var alternateName = _compilation.NodeFactory.GetSymbolAlternateName(methodCodeNode); if (alternateName != null) { methodImplementations.AppendLine(); methodImplementations.Append(GetCppMethodDeclaration(methodCodeNode.Method, true, alternateName)); methodImplementations.AppendLine(); methodImplementations.Append("{"); methodImplementations.Indent(); methodImplementations.AppendLine(); if (!methodCodeNode.Method.Signature.ReturnType.IsVoid) { methodImplementations.Append("return "); } methodImplementations.Append(GetCppMethodDeclarationName(methodCodeNode.Method.OwningType, GetCppMethodName(methodCodeNode.Method))); methodImplementations.Append("("); methodImplementations.Append(GetCppMethodCallParamList(methodCodeNode.Method)); methodImplementations.Append(");"); methodImplementations.Exdent(); methodImplementations.AppendLine(); methodImplementations.Append("}"); } }