diff --git a/Sources/LLVM/ArrayType.swift b/Sources/LLVM/ArrayType.swift index 9d3ab61f..359f5e2e 100644 --- a/Sources/LLVM/ArrayType.swift +++ b/Sources/LLVM/ArrayType.swift @@ -12,6 +12,7 @@ public struct ArrayType: IRType { public let count: Int /// Creates an array type from an underlying element type and count. + /// - note: The context of this type is taken from it's `elementType` public init(elementType: IRType, count: Int) { self.elementType = elementType self.count = count diff --git a/Sources/LLVM/FloatType.swift b/Sources/LLVM/FloatType.swift index 4cb4ca2e..7c7b232d 100644 --- a/Sources/LLVM/FloatType.swift +++ b/Sources/LLVM/FloatType.swift @@ -4,19 +4,51 @@ import cllvm /// `FloatType` enumerates representations of a floating value of a particular /// bit width and semantics. -public enum FloatType: IRType { - /// 16-bit floating point value - case half - /// 32-bit floating point value - case float - /// 64-bit floating point value - case double - /// 80-bit floating point value (X87) - case x86FP80 - /// 128-bit floating point value (112-bit mantissa) - case fp128 - /// 128-bit floating point value (two 64-bits) - case ppcFP128 +public struct FloatType: IRType { + + /// The kind of floating point type this is + public var kind: Kind + + /// Returns the context associated with this type. + public let context: Context + + /// Creates a float type of a particular kind + /// + /// - parameter kind: The kind of floating point type to create + /// - parameter context: The context to create this type in + /// - SeeAlso: http://llvm.org/docs/ProgrammersManual.html#achieving-isolation-with-llvmcontext + public init(kind: Kind, in context: Context = Context.global) { + self.kind = kind + self.context = context + } + + public enum Kind { + /// 16-bit floating point value + case half + /// 32-bit floating point value + case float + /// 64-bit floating point value + case double + /// 80-bit floating point value (X87) + case x86FP80 + /// 128-bit floating point value (112-bit mantissa) + case fp128 + /// 128-bit floating point value (two 64-bits) + case ppcFP128 + } + + /// 16-bit floating point value in the global context + public static let half = FloatType(kind: .half) + /// 32-bit floating point value in the global context + public static let float = FloatType(kind: .float) + /// 64-bit floating point value in the global context + public static let double = FloatType(kind: .double) + /// 80-bit floating point value (X87) in the global context + public static let x86FP80 = FloatType(kind: .x86FP80) + /// 128-bit floating point value (112-bit mantissa) in the global context + public static let fp128 = FloatType(kind: .fp128) + /// 128-bit floating point value (two 64-bits) in the global context + public static let ppcFP128 = FloatType(kind: .ppcFP128) /// Creates a constant floating value of this type from a Swift `Double` value. public func constant(_ value: Double) -> Constant { @@ -25,13 +57,13 @@ public enum FloatType: IRType { /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - switch self { - case .half: return LLVMHalfType() - case .float: return LLVMFloatType() - case .double: return LLVMDoubleType() - case .x86FP80: return LLVMX86FP80Type() - case .fp128: return LLVMFP128Type() - case .ppcFP128: return LLVMPPCFP128Type() + switch kind { + case .half: return LLVMHalfTypeInContext(context.llvm) + case .float: return LLVMFloatTypeInContext(context.llvm) + case .double: return LLVMDoubleTypeInContext(context.llvm) + case .x86FP80: return LLVMX86FP80TypeInContext(context.llvm) + case .fp128: return LLVMFP128TypeInContext(context.llvm) + case .ppcFP128: return LLVMPPCFP128TypeInContext(context.llvm) } } } diff --git a/Sources/LLVM/FunctionType.swift b/Sources/LLVM/FunctionType.swift index acc9cc3b..fe9aba74 100644 --- a/Sources/LLVM/FunctionType.swift +++ b/Sources/LLVM/FunctionType.swift @@ -20,6 +20,7 @@ public struct FunctionType: IRType { /// - parameter returnType: The return type of the function type. /// - parameter isVarArg: Indicates whether this function type is variadic. /// Defaults to `false`. + /// - note: The context of this type is taken from it's `returnType` public init(argTypes: [IRType], returnType: IRType, isVarArg: Bool = false) { self.argTypes = argTypes self.returnType = returnType diff --git a/Sources/LLVM/IRType.swift b/Sources/LLVM/IRType.swift index 95f19253..bc769d28 100644 --- a/Sources/LLVM/IRType.swift +++ b/Sources/LLVM/IRType.swift @@ -29,23 +29,27 @@ public extension IRType { public func constPointerNull() -> IRValue { return LLVMConstPointerNull(asLLVM()) } + + /// Returns the context associated with this type + public var context: Context { + return Context(llvm: LLVMGetTypeContext(asLLVM())) + } } internal func convertType(_ type: LLVMTypeRef) -> IRType { + let context = Context(llvm: LLVMGetTypeContext(type)) switch LLVMGetTypeKind(type) { - case LLVMVoidTypeKind: - return VoidType() - case LLVMHalfTypeKind: - return FloatType.half - case LLVMFloatTypeKind: return FloatType.float - case LLVMDoubleTypeKind: return FloatType.double - case LLVMX86_FP80TypeKind: return FloatType.x86FP80 - case LLVMFP128TypeKind: return FloatType.fp128 - case LLVMPPC_FP128TypeKind: return FloatType.fp128 - case LLVMLabelTypeKind: return LabelType() + case LLVMVoidTypeKind: return VoidType(in: context) + case LLVMFloatTypeKind: return FloatType(kind: .float, in: context) + case LLVMHalfTypeKind: return FloatType(kind: .half, in: context) + case LLVMDoubleTypeKind: return FloatType(kind: .double, in: context) + case LLVMX86_FP80TypeKind: return FloatType(kind: .x86FP80, in: context) + case LLVMFP128TypeKind: return FloatType(kind: .fp128, in: context) + case LLVMPPC_FP128TypeKind: return FloatType(kind: .fp128, in: context) + case LLVMLabelTypeKind: return LabelType(in: context) case LLVMIntegerTypeKind: let width = LLVMGetIntTypeWidth(type) - return IntType(width: Int(width)) + return IntType(width: Int(width), in: context) case LLVMFunctionTypeKind: var params = [IRType]() let count = Int(LLVMCountParamTypes(type)) @@ -76,7 +80,7 @@ internal func convertType(_ type: LLVMTypeRef) -> IRType { case LLVMMetadataTypeKind: return MetadataType(llvm: type) case LLVMX86_MMXTypeKind: - return X86MMXType() + return X86MMXType(in: context) case LLVMTokenTypeKind: return TokenType(llvm: type) default: fatalError("unknown type kind for type \(type)") diff --git a/Sources/LLVM/IntType.swift b/Sources/LLVM/IntType.swift index 2f3e597a..1a2c663d 100644 --- a/Sources/LLVM/IntType.swift +++ b/Sources/LLVM/IntType.swift @@ -11,8 +11,18 @@ public struct IntType: IRType { /// Retrieves the bit width of this integer type. public let width: Int + /// Returns the context associated with this type. + public let context: Context + /// Creates an integer type with the specified bit width. - public init(width: Int) { self.width = width } + /// + /// - parameter width: The width in bits of the integer type + /// - parameter context: The context to create this type in + /// - SeeAlso: http://llvm.org/docs/ProgrammersManual.html#achieving-isolation-with-llvmcontext + public init(width: Int, in context: Context = Context.global) { + self.width = width + self.context = context + } /// Retrieves the `i1` type. public static let int1 = IntType(width: 1) @@ -68,6 +78,6 @@ public struct IntType: IRType { /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - return LLVMIntType(UInt32(width)) + return LLVMIntTypeInContext(context.llvm, UInt32(width)) } } diff --git a/Sources/LLVM/LabelType.swift b/Sources/LLVM/LabelType.swift index c3518b82..74c8facb 100644 --- a/Sources/LLVM/LabelType.swift +++ b/Sources/LLVM/LabelType.swift @@ -4,11 +4,20 @@ import cllvm /// `LabelType` represents code labels. public struct LabelType: IRType { + + /// Returns the context associated with this type. + public let context: Context + /// Creates a code label. - public init() {} + /// + /// - parameter context: The context to create this type in + /// - SeeAlso: http://llvm.org/docs/ProgrammersManual.html#achieving-isolation-with-llvmcontext + public init(in context: Context = Context.global) { + self.context = context + } /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - return LLVMLabelType() + return LLVMLabelTypeInContext(context.llvm) } } diff --git a/Sources/LLVM/Module.swift b/Sources/LLVM/Module.swift index 3facbff7..9a424860 100644 --- a/Sources/LLVM/Module.swift +++ b/Sources/LLVM/Module.swift @@ -5,13 +5,27 @@ import cllvm /// A `Context` represents execution states for the core LLVM IR system. public class Context { internal let llvm: LLVMContextRef + internal let ownsContext: Bool /// Retrieves the global context instance. public static let global = Context(llvm: LLVMGetGlobalContext()!) + /// Creates a `Context` object using `LLVMContextCreate` + public init() { + llvm = LLVMContextCreate() + ownsContext = true + } + /// Creates a `Context` object from an `LLVMContextRef` object. - public init(llvm: LLVMContextRef) { + public init(llvm: LLVMContextRef, ownsContext: Bool = false) { self.llvm = llvm + self.ownsContext = ownsContext + } + + deinit { + if ownsContext { + LLVMContextDispose(llvm) + } } } diff --git a/Sources/LLVM/PointerType.swift b/Sources/LLVM/PointerType.swift index a420aeac..1f9ee2db 100644 --- a/Sources/LLVM/PointerType.swift +++ b/Sources/LLVM/PointerType.swift @@ -23,6 +23,7 @@ public struct PointerType: IRType { /// - parameter pointee: The type of the pointed-to object. /// - parameter addressSpace: The optional address space where the pointed-to /// object resides. + /// - note: The context of this type is taken from it's pointee public init(pointee: IRType, addressSpace: Int = 0) { // FIXME: This class of invalid reference is not caught by Module.verify(), // only `lli`. diff --git a/Sources/LLVM/StructType.swift b/Sources/LLVM/StructType.swift index 085f296f..aa3be8ec 100644 --- a/Sources/LLVM/StructType.swift +++ b/Sources/LLVM/StructType.swift @@ -35,10 +35,12 @@ public struct StructType: IRType { /// - parameter elementTypes: A list of types of members of this structure. /// - parameter isPacked: Whether or not this structure is 1-byte aligned with /// no packing between fields. Defaults to `false`. - public init(elementTypes: [IRType], isPacked: Bool = false) { + /// - parameter context: The context to create this type in + /// - SeeAlso: http://llvm.org/docs/ProgrammersManual.html#achieving-isolation-with-llvmcontext + public init(elementTypes: [IRType], isPacked: Bool = false, in context: Context = Context.global) { var irTypes = elementTypes.map { $0.asLLVM() as Optional } self.llvm = irTypes.withUnsafeMutableBufferPointer { buf in - LLVMStructType(buf.baseAddress, UInt32(buf.count), isPacked.llvm) + return LLVMStructTypeInContext(context.llvm, buf.baseAddress, UInt32(buf.count), isPacked.llvm) } } diff --git a/Sources/LLVM/VectorType.swift b/Sources/LLVM/VectorType.swift index 4a47c409..c7cfeb94 100644 --- a/Sources/LLVM/VectorType.swift +++ b/Sources/LLVM/VectorType.swift @@ -16,6 +16,7 @@ public struct VectorType: IRType { /// /// - parameter elementType: The type of elements of this vector. /// - parameter count: The number of elements in this vector. + /// - note: The context of this type is taken from it's `elementType` public init(elementType: IRType, count: Int) { self.elementType = elementType self.count = count diff --git a/Sources/LLVM/VoidType.swift b/Sources/LLVM/VoidType.swift index ad4a02c0..989f12b2 100644 --- a/Sources/LLVM/VoidType.swift +++ b/Sources/LLVM/VoidType.swift @@ -4,11 +4,20 @@ import cllvm /// The `Void` type represents any value and has no size. public struct VoidType: IRType { + + /// Returns the context associated with this type. + public let context: Context + /// Creates an instance of the `Void` type. - public init() {} + /// + /// - parameter context: The context to create this type in + /// - SeeAlso: http://llvm.org/docs/ProgrammersManual.html#achieving-isolation-with-llvmcontext + public init(in context: Context = Context.global) { + self.context = context + } /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - return LLVMVoidType() + return LLVMVoidTypeInContext(context.llvm) } } diff --git a/Sources/LLVM/X86MMXType.swift b/Sources/LLVM/X86MMXType.swift index 624c8a94..2c1e3539 100644 --- a/Sources/LLVM/X86MMXType.swift +++ b/Sources/LLVM/X86MMXType.swift @@ -9,11 +9,20 @@ import cllvm /// represented as intrinsic or asm calls with arguments and/or results of this /// type. There are no arrays, vectors or constants of this type. public struct X86MMXType: IRType { + + /// Returns the context associated with this type. + public let context: Context + /// Creates an `X86MMXType`. - public init() {} + /// + /// - parameter context: The context to create this type in + /// - SeeAlso: http://llvm.org/docs/ProgrammersManual.html#achieving-isolation-with-llvmcontext + public init(in context: Context = Context.global) { + self.context = context + } /// Retrieves the underlying LLVM type object. public func asLLVM() -> LLVMTypeRef { - return LLVMX86MMXType() + return LLVMX86MMXTypeInContext(context.llvm) } }