/// <summary> /// Defines the global variable that backs a vtable. /// </summary> /// <param name="Module">The module to declare the global in.</param> /// <param name="Type">The type that owns the vtable.</param> /// <param name="VTableEntryImpls"> /// The list of virtual function pointers in the vtable. /// </param> /// <returns>A vtable global variable.</returns> public static LLVMValueRef DefineVTableGlobal( LLVMModuleBuilder Module, IType Type, LLVMValueRef[] VTableEntryImpls) { var fields = new LLVMValueRef[3]; fields[0] = ConstInt(Int64Type(), Module.GetTypeId(Type), false); fields[1] = ConstInt(Int64Type(), Module.GetTypeIndex(Type), false); fields[2] = ConstArray( PointerType(Int8Type(), 0), VTableEntryImpls); var vtableContents = ConstStruct(fields, false); var vtable = Module.DeclareGlobal( vtableContents.TypeOf(), Type.FullName.ToString() + ".vtable"); vtable.SetGlobalConstant(true); vtable.SetLinkage(LLVMLinkage.LLVMInternalLinkage); vtable.SetInitializer(vtableContents); return(vtable); }
/// <summary> /// Defines this stub's body. /// </summary> /// <param name="Module">The module that defines the stub.</param> public void Emit(LLVMModuleBuilder Module) { var entryBlock = AppendBasicBlock(Function, "entry"); var defaultBlock = AppendBasicBlock(Function, "unknown_type"); var builder = CreateBuilder(); PositionBuilderAtEnd(builder, defaultBlock); BuildUnreachable(builder); DisposeBuilder(builder); builder = CreateBuilder(); PositionBuilderAtEnd(builder, entryBlock); var switchInstr = BuildSwitch(builder, GetParam(Function, 0), defaultBlock, (uint)impls.Count); foreach (var pair in impls) { switchInstr.AddCase( ConstInt(Int64Type(), (ulong)Module.GetTypeIndex(pair.Key), false), WriteReturnBlock(pair.Key, pair.Value, Module)); } DisposeBuilder(builder); }