Skip to content

Type contexts #101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/LLVM/ArrayType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
72 changes: 52 additions & 20 deletions Sources/LLVM/FloatType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also make a func half(Context: Context)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The initializer should cover it, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does FloatType(.half, in: context)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that’s fine, but it’s less convenient.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most people won't use contexts other than the global, so this approach favors progressive disclosure. It also lessens the API change by making things like FloatType.double still work.

/// 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<Floating> {
Expand All @@ -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)
}
}
}
1 change: 1 addition & 0 deletions Sources/LLVM/FunctionType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 16 additions & 12 deletions Sources/LLVM/IRType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)")
Expand Down
14 changes: 12 additions & 2 deletions Sources/LLVM/IntType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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))
}
}
13 changes: 11 additions & 2 deletions Sources/LLVM/LabelType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
16 changes: 15 additions & 1 deletion Sources/LLVM/Module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}

Expand Down
1 change: 1 addition & 0 deletions Sources/LLVM/PointerType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
Expand Down
6 changes: 4 additions & 2 deletions Sources/LLVM/StructType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down
1 change: 1 addition & 0 deletions Sources/LLVM/VectorType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 11 additions & 2 deletions Sources/LLVM/VoidType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
13 changes: 11 additions & 2 deletions Sources/LLVM/X86MMXType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}