Skip to content

Commit 903ba37

Browse files
authored
[Xamarin.Android.Build.Tasks, monodroid] LLVM-IR Generator (#7163)
Context: e1af958 Commit e1af958 mentioned a TODO: > * Finish the LLVM code generator so that LLVM Marshal Methods are > emitted into `libxamarin-app.so`. Implement LLVM Marshal Methods LLVM-IR executable code generator: * LLVM-IR Generation Infrastructure: * function and instruction attributes * function parameter (declaration/definition) and argument (runtime) handling * function variable (including parameters) handling, including unnamed local variables * support for native function signatures and pointers to functions * The ret, store, load, icmp, br, call and phi instructions * LLVM-IR Marshal Method generator * managed to JNI signature and symbol name translations When `ENABLE_MARSHAL_METHODS` is defined, LLVM-IR code is generated, compiled, and linked. Generated code is minimally tested for runtime behavior, as not all the infrastructure on the Xamarin.Android side is implemented yet. This is on purpose, to keep commits smaller. Support for various LLVM IR instructions is limited only to those we actually use and only to elements of those constructions that we use. As such, it's not a general purpose code generator which allows us to make some assumptions and take some shortcuts, without compromising correctness and validity of the generated code. The native type handling system portion of this commit is to be treated as proof-of-concept: is is not as optimized (design wise) as it should be. The reason for this limitation is that it requires modifying the previous LLVM IR data generation code and it would contribute to this commits' already substantial size. ~~ TODO ~~ Update/rewrite infrastructure to focus on implementing the runtime side of marshal methods, making it possible to actually run applications which use marshal methods. Finish prototyping the infrastructure so that a MAUI app can be run with LLVm Marshal Methods enabled.
1 parent 31bad9c commit 903ba37

28 files changed

+2477
-54
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,9 @@ void Run (DirectoryAssemblyResolver res)
237237
string managedKey = type.FullName.Replace ('/', '.');
238238
string javaKey = JavaNativeTypeManager.ToJniName (type, cache).Replace ('/', '.');
239239

240+
#if ENABLE_MARSHAL_METHODS
241+
Console.WriteLine ($"##G2: {type.FullName} -> {javaKey}");
242+
#endif
240243
acw_map.Write (type.GetPartialAssemblyQualifiedName (cache));
241244
acw_map.Write (';');
242245
acw_map.Write (javaKey);
@@ -384,6 +387,9 @@ bool CreateJavaSources (IEnumerable<TypeDefinition> javaTypes, TypeDefinitionCac
384387

385388
bool ok = true;
386389
foreach (var t in javaTypes) {
390+
#if ENABLE_MARSHAL_METHODS
391+
Console.WriteLine ($"##G0: JCW for {t.FullName}");
392+
#endif
387393
if (t.IsInterface) {
388394
// Interfaces are in typemap but they shouldn't have JCW generated for them
389395
continue;

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class Arm32LlvmIrGenerator : LlvmIrGenerator
1616
public override int PointerSize => 4;
1717
protected override string Triple => "armv7-unknown-linux-android"; // NDK appends API level, we don't need that
1818

19+
static readonly LlvmFunctionAttributeSet commonAttributes = new LlvmFunctionAttributeSet {
20+
new FramePointerFunctionAttribute ("all"),
21+
new TargetCpuFunctionAttribute ("generic"),
22+
new TargetFeaturesFunctionAttribute ("+armv7-a,+d32,+dsp,+fp64,+neon,+thumb-mode,+vfp2,+vfp2sp,+vfp3,+vfp3d16,+vfp3d16sp,+vfp3sp,-aes,-fp-armv8,-fp-armv8d16,-fp-armv8d16sp,-fp-armv8sp,-fp16,-fp16fml,-fullfp16,-sha2,-vfp4,-vfp4d16,-vfp4d16sp,-vfp4sp"),
23+
};
24+
1925
public Arm32LlvmIrGenerator (AndroidTargetArch arch, StreamWriter output, string fileName)
2026
: base (arch, output, fileName)
2127
{}
@@ -25,5 +31,13 @@ protected override void AddModuleFlagsMetadata (List<LlvmIrMetadataItem> flagsFi
2531
base.AddModuleFlagsMetadata (flagsFields);
2632
flagsFields.Add (MetadataManager.AddNumbered (LlvmIrModuleMergeBehavior.Error, "min_enum_size", 4));
2733
}
34+
35+
protected override void InitFunctionAttributes ()
36+
{
37+
base.InitFunctionAttributes ();
38+
39+
FunctionAttributes[FunctionAttributesXamarinAppInit].Add (commonAttributes);
40+
FunctionAttributes[FunctionAttributesJniMethods].Add (commonAttributes);
41+
}
2842
}
2943
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ class Arm64LlvmIrGenerator : LlvmIrGenerator
1616
public override int PointerSize => 8;
1717
protected override string Triple => "aarch64-unknown-linux-android"; // NDK appends API level, we don't need that
1818

19+
static readonly LlvmFunctionAttributeSet commonAttributes = new LlvmFunctionAttributeSet {
20+
new FramePointerFunctionAttribute ("non-leaf"),
21+
new TargetCpuFunctionAttribute ("generic"),
22+
new TargetFeaturesFunctionAttribute ("+neon,+outline-atomics"),
23+
};
24+
1925
public Arm64LlvmIrGenerator (AndroidTargetArch arch, StreamWriter output, string fileName)
2026
: base (arch, output, fileName)
2127
{}
@@ -29,5 +35,13 @@ protected override void AddModuleFlagsMetadata (List<LlvmIrMetadataItem> flagsFi
2935
flagsFields.Add (MetadataManager.AddNumbered (LlvmIrModuleMergeBehavior.Error, "sign-return-address-all", 0));
3036
flagsFields.Add (MetadataManager.AddNumbered (LlvmIrModuleMergeBehavior.Error, "sign-return-address-with-bkey", 0));
3137
}
38+
39+
protected override void InitFunctionAttributes ()
40+
{
41+
base.InitFunctionAttributes ();
42+
43+
FunctionAttributes[FunctionAttributesXamarinAppInit].Add (commonAttributes);
44+
FunctionAttributes[FunctionAttributesJniMethods].Add (commonAttributes);
45+
}
3246
}
3347
}

0 commit comments

Comments
 (0)