public ModuleRef GenerateModule() { LLVM.DIBuilderCreateCompileUnit(debugBuilder, 0x4, // DW_LANG_C_plus_plus "file", "directory", "SharpLang", false, string.Empty, 1, string.Empty); LLVM.AddModuleFlag(module, "Dwarf Version", 4); LLVM.AddModuleFlag(module, "Debug Info Version", 1); // Process methods while (classesToGenerate.Count > 0) { var classToGenerate = classesToGenerate.Dequeue(); if (classToGenerate.IsLocal) { PrepareClassMethods(classToGenerate); } } // Generate code while (methodsToCompile.Count > 0) { var methodToCompile = methodsToCompile.Dequeue(); Console.WriteLine("Compiling {0}", methodToCompile.Key.FullName); CompileFunction(methodToCompile.Key, methodToCompile.Value); } // Emit "main" which will call the assembly entry point (if any) Function entryPoint; if (assembly.EntryPoint != null && functions.TryGetValue(assembly.EntryPoint, out entryPoint)) { var mainFunctionType = LLVM.FunctionType(int32Type, new TypeRef[0], false); var mainFunction = LLVM.AddFunction(module, "main", mainFunctionType); LLVM.SetLinkage(mainFunction, Linkage.ExternalLinkage); LLVM.PositionBuilderAtEnd(builder, LLVM.AppendBasicBlockInContext(context, mainFunction, string.Empty)); var parameters = (entryPoint.ParameterTypes.Length > 0) ? new[] { LLVM.ConstPointerNull(entryPoint.ParameterTypes[0].DefaultType) } : new ValueRef[0]; LLVM.BuildCall(builder, entryPoint.GeneratedValue, parameters, string.Empty); LLVM.BuildRet(builder, LLVM.ConstInt(int32Type, 0, false)); } LLVM.DIBuilderFinalize(debugBuilder); LLVM.DIBuilderDispose(debugBuilder); LLVM.DisposeBuilder(builder); // Verify module string message; if (LLVM.VerifyModule(module, VerifierFailureAction.PrintMessageAction, out message)) { throw new InvalidOperationException(message); } return(module); }
public ModuleRef GenerateModule() { LLVM.DIBuilderCreateCompileUnit(debugBuilder, 0x4, // DW_LANG_C_plus_plus "file", "directory", "SharpLang", false, string.Empty, 1, string.Empty); LLVM.AddModuleFlag(module, "Dwarf Version", 4); LLVM.AddModuleFlag(module, "Debug Info Version", 1); // Process methods while (classesToGenerate.Count > 0) { var classToGenerate = classesToGenerate.Dequeue(); if (classToGenerate.IsLocal) { PrepareClassMethods(classToGenerate); } } // Generate code while (methodsToCompile.Count > 0) { var methodToCompile = methodsToCompile.Dequeue(); //Console.WriteLine("Compiling {0}", methodToCompile.Key.FullName); CompileFunction(methodToCompile.Key, methodToCompile.Value); } // Prepare global module constructor var globalCtorFunctionType = LLVM.FunctionType(LLVM.VoidTypeInContext(context), new TypeRef[0], false); var globalCtor = LLVM.AddFunction(module, "initializeSharpLangModule", globalCtorFunctionType); LLVM.SetLinkage(globalCtor, Linkage.PrivateLinkage); LLVM.PositionBuilderAtEnd(builder, LLVM.AppendBasicBlockInContext(context, globalCtor, string.Empty)); if (!TestMode) { // Emit metadata var metadataBytes = ReadMetadata(assembly.MainModule.FullyQualifiedName); var metadataData = CreateDataConstant(metadataBytes); var metadataGlobal = LLVM.AddGlobal(module, LLVM.TypeOf(metadataData), "metadata"); LLVM.SetInitializer(metadataGlobal, metadataData); LLVM.SetLinkage(metadataGlobal, Linkage.PrivateLinkage); // Use metadata to initialize a SharpLangModule, that will be created at module load time using a global ctor sharpLangModuleType = GetType(corlib.MainModule.GetType("System.SharpLangModule"), TypeState.VTableEmitted); sharpLangTypeType = GetType(corlib.MainModule.GetType("System.SharpLangTypeDefinition"), TypeState.VTableEmitted); // Was only StackComplete until now // Get ctor for SharpLangModule and SharpLangType var moduleCtor = sharpLangModuleType.Class.Functions.First(x => x.DeclaringType == sharpLangModuleType && x.MethodReference.Resolve().IsConstructor); var registerTypeMethod = sharpLangModuleType.Class.Functions.First(x => x.DeclaringType == sharpLangModuleType && x.MethodReference.Name == "RegisterType"); var sortTypesMethod = sharpLangModuleType.Class.Functions.First(x => x.DeclaringType == sharpLangModuleType && x.MethodReference.Name == "SortTypes"); // Initialize SharpLangModule instance: // new SharpLangModule(moduleName, metadataStart, metadataLength) var sharpLangModuleGlobal = metadataPerModule[assembly.MainModule]; var functionContext = new FunctionCompilerContext(globalCtor); functionContext.Stack = new List <StackValue>(); functionContext.Stack.Add(new StackValue(StackValueType.Object, sharpLangModuleType, sharpLangModuleGlobal)); functionContext.Stack.Add(new StackValue(StackValueType.NativeInt, intPtr, metadataGlobal)); functionContext.Stack.Add(new StackValue(StackValueType.Int32, int32, LLVM.ConstInt(int32LLVM, (ulong)metadataBytes.Length, false))); // Setup initial value (note: VTable should be valid) LLVM.SetLinkage(sharpLangModuleGlobal, Linkage.ExternalLinkage); LLVM.SetInitializer(sharpLangModuleGlobal, SetupVTableConstant(LLVM.ConstNull(sharpLangModuleType.ObjectTypeLLVM), sharpLangModuleType.Class)); metadataPerModule[assembly.MainModule] = sharpLangModuleGlobal; EmitCall(functionContext, moduleCtor.Signature, moduleCtor.GeneratedValue); // Register types foreach (var type in types) { var @class = type.Value.Class; // Skip incomplete types if (@class == null || [email protected]) { continue; } // Skip if no RTTI initializer if (LLVM.GetInitializer(@class.GeneratedEETypeRuntimeLLVM) == ValueRef.Empty) { continue; } // Skip if interface (fake RTTI pointer) if (type.Value.TypeDefinitionCecil.IsInterface) { continue; } functionContext.Stack.Add(new StackValue(StackValueType.NativeInt, intPtr, LLVM.ConstPointerCast(@class.GeneratedEETypeRuntimeLLVM, intPtrLLVM))); EmitCall(functionContext, registerTypeMethod.Signature, registerTypeMethod.GeneratedValue); } // Sort and remove duplicates after adding all our types // TODO: Somehow sort everything before insertion at compile time? EmitCall(functionContext, sortTypesMethod.Signature, sortTypesMethod.GeneratedValue); LLVM.BuildRetVoid(builder); } else { LLVM.BuildRetVoid(builder); } // Prepare global ctors { var globalCtorType = LLVM.StructTypeInContext(context, new[] { int32LLVM, LLVM.PointerType(globalCtorFunctionType, 0) }, true); var globalCtorsGlobal = LLVM.AddGlobal(module, LLVM.ArrayType(globalCtorType, 1), "llvm.global_ctors"); LLVM.SetLinkage(globalCtorsGlobal, Linkage.AppendingLinkage); LLVM.SetInitializer(globalCtorsGlobal, LLVM.ConstArray(globalCtorType, new [] { LLVM.ConstNamedStruct(globalCtorType, new[] { LLVM.ConstInt(int32LLVM, (ulong)65536, false), globalCtor, }) })); } // Emit "main" which will call the assembly entry point (if any) Function entryPoint; if (assembly.EntryPoint != null && functions.TryGetValue(assembly.EntryPoint, out entryPoint)) { var mainFunctionType = LLVM.FunctionType(int32LLVM, new TypeRef[0], false); var mainFunction = LLVM.AddFunction(module, "main", mainFunctionType); LLVM.SetLinkage(mainFunction, Linkage.ExternalLinkage); LLVM.PositionBuilderAtEnd(builder, LLVM.AppendBasicBlockInContext(context, mainFunction, string.Empty)); var parameters = (entryPoint.ParameterTypes.Length > 0) ? new[] { LLVM.ConstPointerNull(entryPoint.ParameterTypes[0].DefaultTypeLLVM) } : new ValueRef[0]; LLVM.BuildCall(builder, entryPoint.GeneratedValue, parameters, string.Empty); LLVM.BuildRet(builder, LLVM.ConstInt(int32LLVM, 0, false)); } LLVM.DIBuilderFinalize(debugBuilder); LLVM.DIBuilderDispose(debugBuilder); LLVM.DisposeBuilder(builder); return(module); }