Skip to content

Commit ec6feb3

Browse files
committed
Extend Modules functions and cString refactoring
1 parent c5040fc commit ec6feb3

File tree

4 files changed

+233
-33
lines changed

4 files changed

+233
-33
lines changed

llvm-api/LLVM/Core/Context.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ public final class Context: ContextRef {
222222
}
223223
}
224224

225-
///Destroy a context instance.
225+
/// Destroy a context instance.
226226
///
227227
/// This should be called for every call to LLVMContextCreate() or memory will be leaked.
228228
public func dispose() {

llvm-api/LLVM/Core/Modules.swift

+228-27
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,28 @@ public final class Module: ModuleRef {
99
/// Retrieves the underlying LLVM value object.
1010
public var moduleRef: LLVMModuleRef { llvm }
1111

12+
/// Inline Asm Dialect
1213
public enum InlineAsmDialect {
1314
case att
1415
case intel
16+
17+
/// Init inline asm dialect from LLVM
18+
public init(llvm: LLVMInlineAsmDialect) {
19+
switch llvm {
20+
case LLVMInlineAsmDialectATT: self = .att
21+
case LLVMInlineAsmDialectIntel: self = .intel
22+
default:
23+
fatalError("Unknown behavior kind")
24+
}
25+
}
26+
27+
/// Get LLVM representation
28+
public var llvm: LLVMInlineAsmDialect {
29+
switch self {
30+
case .att: LLVMInlineAsmDialectATT
31+
case .intel: LLVMInlineAsmDialectIntel
32+
}
33+
}
1534
}
1635

1736
/// Named Metadata Node
@@ -105,53 +124,97 @@ public final class Module: ModuleRef {
105124
fatalError("Unknown behavior kind")
106125
}
107126
}
127+
128+
/// Converts ModuleFlagBehavior to LLVMModuleFlagBehavior
129+
public var moduleFlagBehavior: LLVMModuleFlagBehavior {
130+
switch self {
131+
case .error:
132+
LLVMModuleFlagBehaviorError
133+
case .warning:
134+
LLVMModuleFlagBehaviorWarning
135+
case .require:
136+
LLVMModuleFlagBehaviorRequire
137+
case .override:
138+
LLVMModuleFlagBehaviorOverride
139+
case .append:
140+
LLVMModuleFlagBehaviorAppend
141+
case .appendUnique:
142+
LLVMModuleFlagBehaviorAppendUnique
143+
}
144+
}
108145
}
109146

110147
class Metadata: MetadataRef {
111-
private let llvm:LLVMMetadataRef
112-
public var metadataRef: LLVMMetadataRef {
113-
llvm }
114-
public init(llvm: LLVMMetadataRef ) {
148+
private let llvm: LLVMMetadataRef
149+
public var metadataRef: LLVMMetadataRef {
150+
llvm
151+
}
152+
153+
public init(llvm: LLVMMetadataRef) {
115154
self.llvm = llvm
116155
}
117156
}
118157

158+
/// Represents the possible errors that can be thrown while interacting with a
159+
/// `Module` object.
160+
public enum ModuleError: Error, CustomStringConvertible {
161+
/// Thrown when a module does not pass the module verification process.
162+
/// Includes the reason the module did not pass verification.
163+
case didNotPassVerification(String)
164+
/// Thrown when a module cannot be printed at a given path. Provides the
165+
/// erroneous path and a deeper reason why printing to that path failed.
166+
case couldNotPrint(path: String, error: String)
167+
/// Thrown when a module cannot emit bitcode because it contains erroneous
168+
/// declarations.
169+
case couldNotEmitBitCode(path: String)
170+
171+
public var description: String {
172+
switch self {
173+
case let .didNotPassVerification(message):
174+
"module did not pass verification: \(message)"
175+
case let .couldNotPrint(path, error):
176+
"could not print to file \(path): \(error)"
177+
case let .couldNotEmitBitCode(path):
178+
"could not emit bitcode to file \(path) for an unknown reason"
179+
}
180+
}
181+
}
182+
119183
public class ModuleFlagEntry {
120184
private let llvm: OpaquePointer?
121185
private let bounds: Int
122186

123-
public init(llvm:OpaquePointer?, bounds: Int) {
187+
public init(llvm: OpaquePointer?, bounds: Int) {
124188
self.llvm = llvm
125189
self.bounds = bounds
126190
}
127191

128192
/// Get Metadata flags etries count
129-
public var count: Int { self.bounds }
193+
public var count: Int { bounds }
130194

131-
/// Returns the flag behavior for a module flag entry at a specific index.
195+
/// Returns the flag behavior for a module flag entry at a specific index.
132196
public func getFlagBehavior(at index: UInt32) -> ModuleFlagBehavior {
133197
let bh = LLVMModuleFlagEntriesGetFlagBehavior(llvm, index)
134198
return ModuleFlagBehavior(raw: bh)
135199
}
136200

137-
/// Returns the key for a module flag entry at a specific index.
201+
/// Returns the key for a module flag entry at a specific index.
138202
public func getKey(at index: UInt32) -> String {
139-
var length: Int = 0
203+
var length = 0
140204
let keyPointer = LLVMModuleFlagEntriesGetKey(llvm, index, &length)
141205
return String(cString: keyPointer!)
142-
143206
}
144207

145-
/// Returns the metadata for a module flag entry at a specific index.
208+
/// Returns the metadata for a module flag entry at a specific index.
146209
public func getMetadata(at index: UInt32) -> MetadataRef {
147210
let metadata = LLVMModuleFlagEntriesGetMetadata(llvm, index)!
148211
return Metadata(llvm: metadata)
149212
}
150213

151214
/// Deinitialize this value and dispose of its resources.
152215
deinit {
153-
guard let ptr = llvm else { return }
154-
LLVMDisposeModuleFlagsMetadata(ptr)
216+
guard let ptr = llvm else { return }
217+
LLVMDisposeModuleFlagsMetadata(ptr)
155218
}
156219
}
157220

@@ -190,10 +253,10 @@ public final class Module: ModuleRef {
190253
/// Get and Set the identifier of a module.
191254
public var moduleIdentifier: String {
192255
get {
193-
self.getModuleIdentifier
256+
getModuleIdentifier
194257
}
195258
set {
196-
self.setModuleIdentifier(identifier: newValue)
259+
setModuleIdentifier(identifier: newValue)
197260
}
198261
}
199262

@@ -214,14 +277,14 @@ public final class Module: ModuleRef {
214277
/// Get and Set the original source file name of a module to a string Name
215278
public var sourceFileName: String {
216279
get {
217-
self.getSourceFileName!
280+
getSourceFileName!
218281
}
219282
set {
220-
self.setSourceFileName(fileName: newValue)
283+
setSourceFileName(fileName: newValue)
221284
}
222285
}
223286

224-
///Set the original source file name of a module to a string Name
287+
/// Set the original source file name of a module to a string Name
225288
public func setSourceFileName(fileName: String) {
226289
fileName.withCString { cString in
227290
LLVMSetSourceFileName(llvm, cString, fileName.utf8.count)
@@ -230,7 +293,7 @@ public final class Module: ModuleRef {
230293

231294
/// Obtain the module's original source file name.
232295
public var getSourceFileName: String? {
233-
var length: Int = 0
296+
var length = 0
234297
guard let cString = LLVMGetSourceFileName(llvm, &length) else {
235298
return nil
236299
}
@@ -252,8 +315,7 @@ public final class Module: ModuleRef {
252315
return String(cString: cString)
253316
}
254317

255-
256-
/// Obtain the target triple for a module.
318+
/// Obtain the target triple for a module.
257319
func getTargetTriple() -> String {
258320
guard let targetTriplePointer = LLVMGetTarget(llvm) else {
259321
return ""
@@ -268,14 +330,153 @@ public final class Module: ModuleRef {
268330
}
269331
}
270332

271-
/// Returns the module flags as an array of flag-key-value triples. The caller
272-
/// is responsible for freeing this array by calling
273-
/// `LLVMDisposeModuleFlagsMetadata`.
333+
/// Returns the module flags as an array of flag-key-value triples. The caller
334+
/// is responsible for freeing this array by calling
335+
/// `LLVMDisposeModuleFlagsMetadata`.
274336
public func copyModuleFlagsMetadata() -> ModuleFlagEntry? {
275-
var length: Int = 0
276-
guard let flagsPointer = LLVMCopyModuleFlagsMetadata(llvm, &length) else { return nil }
337+
var length = 0
338+
guard let flagsPointer = LLVMCopyModuleFlagsMetadata(llvm, &length) else { return nil }
339+
340+
return ModuleFlagEntry(llvm: flagsPointer, bounds: length)
341+
}
342+
343+
/// Add a module-level flag to the module-level flags metadata if it doesn't
344+
/// already exist.
345+
func getModuleFlag(key: String) -> MetadataRef {
346+
let keyLen = key.utf8.count
347+
let metadata = key.withCString { keyPtr in
348+
LLVMGetModuleFlag(llvm, keyPtr, keyLen)!
349+
}
350+
return Metadata(llvm: metadata)
351+
}
352+
353+
/// Add a module-level flag to the module-level flags metadata if it doesn't
354+
/// already exist.
355+
func addModuleFlag(behavior: ModuleFlagBehavior, key: String, value: MetadataRef) {
356+
let keyLen = key.utf8.count
357+
key.withCString { keyPtr in
358+
LLVMAddModuleFlag(llvm, behavior.moduleFlagBehavior, keyPtr, keyLen, value.metadataRef)
359+
}
360+
}
361+
362+
/// Dump a representation of a module to stderr.
363+
func dump_module() {
364+
LLVMDumpModule(llvm)
365+
}
366+
367+
/// Print a representation of a module to a file. The ErrorMessage needs to be
368+
/// disposed with `LLVMDisposeMessage`. Returns 0 on success, 1 otherwise.
369+
func printToFile(filename: String) throws {
370+
var errorMessage: UnsafeMutablePointer<CChar>?
371+
372+
let result = filename.withCString { filenamePtr in
373+
LLVMPrintModuleToFile(llvm, filenamePtr, &errorMessage)
374+
}
375+
376+
if result != 0, let errorMessage {
377+
defer { LLVMDisposeMessage(errorMessage) }
378+
let errorString = String(cString: errorMessage)
379+
throw ModuleError.couldNotPrint(path: filename, error: errorString)
380+
}
381+
}
382+
383+
/// Return a string representation of the module. Use
384+
/// `LLVMDisposeMessage` to free the string.
385+
func printToString() -> String {
386+
guard let moduleString = LLVMPrintModuleToString(llvm) else {
387+
return ""
388+
}
389+
defer { LLVMDisposeMessage(moduleString) }
390+
return String(cString: moduleString)
391+
}
392+
393+
/// ==========================
394+
/// Get inline assembly for a module.
395+
public func getModuleInlineAsm(module _: LLVMModuleRef) -> String {
396+
var length = 0
397+
let cString = LLVMGetModuleInlineAsm(llvm, &length)
398+
return String(cString: cString!)
399+
}
400+
401+
/// Set inline assembly for a module.
402+
public func setModuleInlineAsm(asm: String) {
403+
asm.withCString { cString in
404+
LLVMSetModuleInlineAsm2(llvm, cString, asm.utf8.count)
405+
}
406+
}
407+
408+
/// Append inline assembly to a module.
409+
public func appendModuleInlineAsm(asm: String) {
410+
asm.withCString { cString in
411+
LLVMAppendModuleInlineAsm(llvm, cString, asm.utf8.count)
412+
}
413+
}
414+
415+
/// Create the specified uniqued inline asm string.
416+
public func getInlineAsm(type: TypeRef, asmString: String, constraints: String,
417+
hasSideEffects: Bool, isAlignStack: Bool,
418+
dialect: InlineAsmDialect, canThrow: Bool) -> ValueRef
419+
{
420+
let inlineAsm = asmString.withCString { asmCString in
421+
constraints.withCString { constraintsCString in
422+
LLVMGetInlineAsm(type.typeRef, asmCString, asmString.utf8.count, constraintsCString, constraints.utf8.count, hasSideEffects.llvm, isAlignStack.llvm, dialect.llvm, canThrow.llvm)
423+
}
424+
}
425+
return Value(llvm: inlineAsm!)
426+
}
427+
428+
/// Get the template string used for an inline assembly snippet
429+
public func getInlineAsmAsmString(inlineAsmVal: ValueRef) -> String {
430+
var length = 0
431+
let cString = LLVMGetInlineAsmAsmString(inlineAsmVal.valueRef, &length)
432+
return String(cString: cString!)
433+
}
434+
435+
/// Get the raw constraint string for an inline assembly snippet
436+
public func getInlineAsmConstraintString(inlineAsmVal: ValueRef) -> String {
437+
var length = 0
438+
let cString = LLVMGetInlineAsmConstraintString(inlineAsmVal.valueRef, &length)
439+
return String(cString: cString!)
440+
}
441+
442+
/// Get the dialect used by the inline asm snippet
443+
public func getInlineAsmDialect(inlineAsmVal: ValueRef) -> InlineAsmDialect {
444+
let dialect = LLVMGetInlineAsmDialect(inlineAsmVal.valueRef)
445+
return InlineAsmDialect(llvm: dialect)
446+
}
447+
448+
/// Get the function type of the inline assembly snippet. The same type that
449+
/// was passed into LLVMGetInlineAsm originally
450+
public func getInlineAsmFunctionType(inlineAsmVal: ValueRef) -> TypeRef {
451+
let typeRef = LLVMGetInlineAsmFunctionType(inlineAsmVal.valueRef)
452+
return Types(llvm: typeRef!)
453+
}
454+
455+
/// Get if the inline asm snippet has side effects
456+
public func inlineAsmHasSideEffects(inlineAsmVal: ValueRef) -> Bool {
457+
LLVMGetInlineAsmHasSideEffects(inlineAsmVal.valueRef) != 0
458+
}
459+
460+
/// Get if the inline asm snippet needs an aligned stack
461+
public func inlineAsmNeedsAlignedStack(inlineAsmVal: ValueRef) -> Bool {
462+
LLVMGetInlineAsmNeedsAlignedStack(inlineAsmVal.valueRef) != 0
463+
}
464+
465+
/// Get if the inline asm snippet may unwind the stack
466+
public func inlineAsmCanUnwind(inlineAsmVal: ValueRef) -> Bool {
467+
LLVMGetInlineAsmCanUnwind(inlineAsmVal.valueRef) != 0
468+
}
469+
470+
/// Obtain the context to which this module is associated.
471+
func getModuleContext() -> ContextRef {
472+
let context = LLVMGetModuleContext(llvm)
473+
return Context(llvm: context!)
474+
}
277475

278-
return ModuleFlagEntry(llvm: flagsPointer, bounds: length)
476+
/// Obtain an iterator to the first NamedMDNode in a Module.
477+
func getFirstNamedMetadata() -> NamedMetadataNodeRef {
478+
let namedMD = LLVMGetFirstNamedMetadata(llvm)
479+
return NamedMetadataNode(llvm: namedMD!)
279480
}
280481

281482
/// Destroy a module instance.

llvm-api/LLVM/Core/Types/Types.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public protocol ModuleRef {
7272
}
7373

7474
/// Represents an LLVM Named Metadata Node (NamedMDNodeRef).
75-
public protocol NamedMetadataNodeRef {
75+
public protocol NamedMetadataNodeRef {
7676
var namedMetadataNodeRef: LLVMNamedMDNodeRef { get }
7777
}
7878

llvm-api/LLVM/Core/Values/Constants/Composite.swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public enum CompositeConstant {
2727
}
2828

2929
/// Get the given constant data sequential as a string.
30-
public static func getString(value: ValueRef) -> (String, UInt) {
30+
public static func getString(value: ValueRef) -> String? {
3131
var length: UInt = 0
3232
let lengthPtr = UnsafeMutablePointer<UInt>.allocate(capacity: 1)
3333
defer {
@@ -36,10 +36,9 @@ public enum CompositeConstant {
3636

3737
if let cStr = LLVMGetAsString(value.valueRef, lengthPtr) {
3838
length = lengthPtr.pointee
39-
let swiftStr = String(cString: cStr)
40-
return (swiftStr, length)
39+
return String(cString: cStr)
4140
} else {
42-
return ("", 0)
41+
return nil
4342
}
4443
}
4544

0 commit comments

Comments
 (0)