Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for the CHERI-LLVM toolchain for RV32 baremetal apps #4

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions config/registration.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

load("@crt//toolchains/gcc_arm_none_eabi:repository.bzl", "gcc_arm_none_eabi_repos")
load("@crt//toolchains/lowrisc_rv32imcb:repository.bzl", "lowrisc_rv32imcb_repos")
load("@crt//toolchains/cheri_llvm:repository.bzl", "cheri_llvm_repos")
load("@crt//toolchains/gcc_mxe_mingw64:repository.bzl", "gcc_mxe_mingw64_repos")
load("@crt//toolchains/cc65:repository.bzl", "cc65_repos")

def crt_register_toolchains(
arm = False,
m6502 = False,
riscv32 = False,
cheri_riscv32 = False,
win64 = False):
native.register_execution_platforms("@local_config_platform//:host")
if arm:
Expand All @@ -28,6 +30,11 @@ def crt_register_toolchains(
native.register_execution_platforms("@crt//platforms/riscv32:all")
native.register_toolchains("@crt//toolchains/lowrisc_rv32imcb:all")

if cheri_riscv32:
cheri_llvm_repos()
native.register_execution_platforms("@crt//platforms/cheri/riscv32:all")
native.register_toolchains("@crt//toolchains/cheri_llvm:all")

if win64:
gcc_mxe_mingw64_repos()
native.register_execution_platforms("@crt//platforms/x86_64:all")
Expand Down
5 changes: 5 additions & 0 deletions constraints/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

package(default_visibility = ["//visibility:public"])
8 changes: 8 additions & 0 deletions constraints/extension/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package(default_visibility = ["//visibility:public"])

constraint_setting(name = "extension")

constraint_value(
name = "cheri",
constraint_setting = ":extension",
)
1 change: 1 addition & 0 deletions platforms/cheri/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package(default_visibility = ["//visibility:public"])
11 changes: 11 additions & 0 deletions platforms/cheri/riscv32/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package(default_visibility = ["//visibility:public"])

load("//config:execution.bzl", "exec_config")

platform(
name = "cheri-riscv32",
constraint_values = [
"@platforms//cpu:riscv32",
"//constraints/extension:cheri",
],
)
28 changes: 28 additions & 0 deletions platforms/cheri/riscv32/devices.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
load("//config:device.bzl", "device_config")
load("//config:compiler.bzl", "listify_flags")

DEVICES = [
device_config(
name = "cheri-riscv32",
architecture = "rv32imcxcheri",
feature_set = "//platforms/cheri/riscv32/features:rv32imcxcheri",
constraints = [
"@platforms//cpu:riscv32",
"//constraints/extension:cheri",
],
substitutions = {
"ARCHITECTURE": "rv32imcxcheri",
"ABI": "il32pc64",
"CMODEL": "medany",
"ENDIAN": "little",
"TARGET": "riscv32-unknown-elf",
"[STACK_PROTECTOR]": "",
"[SYSTEM_LIBRARY_PATHS]": listify_flags(
"-L{}",
[
"external/cheri_llvm_files/sdk/baremetal/baremetal-riscv32-purecap/riscv32-unknown-elf/lib/",
],
),
},
),
]
86 changes: 86 additions & 0 deletions platforms/cheri/riscv32/features/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
load(
"//config:features.bzl",
"CPP_ALL_COMPILE_ACTIONS",
"C_ALL_COMPILE_ACTIONS",
"LD_ALL_ACTIONS",
"feature",
"feature_set",
"flag_group",
"flag_set",
)

package(default_visibility = ["//visibility:public"])

feature(
name = "architecture",
enabled = True,
flag_sets = [
flag_set(
actions = CPP_ALL_COMPILE_ACTIONS + C_ALL_COMPILE_ACTIONS + LD_ALL_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-march=ARCHITECTURE",
"-mabi=ABI",
"-mcmodel=CMODEL",
"-mENDIAN-endian",
"--target=TARGET",
"-mno-relax",
],
),
],
),
],
)

feature(
name = "fastbuild",
enabled = False,
flag_sets = [
flag_set(
actions = CPP_ALL_COMPILE_ACTIONS + C_ALL_COMPILE_ACTIONS,
flag_groups = [
flag_group(
flags = [
"-Os",
"-g",
],
),
],
),
],
provides = ["compilation_mode"],
)

feature(
name = "library_search_directories",
enabled = True,
flag_sets = [
flag_set(
actions = LD_ALL_ACTIONS,
flag_groups = [
flag_group(
flags = ["[SYSTEM_LIBRARY_PATHS]"],
),
flag_group(
expand_if_available = "library_search_directories",
flags = ["-L%{library_search_directories}"],
iterate_over = "library_search_directories",
),
],
),
],
)

feature_set(
name = "rv32imcxcheri",
base = [
"//features/common",
"//features/embedded",
],
feature = [
":architecture",
":fastbuild",
":library_search_directories",
],
)
41 changes: 41 additions & 0 deletions toolchains/cheri_llvm/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
load("//config:compiler.bzl", "setup")
load("//platforms/cheri/riscv32:devices.bzl", "DEVICES")

package(default_visibility = ["//visibility:public"])

SYSTEM_INCLUDE_PATHS = [
"external/cheri_llvm_files/sdk/lib/clang/13.0.0/include",
"external/cheri_llvm_files/sdk/baremetal/baremetal-riscv32-purecap/riscv32-unknown-elf/include/",
]

filegroup(
name = "compiler_components",
srcs = [
"//toolchains/cheri_llvm/wrappers:all",
"@cheri_llvm_files//:all",
],
)

[setup(
name = device.name,
architecture = device.architecture,
artifact_naming = device.artifact_naming,
compiler_components = ":compiler_components",
constraints = device.constraints,
feature_set = device.feature_set,
include_directories = SYSTEM_INCLUDE_PATHS,
params = {
"compiler": "clang",
},
substitutions = device.substitutions,
tools = {
"ar": "wrappers/ar",
"cpp": "wrappers/cpp",
"gcc": "wrappers/clang",
"ld": "wrappers/ld",
"nm": "wrappers/nm",
"objcopy": "wrappers/objcopy",
"objdump": "wrappers/objdump",
"strip": "wrappers/strip",
},
) for device in DEVICES]
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/archive/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package(default_visibility = ["//visibility:public"])
23 changes: 23 additions & 0 deletions toolchains/cheri_llvm/archive/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
### Instructions for building the CHERI-LLVM toolchain archive for purecap riscv32

This will use [cheribuild](https://github.com/CTSRD-CHERI/cheribuild) to build
the CHERI-LLVM RISC-V 32bit "purecap" toolchain for embedded development.
By default, the sources and toolchain will be fetched and built in `~/cheri/`.
This can be changed using the `--source-root`, `--output-root`, `--build-root`,
and `--tools-root` arguments. `-d` ensures required steps are executed (i.e.
builds LLVM & Clang before compiling the libraries). `-j` controls the number
of threads to be used for compilation.

Clone the cheribuild repository anywhere (its directory will not be used for building), then:

`./cheribuild.py newlib-baremetal-riscv32-purecap -d` (for libc, libm, libg)
`./cheribuild.py compiler-rt-builtins-baremetal-riscv32-purecap -d` (for builtins)

Then `cd` to wherever the sdk folder is (`~/cheri/output/` by default,
or within either of the directories pointed to when passing
`--tool-root` or `--output-root`) and tar the `sdk` folder:
`tar -cvzf cheri_llvm_sdk.tar.gz sdk/`

Lastly, copy `cheri_llvm_sdk.tar.gz` to this folder. The name must match the
filename in the `archive` field in `../repository.bzl`
Comment on lines +21 to +22
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should discuss how to allow you to provide the compiler archive without requiring it to be in this repository or requiring the user to take a repository modifying action (e.g. copying the file into this subdir). Modifying the repository as a build step is "bad".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been thinking about how to allow you to supply the compiler archive without needing to ask the user to modify the repository. There are two mechanisms I can think of:

  1. Supply the repository yourself and forego the call to cheri_llvm_repos() in crt_register_toolchains. In your WORKSPACE, you could then do something like this:
load("//third_party/crt:repos.bzl", "crt_repos")
crt_repos()
load("@crt//:repos.bzl", "crt_repos")
crt_repos()
load("@crt//:deps.bzl", "crt_deps")
crt_deps()

load("@crt//config:repo.bzl", "compiler_repository")
compiler_repository(
    name = "cheri_llvm_files",
    archive = "/path/to/your/cheri_llvm_sdk.tar.gz",
    exports = [ ... ],
)

load("@crt//config:registration.bzl", "crt_register_toolchains")
crt_register_toolchains(riscv32_cheri = True)
  1. Modify the interface to crt_register_toolchains to allow you to pass the path to the compiler archive. Your WORKSPACE would then have something like:
crt_register_toolchains(
    riscv32_cheri = "/path/to/your/cheri_llvm_sdk.tar.gz",
)

crt_register_toolchains can then pass the archive location on to cheri_llvm_repos() which will instantiate the compiler_repository.

I've been considering something like (2) for a while to enable end users to pass in alternate compilers, but I haven't yet had a need for it and I'd probably want to plumb things up a bit more to make the archive properties more configurable.


8 changes: 8 additions & 0 deletions toolchains/cheri_llvm/repository.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
load("@crt//config:repo.bzl", "compiler_repository")

def cheri_llvm_repos():
compiler_repository(
name = "cheri_llvm_files",
archive = "@crt//toolchains/cheri_llvm/archive:cheri_llvm_sdk.tar.gz",
exports = ["sdk/bin/**"],
)
17 changes: 17 additions & 0 deletions toolchains/cheri_llvm/wrappers/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package(default_visibility = ["//visibility:public"])

exports_files(glob(["*"]))

filegroup(
name = "all",
srcs = [
"ar",
"clang",
"cpp",
"ld",
"nm",
"objcopy",
"objdump",
"strip",
],
)
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/ar
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/clang
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/cpp
13 changes: 13 additions & 0 deletions toolchains/cheri_llvm/wrappers/driver.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash --norc

PROG=${0##*/}
TOOLCHAIN="cheri_llvm_files"
VERSION="13.0.0"

ARGS=()
POSTARGS=()

exec "external/${TOOLCHAIN}/sdk/bin/${PROG}" \
"${ARGS[@]}" \
"$@"\
"${POSTARGS[@]}"
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/ld
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/nm
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/objcopy
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/objdump
1 change: 1 addition & 0 deletions toolchains/cheri_llvm/wrappers/strip