/// <summary> /// Declares a method. /// </summary> /// <param name="methodDef">The CIL method definition</param> /// <returns>The LLVM value reference</returns> public LLVMValueRef DeclareMethod(MethodDefinition methodDef) { int offset = methodDef.HasThis ? 1 : 0; var paramTypes = new LLVMTypeRef[methodDef.Parameters.Count + offset]; for (int i = 0; i < paramTypes.Length - offset; ++i) { paramTypes[i + offset] = typeLookup.GetLLVMTypeRef(methodDef.Parameters[i].ParameterType); } if (methodDef.HasThis) { paramTypes[0] = typeLookup.GetLLVMTypeRef(methodDef.DeclaringType); if (methodDef.DeclaringType.IsValueType) { paramTypes[0] = LLVM.PointerType(paramTypes[0], 0); } } var fnType = LLVM.FunctionType( typeLookup.GetLLVMTypeRef(methodDef.MethodReturnType.ReturnType), paramTypes, false ); var valueRef = LLVM.AddFunction(moduleRef, methodDef.FullName, fnType); methodMap.Add(methodDef.FullName, valueRef); if (methodDef.IsConstructor && methodDef.IsStatic) { LLVM.SetLinkage(valueRef, LLVMLinkage.LLVMInternalLinkage); LLVM.BuildCall(cctorCallBuilder, valueRef, new LLVMValueRef[0], string.Empty); } return(valueRef); }
/// <summary> /// Declares a static field. /// </summary> /// <param name="fieldDef">The static field definition</param> public void DeclareField(FieldDefinition fieldDef) { var globalType = typeLookup.GetLLVMTypeRef(fieldDef.FieldType); var globalValue = LLVM.AddGlobal(moduleRef, globalType, fieldDef.FullName); fieldMap.Add(fieldDef, globalValue); // TODO: optimize using InitialValue? /*System.Console.WriteLine(fieldDef.InitialValue); * foreach(byte b in fieldDef.InitialValue) * System.Console.WriteLine(b);*/ LLVM.SetInitializer(globalValue, LLVM.ConstNull(globalType)); }
public void Compile() { if (offsetToBasicBlock.Count > 0) { throw new InvalidOperationException("This method is already compiled."); } LLVMBuilderRef builder = LLVM.CreateBuilder(); // Add the entry point as the first basic block. { var it = MethodDef.Body.Instructions.GetEnumerator(); it.MoveNext(); AddBasicBlockAt(it.Current); } // Generate the entry point code for arguments. LLVM.PositionBuilderAtEnd(builder, offsetToBasicBlock[0].LLVMBlock); uint paramCount = LLVM.CountParams(FunctionValueRef); ArgumentValues = new EmulatedStateValue[paramCount]; int offset = MethodDef.HasThis ? 1 : 0; for (uint i = 0; i < paramCount; ++i) { LLVMValueRef param = LLVM.GetParam(FunctionValueRef, i); var valueRef = LLVM.BuildAlloca(builder, LLVM.TypeOf(param), "arg" + i); TypeInfo typeInfo; if (MethodDef.HasThis && i == 0) { typeInfo = TypeInfo.Reference; } else { typeInfo = MethodDef.Parameters[(int)i - offset].ParameterType.GetTypeInfo(); } ArgumentValues[i] = new EmulatedStateValue(valueRef, typeInfo); LLVM.BuildStore(builder, param, valueRef); } // Generate the entry point code for locals. { var locals = MethodDef.Body.Variables; LocalValues = new EmulatedStateValue[locals.Count]; for (int i = 0; i < locals.Count; ++i) { var cilType = locals[i].VariableType; var valueRef = LLVM.BuildAlloca(builder, TypeLookup.GetLLVMTypeRef(cilType), "local" + i); LocalValues[i] = new EmulatedStateValue(valueRef, cilType.GetTypeInfo()); } } // Now, find the basic blocks. { int currentBlockIndex = 0; foreach (Instruction insn in MethodDef.Body.Instructions) { if (HasBasicBlock(insn.Offset)) { // This is a fallthrough? if (currentBlockIndex != insn.Offset) { // Can't be fallthrough if previous instruction was an unconditional branch. if (!insn.Previous.IsUnconditionalBranchInstruction()) { AddOutgoingEdge(currentBlockIndex, insn.Offset); } } currentBlockIndex = insn.Offset; } if (insn.IsBranchInstruction()) { AddBasicBlockAt((Instruction)insn.Operand); AddOutgoingEdge(currentBlockIndex, ((Instruction)insn.Operand).Offset); AddBasicBlockAt(insn.Next); // Can't be fallthrough if current instruction was an unconditional branch. if (!insn.IsUnconditionalBranchInstruction()) { AddOutgoingEdge(currentBlockIndex, insn.Next.Offset); } } } } compileBasicBlock(builder, 0); LLVM.DisposeBuilder(builder); }