swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.19k stars 10.32k forks source link

[compiler] Add ability to specify `arch` when compiling Swift #61908

Closed colemancda closed 7 months ago

colemancda commented 1 year ago

Is your feature request related to a problem? Please describe.

I'm trying to build Swift for RISCV64 where the C and CXX code is all built with the following Clang flags:

-target riscv64-unknown-linux-gnu -mno-relax -mabi=lp64d -march=rv64imafd

When building the Swift StdLib, the C and CXX sources are compiled and linking correctly with the Linux runtime libraries, but the Swift sources are built targeting soft float ABI and the linking phase fails. I have been able to convert the following Clang arguments to their swiftc equivalents:

Clang Swift
-target riscv64-unknown-linux-gnu -target riscv64-unknown-linux-gnu
-mno-relax -Xcc -mno-relax
-mabi=lp64d -target-variant lp64d

The last argument, -march has no equivalent with the Swift compiler. The Swift compiler should have a flag equivalent to -march to produce code that has the same CPU features and Floating point ABI as the C code its linking against. Here is the example output I am getting with readelf when passing -target-cpu generic-rv64 to the Swift compiler:

coleman@hp-laptop:~/Developer/buildroot-swift$ readelf -h '/home/coleman/Developer/buildroot/output/build/swift-5.7/build/stdlib/public/core/LINUX/riscv64/Swift.o'
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           RISC-V
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          12354992 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         45
  Section header string table index: 1

Meanwhile my C code like libdispatch.so output the following, notice the different output of Flags:

coleman@hp-laptop:~/Developer/buildroot-swift$ readelf -h /home/coleman/Developer/buildroot/output/build/swift-5.7/build/lib/swift/linux/riscv64/libdispatch.so
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           RISC-V
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          467240 (bytes into file)
  Flags:                             0x4, double-float ABI
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         10
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 27

Describe the solution you'd like A Swift compiler flag like -target-arch which configures the underlying LLVM instance the same way Clang's -march does would solve my problem.

Describe alternatives you've considered There is another argument -target-cpu which is the Swift equivalent of Clang's -march and in some situations this can indirectly provide the desired arch targeted. For example, The Swift arguments -target-cpu sifive-e20 would be equivalent to -mcpu=sifive-e20 -march=rv32imc with Clang. The issue that arises is that there are a lot more RISCV CPU variants with different ABIs compared to mainstream processors like x86 and ARM, and submitting an LLVM patch to modify llvm/include/llvm/Support/RISCVTargetParser.def for each is both impractical and likely will never be merged. I'm my case I would have to add the following entry to RISCVTargetParser.def for building for the Allwinner D1 CPU:

PROC(ALLWINNER_D1, {"allwinner-d1"}, FK_64BIT & FK_STDEXTM & FK_STDEXTA & FK_STDEXTF & FK_STDEXTD & FK_STDEXTC, {"rv64imafdcvu"})

The default -target-cpu generic-rv64 does not satisfy my requirements nor do the other entries in that table.

Additional context I am building Swift 5.7 compiler with patches specific to enable RISCV outlined in SR-16005.

colemancda commented 1 year ago

@CodaFi @compnerd If there are any Swift flags you are aware of that already exist and would solve my problem, I'd appreciate it.

compnerd commented 1 year ago

I don't think that there is. This is why I had stopped the RISCV64 port that I was doing :). There was more stuff that I needed to finish off in the IRGen/LLVM side of the world. You are going to have to make code changes for that. Note that -march is particularly important as -march=rv64gc vs -march=rv64gcv_zihintpause is relevant to IRGen as that impacts the subtarget features.

colemancda commented 1 year ago

Well, I have it working with Soft Float since Swift 5.6, so that's doable with Buildroot. Compiling Swift for Debian riscv64 is gonna be blocked until we can specify the CPU features and ABI.

colemancda commented 1 year ago

I am going try my alternative and modify RISCVTargetParser.def and build a modified LLVM, do you think that will provide enough info to the IRGen @compnerd ?

compnerd commented 1 year ago

@colemancda sorry I'm not sure what you are proposing here. I don't think it is sufficient to just modify the target parser. Also, note that with the next rebase we should be able to enable the relaxation. The -march is something we might be able to handle similar to -mtune and should look at how we want to handle the uarch details. I don't think that editing just the target parser is the right approach here. This is going to require a lot more careful thinking, planning, and staging.

colemancda commented 1 year ago

Ok, well at least this is documented somewhere and my hours digging will help someday. Would be cool for Swift 6.0 release.

colemancda commented 1 year ago

Even when specifying the arch, Swift is still being compiled targeting Soft Float. What is off is that I was able to target RVC, Soft Float so the compressed featured is being enabled / disabled. https://github.com/MillerTechnologyPeru/llvm-project/commit/d9a1ac34914cbc190118f858695477658cec0193

MaxDesiatov commented 7 months ago

I don't think this issue is valid as described. You can pass -march with -Xcc to influence LLVM machine code generation in swiftc, as discussed in this thread: https://forums.swift.org/t/targeting-specific-microarchitectures/69505