Skip to content

Commit 8760482

Browse files
committed
Eliminate allocations for enumerable properties
1 parent 21f258a commit 8760482

11 files changed

Lines changed: 248 additions & 98 deletions
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
7+
namespace LLVMSharp.Interop;
8+
9+
public readonly record struct LLVMBasicBlockInstructionsEnumerable(LLVMBasicBlockRef BasicBlock) : IEnumerable<LLVMValueRef>
10+
{
11+
public Enumerator GetEnumerator() => new(BasicBlock);
12+
IEnumerator<LLVMValueRef> IEnumerable<LLVMValueRef>.GetEnumerator() => GetEnumerator();
13+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
14+
15+
public struct Enumerator(LLVMBasicBlockRef basicBlock) : IEnumerator<LLVMValueRef>
16+
{
17+
public LLVMValueRef Current { get; private set; }
18+
readonly object IEnumerator.Current => Current;
19+
readonly void IDisposable.Dispose() { }
20+
public bool MoveNext()
21+
{
22+
if (Current.Handle == 0)
23+
{
24+
Current = basicBlock.FirstInstruction;
25+
}
26+
else
27+
{
28+
Current = Current.NextInstruction;
29+
}
30+
return Current.Handle != 0;
31+
}
32+
public void Reset() => Current = default;
33+
}
34+
}

sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockRef.cs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
22

33
using System;
4-
using System.Collections.Generic;
54

65
namespace LLVMSharp.Interop;
76

@@ -11,18 +10,7 @@ public unsafe partial struct LLVMBasicBlockRef(IntPtr handle) : IEquatable<LLVMB
1110

1211
public readonly LLVMValueRef FirstInstruction => (Handle != IntPtr.Zero) ? LLVM.GetFirstInstruction(this) : default;
1312

14-
public readonly IEnumerable<LLVMValueRef> Instructions
15-
{
16-
get
17-
{
18-
var instruction = FirstInstruction;
19-
while (instruction.Handle != IntPtr.Zero)
20-
{
21-
yield return instruction;
22-
instruction = instruction.NextInstruction;
23-
}
24-
}
25-
}
13+
public readonly LLVMBasicBlockInstructionsEnumerable Instructions => new LLVMBasicBlockInstructionsEnumerable(this);
2614

2715
public readonly LLVMValueRef LastInstruction => (Handle != IntPtr.Zero) ? LLVM.GetLastInstruction(this) : default;
2816

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
7+
namespace LLVMSharp.Interop;
8+
9+
public readonly record struct LLVMModuleFunctionsEnumerable(LLVMModuleRef Module) : IEnumerable<LLVMValueRef>
10+
{
11+
public Enumerator GetEnumerator() => new(Module);
12+
IEnumerator<LLVMValueRef> IEnumerable<LLVMValueRef>.GetEnumerator() => GetEnumerator();
13+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
14+
15+
public struct Enumerator(LLVMModuleRef module) : IEnumerator<LLVMValueRef>
16+
{
17+
public LLVMValueRef Current { get; private set; }
18+
readonly object IEnumerator.Current => Current;
19+
readonly void IDisposable.Dispose() { }
20+
public bool MoveNext()
21+
{
22+
if (Current.Handle == 0)
23+
{
24+
Current = module.FirstFunction;
25+
}
26+
else
27+
{
28+
Current = Current.NextFunction;
29+
}
30+
return Current.Handle != 0;
31+
}
32+
public void Reset() => Current = default;
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
7+
namespace LLVMSharp.Interop;
8+
9+
public readonly record struct LLVMModuleGlobalAliasesEnumerable(LLVMModuleRef Module) : IEnumerable<LLVMValueRef>
10+
{
11+
public Enumerator GetEnumerator() => new(Module);
12+
IEnumerator<LLVMValueRef> IEnumerable<LLVMValueRef>.GetEnumerator() => GetEnumerator();
13+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
14+
15+
public struct Enumerator(LLVMModuleRef module) : IEnumerator<LLVMValueRef>
16+
{
17+
public LLVMValueRef Current { get; private set; }
18+
readonly object IEnumerator.Current => Current;
19+
readonly void IDisposable.Dispose() { }
20+
public bool MoveNext()
21+
{
22+
if (Current.Handle == 0)
23+
{
24+
Current = module.FirstGlobalAlias;
25+
}
26+
else
27+
{
28+
Current = Current.NextGlobalAlias;
29+
}
30+
return Current.Handle != 0;
31+
}
32+
public void Reset() => Current = default;
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
7+
namespace LLVMSharp.Interop;
8+
9+
public readonly record struct LLVMModuleGlobalIFuncsEnumerable(LLVMModuleRef Module) : IEnumerable<LLVMValueRef>
10+
{
11+
public Enumerator GetEnumerator() => new(Module);
12+
IEnumerator<LLVMValueRef> IEnumerable<LLVMValueRef>.GetEnumerator() => GetEnumerator();
13+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
14+
15+
public struct Enumerator(LLVMModuleRef module) : IEnumerator<LLVMValueRef>
16+
{
17+
public LLVMValueRef Current { get; private set; }
18+
readonly object IEnumerator.Current => Current;
19+
readonly void IDisposable.Dispose() { }
20+
public bool MoveNext()
21+
{
22+
if (Current.Handle == 0)
23+
{
24+
Current = module.FirstGlobalIFunc;
25+
}
26+
else
27+
{
28+
Current = Current.NextGlobalIFunc;
29+
}
30+
return Current.Handle != 0;
31+
}
32+
public void Reset() => Current = default;
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
7+
namespace LLVMSharp.Interop;
8+
9+
public readonly record struct LLVMModuleGlobalsEnumerable(LLVMModuleRef Module) : IEnumerable<LLVMValueRef>
10+
{
11+
public Enumerator GetEnumerator() => new(Module);
12+
IEnumerator<LLVMValueRef> IEnumerable<LLVMValueRef>.GetEnumerator() => GetEnumerator();
13+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
14+
15+
public struct Enumerator(LLVMModuleRef module) : IEnumerator<LLVMValueRef>
16+
{
17+
public LLVMValueRef Current { get; private set; }
18+
readonly object IEnumerator.Current => Current;
19+
readonly void IDisposable.Dispose() { }
20+
public bool MoveNext()
21+
{
22+
if (Current.Handle == 0)
23+
{
24+
Current = module.FirstGlobal;
25+
}
26+
else
27+
{
28+
Current = Current.NextGlobal;
29+
}
30+
return Current.Handle != 0;
31+
}
32+
public void Reset() => Current = default;
33+
}
34+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
2+
3+
using System;
4+
using System.Collections;
5+
using System.Collections.Generic;
6+
7+
namespace LLVMSharp.Interop;
8+
9+
public readonly record struct LLVMModuleNamedMetadataEnumerable(LLVMModuleRef Module) : IEnumerable<LLVMNamedMDNodeRef>
10+
{
11+
public Enumerator GetEnumerator() => new(Module);
12+
IEnumerator<LLVMNamedMDNodeRef> IEnumerable<LLVMNamedMDNodeRef>.GetEnumerator() => GetEnumerator();
13+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
14+
15+
public struct Enumerator(LLVMModuleRef module) : IEnumerator<LLVMNamedMDNodeRef>
16+
{
17+
public LLVMNamedMDNodeRef Current { get; private set; }
18+
readonly object IEnumerator.Current => Current;
19+
readonly void IDisposable.Dispose() { }
20+
public bool MoveNext()
21+
{
22+
if (Current.Handle == 0)
23+
{
24+
Current = module.FirstNamedMetadata;
25+
}
26+
else
27+
{
28+
Current = Current.NextNamedMetadata;
29+
}
30+
return Current.Handle != 0;
31+
}
32+
public void Reset() => Current = default;
33+
}
34+
}

sources/LLVMSharp.Interop/Extensions/LLVMModuleRef.cs

Lines changed: 5 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -48,57 +48,13 @@ public readonly string DataLayout
4848

4949
public readonly LLVMNamedMDNodeRef FirstNamedMetadata => (Handle != IntPtr.Zero) ? LLVM.GetFirstNamedMetadata(this) : default;
5050

51-
public readonly IEnumerable<LLVMValueRef> Functions
52-
{
53-
get
54-
{
55-
LLVMValueRef function = FirstFunction;
56-
while (function.Handle != 0)
57-
{
58-
yield return function;
59-
function = function.NextFunction;
60-
}
61-
}
62-
}
51+
public readonly LLVMModuleFunctionsEnumerable Functions => new(this);
6352

64-
public readonly IEnumerable<LLVMValueRef> Globals
65-
{
66-
get
67-
{
68-
LLVMValueRef global = FirstGlobal;
69-
while (global.Handle != 0)
70-
{
71-
yield return global;
72-
global = global.NextGlobal;
73-
}
74-
}
75-
}
53+
public readonly LLVMModuleGlobalsEnumerable Globals => new(this);
7654

77-
public readonly IEnumerable<LLVMValueRef> GlobalAliases
78-
{
79-
get
80-
{
81-
LLVMValueRef alias = FirstGlobalAlias;
82-
while (alias.Handle != 0)
83-
{
84-
yield return alias;
85-
alias = alias.NextGlobalAlias;
86-
}
87-
}
88-
}
55+
public readonly LLVMModuleGlobalAliasesEnumerable GlobalAliases => new(this);
8956

90-
public readonly IEnumerable<LLVMValueRef> GlobalIFuncs
91-
{
92-
get
93-
{
94-
LLVMValueRef ifunc = FirstGlobalIFunc;
95-
while (ifunc.Handle != 0)
96-
{
97-
yield return ifunc;
98-
ifunc = ifunc.NextGlobalIFunc;
99-
}
100-
}
101-
}
57+
public readonly LLVMModuleGlobalIFuncsEnumerable GlobalIFuncs => new(this);
10258

10359
public readonly LLVMValueRef LastFunction => (Handle != IntPtr.Zero) ? LLVM.GetLastFunction(this) : default;
10460

@@ -110,18 +66,7 @@ public readonly IEnumerable<LLVMValueRef> GlobalIFuncs
11066

11167
public readonly LLVMNamedMDNodeRef LastNamedMetadata => (Handle != IntPtr.Zero) ? LLVM.GetLastNamedMetadata(this) : default;
11268

113-
public readonly IEnumerable<LLVMNamedMDNodeRef> NamedMetadata
114-
{
115-
get
116-
{
117-
LLVMNamedMDNodeRef namedMetadata = FirstNamedMetadata;
118-
while (namedMetadata.Handle != 0)
119-
{
120-
yield return namedMetadata;
121-
namedMetadata = namedMetadata.NextNamedMetadata;
122-
}
123-
}
124-
}
69+
public readonly LLVMModuleNamedMetadataEnumerable NamedMetadata => new(this);
12570

12671
public readonly string Target
12772
{

sources/LLVMSharp.Interop/Extensions/LLVMUseRef.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public unsafe partial struct LLVMUseRef(IntPtr handle) : IEquatable<LLVMUseRef>
88
{
99
public IntPtr Handle = handle;
1010

11-
public readonly LLVMUseRef Next => Handle != IntPtr.Zero ? LLVM.GetNextUse(this) : default;
11+
public readonly LLVMUseRef NextUse => Handle != IntPtr.Zero ? LLVM.GetNextUse(this) : default;
1212

1313
public readonly LLVMValueRef User => Handle != IntPtr.Zero ? LLVM.GetUser(this) : default;
1414

sources/LLVMSharp.Interop/Extensions/LLVMValueRef.cs

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
using System;
44
using System.Collections.Generic;
5+
using System.Linq;
56
using static LLVMSharp.Interop.LLVMTailCallKind;
67

78
namespace LLVMSharp.Interop;
@@ -182,7 +183,7 @@ public readonly IEnumerable<LLVMValueRef> Instructions
182183
{
183184
if (IsAFunction != default)
184185
{
185-
return GetFunctionInstructions(this);
186+
return GetBasicBlocks().SelectMany(b => b.Instructions);
186187
}
187188
else if (IsABasicBlock != default)
188189
{
@@ -196,17 +197,6 @@ public readonly IEnumerable<LLVMValueRef> Instructions
196197
{
197198
return [];
198199
}
199-
200-
static IEnumerable<LLVMValueRef> GetFunctionInstructions(LLVMValueRef function)
201-
{
202-
foreach (LLVMBasicBlockRef basicBlock in function.GetBasicBlocks())
203-
{
204-
foreach (LLVMValueRef instruction in basicBlock.Instructions)
205-
{
206-
yield return instruction;
207-
}
208-
}
209-
}
210200
}
211201
}
212202

@@ -629,18 +619,7 @@ public readonly LLVMThreadLocalMode ThreadLocalMode
629619

630620
public readonly LLVMTypeRef TypeOf => (Handle != IntPtr.Zero) ? LLVM.TypeOf(this) : default;
631621

632-
public readonly IEnumerable<LLVMValueRef> Uses
633-
{
634-
get
635-
{
636-
var use = FirstUse;
637-
while (use.Handle != IntPtr.Zero)
638-
{
639-
yield return use.User;
640-
use = use.Next;
641-
}
642-
}
643-
}
622+
public readonly LLVMValueUsesEnumerable Uses => new(this);
644623

645624
public readonly LLVMVisibility Visibility
646625
{

0 commit comments

Comments
 (0)