summaryrefslogtreecommitdiff
blob: 0dcd6cde197bfcb82dd672a58062fcd23782a515 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
GHC supplied all of the information necessary for a registerised build on riscv using LLVM codegen in 9.2.
Andreas Schwab backported this to 8.10.7 in OpenSUSE:  https://build.opensuse.org/package/show/openSUSE:Factory:RISCV/ghc
This is a forward-port of the backport to 9.0.

diff --git a/compiler/GHC/CmmToAsm.hs b/compiler/GHC/CmmToAsm.hs
index 23175a1cd2..3f77573495 100644
--- a/compiler/GHC/CmmToAsm.hs
+++ b/compiler/GHC/CmmToAsm.hs
@@ -182,6 +182,7 @@ nativeCodeGen dflags this_mod modLoc h us cmms
       ArchAlpha     -> panic "nativeCodeGen: No NCG for Alpha"
       ArchMipseb    -> panic "nativeCodeGen: No NCG for mipseb"
       ArchMipsel    -> panic "nativeCodeGen: No NCG for mipsel"
+      ArchRISCV64   -> panic "nativeCodeGen: No NCG for RISCV64"
       ArchUnknown   -> panic "nativeCodeGen: No NCG for unknown arch"
       ArchJavaScript-> panic "nativeCodeGen: No NCG for JavaScript"

diff --git a/compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs b/compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs
index 105e2ebdf9..07eca93ac3 100644
--- a/compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs
@@ -120,6 +120,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcInteger conflicts excl
                             ArchMipseb    -> panic "trivColorable ArchMipseb"
                             ArchMipsel    -> panic "trivColorable ArchMipsel"
                             ArchS390X     -> panic "trivColorable ArchS390X"
+                            ArchRISCV64   -> panic "trivColorable ArchRISCV64"
                             ArchJavaScript-> panic "trivColorable ArchJavaScript"
                             ArchUnknown   -> panic "trivColorable ArchUnknown")
         , count2        <- accSqueeze 0 cALLOCATABLE_REGS_INTEGER
@@ -151,6 +152,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcFloat conflicts exclus
                             ArchMipseb    -> panic "trivColorable ArchMipseb"
                             ArchMipsel    -> panic "trivColorable ArchMipsel"
                             ArchS390X     -> panic "trivColorable ArchS390X"
+                            ArchRISCV64   -> panic "trivColorable ArchRISCV64"
                             ArchJavaScript-> panic "trivColorable ArchJavaScript"
                             ArchUnknown   -> panic "trivColorable ArchUnknown")
         , count2        <- accSqueeze 0 cALLOCATABLE_REGS_FLOAT
@@ -184,6 +186,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcDouble conflicts exclu
                             ArchMipseb    -> panic "trivColorable ArchMipseb"
                             ArchMipsel    -> panic "trivColorable ArchMipsel"
                             ArchS390X     -> panic "trivColorable ArchS390X"
+                            ArchRISCV64   -> panic "trivColorable ArchRISCV64"
                             ArchJavaScript-> panic "trivColorable ArchJavaScript"
                             ArchUnknown   -> panic "trivColorable ArchUnknown")
         , count2        <- accSqueeze 0 cALLOCATABLE_REGS_DOUBLE
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear.hs b/compiler/GHC/CmmToAsm/Reg/Linear.hs
index 1ab353cc34..d8228c69cd 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear.hs
@@ -225,6 +225,7 @@ linearRegAlloc config entry_ids block_live sccs
       ArchAlpha      -> panic "linearRegAlloc ArchAlpha"
       ArchMipseb     -> panic "linearRegAlloc ArchMipseb"
       ArchMipsel     -> panic "linearRegAlloc ArchMipsel"
+      ArchRISCV64    -> panic "linearRegAlloc ArchRISCV64"
       ArchJavaScript -> panic "linearRegAlloc ArchJavaScript"
       ArchUnknown    -> panic "linearRegAlloc ArchUnknown"
  where
diff --git a/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs b/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
index b89c056a82..1768422f5c 100644
--- a/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Linear/FreeRegs.hs
@@ -83,5 +83,6 @@ maxSpillSlots config = case platformArch (ncgPlatform config) of
    ArchAlpha     -> panic "maxSpillSlots ArchAlpha"
    ArchMipseb    -> panic "maxSpillSlots ArchMipseb"
    ArchMipsel    -> panic "maxSpillSlots ArchMipsel"
+   ArchRISCV64   -> panic "maxSpillSlots ArchRISCV64"
    ArchJavaScript-> panic "maxSpillSlots ArchJavaScript"
    ArchUnknown   -> panic "maxSpillSlots ArchUnknown"
diff --git a/compiler/GHC/CmmToAsm/Reg/Target.hs b/compiler/GHC/CmmToAsm/Reg/Target.hs
index ba249801ba..284df45983 100644
--- a/compiler/GHC/CmmToAsm/Reg/Target.hs
+++ b/compiler/GHC/CmmToAsm/Reg/Target.hs
@@ -51,6 +51,7 @@ targetVirtualRegSqueeze platform
       ArchAlpha     -> panic "targetVirtualRegSqueeze ArchAlpha"
       ArchMipseb    -> panic "targetVirtualRegSqueeze ArchMipseb"
       ArchMipsel    -> panic "targetVirtualRegSqueeze ArchMipsel"
+      ArchRISCV64   -> panic "targetVirtualRegSqueeze ArchRISCV64"
       ArchJavaScript-> panic "targetVirtualRegSqueeze ArchJavaScript"
       ArchUnknown   -> panic "targetVirtualRegSqueeze ArchUnknown"

@@ -70,6 +71,7 @@ targetRealRegSqueeze platform
       ArchAlpha     -> panic "targetRealRegSqueeze ArchAlpha"
       ArchMipseb    -> panic "targetRealRegSqueeze ArchMipseb"
       ArchMipsel    -> panic "targetRealRegSqueeze ArchMipsel"
+      ArchRISCV64   -> panic "targetRealRegSqueeze ArchRISCV64"
       ArchJavaScript-> panic "targetRealRegSqueeze ArchJavaScript"
       ArchUnknown   -> panic "targetRealRegSqueeze ArchUnknown"

@@ -88,6 +90,7 @@ targetClassOfRealReg platform
       ArchAlpha     -> panic "targetClassOfRealReg ArchAlpha"
       ArchMipseb    -> panic "targetClassOfRealReg ArchMipseb"
       ArchMipsel    -> panic "targetClassOfRealReg ArchMipsel"
+      ArchRISCV64   -> panic "targetClassOfRealReg ArchRISCV64"
       ArchJavaScript-> panic "targetClassOfRealReg ArchJavaScript"
       ArchUnknown   -> panic "targetClassOfRealReg ArchUnknown"

@@ -106,6 +109,7 @@ targetMkVirtualReg platform
       ArchAlpha     -> panic "targetMkVirtualReg ArchAlpha"
       ArchMipseb    -> panic "targetMkVirtualReg ArchMipseb"
       ArchMipsel    -> panic "targetMkVirtualReg ArchMipsel"
+      ArchRISCV64   -> panic "targetMkVirtualReg ArchRISCV64"
       ArchJavaScript-> panic "targetMkVirtualReg ArchJavaScript"
       ArchUnknown   -> panic "targetMkVirtualReg ArchUnknown"

@@ -124,6 +128,7 @@ targetRegDotColor platform
       ArchAlpha     -> panic "targetRegDotColor ArchAlpha"
       ArchMipseb    -> panic "targetRegDotColor ArchMipseb"
       ArchMipsel    -> panic "targetRegDotColor ArchMipsel"
+      ArchRISCV64   -> panic "targetRegDotColor ArchRISCV64"
       ArchJavaScript-> panic "targetRegDotColor ArchJavaScript"
       ArchUnknown   -> panic "targetRegDotColor ArchUnknown"

diff --git a/compiler/GHC/CmmToLlvm/Mangler.hs b/compiler/GHC/CmmToLlvm/Mangler.hs
index 0436dbcf07..5c71655ab3 100644
--- a/compiler/GHC/CmmToLlvm/Mangler.hs
+++ b/compiler/GHC/CmmToLlvm/Mangler.hs
@@ -42,7 +42,7 @@ llvmFixupAsm dflags f1 f2 = {-# SCC "llvm_mangler" #-}

 -- | These are the rewrites that the mangler will perform
 rewrites :: [Rewrite]
-rewrites = [rewriteSymType, rewriteAVX]
+rewrites = [rewriteSymType, rewriteAVX, rewriteCall]

 type Rewrite = DynFlags -> B.ByteString -> Maybe B.ByteString

@@ -106,6 +106,27 @@ rewriteAVX dflags s
     isVmovdqa = B.isPrefixOf (B.pack "vmovdqa")
     isVmovap = B.isPrefixOf (B.pack "vmovap")

+-- | This rewrites (tail) calls to avoid creating PLT entries for
+-- functions on riscv64. The replacement will load the address from the
+-- GOT, which is resolved to point to the real address of the function.
+rewriteCall :: Rewrite
+rewriteCall dflags l
+  | not isRISCV64 = Nothing
+  | isCall l      = Just $ replaceCall "call" "jalr" "ra" l
+  | isTail l      = Just $ replaceCall "tail" "jr" "t1" l
+  | otherwise     = Nothing
+  where
+    isRISCV64 = platformArch (targetPlatform dflags) == ArchRISCV64
+    isCall = B.isPrefixOf (B.pack "call\t")
+    isTail = B.isPrefixOf (B.pack "tail\t")
+
+    replaceCall call jump reg l =
+        appendInsn (jump ++ "\t" ++ reg) $ removePlt $
+        replaceOnce (B.pack call) (B.pack ("la\t" ++ reg ++ ",")) l
+      where
+        removePlt = replaceOnce (B.pack "@plt") (B.pack "")
+        appendInsn i = (`B.append` B.pack ("\n\t" ++ i))
+
 -- | @replaceOnce match replace bs@ replaces the first occurrence of the
 -- substring @match@ in @bs@ with @replace@.
 replaceOnce :: B.ByteString -> B.ByteString -> B.ByteString -> B.ByteString
diff --git a/compiler/GHC/Driver/Pipeline.hs b/compiler/GHC/Driver/Pipeline.hs
index 8edf49dfdd..d66404e916 100644
--- a/compiler/GHC/Driver/Pipeline.hs
+++ b/compiler/GHC/Driver/Pipeline.hs
@@ -936,6 +936,7 @@ llvmOptions dflags =
     ++ [("", "-mcpu=" ++ mcpu)   | not (null mcpu)
                                  , not (any (isInfixOf "-mcpu") (getOpts dflags opt_lc)) ]
     ++ [("", "-mattr=" ++ attrs) | not (null attrs) ]
+    ++ [("", "-target-abi=" ++ abi) | not (null abi) ]

   where target = platformMisc_llvmTarget $ platformMisc dflags
         Just (LlvmTarget _ mcpu mattr) = lookup target (llvmTargets $ llvmConfig dflags)
@@ -965,6 +966,11 @@ llvmOptions dflags =
               ++ ["+bmi"     | isBmiEnabled dflags      ]
               ++ ["+bmi2"    | isBmi2Enabled dflags     ]

+        abi :: String
+        abi = case platformArch (targetPlatform dflags) of
+             ArchRISCV64 -> "lp64d"
+             _           -> ""
+
 -- -----------------------------------------------------------------------------
 -- | Each phase in the pipeline returns the next phase to execute, and the
 -- name of the file in which the output was placed.
diff --git a/compiler/GHC/Platform/RISCV64.hs b/compiler/GHC/Platform/RISCV64.hs
new file mode 100644
index 0000000000..289e2e27a8
--- /dev/null
+++ b/compiler/GHC/Platform/RISCV64.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE CPP #-}
+
+module GHC.Platform.RISCV64 where
+
+import GHC.Prelude
+
+#define MACHREGS_NO_REGS 0
+#define MACHREGS_riscv64 1
+#include "../../../includes/CodeGen.Platform.hs"
diff --git a/compiler/GHC/Platform/Regs.hs b/compiler/GHC/Platform/Regs.hs
index 1bf21370c7..e0bdf5d6e5 100644
--- a/compiler/GHC/Platform/Regs.hs
+++ b/compiler/GHC/Platform/Regs.hs
@@ -15,6 +15,7 @@ import qualified GHC.Platform.S390X      as S390X
 import qualified GHC.Platform.SPARC      as SPARC
 import qualified GHC.Platform.X86        as X86
 import qualified GHC.Platform.X86_64     as X86_64
+import qualified GHC.Platform.RISCV64    as RISCV64
 import qualified GHC.Platform.NoRegs     as NoRegs

 -- | Returns 'True' if this global register is stored in a caller-saves
@@ -31,6 +32,7 @@ callerSaves platform
    ArchSPARC   -> SPARC.callerSaves
    ArchARM {}  -> ARM.callerSaves
    ArchAArch64 -> AArch64.callerSaves
+   ArchRISCV64 -> RISCV64.callerSaves
    arch
     | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
         PPC.callerSaves
@@ -53,6 +55,7 @@ activeStgRegs platform
    ArchSPARC   -> SPARC.activeStgRegs
    ArchARM {}  -> ARM.activeStgRegs
    ArchAArch64 -> AArch64.activeStgRegs
+   ArchRISCV64 -> RISCV64.activeStgRegs
    arch
     | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
         PPC.activeStgRegs
@@ -70,6 +73,7 @@ haveRegBase platform
    ArchSPARC   -> SPARC.haveRegBase
    ArchARM {}  -> ARM.haveRegBase
    ArchAArch64 -> AArch64.haveRegBase
+   ArchRISCV64 -> RISCV64.haveRegBase
    arch
     | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
         PPC.haveRegBase
@@ -87,6 +91,7 @@ globalRegMaybe platform
    ArchSPARC   -> SPARC.globalRegMaybe
    ArchARM {}  -> ARM.globalRegMaybe
    ArchAArch64 -> AArch64.globalRegMaybe
+   ArchRISCV64 -> RISCV64.globalRegMaybe
    arch
     | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
         PPC.globalRegMaybe
@@ -104,6 +109,7 @@ freeReg platform
    ArchSPARC   -> SPARC.freeReg
    ArchARM {}  -> ARM.freeReg
    ArchAArch64 -> AArch64.freeReg
+   ArchRISCV64 -> RISCV64.freeReg
    arch
     | arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
         PPC.freeReg
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index de53f7f548..483a601602 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -261,6 +261,7 @@ Library
         GHC.Platform.AArch64
         GHC.Platform.NoRegs
         GHC.Platform.PPC
+        GHC.Platform.RISCV64
         GHC.Platform.S390X
         GHC.Platform.SPARC
         GHC.Platform.X86
diff --git a/configure.ac b/configure.ac
index 20911ae43f..b017d50bd6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -283,7 +283,7 @@ dnl --------------------------------------------------------------

 AC_MSG_CHECKING(whether target supports a registerised ABI)
 case "$TargetArch" in
-    i386|x86_64|powerpc|powerpc64|powerpc64le|s390x|arm|aarch64)
+    i386|x86_64|powerpc|powerpc64|powerpc64le|s390x|arm|aarch64|riscv64)
         UnregisterisedDefault=NO
         AC_MSG_RESULT([yes])
         ;;
@@ -318,7 +318,7 @@ AC_MSG_CHECKING(whether target supports tables next to code)
 case "$Unregisterised" in
     NO)
         case "$TargetArch" in
-            ia64|powerpc64|powerpc64le|s390x)
+            ia64|powerpc64|powerpc64le|s390x|riscv64)
                 TablesNextToCodeDefault=NO
                 AC_MSG_RESULT([no])
                 ;;
@@ -347,7 +347,7 @@ AC_SUBST(TablesNextToCode)
 dnl ** Does target have runtime linker support?
 dnl --------------------------------------------------------------
 case "$target" in
-    powerpc64-*|powerpc64le-*|powerpc-ibm-aix*|s390x-ibm-linux)
+    powerpc64-*|powerpc64le-*|powerpc-ibm-aix*|s390x-ibm-linux|riscv64-*)
         TargetHasRTSLinker=NO
         ;;
     *)
diff --git a/includes/CodeGen.Platform.hs b/includes/CodeGen.Platform.hs
index b00acfa38a..8c942662e6 100644
--- a/includes/CodeGen.Platform.hs
+++ b/includes/CodeGen.Platform.hs
@@ -380,6 +380,74 @@ import GHC.Platform.Reg
 # define f14 30
 # define f15 31

+#elif defined(MACHREGS_riscv64)
+
+# define zero 0
+# define ra   1
+# define sp   2
+# define gp   3
+# define tp   4
+# define t0   5
+# define t1   6
+# define t2   7
+# define s0   8
+# define s1   9
+# define a0  10
+# define a1  11
+# define a2  12
+# define a3  13
+# define a4  14
+# define a5  15
+# define a6  16
+# define a7  17
+# define s2  18
+# define s3  19
+# define s4  20
+# define s5  21
+# define s6  22
+# define s7  23
+# define s8  24
+# define s9  25
+# define s10 26
+# define s11 27
+# define t3  28
+# define t4  29
+# define t5  30
+# define t6  31
+
+# define ft0  32
+# define ft1  33
+# define ft2  34
+# define ft3  35
+# define ft4  36
+# define ft5  37
+# define ft6  38
+# define ft7  39
+# define fs0  40
+# define fs1  41
+# define fa0  42
+# define fa1  43
+# define fa2  44
+# define fa3  45
+# define fa4  46
+# define fa5  47
+# define fa6  48
+# define fa7  49
+# define fs2  50
+# define fs3  51
+# define fs4  52
+# define fs5  53
+# define fs6  54
+# define fs7  55
+# define fs8  56
+# define fs9  57
+# define fs10 58
+# define fs11 59
+# define ft8  60
+# define ft9  61
+# define ft10 62
+# define ft11 63
+
 #endif

 callerSaves :: GlobalReg -> Bool
@@ -667,7 +735,7 @@ globalRegMaybe :: GlobalReg -> Maybe RealReg
 #if defined(MACHREGS_i386) || defined(MACHREGS_x86_64) \
     || defined(MACHREGS_sparc) || defined(MACHREGS_powerpc) \
     || defined(MACHREGS_arm) || defined(MACHREGS_aarch64) \
-    || defined(MACHREGS_s390x)
+    || defined(MACHREGS_s390x) || defined(MACHREGS_riscv64)
 # if defined(REG_Base)
 globalRegMaybe BaseReg                  = Just (RealRegSingle REG_Base)
 # endif
diff --git a/includes/stg/MachRegs.h b/includes/stg/MachRegs.h
index be7b7d60b4..1a9012e7ef 100644
--- a/includes/stg/MachRegs.h
+++ b/includes/stg/MachRegs.h
@@ -663,6 +663,68 @@ the stack. See Note [Overlapping global registers] for implications.
 #define CALLER_SAVES_D5
 #define CALLER_SAVES_D6

+/* -----------------------------------------------------------------------------
+   The riscv64 register mapping
+
+   Register    | Role(s)                                 | Call effect
+   ------------+-----------------------------------------+-------------
+   zero        | Hard-wired zero                         | -
+   ra          | Return address                          | caller-saved
+   sp          | Stack pointer                           | callee-saved
+   gp          | Global pointer                          | callee-saved
+   tp          | Thread pointer                          | callee-saved
+   t0,t1,t2    | -                                       | caller-saved
+   s0          | Frame pointer                           | callee-saved
+   s1          | -                                       | callee-saved
+   a0,a1       | Arguments / return values               | caller-saved
+   a2..a7      | Arguments                               | caller-saved
+   s2..s11     | -                                       | callee-saved
+   t3..t6      | -                                       | caller-saved
+   ft0..ft7    | -                                       | caller-saved
+   fs0,fs1     | -                                       | callee-saved
+   fa0,fa1     | Arguments / return values               | caller-saved
+   fa2..fa7    | Arguments                               | caller-saved
+   fs2..fs11   | -                                       | callee-saved
+   ft8..ft11   | -                                       | caller-saved
+
+   Each general purpose register as well as each floating-point
+   register is 64 bits wide.
+
+   -------------------------------------------------------------------------- */
+
+#elif defined(MACHREGS_riscv64)
+
+#define REG(x) __asm__(#x)
+
+#define REG_Base        s1
+#define REG_Sp          s2
+#define REG_Hp          s3
+#define REG_R1          s4
+#define REG_R2          s5
+#define REG_R3          s6
+#define REG_R4          s7
+#define REG_R5          s8
+#define REG_R6          s9
+#define REG_R7          s10
+#define REG_SpLim       s11
+
+#define REG_F1          fs0
+#define REG_F2          fs1
+#define REG_F3          fs2
+#define REG_F4          fs3
+#define REG_F5          fs4
+#define REG_F6          fs5
+
+#define REG_D1          fs6
+#define REG_D2          fs7
+#define REG_D3          fs8
+#define REG_D4          fs9
+#define REG_D5          fs10
+#define REG_D6          fs11
+
+#define MAX_REAL_FLOAT_REG   6
+#define MAX_REAL_DOUBLE_REG  6
+
 #else

 #error Cannot find platform to give register info for
diff --git a/includes/stg/MachRegsForHost.h b/includes/stg/MachRegsForHost.h
index 3597b2be90..e902d528f6 100644
--- a/includes/stg/MachRegsForHost.h
+++ b/includes/stg/MachRegsForHost.h
@@ -71,6 +71,10 @@
 #define MACHREGS_s390x    1
 #endif

+#if defined(riscv64_HOST_ARCH)
+#define MACHREGS_riscv64  1
+#endif
+
 #endif

 #include "MachRegs.h"
diff --git a/includes/stg/SMP.h b/includes/stg/SMP.h
index 389dd95c88..f12fd3f71b 100644
--- a/includes/stg/SMP.h
+++ b/includes/stg/SMP.h
@@ -377,6 +377,8 @@ write_barrier(void) {
     __asm__ __volatile__ ("" : : : "memory");
 #elif defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH)
     __asm__ __volatile__ ("dmb  st" : : : "memory");
+#elif defined(riscv64_HOST_ARCH)
+    __asm__ __volatile__ ("fence w,w" : : : "memory");
 #else
 #error memory barriers unimplemented on this architecture
 #endif
@@ -401,6 +403,8 @@ store_load_barrier(void) {
     __asm__ __volatile__ ("dmb" : : : "memory");
 #elif defined(aarch64_HOST_ARCH)
     __asm__ __volatile__ ("dmb sy" : : : "memory");
+#elif defined(riscv64_HOST_ARCH)
+    __asm__ __volatile__ ("fence w,r" : : : "memory");
 #else
 #error memory barriers unimplemented on this architecture
 #endif
@@ -426,6 +430,8 @@ load_load_barrier(void) {
     __asm__ __volatile__ ("dmb" : : : "memory");
 #elif defined(aarch64_HOST_ARCH)
     __asm__ __volatile__ ("dmb sy" : : : "memory");
+#elif defined(riscv64_HOST_ARCH)
+    __asm__ __volatile__ ("fence w,r" : : : "memory");
 #else
 #error memory barriers unimplemented on this architecture
 #endif
diff --git a/libraries/ghc-boot/GHC/Platform.hs b/libraries/ghc-boot/GHC/Platform.hs
index 186f8c8af6..44d2c68c0a 100644
--- a/libraries/ghc-boot/GHC/Platform.hs
+++ b/libraries/ghc-boot/GHC/Platform.hs
@@ -130,6 +130,7 @@ data Arch
         | ArchAlpha
         | ArchMipseb
         | ArchMipsel
+        | ArchRISCV64
         | ArchJavaScript
         deriving (Read, Show, Eq)

@@ -171,6 +172,7 @@ stringEncodeArch = \case
   ArchAlpha -> "alpha"
   ArchMipseb -> "mipseb"
   ArchMipsel -> "mipsel"
+  ArchRISCV64 -> "riscv64"
   ArchJavaScript -> "js"

 isARM :: Arch -> Bool
@@ -338,6 +340,7 @@ platformCConvNeedsExtension :: Platform -> Bool
 platformCConvNeedsExtension platform = case platformArch platform of
   ArchPPC_64 _ -> True
   ArchS390X    -> True
+  ArchRISCV64  -> True
   _            -> False


diff --git a/libraries/ghci/GHCi/InfoTable.hsc b/libraries/ghci/GHCi/InfoTable.hsc
index ad4eb4d6a8..1d1f8cd074 100644
--- a/libraries/ghci/GHCi/InfoTable.hsc
+++ b/libraries/ghci/GHCi/InfoTable.hsc
@@ -73,6 +73,7 @@ data Arch = ArchSPARC
           | ArchPPC64
           | ArchPPC64LE
           | ArchS390X
+          | ArchRISCV64
  deriving Show

 mkJumpToAddr :: MonadFail m => EntryFunPtr-> m ItblCodes
@@ -109,6 +110,8 @@ mArch =
        Just ArchPPC64LE
 #elif defined(s390x_HOST_ARCH)
        Just ArchS390X
+#elif defined(riscv64_HOST_ARCH)
+        Just ArchRISCV64
 #else
        Nothing
 #endif
@@ -288,6 +291,15 @@ mkJumpToAddr' platform a = case platform of
                   0xC0, 0x19, byte3 w64, byte2 w64, byte1 w64, byte0 w64,
                   0x07, 0xF1 ]

+    ArchRISCV64 ->
+        let w64 = fromIntegral (funPtrToInt a) :: Word64
+        in Right [ 0x00000297          -- auipc t0,0
+                 , 0x01053283          -- ld    t0,16(t0)
+                 , 0x00028067          -- jr    t0
+                 , 0x00000013          -- nop
+                 , fromIntegral w64
+                 , fromIntegral (w64 `shiftR` 32) ]
+
 byte0 :: (Integral w) => w -> Word8
 byte0 w = fromIntegral w

diff --git a/llvm-targets b/llvm-targets
index c328b2e001..0f809b2418 100644
--- a/llvm-targets
+++ b/llvm-targets
@@ -38,6 +38,8 @@
 ,("powerpc64le-unknown-linux-musl", ("e-m:e-i64:64-n32:64", "ppc64le", "+secure-plt"))
 ,("powerpc64le-unknown-linux", ("e-m:e-i64:64-n32:64", "ppc64le", ""))
 ,("s390x-ibm-linux", ("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64", "z10", ""))
+,("riscv64-unknown-linux-gnu", ("e-m:e-p:64:64-i64:64-i128:128-n64-S128", "", "+m +a +f +d +c +relax"))
+,("riscv64-unknown-linux", ("e-m:e-p:64:64-i64:64-i128:128-n64-S128", "", "+m +a +f +d +c +relax"))
 ,("i386-apple-darwin", ("e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:128-n8:16:32-S128", "penryn", ""))
 ,("x86_64-apple-darwin", ("e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128", "penryn", ""))
 ,("arm64-apple-darwin", ("e-m:o-i64:64-i128:128-n32:64-S128", "apple-a12", "+v8.3a +fp-armv8 +neon +crc +crypto +fullfp16 +ras +lse +rdm +rcpc +zcm +zcz +sha2 +aes"))
diff --git a/m4/fptools.m4 b/m4/fptools.m4
index 8c6c9b7062..7dbe53d3b4 100644
--- a/m4/fptools.m4
+++ b/m4/fptools.m4
@@ -231,7 +231,10 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS],
         mipsel)
             test -z "[$]2" || eval "[$]2=ArchMipsel"
             ;;
-        hppa|hppa1_1|ia64|m68k|nios2|riscv32|riscv64|rs6000|s390|sh4|vax)
+        riscv64)
+            test -z "[$]2" || eval "[$]2=ArchRISCV64"
+            ;;
+        hppa|hppa1_1|ia64|m68k|nios2|riscv32|rs6000|s390|sh4|vax)
             test -z "[$]2" || eval "[$]2=ArchUnknown"
             ;;
         *)
diff --git a/mk/config.mk.in b/mk/config.mk.in
index 48b8e23145..e260730991 100644
--- a/mk/config.mk.in
+++ b/mk/config.mk.in
@@ -179,7 +179,7 @@ ifeq "$(TargetArch_CPP)" "arm"
 # We don't support load/store barriers pre-ARMv7. See #10433.
 ArchSupportsSMP=$(if $(filter $(ARM_ISA),ARMv5 ARMv6),NO,YES)
 else
-ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le s390x aarch64)))
+ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le s390x aarch64 riscv64)))
 endif

 # The THREADED_RTS requires `BaseReg` to be in a register and the
diff --git a/rts/StgCRunAsm.S b/rts/StgCRunAsm.S
index 60f1bf9a13..16b125a7e8 100644
--- a/rts/StgCRunAsm.S
+++ b/rts/StgCRunAsm.S
@@ -232,6 +232,150 @@ StgReturn:
 	.size StgReturn, .-StgReturn

 	.section	.note.GNU-stack,"",@progbits
+
+#elif defined(riscv64_HOST_ARCH)
+# define STACK_FRAME_SIZE (RESERVED_C_STACK_BYTES+208)
+       .text
+       .align 1
+       .globl StgRun
+       .type StgRun, @function
+StgRun:
+       .cfi_startproc
+       addi    sp,sp,-208
+       .cfi_def_cfa_offset 208
+       /* save callee-saved registers */
+       sd ra,200(sp)
+       sd s0,192(sp)
+       sd s1,184(sp)
+       sd s2,176(sp)
+       sd s3,168(sp)
+       sd s4,160(sp)
+       sd s5,152(sp)
+       sd s6,144(sp)
+       sd s7,136(sp)
+       sd s8,128(sp)
+       sd s9,120(sp)
+       sd s10,112(sp)
+       sd s11,104(sp)
+       fsd fs0,88(sp)
+       fsd fs1,80(sp)
+       fsd fs2,72(sp)
+       fsd fs3,64(sp)
+       fsd fs4,56(sp)
+       fsd fs5,48(sp)
+       fsd fs6,40(sp)
+       fsd fs7,32(sp)
+       fsd fs8,24(sp)
+       fsd fs9,16(sp)
+       fsd fs10,8(sp)
+       fsd fs11,0(sp)
+       /* allocate stack frame */
+       li t0,RESERVED_C_STACK_BYTES
+       sub sp,sp,t0
+       .cfi_def_cfa_offset STACK_FRAME_SIZE
+       .cfi_offset 1, -8
+       .cfi_offset 8, -16
+       .cfi_offset 9, -24
+       .cfi_offset 18, -32
+       .cfi_offset 19, -40
+       .cfi_offset 20, -48
+       .cfi_offset 21, -56
+       .cfi_offset 22, -64
+       .cfi_offset 23, -72
+       .cfi_offset 24, -80
+       .cfi_offset 25, -88
+       .cfi_offset 26, -96
+       .cfi_offset 27, -104
+       .cfi_offset 40, -120
+       .cfi_offset 41, -128
+       .cfi_offset 50, -136
+       .cfi_offset 51, -144
+       .cfi_offset 52, -152
+       .cfi_offset 53, -160
+       .cfi_offset 54, -168
+       .cfi_offset 55, -176
+       .cfi_offset 56, -184
+       .cfi_offset 57, -192
+       .cfi_offset 58, -200
+       .cfi_offset 59, -208
+       /* set STGs BaseReg from RISCV a1 */
+        mv s1,a1
+       /* jump to STG function */
+        jr a0
+       .cfi_endproc
+       .size StgRun, .-StgRun
+
+       .text
+       .align 1
+       .globl StgReturn
+       .type StgReturn, @function
+StgReturn:
+       .cfi_startproc
+       /* set return value from STGs R1 (RISCV s4) */
+       mv a0,s4
+       /* deallocate stack frame */
+       li t0,RESERVED_C_STACK_BYTES
+       add sp,sp,t0
+       .cfi_def_cfa_offset 208
+       /* restore callee-saved registers */
+       ld      ra,200(sp)
+       .cfi_restore 1
+       ld      s0,192(sp)
+       .cfi_restore 8
+       ld      s1,184(sp)
+       .cfi_restore 9
+       ld      s2,176(sp)
+       .cfi_restore 18
+       ld      s3,168(sp)
+       .cfi_restore 19
+       ld      s4,160(sp)
+       .cfi_restore 20
+       ld      s5,152(sp)
+       .cfi_restore 21
+       ld      s6,144(sp)
+       .cfi_restore 22
+       ld      s7,136(sp)
+       .cfi_restore 23
+       ld      s8,128(sp)
+       .cfi_restore 24
+       ld      s9,120(sp)
+       .cfi_restore 25
+       ld      s10,112(sp)
+       .cfi_restore 26
+       ld      s11,104(sp)
+       .cfi_restore 27
+       fld     fs0,88(sp)
+       .cfi_restore 40
+       fld     fs1,80(sp)
+       .cfi_restore 41
+       fld     fs2,72(sp)
+       .cfi_restore 50
+       fld     fs3,64(sp)
+       .cfi_restore 51
+       fld     fs4,56(sp)
+       .cfi_restore 52
+       fld     fs5,48(sp)
+       .cfi_restore 53
+       fld     fs6,40(sp)
+       .cfi_restore 54
+       fld     fs7,32(sp)
+       .cfi_restore 55
+       fld     fs8,24(sp)
+       .cfi_restore 56
+       fld     fs9,16(sp)
+       .cfi_restore 57
+       fld     fs10,8(sp)
+       .cfi_restore 58
+       fld     fs11,0(sp)
+       .cfi_restore 59
+       addi    sp,sp,208
+       .cfi_def_cfa_offset 0
+       /* jump back to caller of StgRun() */
+       ret
+       .cfi_endproc
+       .size StgReturn, .-StgReturn
+
+       .section        .note.GNU-stack,"",@progbits
 #endif

 #endif /* !USE_MINIINTERPRETER */
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c
index 1da69d03fa..0aa1c8dd3f 100644
--- a/rts/linker/Elf.c
+++ b/rts/linker/Elf.c
@@ -412,6 +412,12 @@ ocVerifyImage_ELF ( ObjectCode* oc )
 #endif
 #if defined(EM_AARCH64)
       case EM_AARCH64: IF_DEBUG(linker,debugBelch( "aarch64" )); break;
+#endif
+#if defined(EM_RISCV)
+      case EM_RISCV:   IF_DEBUG(linker,debugBelch( "riscv" ));
+          errorBelch("%s: RTS linker not implemented on riscv",
+                     oc->fileName);
+          return 0;
 #endif
        default:       IF_DEBUG(linker,debugBelch( "unknown" ));
                      errorBelch("%s: unknown architecture (e_machine == %d)"
diff --git a/utils/genapply/Main.hs b/utils/genapply/Main.hs
index a6d944efa4..a5697b427f 100644
--- a/utils/genapply/Main.hs
+++ b/utils/genapply/Main.hs
@@ -17,6 +17,8 @@ module Main(main) where
 -- We improperly include *HOST* macros for our target...
 #include "../../includes/ghcconfig.h"

+#undef UnregisterisedCompiler
+
 -- ...so that this header defines the right stuff.  It is the RTS's host, but
 -- our target, as we are generating code that uses that RTS.
 #include "../../includes/stg/MachRegsForHost.h"
diff --git a/utils/llvm-targets/gen-data-layout.sh b/utils/llvm-targets/gen-data-layout.sh
index 32032cb97e..092e0892e5 100755
--- a/utils/llvm-targets/gen-data-layout.sh
+++ b/utils/llvm-targets/gen-data-layout.sh
@@ -76,6 +76,9 @@ TARGETS=(
     "powerpc64le-unknown-linux"
     # Linux s390x
     "s390x-ibm-linux"
+    # Linux riscv64
+    "riscv64-unknown-linux-gnu"
+    "riscv64-unknown-linux"

     #########################
     # Darwin