Skip to content

Commit 1ef3255

Browse files
committed
Add some more tracing capabilities
1 parent 95d423d commit 1ef3255

File tree

5 files changed

+157
-3
lines changed

5 files changed

+157
-3
lines changed

src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrFunctionBody.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,4 +301,12 @@ public LlvmIrInstructions.Store Store (LlvmIrVariable to, LlvmIrMetadataItem? tb
301301
Add (ret);
302302
return ret;
303303
}
304+
305+
public LlvmIrInstructions.Unreachable Unreachable ()
306+
{
307+
var ret = new LlvmIrInstructions.Unreachable ();
308+
309+
Add (ret);
310+
return ret;
311+
}
304312
}

src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrInstructions.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -575,4 +575,11 @@ protected override void WriteBody (GeneratorWriteContext context)
575575
WriteAlignment (context, size, isPointer);
576576
}
577577
}
578+
579+
public class Unreachable : LlvmIrInstruction
580+
{
581+
public Unreachable ()
582+
: base ("unreachable")
583+
{}
584+
}
578585
}

src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrModule.cs

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ partial class LlvmIrModule
4040

4141
List<LlvmIrGlobalVariable>? globalVariables;
4242

43+
LlvmIrFunction? puts;
44+
LlvmIrFunction? abort;
45+
4346
public LlvmIrModule ()
4447
{
4548
metadataManager = new LlvmIrMetadataManager ();
@@ -125,6 +128,119 @@ public void Add (LlvmIrFunction func)
125128
functions.Add (func, func);
126129
}
127130

131+
public LlvmIrInstructions.Call CreatePuts (string text, LlvmIrVariable result)
132+
{
133+
EnsurePuts ();
134+
RegisterString (text);
135+
return new LlvmIrInstructions.Call (puts, result, new List<object?> { text });
136+
}
137+
138+
/// <summary>
139+
/// Generate code to call the `puts(3)` C library function to print a simple string to standard output.
140+
/// </summary>
141+
public LlvmIrInstructions.Call AddPuts (LlvmIrFunction function, string text, LlvmIrVariable result)
142+
{
143+
EnsurePuts ();
144+
RegisterString (text);
145+
return function.Body.Call (puts, result, new List<object?> { text });
146+
}
147+
148+
void EnsurePuts ()
149+
{
150+
if (puts != null) {
151+
return;
152+
}
153+
154+
var puts_params = new List<LlvmIrFunctionParameter> {
155+
new (typeof(string), "s"),
156+
};
157+
158+
var puts_sig = new LlvmIrFunctionSignature (
159+
name: "puts",
160+
returnType: typeof(int),
161+
parameters: puts_params
162+
);
163+
puts_sig.ReturnAttributes.NoUndef = true;
164+
165+
puts = DeclareExternalFunction (puts_sig, MakePutsAttributeSet ());
166+
}
167+
168+
LlvmIrFunctionAttributeSet MakePutsAttributeSet ()
169+
{
170+
var ret = new LlvmIrFunctionAttributeSet {
171+
new NofreeFunctionAttribute (),
172+
new NounwindFunctionAttribute (),
173+
};
174+
175+
ret.DoNotAddTargetSpecificAttributes = true;
176+
return AddAttributeSet (ret);
177+
}
178+
179+
public LlvmIrInstructions.Call CreateAbort ()
180+
{
181+
EnsureAbort ();
182+
return new LlvmIrInstructions.Call (abort);
183+
}
184+
185+
public LlvmIrInstructions.Call AddAbort (LlvmIrFunction function)
186+
{
187+
EnsureAbort ();
188+
LlvmIrInstructions.Call ret = function.Body.Call (abort);
189+
function.Body.Unreachable ();
190+
191+
return ret;
192+
}
193+
194+
void EnsureAbort ()
195+
{
196+
if (abort != null) {
197+
return;
198+
}
199+
200+
var abort_sig = new LlvmIrFunctionSignature (name: "abort", returnType: typeof(void));
201+
abort = DeclareExternalFunction (abort_sig, MakeAbortAttributeSet ());
202+
}
203+
204+
LlvmIrFunctionAttributeSet MakeAbortAttributeSet ()
205+
{
206+
var ret = new LlvmIrFunctionAttributeSet {
207+
new NoreturnFunctionAttribute (),
208+
new NounwindFunctionAttribute (),
209+
new NoTrappingMathFunctionAttribute (true),
210+
new StackProtectorBufferSizeFunctionAttribute (8),
211+
};
212+
213+
return AddAttributeSet (ret);
214+
}
215+
216+
public void AddIfThenElse (LlvmIrFunction function, LlvmIrVariable result, LlvmIrIcmpCond condition, LlvmIrVariable conditionVariable, object? conditionComparand, ICollection<LlvmIrInstruction> codeIfThen, ICollection<LlvmIrInstruction>? codeIfElse = null)
217+
{
218+
function.Body.Icmp (condition, conditionVariable, conditionComparand, result);
219+
220+
var labelIfThen = new LlvmIrFunctionLabelItem ();
221+
LlvmIrFunctionLabelItem? labelIfElse = codeIfElse != null ? new LlvmIrFunctionLabelItem () : null;
222+
var labelIfDone = new LlvmIrFunctionLabelItem ();
223+
224+
function.Body.Br (result, labelIfThen, labelIfElse == null ? labelIfDone : labelIfElse);
225+
function.Body.Add (labelIfThen);
226+
227+
AddInstructions (codeIfThen);
228+
229+
if (codeIfElse != null) {
230+
function.Body.Add (labelIfElse);
231+
AddInstructions (codeIfElse);
232+
}
233+
234+
function.Body.Add (labelIfDone);
235+
236+
void AddInstructions (ICollection<LlvmIrInstruction> instructions)
237+
{
238+
foreach (LlvmIrInstruction ins in instructions) {
239+
function.Body.Add (ins);
240+
}
241+
}
242+
}
243+
128244
/// <summary>
129245
/// A shortcut way to add a global variable without first having to create an instance of <see cref="LlvmIrGlobalVariable"/> first. This overload
130246
/// requires the <paramref name="value"/> parameter to not be <c>null</c>.
@@ -509,6 +625,11 @@ public LlvmIrFunction DeclareExternalFunction (LlvmIrFunction func)
509625
return func;
510626
}
511627

628+
public LlvmIrFunction DeclareExternalFunction (LlvmIrFunctionSignature sig, LlvmIrFunctionAttributeSet? attrSet = null)
629+
{
630+
return DeclareExternalFunction (new LlvmIrFunction (sig, attrSet));
631+
}
632+
512633
/// <summary>
513634
/// Since LLVM IR is strongly typed, it requires each structure to be properly declared before it is
514635
/// used throughout the code. This method uses reflection to scan the managed type <typeparamref name="T"/>

src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsNativeAssemblyGenerator.Tracing.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,9 @@ void DoWriteAsprintfCall (LlvmIrFunction func, List<object?> variadicArgs, Aspri
336336
LlvmIrLocalVariable asprintf_failed = func.CreateLocalVariable (typeof(bool), "asprintf_failed");
337337
func.Body.Icmp (LlvmIrIcmpCond.SignedLessThan, asprintf_failed, (int)0, asprintf_failed);
338338

339-
var asprintfIfThenLabel = new LlvmIrFunctionLabelItem ("if.then");
340-
var asprintfIfElseLabel = new LlvmIrFunctionLabelItem ("if.else");
341-
var ifElseDoneLabel = new LlvmIrFunctionLabelItem ("if.done");
339+
var asprintfIfThenLabel = new LlvmIrFunctionLabelItem ();
340+
var asprintfIfElseLabel = new LlvmIrFunctionLabelItem ();
341+
var ifElseDoneLabel = new LlvmIrFunctionLabelItem ();
342342

343343
func.Body.Br (asprintf_failed, asprintfIfThenLabel, asprintfIfElseLabel);
344344

src/Xamarin.Android.Build.Tasks/Utilities/MarshalMethodsNativeAssemblyGenerator.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,24 @@ LlvmIrFunctionAttributeSet MakeMarshalMethodAttributeSet (LlvmIrModule module)
817817

818818
LlvmIrFunctionAttributeSet attrSet = MakeXamarinAppInitAttributeSet (module);
819819
var xamarin_app_init = new LlvmIrFunction (init_signature, attrSet);
820+
821+
// If `fn` is nullptr, print a message and abort...
822+
//
823+
// We must allocate result variables for both the null comparison and puts call here and with names, because
824+
// labels and local unnamed variables must be numbered sequentially otherwise and the `AddIfThenElse` call will
825+
// allocate up to 3 labels which would have been **defined** after these labels, but **used** before them - and
826+
// thus the numbering sequence would be out of order and the .ll file wouldn't build.
827+
var fnNullResult = xamarin_app_init.CreateLocalVariable (typeof(bool), "fnIsNull");
828+
LlvmIrVariable putsResult = xamarin_app_init.CreateLocalVariable (typeof(int), "putsResult");
829+
var ifThenInstructions = new List<LlvmIrInstruction> {
830+
module.CreatePuts ("get_function_pointer MUST be specified\n", putsResult),
831+
module.CreateAbort (),
832+
new LlvmIrInstructions.Unreachable (),
833+
};
834+
835+
module.AddIfThenElse (xamarin_app_init, fnNullResult, LlvmIrIcmpCond.Equal, init_params[1], null, ifThenInstructions);
836+
837+
// ...otherwise store the pointer and return
820838
xamarin_app_init.Body.Store (init_params[1], getFunctionPtrVariable, module.TbaaAnyPointer);
821839
xamarin_app_init.Body.Ret (typeof(void));
822840

0 commit comments

Comments
 (0)