This is an archive of the discontinued LLVM Phabricator instance.

[llvm/Target] Add Windows COFF support for RISC-V
Needs ReviewPublic

Authored by luojia on Mar 7 2023, 7:14 PM.

Details

Summary

RISC-V UEFI development requires to write output assembly into a PE/COFF object. This patch would allow RISC-V PE/COFF development when supplied Target requires binary format as COFF.

Although it's possible to llvm-objcopy from ELF to COFF, it will be more convenient to build directly into COFF files by selecting build targets, especially in languages like Rust where it would require amounts of work on more compilation steps in system development.

Diff Detail

Event Timeline

luojia created this revision.Mar 7 2023, 7:14 PM
luojia requested review of this revision.Mar 7 2023, 7:14 PM
jrtc27 added a comment.Mar 7 2023, 7:27 PM

I'm guessing this is so you can llvm-objcopy an ELF into a PE/COFF?.. Because without relocations being defined you can't do much else of use...

And please upload diffs with full context as per https://llvm.org/docs/DeveloperPolicy.html#making-and-submitting-a-patch

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
670

Isn't this available from the parent class's STI?

688

Can be after the if

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
97

Unnecessary churn

llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFObjectWriter.cpp
33

static

39

Don't think this adds value... the backend would need extensive changes for RV128

53

This isn't actionable unless Microsoft gain an interest in Windows on RISC-V, so I don't think this is something we want to have a comment for as it's not possible to fix

55

This doesn't print its error message in NDEBUG builds, it's just __builtin_unreachable. I think you want report_fatal_error.

luojia updated this revision to Diff 503214.Mar 7 2023, 7:36 PM

Update full-context diff.

luojia updated this revision to Diff 503215.Mar 7 2023, 7:54 PM
luojia marked 4 inline comments as done.
luojia edited the summary of this revision. (Show Details)

Applied suggestions from @jrtc27.

luojia added a comment.Mar 7 2023, 7:58 PM

I'm guessing this is so you can llvm-objcopy an ELF into a PE/COFF?.. Because without relocations being defined you can't do much else of use...

Yes llvm-objcopy can do this and this is the current approach on EDK2 RISC-V. But for languages like Rust it will be more convenient if the compiler backend writes it out directly from build target configuration, or it will require following building steps (in this case, a objcopy step) where complex build frameworks like xtask would have to be used; it would also sometimes result in difference of output file paths where automatic tests (e.g. build a list of UEFI apps to test UEFI implementation) would be complex to develop.

And please upload diffs with full context as per https://llvm.org/docs/DeveloperPolicy.html#making-and-submitting-a-patch

Thanks! I'll do that.

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
670

Thanks! I'll make STI protected in super class and use STI.getTargetTriple() on createObjectTargetWriter function.

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.h
97

Thanks! Will remove.

llvm/lib/Target/RISCV/MCTargetDesc/RISCVWinCOFFObjectWriter.cpp
33

modified to static unsigned

39

Yes. It's a note that future RV128 developers may need to change this part when they are adapting LLVM to RV128.

53

I'll modify comments to show that this is unlikely to happen.

55

Changed to report_fatal_error.

jrtc27 added a comment.Mar 7 2023, 7:59 PM

I'm guessing this is so you can llvm-objcopy an ELF into a PE/COFF?.. Because without relocations being defined you can't do much else of use...

Yes llvm-objcopy can do this and this is the current approach on EDK2 RISC-V. But for languages like Rust it will be more convenient if the compiler backend writes it out directly from build target configuration

And how are you going to do that without a full PE/COFF specification for RISC-V?

luojia marked an inline comment as done.Mar 7 2023, 8:07 PM

I'm guessing this is so you can llvm-objcopy an ELF into a PE/COFF?.. Because without relocations being defined you can't do much else of use...

Yes llvm-objcopy can do this and this is the current approach on EDK2 RISC-V. But for languages like Rust it will be more convenient if the compiler backend writes it out directly from build target configuration

And how are you going to do that without a full PE/COFF specification for RISC-V?

Thanks for mentioning! If I am correct, PE/COFF specification has definitions of machine architecture in headers. In this part PE/COFF included RISC-V architecture types. It does not provide relocation types on RISC-V, so for now PE/COFF specification allows us to emit RISC-V COFF binaries without any relocations. This could be a use case for RISC-V UEFI applications where it's mainly statically linked without any relocations. If there are more demands on RISC-V PE/COFF which need relocations, the current PE/COFF specification will not support them and LLVM (after this patch) would raise fatal error instead.

I have limited information about RISC-V PE/COFF support as well; I don't know if other reviewers have different opinion about this part.

llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
688

Thanks! Modified.

jrtc27 added a comment.Mar 7 2023, 8:09 PM

I'm guessing this is so you can llvm-objcopy an ELF into a PE/COFF?.. Because without relocations being defined you can't do much else of use...

Yes llvm-objcopy can do this and this is the current approach on EDK2 RISC-V. But for languages like Rust it will be more convenient if the compiler backend writes it out directly from build target configuration

And how are you going to do that without a full PE/COFF specification for RISC-V?

Thanks for mentioning! If I am correct, PE/COFF specification has definitions of machine architecture in headers. In this part PE/COFF included RISC-V architecture types. It does not provide relocation types on RISC-V, so for now PE/COFF specification allows us to emit RISC-V COFF binaries without any relocations. This could be a use case for RISC-V UEFI applications where it's mainly statically linked without any relocations. If there are more demands on RISC-V PE/COFF which need relocations, the current PE/COFF specification will not support them and LLVM (after this patch) would raise fatal error instead.

I have limited information about RISC-V PE/COFF support as well; I don't know if other reviewers have different opinion about this part.

Well, you can't produce intermediate object files without relocations, and LLD can't read in an ELF and produce a PE/COFF, so I'm still not sure how static linking helps avoid the need for llvm-objcopy...

Although it's possible to llvm-objcopy from ELF to COFF

llvm-objcopy doesn't support this. GNU objcopy can convert an ELF file to a PE/COFF file, but the semantics are poorly defined.

philipc added a subscriber: philipc.Mar 8 2023, 3:39 AM

If I am correct, PE/COFF specification has definitions of machine architecture in headers. In this part PE/COFF included RISC-V architecture types. It does not provide relocation types on RISC-V, so for now PE/COFF specification allows us to emit RISC-V COFF binaries without any relocations. This could be a use case for RISC-V UEFI applications where it's mainly statically linked without any relocations.

It's not true that the resulting UEFI application has no relocations. For example, when compiling to ELF and converting to PE/COFF, I had to convert a number of ELF relocations into PE base relocations: https://github.com/gimli-rs/object/blob/39e1bb37c613fd360a3b9b91c31d2d305945a5c4/crates/examples/src/bin/elftoefi.rs#L230-L268.

Well, you can't produce intermediate object files without relocations, and LLD can't read in an ELF and produce a PE/COFF, so I'm still not sure how static linking helps avoid the need for llvm-objcopy...

What they are trying to do is add a RISCV UEFI target to the rust compiler that compiles to COFF intermediate object files and links to a PE/COFF UEFI application, similar to existing x86 and aarch64 UEFI targets, but this can't currently work because it would require defining RISCV relocations for the COFF intermediate object files.