private static void AppendFormattedByteArray(CppGenerationBuffer sb, byte[] array, int startIndex, int endIndex) { sb.Append("{"); sb.Append("0x"); sb.Append(BitConverter.ToString(array, startIndex, endIndex - startIndex).Replace("-", ",0x")); sb.Append("}"); }
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()); }
public override void Append(CppGenerationBuffer _builder) { long val = BitConverter.DoubleToInt64Bits(Value); _builder.Append("__uint64_to_double(0x"); _builder.Append(val.ToStringInvariant("x8")); _builder.Append(')'); // Let's print the actual value as comment. _builder.Append("/* "); if (Double.IsNaN(Value)) { _builder.Append("NaN"); } else if (Double.IsPositiveInfinity(Value)) { _builder.Append("+Inf"); } else if (Double.IsNegativeInfinity(Value)) { _builder.Append("-Inf"); } else { _builder.Append(Value.ToStringInvariant()); } _builder.Append(" */"); }
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 override void Append(CppGenerationBuffer _builder) { if (Value == long.MinValue) { // See comment on Int32ConstantEntry.Append _builder.Append("(int64_t)(INT64VAL(0x8000000000000000))"); } else { _builder.Append("INT64VAL("); _builder.Append(Value.ToStringInvariant()); _builder.Append(')'); } }
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()); }
private String GetCodeForReloc(Relocation reloc, DependencyNode node, NodeFactory factory) { CppGenerationBuffer relocCode = new CppGenerationBuffer(); if (reloc.Target is CppMethodCodeNode) { var method = reloc.Target as CppMethodCodeNode; relocCode.Append("(void*)&"); relocCode.Append(GetCppMethodDeclarationName(method.Method.OwningType, GetCppMethodName(method.Method), false)); } else if (reloc.Target is EETypeNode && node is EETypeNode) { relocCode.Append(GetCppMethodDeclarationName((reloc.Target as EETypeNode).Type, "__getMethodTable", false)); relocCode.Append("()"); } // Node is either an non-emitted type or a generic composition - both are ignored for CPP codegen else if ((reloc.Target is TypeManagerIndirectionNode || reloc.Target is InterfaceDispatchMapNode || reloc.Target is EETypeOptionalFieldsNode || reloc.Target is GenericCompositionNode) && !(reloc.Target as ObjectNode).ShouldSkipEmittingObjectNode(factory)) { string mangledTargetName = reloc.Target.GetMangledName(factory.NameMangler); bool shouldReplaceNamespaceQualifier = reloc.Target is GenericCompositionNode || reloc.Target is EETypeOptionalFieldsNode; relocCode.Append(shouldReplaceNamespaceQualifier ? mangledTargetName.Replace("::", "_") : mangledTargetName); relocCode.Append("()"); } else if (reloc.Target is ObjectAndOffsetSymbolNode && (reloc.Target as ObjectAndOffsetSymbolNode).Target is ArrayOfEmbeddedPointersNode <InterfaceDispatchMapNode> ) { relocCode.Append("dispatchMapModule"); } else { relocCode.Append("NULL"); } return(relocCode.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(); sb.Append(GetCppMethodDeclaration(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("("); sb.Append(GetCppMethodCallParamList(methodCodeNode.Method)); sb.Append(");"); sb.Exdent(); sb.AppendLine(); sb.Append("}"); Out.Write(sb.ToString()); } }
public override void Append(CppGenerationBuffer _builder) { if (Value == Int32.MinValue) { // Special case as if we were to print int.MinValue in decimal it would be // -2147483648 but C does not understand it this way, it understands // -(2147483648) and 2147483648 does not fit onto a 32-bit integer. // We use an hex value instead. _builder.Append("(int32_t)(0x80000000)"); } else { _builder.Append(Value.ToStringInvariant()); } }
public string GetCppMethodCallParamList(MethodDesc method) { var sb = new CppGenerationBuffer(); var methodSignature = method.Signature; bool hasThis = !methodSignature.IsStatic; int argCount = methodSignature.Length; if (hasThis) { argCount++; } List <string> parameterNames = null; IEnumerable <string> parameters = _compilation.TypeSystemContext.GetParameterNamesForMethod(method); if (parameters != null) { parameterNames = new List <string>(parameters); if (parameterNames.Count != 0) { System.Diagnostics.Debug.Assert(parameterNames.Count == argCount); } else { parameterNames = null; } } for (int i = 0; i < argCount; i++) { if (parameterNames != null) { sb.Append(SanitizeCppVarName(parameterNames[i])); } else { sb.Append("_a"); sb.Append(i.ToStringInvariant()); } if (i != argCount - 1) { sb.Append(", "); } } return(sb.ToString()); }
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 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(); sb.Append(GetCppMethodDeclaration(null, false, importName, externC.Value)); } } 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 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> private void OutputNodes(IEnumerable <DependencyNode> nodes, NodeFactory factory) { CppGenerationBuffer forwardDefinitions = new CppGenerationBuffer(); CppGenerationBuffer typeDefinitions = new CppGenerationBuffer(); CppGenerationBuffer methodTables = new CppGenerationBuffer(); CppGenerationBuffer optionalFields = new CppGenerationBuffer(); DependencyNodeIterator nodeIterator = new DependencyNodeIterator(nodes, factory); // Output well-known types to avoid build errors if (_wellKnownTypeNodes != null) { foreach (var wellKnownTypeNode in _wellKnownTypeNodes) { OutputTypeNode(wellKnownTypeNode, factory, forwardDefinitions, typeDefinitions, methodTables); } } // Iterate through nodes foreach (var node in nodeIterator.GetNodes()) { if (node is EETypeNode && !_emittedTypes.Contains(((EETypeNode)node).Type)) { OutputTypeNode(node as EETypeNode, factory, forwardDefinitions, typeDefinitions, methodTables); } // TODO: Remove the need for the skip check // https://github.com/dotnet/corert/issues/1826 else if (node is EETypeOptionalFieldsNode && (node as ObjectNode).ShouldSkipEmittingObjectNode(factory)) { optionalFields.Append(GetCodeForObjectNode(node as EETypeOptionalFieldsNode, factory)); } } Out.Write(forwardDefinitions.ToString()); Out.Write(typeDefinitions.ToString()); Out.Write(methodTables.ToString()); Out.Write(optionalFields.ToString()); }
private String GetCodeForVirtualMethod(MethodDesc method, int slot) { var sb = new CppGenerationBuffer(); AppendSlotTypeDef(sb, method); 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("};"); return(sb.ToString()); }
public override void Append(CppGenerationBuffer _builder) { _builder.Append("// FIXME: An invalid value was pushed onto the evaluation stack."); Debug.Fail("Invalid stack values shouldn't be appended."); }
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 ISymbolDefinitionNode) { offset = (node as ISymbolDefinitionNode).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(factory.NameMangler); // 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 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 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("};"); } }
private void OutputMethod(CppGenerationBuffer sb, MethodDesc m) { sb.AppendLine(); sb.Append(GetCppMethodDeclaration(m, false)); }
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(); }
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(); } }
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()); } }
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>()); } }
/// <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(factory.NameMangler)); 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); }
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(); }
public string GetCppMethodDeclaration(MethodDesc method, bool implementation, string externalMethodName = null, MethodSignature methodSignature = null) { var sb = new CppGenerationBuffer(); if (methodSignature == null) { methodSignature = method.Signature; } if (externalMethodName != null) { sb.Append("extern \"C\" "); } else { if (!implementation) { sb.Append("static "); } } sb.Append(GetCppSignatureTypeName(methodSignature.ReturnType)); sb.Append(" "); if (externalMethodName != null) { sb.Append(externalMethodName); } else { if (implementation) { sb.Append(GetCppMethodDeclarationName(method.OwningType, GetCppMethodName(method))); } else { sb.Append(GetCppMethodName(method)); } } sb.Append("("); bool hasThis = !methodSignature.IsStatic; int argCount = methodSignature.Length; if (hasThis) { argCount++; } List <string> parameterNames = null; if (method != null) { IEnumerable <string> parameters = _compilation.TypeSystemContext.GetParameterNamesForMethod(method); if (parameters != null) { parameterNames = new List <string>(parameters); if (parameterNames.Count != 0) { System.Diagnostics.Debug.Assert(parameterNames.Count == argCount); } else { parameterNames = null; } } } for (int i = 0; i < argCount; i++) { if (hasThis) { if (i == 0) { var thisType = method.OwningType; if (thisType.IsValueType) { thisType = thisType.MakeByRefType(); } sb.Append(GetCppSignatureTypeName(thisType)); } else { sb.Append(GetCppSignatureTypeName(methodSignature[i - 1])); } } else { sb.Append(GetCppSignatureTypeName(methodSignature[i])); } if (implementation) { sb.Append(" "); if (parameterNames != null) { sb.Append(SanitizeCppVarName(parameterNames[i])); } else { sb.Append("_a"); sb.Append(i.ToStringInvariant()); } } if (i != argCount - 1) { sb.Append(", "); } } sb.Append(")"); if (!implementation) { sb.Append(";"); } return(sb.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()); }
public override void Append(CppGenerationBuffer _builder) { _builder.Append(Name); }