private static void BuildStringConcatFunction(Module stringModule, CommonExternalFunctions externalFunctions) { LLVMValueRef stringConcatFunction = stringModule.AddFunction(StringConcatName, CommonModuleSignatures[StringConcatName]); LLVMBasicBlockRef entryBlock = stringConcatFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef slice0 = stringConcatFunction.GetParam(0u), slice1 = stringConcatFunction.GetParam(1u), sliceSize0 = builder.CreateExtractValue(slice0, 1u, "sliceSize0"), sliceSize1 = builder.CreateExtractValue(slice1, 1u, "sliceSize1"), concatSize = builder.CreateAdd(sliceSize0, sliceSize1, "concatSize"), concatAllocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), concatSize, "concatAllocationPtr"), concatAllocationOffsetPtr = builder.CreateGEP(concatAllocationPtr, new LLVMValueRef[] { sliceSize0 }, "concatAllocationOffsetPtr"), stringPtr = stringConcatFunction.GetParam(2u), stringAllocationPtrPtr = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"), stringSizePtr = builder.CreateStructGEP(stringPtr, 1u, "stringSizePtr"); builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { slice0, concatAllocationPtr }, string.Empty); builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { slice1, concatAllocationOffsetPtr }, string.Empty); builder.CreateStore(concatAllocationPtr, stringAllocationPtrPtr); builder.CreateStore(concatSize, stringSizePtr); builder.CreateRetVoid(); }
public LLVMModuleRef GenerateLLVM() { LLVMTypeRef stringType = LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0); var printfArguments = new LLVMTypeRef[] { stringType }; var printf = LLVM.AddFunction(_module, "printf", LLVM.FunctionType(LLVMTypeRef.Int32Type(), printfArguments, LLVMBoolTrue)); LLVM.SetLinkage(printf, LLVMLinkage.LLVMExternalLinkage); var scanfArguments = new LLVMTypeRef[] { stringType }; var scanf = LLVM.AddFunction(_module, "scanf", LLVM.FunctionType(LLVMTypeRef.Int32Type(), scanfArguments, LLVMBoolTrue)); LLVM.SetLinkage(scanf, LLVMLinkage.LLVMExternalLinkage); // Generate functions, globals, etc. for (int i = 0; i < _statements.Count; i++) { _statements[i].Accept(this); } // Generate everything inside the functions while (_valueStack.Count > 0) { _valueStack.Peek().Item2.Accept(this); } return(_module); }
private static void BuildStringFromSliceFunction(Module stringModule, CommonExternalFunctions externalFunctions) { LLVMValueRef stringFromSliceFunction = stringModule.AddFunction(StringFromSliceName, CommonModuleSignatures[StringFromSliceName]); LLVMBasicBlockRef entryBlock = stringFromSliceFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef stringSliceReference = stringFromSliceFunction.GetParam(0u), stringPtr = stringFromSliceFunction.GetParam(1u), stringAllocationPtrPtr = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"), stringSizePtr = builder.CreateStructGEP(stringPtr, 1u, "stringSizePtr"); LLVMValueRef sliceAllocationPtr = builder.CreateExtractValue(stringSliceReference, 0u, "sliceAllocationPtr"); LLVMValueRef sliceSize = builder.CreateExtractValue(stringSliceReference, 1u, "sliceSize"); // Get a pointer to a heap allocation big enough for the string LLVMValueRef allocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), sliceSize, "allocationPtr"); builder.CreateStore(allocationPtr, stringAllocationPtrPtr); // Copy the data from the string slice to the heap allocation LLVMValueRef sizeExtend = builder.CreateSExt(sliceSize, LLVMTypeRef.Int64Type(), "sizeExtend"); builder.CreateCall(externalFunctions.CopyMemoryFunction, new LLVMValueRef[] { allocationPtr, sliceAllocationPtr, sizeExtend }, string.Empty); // Copy actual size into string handle builder.CreateStore(sliceSize, stringSizePtr); builder.CreateRetVoid(); }
public static LLVMTypeRef AsLLVMType(this NIType niType) { if (niType.IsInteger()) { switch (niType.GetKind()) { case NITypeKind.UInt8: case NITypeKind.Int8: return(LLVMTypeRef.Int8Type()); case NITypeKind.UInt16: case NITypeKind.Int16: return(LLVMTypeRef.Int16Type()); case NITypeKind.UInt32: case NITypeKind.Int32: return(LLVMTypeRef.Int32Type()); case NITypeKind.UInt64: case NITypeKind.Int64: return(LLVMTypeRef.Int64Type()); } } if (niType.IsBoolean()) { return(LLVMTypeRef.Int1Type()); } if (niType.IsString()) { return(StringType); } if (niType.IsRebarReferenceType()) { NIType referentType = niType.GetReferentType(); if (referentType == DataTypes.StringSliceType) { return(StringSliceReferenceType); } return(LLVMTypeRef.PointerType(referentType.AsLLVMType(), 0u)); } if (niType == DataTypes.FileHandleType) { return(FileHandleType); } NIType innerType; if (niType.TryDestructureOptionType(out innerType)) { return(CreateLLVMOptionType(innerType.AsLLVMType())); } if (niType == DataTypes.RangeIteratorType) { return(RangeIteratorType); } throw new NotSupportedException("Unsupported type: " + niType); }
public static LLVMTypeRef ToLLVMType(this Type type) { if (type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Vector128 <>)) { var et = type.GetGenericArguments()[0]; return(LLVMTypeRef.VectorType(et.ToLLVMType(), 16U / (uint)Marshal.SizeOf(et))); } if (typeof(MulticastDelegate).IsAssignableFrom(type)) { var mi = type.GetMethod("Invoke"); return(LLVMTypeRef.FunctionType(mi.ReturnType.ToLLVMType(), mi.GetParameters().Select(x => x.ParameterType.ToLLVMType()).ToArray(), false)); } if (type == typeof(void)) { return(LLVMTypeRef.VoidType()); } if (type.IsPointer) { return(LLVMTypeRef.Int64Type()); } switch (Activator.CreateInstance(type)) { case sbyte _: case byte _: return(LLVMTypeRef.Int8Type()); case short _: case ushort _: return(LLVMTypeRef.Int16Type()); case int _: case uint _: return(LLVMTypeRef.Int32Type()); case long _: case ulong _: return(LLVMTypeRef.Int64Type()); case Int128 _: case UInt128 _: return(LLVMTypeRef.IntType(128)); case float _: return(LLVMTypeRef.FloatType()); case double _: return(LLVMTypeRef.DoubleType()); case bool _: return(LLVMTypeRef.IntType(1)); default: throw new NotSupportedException(type.Name); } }
private static void BuildCreateEmptyStringFunction(Module stringModule) { _createEmptyStringFunction = stringModule.AddFunction(CreateEmptyStringName, CommonModuleSignatures[CreateEmptyStringName]); LLVMBasicBlockRef entryBlock = _createEmptyStringFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef stringPtr = _createEmptyStringFunction.GetParam(0u), stringAllocationPtrPtr = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"), stringLengthPtr = builder.CreateStructGEP(stringPtr, 1u, "stringLengthPtr"), allocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), 4.AsLLVMValue(), "allocationPtr"); builder.CreateStore(allocationPtr, stringAllocationPtrPtr); builder.CreateStore(0.AsLLVMValue(), stringLengthPtr); builder.CreateRetVoid(); }
public static LLVMTypeRef LlvmTypeFromName(string name) { // TODO: Implement functionality for pointer types. // Special case for string type. if (name == TypeName.String) { return(LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0)); } // Otherwise, use LLVM type map. else if (LlvmTypeMap.ContainsKey(name)) { return(LlvmTypeMap[name]()); } // Throw an exception. throw new Exception($"Non-registered type resolver for type '{name}'"); }
private static LLVMTypeRef GetLlvmType([NotNull] Type lambdaTypeParam) { switch (lambdaTypeParam) { case PrimaryType primaryType: if (string.Equals(primaryType.Name, "f64", Ordinal)) { return(LLVMSharp.LLVM.DoubleType()); } if (string.Equals(primaryType.Name, "f32", Ordinal)) { return(LLVMTypeRef.FloatType()); } if (string.Equals(primaryType.Name, "i8", Ordinal)) { return(LLVMTypeRef.Int8Type()); } if (string.Equals(primaryType.Name, "i16", Ordinal)) { return(LLVMTypeRef.Int16Type()); } if (string.Equals(primaryType.Name, "i32", Ordinal)) { return(LLVMTypeRef.Int32Type()); } if (string.Equals(primaryType.Name, "i64", Ordinal)) { return(LLVMTypeRef.Int64Type()); } break; case LambdaType lambdaType: return(LLVMTypeRef.FunctionType(GetLlvmType(lambdaType.RetType), (from type in lambdaType.ParamsList select GetLlvmType(type)).ToArray(), false)); case SecondaryType secondaryType: break; } throw new NotImplementedException(); }
private static void BuildStringAppendFunction(Module stringModule, CommonExternalFunctions externalFunctions) { _stringAppendFunction = stringModule.AddFunction(StringAppendName, CommonModuleSignatures[StringAppendName]); LLVMBasicBlockRef entryBlock = _stringAppendFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef stringPtr = _stringAppendFunction.GetParam(0u), sliceReference = _stringAppendFunction.GetParam(1u); // for now, always create a new allocation, rather than trying to use existing one // compute the new allocation size and allocate it LLVMValueRef stringAllocationPtrPtr = builder.CreateStructGEP(stringPtr, 0u, "stringAllocationPtrPtr"), stringSizePtr = builder.CreateStructGEP(stringPtr, 1u, "stringSizePtr"), stringAllocationPtr = builder.CreateLoad(stringAllocationPtrPtr, "stringAllocationPtr"), stringSize = builder.CreateLoad(stringSizePtr, "stringSize"), sliceSize = builder.CreateExtractValue(sliceReference, 1u, "sliceSize"), appendedSize = builder.CreateAdd(stringSize, sliceSize, "appendedSize"), newAllocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), appendedSize, "newAllocationPtr"); // copy from old allocation to new allocation LLVMValueRef stringSlice = builder.CreateCall(_stringFromSliceRetFunction, new LLVMValueRef[] { stringPtr }, "stringSlice"); builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { stringSlice, newAllocationPtr }, string.Empty); // copy from slice to offset in new allocation LLVMValueRef newAllocationOffsetPtr = builder.CreateGEP(newAllocationPtr, new LLVMValueRef[] { stringSize }, "newAllocationOffsetPtr"); builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { sliceReference, newAllocationOffsetPtr }, string.Empty); // free old allocation and update string fields builder.CreateFree(stringAllocationPtr); builder.CreateStore(newAllocationPtr, stringAllocationPtrPtr); builder.CreateStore(appendedSize, stringSizePtr); builder.CreateRetVoid(); }
public static LLVMTypeRef ToLLVMType(this BaseType baseType) { switch (baseType) { case BaseType.String: return(LLVM.PointerType(LLVMTypeRef.Int8Type(), 0)); case BaseType.Int1: return(LLVM.Int1Type()); case BaseType.Int8: return(LLVM.Int8Type()); case BaseType.Int16: return(LLVM.Int16Type()); case BaseType.Int32: return(LLVM.Int32Type()); case BaseType.Int64: return(LLVM.Int64Type()); case BaseType.Int128: return(LLVM.Int128Type()); case BaseType.Float16: return(LLVM.HalfType()); case BaseType.Float32: return(LLVM.FloatType()); case BaseType.Float64: return(LLVM.DoubleType()); case BaseType.Float80: return(LLVM.X86FP80Type()); case BaseType.Float128: return(LLVM.PPCFP128Type()); case BaseType.True: return(LLVM.Int1Type()); case BaseType.False: return(LLVM.Int1Type()); default: throw new Exception("Variable type can't be converted to LLVM type."); } }
private void ImportStoreField(int token, bool isStatic) { if (isStatic) { throw new NotImplementedException("static stfld"); } FieldDesc field = (FieldDesc)_methodIL.GetObject(token); StackEntry valueEntry = _stack.Pop(); StackEntry objectEntry = _stack.Pop(); LLVMValueRef value = valueEntry.LLVMValue; // All integers are int32 on the stack, but need to be resized to fit fields if (valueEntry.Kind == StackValueKind.Int32) { value = LLVM.BuildIntCast(_builder, value, GetLLVMTypeForTypeDesc(field.FieldType), "intfieldcast"); } var untypedObjectPointer = LLVM.BuildPointerCast(_builder, objectEntry.LLVMValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), "stfld"); var storeLocation = LLVM.BuildGEP(_builder, untypedObjectPointer, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)field.Offset.AsInt, LLVMMisc.False) }, "stfld"); var typedStoreLocation = LLVM.BuildPointerCast(_builder, storeLocation, LLVM.PointerType(GetLLVMTypeForTypeDesc(field.FieldType), 0), "stfld"); LLVM.BuildStore(_builder, value, typedStoreLocation); }
public static LLVMValueRef AsLLVMValue(this byte intValue) { return(LLVMSharp.LLVM.ConstInt(LLVMTypeRef.Int8Type(), intValue, false)); }
public bool VisitConstant(Constant constant) { ValueSource outputAllocation = GetTerminalValueSource(constant.OutputTerminal); if (constant.DataType.IsInteger()) { LLVMValueRef constantValueRef; switch (constant.DataType.GetKind()) { case NITypeKind.Int8: constantValueRef = ((sbyte)constant.Value).AsLLVMValue(); break; case NITypeKind.UInt8: constantValueRef = ((byte)constant.Value).AsLLVMValue(); break; case NITypeKind.Int16: constantValueRef = ((short)constant.Value).AsLLVMValue(); break; case NITypeKind.UInt16: constantValueRef = ((ushort)constant.Value).AsLLVMValue(); break; case NITypeKind.Int32: constantValueRef = ((int)constant.Value).AsLLVMValue(); break; case NITypeKind.UInt32: constantValueRef = ((uint)constant.Value).AsLLVMValue(); break; case NITypeKind.Int64: constantValueRef = ((long)constant.Value).AsLLVMValue(); break; case NITypeKind.UInt64: constantValueRef = ((ulong)constant.Value).AsLLVMValue(); break; default: throw new NotSupportedException("Unsupported numeric constant type: " + constant.DataType); } outputAllocation.UpdateValue(_builder, constantValueRef); } else if (constant.Value is bool) { LLVMValueRef constantValueRef = ((bool)constant.Value).AsLLVMValue(); outputAllocation.UpdateValue(_builder, constantValueRef); } else if (constant.Value is string) { VariableReference output = constant.OutputTerminal.GetTrueVariable(); if (output.Type.IsRebarReferenceType() && output.Type.GetReferentType() == DataTypes.StringSliceType) { string stringValue = (string)constant.Value; int length = Encoding.UTF8.GetByteCount(stringValue); LLVMValueRef stringValueConstant = LLVMSharp.LLVM.ConstString(stringValue, (uint)length, true); LLVMValueRef stringConstantPtr = Module.AddGlobal(stringValueConstant.TypeOf(), $"string{constant.UniqueId}"); stringConstantPtr.SetInitializer(stringValueConstant); LLVMValueRef castPointer = _builder.CreateBitCast( stringConstantPtr, LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0), "ptrCast"); LLVMValueRef[] stringSliceFields = new LLVMValueRef[] { castPointer, length.AsLLVMValue() }; LLVMValueRef stringSliceValue = LLVMValueRef.ConstStruct(stringSliceFields, false); outputAllocation.UpdateValue(_builder, stringSliceValue); } } else { throw new NotImplementedException(); } return(true); }
private void ImportStoreField(int token, bool isStatic) { if (isStatic) { throw new NotImplementedException("static stfld"); } FieldDesc field = (FieldDesc)_methodIL.GetObject(token); StackEntry valueEntry = _stack.Pop(); StackEntry objectEntry = _stack.Pop(); var untypedObjectPointer = LLVM.BuildPointerCast(_builder, objectEntry.LLVMValue, LLVM.PointerType(LLVMTypeRef.Int8Type(), 0), "stfld"); var storeLocation = LLVM.BuildGEP(_builder, untypedObjectPointer, new LLVMValueRef[] { LLVM.ConstInt(LLVM.Int32Type(), (ulong)field.Offset.AsInt, LLVMMisc.False) }, "stfld"); var typedStoreLocation = LLVM.BuildPointerCast(_builder, storeLocation, LLVM.PointerType(GetLLVMTypeForTypeDesc(valueEntry.Type), 0), "stfld"); LLVM.BuildStore(_builder, valueEntry.LLVMValue, typedStoreLocation); }
public CommonExternalFunctions(Module addTo) { LLVMTypeRef bytePointerType = LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0); // NB: this will get resolved to the Win32 RtlCopyMemory function. LLVMTypeRef copyMemoryFunctionType = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { bytePointerType, bytePointerType, LLVMTypeRef.Int64Type() }, false); CopyMemoryFunction = addTo.AddFunction("CopyMemory", copyMemoryFunctionType); CopyMemoryFunction.SetLinkage(LLVMLinkage.LLVMExternalLinkage); OutputBoolFunction = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int1Type(), "output_bool"); OutputInt8Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int8Type(), "output_int8"); OutputUInt8Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int8Type(), "output_uint8"); OutputInt16Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int16Type(), "output_int16"); OutputUInt16Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int16Type(), "output_uint16"); OutputInt32Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int32Type(), "output_int32"); OutputUInt32Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int32Type(), "output_uint32"); OutputInt64Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int64Type(), "output_int64"); OutputUInt64Function = CreateSingleParameterVoidFunction(addTo, LLVMTypeRef.Int64Type(), "output_uint64"); LLVMTypeRef outputStringFunctionType = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { bytePointerType, LLVMTypeRef.Int32Type() }, false); OutputStringFunction = addTo.AddFunction("output_string", outputStringFunctionType); OutputStringFunction.SetLinkage(LLVMLinkage.LLVMExternalLinkage); LLVMTypeRef closeHandleFunctionType = LLVMSharp.LLVM.FunctionType( LLVMTypeRef.Int32Type(), // bool new LLVMTypeRef[] { LLVMExtensions.VoidPointerType }, false); CloseHandleFunction = addTo.AddFunction("CloseHandle", closeHandleFunctionType); LLVMTypeRef createFileAFunctionType = LLVMSharp.LLVM.FunctionType( LLVMExtensions.VoidPointerType, new LLVMTypeRef[] { bytePointerType, // filename LLVMTypeRef.Int32Type(), // access LLVMTypeRef.Int32Type(), // share LLVMExtensions.VoidPointerType, // securityAttributes LLVMTypeRef.Int32Type(), // creationDisposition LLVMTypeRef.Int32Type(), // flagsAndAttributes LLVMExtensions.VoidPointerType, // templateFile }, false); CreateFileAFunction = addTo.AddFunction("CreateFileA", createFileAFunctionType); LLVMTypeRef readFileFunctionType = LLVMSharp.LLVM.FunctionType( LLVMTypeRef.Int32Type(), // bool new LLVMTypeRef[] { LLVMExtensions.VoidPointerType, // hFile LLVMExtensions.VoidPointerType, // lpBuffer LLVMTypeRef.Int32Type(), // nNumberOfBytesToRead LLVMTypeRef.PointerType(LLVMTypeRef.Int32Type(), 0), // lpNumberOfBytesRead LLVMExtensions.VoidPointerType, // lpOverlapped }, false); ReadFileFunction = addTo.AddFunction("ReadFile", readFileFunctionType); LLVMTypeRef writeFileFunctionType = LLVMSharp.LLVM.FunctionType( LLVMTypeRef.Int32Type(), // bool new LLVMTypeRef[] { LLVMExtensions.VoidPointerType, // hFile LLVMExtensions.VoidPointerType, // lpBuffer LLVMTypeRef.Int32Type(), // nNumberOfBytesToWrite, LLVMTypeRef.PointerType(LLVMTypeRef.Int32Type(), 0), // lpNumberOfBytesWritten LLVMExtensions.VoidPointerType, // lpOverlapped }, false); WriteFileFunction = addTo.AddFunction("WriteFile", writeFileFunctionType); }
private static void CreateStringModule(Module stringModule) { var externalFunctions = new CommonExternalFunctions(stringModule); CommonModuleSignatures[CopySliceToPointerName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMTypeRef.Int8Type(), 0) }, false); BuildCopySliceToPointerFunction(stringModule, externalFunctions); CommonModuleSignatures[CreateEmptyStringName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) }, false); BuildCreateEmptyStringFunction(stringModule); CommonModuleSignatures[CreateNullTerminatedStringFromSliceName] = LLVMSharp.LLVM.FunctionType( LLVMExtensions.BytePointerType, new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType }, false); BuildCreateNullTerminatedStringFromSlice(stringModule); CommonModuleSignatures[DropStringName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) }, false); BuildDropStringFunction(stringModule); CommonModuleSignatures[OutputStringSliceName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType }, false); BuildOutputStringSliceFunction(stringModule, externalFunctions); CommonModuleSignatures[StringFromSliceName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) }, false); BuildStringFromSliceFunction(stringModule, externalFunctions); CommonModuleSignatures[StringToSliceRetName] = LLVMSharp.LLVM.FunctionType( LLVMExtensions.StringSliceReferenceType, new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0), }, false); BuildStringToSliceRetFunction(stringModule); CommonModuleSignatures[StringToSliceName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0), LLVMTypeRef.PointerType(LLVMExtensions.StringSliceReferenceType, 0) }, false); BuildStringToSliceFunction(stringModule); CommonModuleSignatures[StringAppendName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0), LLVMExtensions.StringSliceReferenceType }, false); BuildStringAppendFunction(stringModule, externalFunctions); CommonModuleSignatures[StringConcatName] = LLVMSharp.LLVM.FunctionType( LLVMSharp.LLVM.VoidType(), new LLVMTypeRef[] { LLVMExtensions.StringSliceReferenceType, LLVMExtensions.StringSliceReferenceType, LLVMTypeRef.PointerType(LLVMExtensions.StringType, 0) }, false); BuildStringConcatFunction(stringModule, externalFunctions); stringModule.VerifyAndThrowIfInvalid(); }
private static void BuildReadLineFromFileHandleFunction(Module fileModule, CommonExternalFunctions externalFunctions) { LLVMValueRef readLineFromFileHandleFunction = fileModule.AddFunction(ReadLineFromFileHandleName, CommonModuleSignatures[ReadLineFromFileHandleName]); LLVMBasicBlockRef entryBlock = readLineFromFileHandleFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMBasicBlockRef loopStartBlock = readLineFromFileHandleFunction.AppendBasicBlock("loopStart"), handleByteBlock = readLineFromFileHandleFunction.AppendBasicBlock("handleByte"), byteIsCRBlock = readLineFromFileHandleFunction.AppendBasicBlock("byteIsCR"), byteIsNotCRBlock = readLineFromFileHandleFunction.AppendBasicBlock("byteIsNotCR"), notNewLineBlock = readLineFromFileHandleFunction.AppendBasicBlock("notNewLine"), appendCRBlock = readLineFromFileHandleFunction.AppendBasicBlock("appendCR"), appendByteBlock = readLineFromFileHandleFunction.AppendBasicBlock("appendByte"), loopEndBlock = readLineFromFileHandleFunction.AppendBasicBlock("loopEnd"), nonEmptyStringBlock = readLineFromFileHandleFunction.AppendBasicBlock("nonEmptyString"), emptyStringBlock = readLineFromFileHandleFunction.AppendBasicBlock("emptyString"); LLVMValueRef fileHandlePtr = readLineFromFileHandleFunction.GetParam(0u), stringPtr = builder.CreateAlloca(LLVMExtensions.StringType, "stringPtr"), carriageReturnPtr = builder.CreateAlloca(LLVMTypeRef.Int8Type(), "carriageReturnPtr"), carriageReturn = ((byte)0xD).AsLLVMValue(), byteReadPtr = builder.CreateAlloca(LLVMTypeRef.Int8Type(), "byteReadPtr"), bytesReadPtr = builder.CreateAlloca(LLVMTypeRef.Int32Type(), "bytesReadPtr"), nonEmptyStringPtr = builder.CreateAlloca(LLVMTypeRef.Int1Type(), "nonEmptyStringPtr"), seenCRPtr = builder.CreateAlloca(LLVMTypeRef.Int1Type(), "seenCRPtr"); builder.CreateStore(carriageReturn, carriageReturnPtr); builder.CreateStore(false.AsLLVMValue(), seenCRPtr); builder.CreateStore(false.AsLLVMValue(), nonEmptyStringPtr); builder.CreateCall(_createEmptyStringFunction, new LLVMValueRef[] { stringPtr }, string.Empty); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(loopStartBlock); LLVMValueRef hFilePtr = builder.CreateStructGEP(fileHandlePtr, 0u, "hFilePtr"), hFile = builder.CreateLoad(hFilePtr, "hFile"); LLVMValueRef readFileResult = builder.CreateCall( externalFunctions.ReadFileFunction, new LLVMValueRef[] { hFile, byteReadPtr, 1.AsLLVMValue(), bytesReadPtr, LLVMExtensions.NullVoidPointer }, "readFileResult"), readFileResultBool = builder.CreateICmp(LLVMIntPredicate.LLVMIntNE, readFileResult, 0.AsLLVMValue(), "readFileResultBool"), bytesRead = builder.CreateLoad(bytesReadPtr, "bytesRead"), zeroBytesRead = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, bytesRead, 0.AsLLVMValue(), "zeroBytesRead"), eof = builder.CreateAnd(readFileResultBool, zeroBytesRead, "eof"); builder.CreateCondBr(eof, loopEndBlock, handleByteBlock); builder.PositionBuilderAtEnd(handleByteBlock); LLVMValueRef byteRead = builder.CreateLoad(byteReadPtr, "byteRead"), byteReadIsCR = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, byteRead, carriageReturn, "byteReadIsCR"); builder.CreateCondBr(byteReadIsCR, byteIsCRBlock, byteIsNotCRBlock); builder.PositionBuilderAtEnd(byteIsCRBlock); builder.CreateStore(true.AsLLVMValue(), seenCRPtr); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(byteIsNotCRBlock); LLVMValueRef byteIsLF = builder.CreateICmp(LLVMIntPredicate.LLVMIntEQ, byteRead, ((byte)0xA).AsLLVMValue(), "byteIsLF"), seenCR = builder.CreateLoad(seenCRPtr, "seenCR"), newLine = builder.CreateAnd(byteIsLF, seenCR, "newLine"); builder.CreateCondBr(newLine, loopEndBlock, notNewLineBlock); builder.PositionBuilderAtEnd(notNewLineBlock); builder.CreateCondBr(seenCR, appendCRBlock, appendByteBlock); builder.PositionBuilderAtEnd(appendCRBlock); LLVMValueRef crSlice = builder.BuildStringSliceReferenceValue(carriageReturnPtr, 1.AsLLVMValue()); builder.CreateCall(_stringAppendFunction, new LLVMValueRef[] { stringPtr, crSlice }, string.Empty); builder.CreateBr(appendByteBlock); builder.PositionBuilderAtEnd(appendByteBlock); LLVMValueRef byteSlice = builder.BuildStringSliceReferenceValue(byteReadPtr, 1.AsLLVMValue()); builder.CreateCall(_stringAppendFunction, new LLVMValueRef[] { stringPtr, byteSlice }, string.Empty); builder.CreateStore(true.AsLLVMValue(), nonEmptyStringPtr); builder.CreateStore(false.AsLLVMValue(), seenCRPtr); builder.CreateBr(loopStartBlock); builder.PositionBuilderAtEnd(loopEndBlock); LLVMValueRef optionStringPtr = readLineFromFileHandleFunction.GetParam(1u), optionStringIsSomePtr = builder.CreateStructGEP(optionStringPtr, 0u, "optionStringIsSomePtr"), nonEmptyString = builder.CreateLoad(nonEmptyStringPtr, "nonEmptyString"); builder.CreateCondBr(nonEmptyString, nonEmptyStringBlock, emptyStringBlock); builder.PositionBuilderAtEnd(nonEmptyStringBlock); builder.CreateStore(true.AsLLVMValue(), optionStringIsSomePtr); LLVMValueRef optionStringInnerValuePtr = builder.CreateStructGEP(optionStringPtr, 1u, "optionStringInnerValuePtr"), stringValue = builder.CreateLoad(stringPtr, "string"); builder.CreateStore(stringValue, optionStringInnerValuePtr); builder.CreateRetVoid(); builder.PositionBuilderAtEnd(emptyStringBlock); builder.CreateStore(false.AsLLVMValue(), optionStringIsSomePtr); builder.CreateCall(_dropStringFunction, new LLVMValueRef[] { stringPtr }, string.Empty); builder.CreateRetVoid(); }
public static LLVMValueRef AsLLVMValue(this sbyte intValue) { return(LLVMSharp.LLVM.ConstInt(LLVMTypeRef.Int8Type(), (ulong)intValue, true)); }
private static void BuildCreateNullTerminatedStringFromSlice(Module stringModule) { _createNullTerminatedStringFromSliceFunction = stringModule.AddFunction(CreateNullTerminatedStringFromSliceName, CommonModuleSignatures[CreateNullTerminatedStringFromSliceName]); LLVMBasicBlockRef entryBlock = _createNullTerminatedStringFromSliceFunction.AppendBasicBlock("entry"); var builder = new IRBuilder(); builder.PositionBuilderAtEnd(entryBlock); LLVMValueRef stringSliceReference = _createNullTerminatedStringFromSliceFunction.GetParam(0u), stringSliceAllocationPtr = builder.CreateExtractValue(stringSliceReference, 0u, "stringSliceAllocationPtr"), stringSliceLength = builder.CreateExtractValue(stringSliceReference, 1u, "stringSliceLength"), nullTerminatedStringLength = builder.CreateAdd(stringSliceLength, 1.AsLLVMValue(), "nullTerminatedStringLength"), nullTerminatedStringAllocationPtr = builder.CreateArrayMalloc(LLVMTypeRef.Int8Type(), nullTerminatedStringLength, "nullTerminatedStringAllocationPtr"), nullBytePtr = builder.CreateGEP(nullTerminatedStringAllocationPtr, new LLVMValueRef[] { stringSliceLength }, "nullBytePtr"); builder.CreateCall(_copySliceToPointerFunction, new LLVMValueRef[] { stringSliceReference, nullTerminatedStringAllocationPtr }, string.Empty); builder.CreateStore(((byte)0).AsLLVMValue(), nullBytePtr); builder.CreateRet(nullTerminatedStringAllocationPtr); }