riscv64: rewrite `CreateTrampoline` using assembler to generate code.

Previously we did not have an assembler for RISC-V, so the instructions
were hardcoded manually. This commit does not change the generated
instructions (aside from using a different temporary register).

Also, fix a clang-tidy error triggered by this commit (add noexcept to
constructor).

Bug: 283082089

Test: boot cuttlefish, observe no crashes in zygote:
  $ lunch aosp_cf_riscv64_phone-userdebug && m
  $ launch_cvd --gpu_mode=drm_virgl

Test: lunch aosp_arm64-userdebug && m art-tidy

Change-Id: I512a1d408ee3837a4a7631cad6e5da6244b402d4
diff --git a/compiler/trampolines/trampoline_compiler.cc b/compiler/trampolines/trampoline_compiler.cc
index e542763..3821399 100644
--- a/compiler/trampolines/trampoline_compiler.cc
+++ b/compiler/trampolines/trampoline_compiler.cc
@@ -28,6 +28,10 @@
 #include "utils/arm64/assembler_arm64.h"
 #endif
 
+#ifdef ART_ENABLE_CODEGEN_riscv64
+#include "utils/riscv64/assembler_riscv64.h"
+#endif
+
 #ifdef ART_ENABLE_CODEGEN_x86
 #include "utils/x86/assembler_x86.h"
 #endif
@@ -129,48 +133,33 @@
 
 #ifdef ART_ENABLE_CODEGEN_riscv64
 namespace riscv64 {
-static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(
-    ArenaAllocator* /*allocator*/, EntryPointCallingConvention abi, ThreadOffset64 offset) {
-  if (abi == kJniAbi) {
-    // TODO(riscv64): implement this properly once we have macro-assembler for RISC-V.
-    std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(2));
-    uint8_t* bytes = entry_stub->data();
+static std::unique_ptr<const std::vector<uint8_t>> CreateTrampoline(ArenaAllocator* allocator,
+                                                                    EntryPointCallingConvention abi,
+                                                                    ThreadOffset64 offset) {
+  Riscv64Assembler assembler(allocator);
 
-    // 0000    unimp
-    bytes[0] = 0x00;
-    bytes[1] = 0x00;
-
-    return std::move(entry_stub);
-  } else {
-    CHECK_LE(offset.Int32Value(), 0x7ff);
-    uint8_t offset_hi = (offset.Int32Value() & 0x7ff) >> 4;
-    uint8_t offset_lo = (offset.Int32Value() & 0xf) << 4;
-
-    std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(6));
-    uint8_t* bytes = entry_stub->data();
-
-    if (abi == kInterpreterAbi) {
-      // Thread* is first argument (A0) in interpreter ABI.
-      // xxx53283     ld t0, xxx(a0)
-      bytes[0] = 0x83;
-      bytes[1] = 0x32;
-      bytes[2] = offset_lo | 0x05;
-      bytes[3] = offset_hi;
-    } else {
-      // abi == kQuickAbi: TR holds Thread*.
-      // xxx4b283     ld t0, xxx(s1)
-      bytes[0] = 0x83;
-      bytes[1] = 0xb2;
-      bytes[2] = offset_lo | 0x04;
-      bytes[3] = offset_hi;
-    }
-
-    // 8282    jr t0
-    bytes[4] = 0x82;
-    bytes[5] = 0x82;
-
-    return std::move(entry_stub);
+  switch (abi) {
+    case kInterpreterAbi:  // Thread* is first argument (A0) in interpreter ABI.
+      __ Loadd(TMP, A0, offset.Int32Value());
+      __ Jr(TMP);
+      break;
+    case kJniAbi:  // Load via Thread* held in JNIEnv* in first argument (A0).
+      // TODO(riscv64): implement this.
+      __ Unimp();
+      break;
+    case kQuickAbi:  // TR holds Thread*.
+      __ Loadd(TMP, TR, offset.Int32Value());
+      __ Jr(TMP);
+      break;
   }
+
+  __ FinalizeCode();
+  size_t cs = __ CodeSize();
+  std::unique_ptr<std::vector<uint8_t>> entry_stub(new std::vector<uint8_t>(cs));
+  MemoryRegion code(entry_stub->data(), entry_stub->size());
+  __ FinalizeInstructions(code);
+
+  return std::move(entry_stub);
 }
 }  // namespace riscv64
 #endif  // ART_ENABLE_CODEGEN_riscv64
diff --git a/compiler/utils/riscv64/assembler_riscv64.h b/compiler/utils/riscv64/assembler_riscv64.h
index d94433f..9cb6519 100644
--- a/compiler/utils/riscv64/assembler_riscv64.h
+++ b/compiler/utils/riscv64/assembler_riscv64.h
@@ -66,7 +66,7 @@
  public:
   Riscv64Label() : prev_branch_id_(kNoPrevBranchId) {}
 
-  Riscv64Label(Riscv64Label&& src)
+  Riscv64Label(Riscv64Label&& src) noexcept
       : Label(std::move(src)), prev_branch_id_(src.prev_branch_id_) {}
 
  private: