diff --git a/Sources/LLVM/Function.swift b/Sources/LLVM/Function.swift index 95cffe0a..4b5e618b 100644 --- a/Sources/LLVM/Function.swift +++ b/Sources/LLVM/Function.swift @@ -113,6 +113,12 @@ public class Function: IRValue { set { LLVMSetLinkage(asLLVM(), newValue.llvm) } } + /// Retrieves the visibility style for this function. + public var visibility: Visibility { + get { return Visibility(llvm: LLVMGetVisibility(asLLVM())) } + set { LLVMSetVisibility(asLLVM(), newValue.llvm) } + } + /// Retrieves the underlying LLVM value object. public func asLLVM() -> LLVMValueRef { return llvm diff --git a/Sources/LLVM/Global.swift b/Sources/LLVM/Global.swift index 15bc5e34..e373f6ed 100644 --- a/Sources/LLVM/Global.swift +++ b/Sources/LLVM/Global.swift @@ -39,6 +39,12 @@ public struct Global: IRValue { set { LLVMSetLinkage(asLLVM(), newValue.llvm) } } + /// Retrieves the visibility style for this global value. + public var visibility: Visibility { + get { return Visibility(llvm: LLVMGetVisibility(asLLVM())) } + set { LLVMSetVisibility(asLLVM(), newValue.llvm) } + } + /// Deletes the global variable from its containing module. /// - note: This does not remove references to this global from the /// module. Ensure you have removed all insructions that reference diff --git a/Sources/LLVM/Linkage.swift b/Sources/LLVM/Linkage.swift index 97123fe0..afc11691 100644 --- a/Sources/LLVM/Linkage.swift +++ b/Sources/LLVM/Linkage.swift @@ -1,5 +1,46 @@ import cllvm +/// `Visibility` enumerates available visibility styles. +public enum Visibility { + /// On targets that use the ELF object file format, default visibility means + /// that the declaration is visible to other modules and, in shared libraries, + /// means that the declared entity may be overridden. On Darwin, default + /// visibility means that the declaration is visible to other modules. Default + /// visibility corresponds to "external linkage" in the language. + case `default` + /// Two declarations of an object with hidden visibility refer to the same + /// object if they are in the same shared object. Usually, hidden visibility + /// indicates that the symbol will not be placed into the dynamic symbol + /// table, so no other module (executable or shared library) can reference it + /// directly. + case hidden + /// On ELF, protected visibility indicates that the symbol will be placed in + /// the dynamic symbol table, but that references within the defining module + /// will bind to the local symbol. That is, the symbol cannot be overridden by + /// another module. + case protected + + static let visibilityMapping: [Visibility: LLVMVisibility] = [ + .default: LLVMDefaultVisibility, + .hidden: LLVMHiddenVisibility, + .protected: LLVMProtectedVisibility, + ] + + internal init(llvm: LLVMVisibility) { + switch llvm { + case LLVMDefaultVisibility: self = .default + case LLVMHiddenVisibility: self = .hidden + case LLVMProtectedVisibility: self = .protected + default: fatalError("unknown visibility type \(llvm)") + } + } + + /// Retrieves the corresponding `LLVMLinkage`. + public var llvm: LLVMVisibility { + return Visibility.visibilityMapping[self]! + } +} + /// `Linkage` enumerates the supported kinds of linkage for global values. All /// global variables and functions have a linkage. public enum Linkage {