mirror of
https://github.com/roc-lang/roc.git
synced 2024-10-27 02:40:53 +03:00
Merge branch 'trunk' into update_zig
This commit is contained in:
commit
c11d85b41f
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -22,4 +22,3 @@ jobs:
|
|||||||
|
|
||||||
- name: install dependencies, build, run zig tests, rustfmt, clippy, cargo test --release
|
- name: install dependencies, build, run zig tests, rustfmt, clippy, cargo test --release
|
||||||
run: ./ci/safe-earthly.sh +test-all
|
run: ./ci/safe-earthly.sh +test-all
|
||||||
|
|
||||||
|
22
.github/workflows/www.yml
vendored
Normal file
22
.github/workflows/www.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
name: deploy www.roc-lang.org
|
||||||
|
|
||||||
|
# Whenever a commit lands on trunk, deploy the site
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- deploy-www # TODO change to trunk
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: 'Deploy to Netlify'
|
||||||
|
runs-on: [self-hosted]
|
||||||
|
steps:
|
||||||
|
- uses: jsmrcaga/action-netlify-deploy@v1.6.0
|
||||||
|
with:
|
||||||
|
install_command: 'pwd; cd ../../www'
|
||||||
|
build_command: 'bash build.sh'
|
||||||
|
build_directory: 'build'
|
||||||
|
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
|
||||||
|
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
|
||||||
|
NETLIFY_DEPLOY_MESSAGE: "Deploy git ref ${{ github.ref }}"
|
||||||
|
NETLIFY_DEPLOY_TO_PROD: true
|
@ -32,6 +32,12 @@ members = [
|
|||||||
"roc_std",
|
"roc_std",
|
||||||
"docs"
|
"docs"
|
||||||
]
|
]
|
||||||
|
# Needed to be able to run `cargo run -p roc_cli --no-default-features` -
|
||||||
|
# see www/build.sh for more.
|
||||||
|
#
|
||||||
|
# Without the `-p` flag, cargo ignores `--no-default-features` when you have a
|
||||||
|
# workspace, and without `resolver = "2"` here, you can't use `-p` like this.
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
# Optimizations based on https://deterministic.space/high-performance-rust.html
|
# Optimizations based on https://deterministic.space/high-performance-rust.html
|
||||||
[profile.release]
|
[profile.release]
|
||||||
|
@ -15,7 +15,12 @@ test = false
|
|||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["target-x86"]
|
default = ["target-x86", "llvm", "editor"]
|
||||||
|
|
||||||
|
# This is a separate feature because when we generate docs on Netlify,
|
||||||
|
# it doesn't have LLVM installed. (Also, it doesn't need to do code gen.)
|
||||||
|
llvm = ["inkwell", "roc_gen", "roc_build/llvm"]
|
||||||
|
editor = ["roc_editor"]
|
||||||
|
|
||||||
target-x86 = []
|
target-x86 = []
|
||||||
|
|
||||||
@ -45,11 +50,11 @@ roc_unify = { path = "../compiler/unify" }
|
|||||||
roc_solve = { path = "../compiler/solve" }
|
roc_solve = { path = "../compiler/solve" }
|
||||||
roc_mono = { path = "../compiler/mono" }
|
roc_mono = { path = "../compiler/mono" }
|
||||||
roc_load = { path = "../compiler/load" }
|
roc_load = { path = "../compiler/load" }
|
||||||
roc_gen = { path = "../compiler/gen" }
|
roc_gen = { path = "../compiler/gen", optional = true }
|
||||||
roc_build = { path = "../compiler/build" }
|
roc_build = { path = "../compiler/build", default-features = false }
|
||||||
roc_fmt = { path = "../compiler/fmt" }
|
roc_fmt = { path = "../compiler/fmt" }
|
||||||
roc_reporting = { path = "../compiler/reporting" }
|
roc_reporting = { path = "../compiler/reporting" }
|
||||||
roc_editor = { path = "../editor" }
|
roc_editor = { path = "../editor", optional = true }
|
||||||
# TODO switch to clap 3.0.0 once it's out. Tried adding clap = "~3.0.0-beta.1" and cargo wouldn't accept it
|
# TODO switch to clap 3.0.0 once it's out. Tried adding clap = "~3.0.0-beta.1" and cargo wouldn't accept it
|
||||||
clap = { git = "https://github.com/rtfeldman/clap", branch = "master" }
|
clap = { git = "https://github.com/rtfeldman/clap", branch = "master" }
|
||||||
const_format = "0.2.8"
|
const_format = "0.2.8"
|
||||||
@ -62,7 +67,7 @@ inlinable_string = "0.1"
|
|||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libloading = "0.6"
|
libloading = "0.6"
|
||||||
|
|
||||||
inkwell = { path = "../vendor/inkwell" }
|
inkwell = { path = "../vendor/inkwell", optional = true }
|
||||||
target-lexicon = "0.10"
|
target-lexicon = "0.10"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
|
@ -5,8 +5,8 @@ use roc_build::{
|
|||||||
};
|
};
|
||||||
use roc_can::builtins::builtin_defs_map;
|
use roc_can::builtins::builtin_defs_map;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_gen::llvm::build::OptLevel;
|
|
||||||
use roc_load::file::LoadingProblem;
|
use roc_load::file::LoadingProblem;
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
@ -32,6 +32,7 @@ pub struct BuiltFile {
|
|||||||
pub total_time: Duration,
|
pub total_time: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
pub fn build_file<'a>(
|
pub fn build_file<'a>(
|
||||||
arena: &'a Bump,
|
arena: &'a Bump,
|
||||||
target: &Triple,
|
target: &Triple,
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate clap;
|
extern crate clap;
|
||||||
|
|
||||||
use build::{build_file, BuildOutcome, BuiltFile};
|
use build::{BuildOutcome, BuiltFile};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||||
use roc_build::link::LinkType;
|
use roc_build::link::LinkType;
|
||||||
use roc_gen::llvm::build::OptLevel;
|
|
||||||
use roc_load::file::LoadingProblem;
|
use roc_load::file::LoadingProblem;
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -116,7 +116,9 @@ pub enum BuildConfig {
|
|||||||
BuildAndRun { roc_file_arg_index: usize },
|
BuildAndRun { roc_file_arg_index: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
pub fn build(target: &Triple, matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
pub fn build(target: &Triple, matches: &ArgMatches, config: BuildConfig) -> io::Result<i32> {
|
||||||
|
use build::build_file;
|
||||||
use BuildConfig::*;
|
use BuildConfig::*;
|
||||||
|
|
||||||
let arena = Bump::new();
|
let arena = Bump::new();
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
use roc_cli::{
|
use roc_cli::{
|
||||||
build, build_app, docs, repl, BuildConfig, CMD_BUILD, CMD_DOCS, CMD_EDIT, CMD_REPL, CMD_RUN,
|
build_app, docs, repl, BuildConfig, CMD_BUILD, CMD_DOCS, CMD_EDIT, CMD_REPL, CMD_RUN,
|
||||||
DIRECTORY_OR_FILES, ROC_FILE,
|
DIRECTORY_OR_FILES, ROC_FILE,
|
||||||
};
|
};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
use roc_cli::build;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "llvm"))]
|
||||||
|
fn build(_target: &Triple, _matches: &clap::ArgMatches, _config: BuildConfig) -> io::Result<i32> {
|
||||||
|
panic!("Building without LLVM is not currently supported.");
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
fn main() -> io::Result<()> {
|
||||||
let matches = build_app().get_matches();
|
let matches = build_app().get_matches();
|
||||||
|
|
||||||
let exit_code = match matches.subcommand_name() {
|
let exit_code = match matches.subcommand_name() {
|
||||||
None => {
|
None => {
|
||||||
roc_editor::launch(&[])?;
|
launch_editor(&[])?;
|
||||||
|
|
||||||
// rustc couldn't infer the error type here
|
// rustc couldn't infer the error type here
|
||||||
Result::<i32, io::Error>::Ok(0)
|
Result::<i32, io::Error>::Ok(0)
|
||||||
@ -44,14 +52,14 @@ fn main() -> io::Result<()> {
|
|||||||
.values_of_os(DIRECTORY_OR_FILES)
|
.values_of_os(DIRECTORY_OR_FILES)
|
||||||
{
|
{
|
||||||
None => {
|
None => {
|
||||||
roc_editor::launch(&[])?;
|
launch_editor(&[])?;
|
||||||
}
|
}
|
||||||
Some(values) => {
|
Some(values) => {
|
||||||
let paths = values
|
let paths = values
|
||||||
.map(|os_str| Path::new(os_str))
|
.map(|os_str| Path::new(os_str))
|
||||||
.collect::<Vec<&Path>>();
|
.collect::<Vec<&Path>>();
|
||||||
|
|
||||||
roc_editor::launch(&paths)?;
|
launch_editor(&paths)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,3 +86,13 @@ fn main() -> io::Result<()> {
|
|||||||
|
|
||||||
std::process::exit(exit_code);
|
std::process::exit(exit_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "editor")]
|
||||||
|
fn launch_editor(filepaths: &[&Path]) -> io::Result<()> {
|
||||||
|
roc_editor::launch(filepaths)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "editor"))]
|
||||||
|
fn launch_editor(_filepaths: &[&Path]) -> io::Result<()> {
|
||||||
|
panic!("Cannot launch the editor because this build of roc did not include `feature = \"editor\"`!");
|
||||||
|
}
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
use const_format::concatcp;
|
use const_format::concatcp;
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
use gen::{gen_and_eval, ReplOutput};
|
use gen::{gen_and_eval, ReplOutput};
|
||||||
use roc_gen::llvm::build::OptLevel;
|
|
||||||
use roc_parse::parser::{EExpr, SyntaxError};
|
use roc_parse::parser::{EExpr, SyntaxError};
|
||||||
use rustyline::error::ReadlineError;
|
|
||||||
use rustyline::highlight::{Highlighter, PromptInfo};
|
use rustyline::highlight::{Highlighter, PromptInfo};
|
||||||
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
|
use rustyline::validate::{self, ValidationContext, ValidationResult, Validator};
|
||||||
use rustyline::Editor;
|
|
||||||
use rustyline_derive::{Completer, Helper, Hinter};
|
use rustyline_derive::{Completer, Helper, Hinter};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::io;
|
use std::io;
|
||||||
use target_lexicon::Triple;
|
|
||||||
|
|
||||||
const BLUE: &str = "\u{001b}[36m";
|
const BLUE: &str = "\u{001b}[36m";
|
||||||
const PINK: &str = "\u{001b}[35m";
|
const PINK: &str = "\u{001b}[35m";
|
||||||
@ -30,7 +27,9 @@ pub const INSTRUCTIONS: &str = "Enter an expression, or :help, or :exit/:q.\n";
|
|||||||
pub const PROMPT: &str = concatcp!("\n", BLUE, "»", END_COL, " ");
|
pub const PROMPT: &str = concatcp!("\n", BLUE, "»", END_COL, " ");
|
||||||
pub const CONT_PROMPT: &str = concatcp!(BLUE, "…", END_COL, " ");
|
pub const CONT_PROMPT: &str = concatcp!(BLUE, "…", END_COL, " ");
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
mod eval;
|
mod eval;
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
mod gen;
|
mod gen;
|
||||||
|
|
||||||
#[derive(Completer, Helper, Hinter)]
|
#[derive(Completer, Helper, Hinter)]
|
||||||
@ -107,7 +106,16 @@ impl Validator for InputValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "llvm"))]
|
||||||
pub fn main() -> io::Result<()> {
|
pub fn main() -> io::Result<()> {
|
||||||
|
panic!("The REPL currently requires being built with LLVM.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
pub fn main() -> io::Result<()> {
|
||||||
|
use rustyline::error::ReadlineError;
|
||||||
|
use rustyline::Editor;
|
||||||
|
|
||||||
// To debug rustyline:
|
// To debug rustyline:
|
||||||
// <UNCOMMENT> env_logger::init();
|
// <UNCOMMENT> env_logger::init();
|
||||||
// <RUN WITH:> RUST_LOG=rustyline=debug cargo run repl 2> debug.log
|
// <RUN WITH:> RUST_LOG=rustyline=debug cargo run repl 2> debug.log
|
||||||
@ -226,7 +234,11 @@ fn report_parse_error(fail: SyntaxError) {
|
|||||||
println!("TODO Gracefully report parse error in repl: {:?}", fail);
|
println!("TODO Gracefully report parse error in repl: {:?}", fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
fn eval_and_format<'a>(src: &str) -> Result<String, SyntaxError<'a>> {
|
fn eval_and_format<'a>(src: &str) -> Result<String, SyntaxError<'a>> {
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
|
use target_lexicon::Triple;
|
||||||
|
|
||||||
gen_and_eval(src.as_bytes(), Triple::host(), OptLevel::Normal).map(|output| match output {
|
gen_and_eval(src.as_bytes(), Triple::host(), OptLevel::Normal).map(|output| match output {
|
||||||
ReplOutput::NoProblems { expr, expr_type } => {
|
ReplOutput::NoProblems { expr, expr_type } => {
|
||||||
format!("\n{} {}:{} {}", expr, PINK, END_COL, expr_type)
|
format!("\n{} {}:{} {}", expr, PINK, END_COL, expr_type)
|
||||||
|
@ -8,9 +8,9 @@ use roc_can::builtins::builtin_defs_map;
|
|||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_fmt::annotation::Formattable;
|
use roc_fmt::annotation::Formattable;
|
||||||
use roc_fmt::annotation::{Newlines, Parens};
|
use roc_fmt::annotation::{Newlines, Parens};
|
||||||
use roc_gen::llvm::build::OptLevel;
|
|
||||||
use roc_gen::llvm::externs::add_default_roc_externs;
|
use roc_gen::llvm::externs::add_default_roc_externs;
|
||||||
use roc_load::file::LoadingProblem;
|
use roc_load::file::LoadingProblem;
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_parse::parser::SyntaxError;
|
use roc_parse::parser::SyntaxError;
|
||||||
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
use roc_types::pretty_print::{content_to_string, name_all_type_vars};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -19,7 +19,7 @@ roc_unify = { path = "../unify" }
|
|||||||
roc_solve = { path = "../solve" }
|
roc_solve = { path = "../solve" }
|
||||||
roc_mono = { path = "../mono" }
|
roc_mono = { path = "../mono" }
|
||||||
roc_load = { path = "../load" }
|
roc_load = { path = "../load" }
|
||||||
roc_gen = { path = "../gen" }
|
roc_gen = { path = "../gen", optional = true }
|
||||||
roc_reporting = { path = "../reporting" }
|
roc_reporting = { path = "../reporting" }
|
||||||
im = "14" # im and im-rc should always have the same version!
|
im = "14" # im and im-rc should always have the same version!
|
||||||
im-rc = "14" # im and im-rc should always have the same version!
|
im-rc = "14" # im and im-rc should always have the same version!
|
||||||
@ -28,7 +28,7 @@ inlinable_string = "0.1.0"
|
|||||||
libloading = "0.6"
|
libloading = "0.6"
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
inkwell = { path = "../../vendor/inkwell" }
|
inkwell = { path = "../../vendor/inkwell", optional = true }
|
||||||
target-lexicon = "0.10"
|
target-lexicon = "0.10"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@ -39,6 +39,10 @@ quickcheck = "0.8"
|
|||||||
quickcheck_macros = "0.8"
|
quickcheck_macros = "0.8"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["llvm"]
|
||||||
target-arm = []
|
target-arm = []
|
||||||
target-aarch64 = []
|
target-aarch64 = []
|
||||||
target-webassembly = []
|
target-webassembly = []
|
||||||
|
# This is a separate feature because when we generate docs on Netlify,
|
||||||
|
# it doesn't have LLVM installed. (Also, it doesn't need to do code gen.)
|
||||||
|
llvm = ["inkwell", "roc_gen"]
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
use crate::target;
|
|
||||||
use crate::target::arch_str;
|
use crate::target::arch_str;
|
||||||
use inkwell::module::Module;
|
#[cfg(feature = "llvm")]
|
||||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
|
||||||
use libloading::{Error, Library};
|
use libloading::{Error, Library};
|
||||||
use roc_gen::llvm::build::OptLevel;
|
#[cfg(feature = "llvm")]
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::process::{Child, Command, Output};
|
use std::process::{Child, Command, Output};
|
||||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||||
use tempfile::tempdir;
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum LinkType {
|
pub enum LinkType {
|
||||||
@ -360,6 +358,9 @@ fn link_linux(
|
|||||||
};
|
};
|
||||||
|
|
||||||
let env_path = env::var("PATH").unwrap_or_else(|_| "".to_string());
|
let env_path = env::var("PATH").unwrap_or_else(|_| "".to_string());
|
||||||
|
|
||||||
|
init_arch(target);
|
||||||
|
|
||||||
// NOTE: order of arguments to `ld` matters here!
|
// NOTE: order of arguments to `ld` matters here!
|
||||||
// The `-l` flags should go after the `.o` arguments
|
// The `-l` flags should go after the `.o` arguments
|
||||||
Ok((
|
Ok((
|
||||||
@ -477,12 +478,16 @@ fn link_macos(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
pub fn module_to_dylib(
|
pub fn module_to_dylib(
|
||||||
module: &Module,
|
module: &inkwell::module::Module,
|
||||||
target: &Triple,
|
target: &Triple,
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
) -> Result<Library, Error> {
|
) -> Result<Library, Error> {
|
||||||
let dir = tempdir().unwrap();
|
use crate::target::{self, convert_opt_level};
|
||||||
|
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||||
|
|
||||||
|
let dir = tempfile::tempdir().unwrap();
|
||||||
let filename = PathBuf::from("Test.roc");
|
let filename = PathBuf::from("Test.roc");
|
||||||
let file_path = dir.path().join(filename);
|
let file_path = dir.path().join(filename);
|
||||||
let mut app_o_file = file_path;
|
let mut app_o_file = file_path;
|
||||||
@ -492,7 +497,8 @@ pub fn module_to_dylib(
|
|||||||
// Emit the .o file using position-indepedent code (PIC) - needed for dylibs
|
// Emit the .o file using position-indepedent code (PIC) - needed for dylibs
|
||||||
let reloc = RelocMode::PIC;
|
let reloc = RelocMode::PIC;
|
||||||
let model = CodeModel::Default;
|
let model = CodeModel::Default;
|
||||||
let target_machine = target::target_machine(target, opt_level.into(), reloc, model).unwrap();
|
let target_machine =
|
||||||
|
target::target_machine(target, convert_opt_level(opt_level), reloc, model).unwrap();
|
||||||
|
|
||||||
target_machine
|
target_machine
|
||||||
.write_to_file(module, FileType::Object, &app_o_file)
|
.write_to_file(module, FileType::Object, &app_o_file)
|
||||||
@ -529,3 +535,13 @@ fn validate_output(file_name: &str, cmd_name: &str, output: Output) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
fn init_arch(target: &Triple) {
|
||||||
|
crate::target::init_arch(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "llvm"))]
|
||||||
|
fn init_arch(_target: &Triple) {
|
||||||
|
panic!("Tried to initialize LLVM when crate was not built with `feature = \"llvm\"` enabled");
|
||||||
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
use crate::target;
|
#[cfg(feature = "llvm")]
|
||||||
use bumpalo::Bump;
|
use roc_gen::llvm::build::module_from_builtins;
|
||||||
use inkwell::context::Context;
|
#[cfg(feature = "llvm")]
|
||||||
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
|
||||||
pub use roc_gen::llvm::build::FunctionIterator;
|
pub use roc_gen::llvm::build::FunctionIterator;
|
||||||
use roc_gen::llvm::build::{module_from_builtins, OptLevel};
|
#[cfg(feature = "llvm")]
|
||||||
use roc_load::file::MonomorphizedModule;
|
use roc_load::file::MonomorphizedModule;
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::Duration;
|
||||||
use target_lexicon::Triple;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default)]
|
#[derive(Debug, Clone, Copy, Default)]
|
||||||
pub struct CodeGenTiming {
|
pub struct CodeGenTiming {
|
||||||
@ -18,16 +19,24 @@ pub struct CodeGenTiming {
|
|||||||
// TODO how should imported modules factor into this? What if those use builtins too?
|
// TODO how should imported modules factor into this? What if those use builtins too?
|
||||||
// TODO this should probably use more helper functions
|
// TODO this should probably use more helper functions
|
||||||
// TODO make this polymorphic in the llvm functions so it can be reused for another backend.
|
// TODO make this polymorphic in the llvm functions so it can be reused for another backend.
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
#[allow(clippy::cognitive_complexity)]
|
#[allow(clippy::cognitive_complexity)]
|
||||||
pub fn gen_from_mono_module(
|
pub fn gen_from_mono_module(
|
||||||
arena: &Bump,
|
arena: &bumpalo::Bump,
|
||||||
mut loaded: MonomorphizedModule,
|
mut loaded: MonomorphizedModule,
|
||||||
roc_file_path: &Path,
|
roc_file_path: &Path,
|
||||||
target: Triple,
|
target: target_lexicon::Triple,
|
||||||
app_o_file: &Path,
|
app_o_file: &Path,
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
emit_debug_info: bool,
|
emit_debug_info: bool,
|
||||||
) -> CodeGenTiming {
|
) -> CodeGenTiming {
|
||||||
|
use crate::target::{self, convert_opt_level};
|
||||||
|
use inkwell::attributes::{Attribute, AttributeLoc};
|
||||||
|
use inkwell::context::Context;
|
||||||
|
use inkwell::module::Linkage;
|
||||||
|
use inkwell::targets::{CodeModel, FileType, RelocMode};
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use roc_reporting::report::{
|
use roc_reporting::report::{
|
||||||
can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE,
|
can_problem, mono_problem, type_problem, RocDocAllocator, DEFAULT_PALETTE,
|
||||||
};
|
};
|
||||||
@ -87,9 +96,6 @@ pub fn gen_from_mono_module(
|
|||||||
// module.strip_debug_info();
|
// module.strip_debug_info();
|
||||||
|
|
||||||
// mark our zig-defined builtins as internal
|
// mark our zig-defined builtins as internal
|
||||||
use inkwell::attributes::{Attribute, AttributeLoc};
|
|
||||||
use inkwell::module::Linkage;
|
|
||||||
|
|
||||||
let app_ll_file = {
|
let app_ll_file = {
|
||||||
let mut temp = PathBuf::from(roc_file_path);
|
let mut temp = PathBuf::from(roc_file_path);
|
||||||
temp.set_extension("ll");
|
temp.set_extension("ll");
|
||||||
@ -226,7 +232,7 @@ pub fn gen_from_mono_module(
|
|||||||
let reloc = RelocMode::Default;
|
let reloc = RelocMode::Default;
|
||||||
let model = CodeModel::Default;
|
let model = CodeModel::Default;
|
||||||
let target_machine =
|
let target_machine =
|
||||||
target::target_machine(&target, opt_level.into(), reloc, model).unwrap();
|
target::target_machine(&target, convert_opt_level(opt_level), reloc, model).unwrap();
|
||||||
|
|
||||||
target_machine
|
target_machine
|
||||||
.write_to_file(&env.module, FileType::Object, &app_o_file)
|
.write_to_file(&env.module, FileType::Object, &app_o_file)
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use inkwell::targets::{
|
#[cfg(feature = "llvm")]
|
||||||
CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple,
|
use inkwell::{
|
||||||
|
targets::{CodeModel, InitializationConfig, RelocMode, Target, TargetMachine, TargetTriple},
|
||||||
|
OptimizationLevel,
|
||||||
};
|
};
|
||||||
use inkwell::OptimizationLevel;
|
#[cfg(feature = "llvm")]
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
use target_lexicon::{Architecture, OperatingSystem, Triple};
|
||||||
|
|
||||||
pub fn target_triple_str(target: &Triple) -> &'static str {
|
pub fn target_triple_str(target: &Triple) -> &'static str {
|
||||||
@ -28,36 +31,20 @@ pub fn target_triple_str(target: &Triple) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// NOTE: arch_str is *not* the same as the beginning of the magic target triple
|
#[cfg(feature = "llvm")]
|
||||||
/// string! For example, if it's "x86-64" here, the magic target triple string
|
pub fn init_arch(target: &Triple) {
|
||||||
/// will begin with "x86_64" (with an underscore) instead.
|
|
||||||
pub fn arch_str(target: &Triple) -> &'static str {
|
|
||||||
// Best guide I've found on how to determine these magic strings:
|
|
||||||
//
|
|
||||||
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
|
|
||||||
match target.architecture {
|
match target.architecture {
|
||||||
Architecture::X86_64 => {
|
Architecture::X86_64 => {
|
||||||
Target::initialize_x86(&InitializationConfig::default());
|
Target::initialize_x86(&InitializationConfig::default());
|
||||||
|
|
||||||
"x86-64"
|
|
||||||
}
|
}
|
||||||
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => {
|
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => {
|
||||||
Target::initialize_aarch64(&InitializationConfig::default());
|
Target::initialize_aarch64(&InitializationConfig::default());
|
||||||
"aarch64"
|
|
||||||
}
|
}
|
||||||
Architecture::Arm(_) if cfg!(feature = "target-arm") => {
|
Architecture::Arm(_) if cfg!(feature = "target-arm") => {
|
||||||
// NOTE: why not enable arm and wasm by default?
|
|
||||||
//
|
|
||||||
// We had some trouble getting them to link properly. This may be resolved in the
|
|
||||||
// future, or maybe it was just some weird configuration on one machine.
|
|
||||||
Target::initialize_arm(&InitializationConfig::default());
|
Target::initialize_arm(&InitializationConfig::default());
|
||||||
|
|
||||||
"arm"
|
|
||||||
}
|
}
|
||||||
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => {
|
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => {
|
||||||
Target::initialize_webassembly(&InitializationConfig::default());
|
Target::initialize_webassembly(&InitializationConfig::default());
|
||||||
|
|
||||||
"wasm32"
|
|
||||||
}
|
}
|
||||||
_ => panic!(
|
_ => panic!(
|
||||||
"TODO gracefully handle unsupported target architecture: {:?}",
|
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||||
@ -66,6 +53,26 @@ pub fn arch_str(target: &Triple) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// NOTE: arch_str is *not* the same as the beginning of the magic target triple
|
||||||
|
/// string! For example, if it's "x86-64" here, the magic target triple string
|
||||||
|
/// will begin with "x86_64" (with an underscore) instead.
|
||||||
|
pub fn arch_str(target: &Triple) -> &'static str {
|
||||||
|
// Best guide I've found on how to determine these magic strings:
|
||||||
|
//
|
||||||
|
// https://stackoverflow.com/questions/15036909/clang-how-to-list-supported-target-architectures
|
||||||
|
match target.architecture {
|
||||||
|
Architecture::X86_64 => "x86-64",
|
||||||
|
Architecture::Aarch64(_) if cfg!(feature = "target-aarch64") => "aarch64",
|
||||||
|
Architecture::Arm(_) if cfg!(feature = "target-arm") => "arm",
|
||||||
|
Architecture::Wasm32 if cfg!(feature = "target-webassembly") => "wasm32",
|
||||||
|
_ => panic!(
|
||||||
|
"TODO gracefully handle unsupported target architecture: {:?}",
|
||||||
|
target.architecture
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
pub fn target_machine(
|
pub fn target_machine(
|
||||||
target: &Triple,
|
target: &Triple,
|
||||||
opt: OptimizationLevel,
|
opt: OptimizationLevel,
|
||||||
@ -74,6 +81,8 @@ pub fn target_machine(
|
|||||||
) -> Option<TargetMachine> {
|
) -> Option<TargetMachine> {
|
||||||
let arch = arch_str(target);
|
let arch = arch_str(target);
|
||||||
|
|
||||||
|
init_arch(target);
|
||||||
|
|
||||||
Target::from_name(arch).unwrap().create_target_machine(
|
Target::from_name(arch).unwrap().create_target_machine(
|
||||||
&TargetTriple::create(target_triple_str(target)),
|
&TargetTriple::create(target_triple_str(target)),
|
||||||
"generic",
|
"generic",
|
||||||
@ -83,3 +92,11 @@ pub fn target_machine(
|
|||||||
model,
|
model,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llvm")]
|
||||||
|
pub fn convert_opt_level(level: OptLevel) -> OptimizationLevel {
|
||||||
|
match level {
|
||||||
|
OptLevel::Normal => OptimizationLevel::None,
|
||||||
|
OptLevel::Optimize => OptimizationLevel::Aggressive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,6 +9,20 @@ use std::str;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||||
|
let dest_obj_path = Path::new(&out_dir).join("builtins.o");
|
||||||
|
let dest_obj = dest_obj_path.to_str().expect("Invalid dest object path");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
println!("cargo:rustc-env=BUILTINS_O={}", dest_obj);
|
||||||
|
|
||||||
|
// When we build on Netlify, zig is not installed (but also not used,
|
||||||
|
// since all we're doing is generating docs), so we can skip the steps
|
||||||
|
// that require having zig installed.
|
||||||
|
if env::var_os("NO_ZIG_INSTALLED").is_some() {
|
||||||
|
// We still need to do the other things before this point, because
|
||||||
|
// setting the env vars is needed for other parts of the build.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let big_sur_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib";
|
let big_sur_path = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib";
|
||||||
let use_build_script = Path::new(big_sur_path).exists();
|
let use_build_script = Path::new(big_sur_path).exists();
|
||||||
@ -34,8 +48,6 @@ fn main() {
|
|||||||
run_command(&bitcode_path, "zig", &["build", "ir", "-Drelease=true"]);
|
run_command(&bitcode_path, "zig", &["build", "ir", "-Drelease=true"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let dest_obj_path = Path::new(&out_dir).join("builtins.o");
|
|
||||||
let dest_obj = dest_obj_path.to_str().expect("Invalid dest object path");
|
|
||||||
println!("Moving zig object to: {}", dest_obj);
|
println!("Moving zig object to: {}", dest_obj);
|
||||||
|
|
||||||
run_command(&bitcode_path, "mv", &[src_obj, dest_obj]);
|
run_command(&bitcode_path, "mv", &[src_obj, dest_obj]);
|
||||||
@ -50,8 +62,6 @@ fn main() {
|
|||||||
&[dest_ir, "-o", dest_bc],
|
&[dest_ir, "-o", dest_bc],
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("cargo:rerun-if-changed=build.rs");
|
|
||||||
println!("cargo:rustc-env=BUILTINS_O={}", dest_obj);
|
|
||||||
get_zig_files(bitcode_path.as_path(), &|path| {
|
get_zig_files(bitcode_path.as_path(), &|path| {
|
||||||
let path: &Path = path;
|
let path: &Path = path;
|
||||||
println!(
|
println!(
|
||||||
|
@ -3,12 +3,6 @@ pub const OBJ_PATH: &str = env!(
|
|||||||
"Env var BUILTINS_O not found. Is there a problem with the build script?"
|
"Env var BUILTINS_O not found. Is there a problem with the build script?"
|
||||||
);
|
);
|
||||||
|
|
||||||
pub fn as_bytes() -> &'static [u8] {
|
|
||||||
// In the build script for the builtins module,
|
|
||||||
// we compile the builtins into LLVM bitcode
|
|
||||||
include_bytes!("../bitcode/builtins.bc")
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const NUM_ASIN: &str = "roc_builtins.num.asin";
|
pub const NUM_ASIN: &str = "roc_builtins.num.asin";
|
||||||
pub const NUM_ACOS: &str = "roc_builtins.num.acos";
|
pub const NUM_ACOS: &str = "roc_builtins.num.acos";
|
||||||
pub const NUM_ATAN: &str = "roc_builtins.num.atan";
|
pub const NUM_ATAN: &str = "roc_builtins.num.atan";
|
||||||
|
@ -49,7 +49,8 @@ use roc_module::ident::TagName;
|
|||||||
use roc_module::low_level::LowLevel;
|
use roc_module::low_level::LowLevel;
|
||||||
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
use roc_module::symbol::{Interns, ModuleId, Symbol};
|
||||||
use roc_mono::ir::{
|
use roc_mono::ir::{
|
||||||
BranchInfo, CallType, ExceptionId, JoinPointId, ModifyRc, TopLevelFunctionLayout, Wrapped,
|
BranchInfo, CallType, ExceptionId, JoinPointId, ModifyRc, OptLevel, TopLevelFunctionLayout,
|
||||||
|
Wrapped,
|
||||||
};
|
};
|
||||||
use roc_mono::layout::{Builtin, InPlace, LambdaSet, Layout, LayoutIds, UnionLayout};
|
use roc_mono::layout::{Builtin, InPlace, LambdaSet, Layout, LayoutIds, UnionLayout};
|
||||||
use target_lexicon::CallingConvention;
|
use target_lexicon::CallingConvention;
|
||||||
@ -86,21 +87,6 @@ macro_rules! debug_info_init {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
|
||||||
pub enum OptLevel {
|
|
||||||
Normal,
|
|
||||||
Optimize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<OptLevel> for OptimizationLevel {
|
|
||||||
fn from(level: OptLevel) -> Self {
|
|
||||||
match level {
|
|
||||||
OptLevel::Normal => OptimizationLevel::None,
|
|
||||||
OptLevel::Optimize => OptimizationLevel::Aggressive,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over all functions in an llvm module
|
/// Iterate over all functions in an llvm module
|
||||||
pub struct FunctionIterator<'ctx> {
|
pub struct FunctionIterator<'ctx> {
|
||||||
next: Option<FunctionValue<'ctx>>,
|
next: Option<FunctionValue<'ctx>>,
|
||||||
@ -355,7 +341,9 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn module_from_builtins<'ctx>(ctx: &'ctx Context, module_name: &str) -> Module<'ctx> {
|
pub fn module_from_builtins<'ctx>(ctx: &'ctx Context, module_name: &str) -> Module<'ctx> {
|
||||||
let bitcode_bytes = bitcode::as_bytes();
|
// In the build script for the builtins module,
|
||||||
|
// we compile the builtins into LLVM bitcode
|
||||||
|
let bitcode_bytes: &[u8] = include_bytes!("../../../builtins/bitcode/builtins.bc");
|
||||||
|
|
||||||
let memory_buffer = MemoryBuffer::create_from_memory_range(&bitcode_bytes, module_name);
|
let memory_buffer = MemoryBuffer::create_from_memory_range(&bitcode_bytes, module_name);
|
||||||
|
|
||||||
|
@ -43,6 +43,12 @@ macro_rules! return_on_layout_error {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum OptLevel {
|
||||||
|
Normal,
|
||||||
|
Optimize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum MonoProblem {
|
pub enum MonoProblem {
|
||||||
PatternProblem(crate::exhaustive::Error),
|
PatternProblem(crate::exhaustive::Error),
|
||||||
|
@ -6,6 +6,7 @@ use roc_can::def::Def;
|
|||||||
use roc_collections::all::{MutMap, MutSet};
|
use roc_collections::all::{MutMap, MutSet};
|
||||||
use roc_gen::llvm::externs::add_default_roc_externs;
|
use roc_gen::llvm::externs::add_default_roc_externs;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_types::subs::VarStore;
|
use roc_types::subs::VarStore;
|
||||||
|
|
||||||
fn promote_expr_to_module(src: &str) -> String {
|
fn promote_expr_to_module(src: &str) -> String {
|
||||||
@ -190,9 +191,9 @@ pub fn helper<'a>(
|
|||||||
module.strip_debug_info();
|
module.strip_debug_info();
|
||||||
|
|
||||||
let opt_level = if cfg!(debug_assertions) {
|
let opt_level = if cfg!(debug_assertions) {
|
||||||
roc_gen::llvm::build::OptLevel::Normal
|
OptLevel::Normal
|
||||||
} else {
|
} else {
|
||||||
roc_gen::llvm::build::OptLevel::Optimize
|
OptLevel::Optimize
|
||||||
};
|
};
|
||||||
|
|
||||||
let module = arena.alloc(module);
|
let module = arena.alloc(module);
|
||||||
|
@ -63,9 +63,10 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
|||||||
// Write each package's module docs html file
|
// Write each package's module docs html file
|
||||||
for (docs_by_id, interns) in package.modules.iter_mut() {
|
for (docs_by_id, interns) in package.modules.iter_mut() {
|
||||||
for module in docs_by_id.values_mut() {
|
for module in docs_by_id.values_mut() {
|
||||||
let mut filename = String::new();
|
let module_dir = build_dir.join(module.name.as_str());
|
||||||
filename.push_str(module.name.as_str());
|
|
||||||
filename.push_str(".html");
|
fs::create_dir(&module_dir)
|
||||||
|
.expect("TODO gracefully handle not being able to create the module dir");
|
||||||
|
|
||||||
let rendered_module = template_html
|
let rendered_module = template_html
|
||||||
.replace(
|
.replace(
|
||||||
@ -78,7 +79,7 @@ pub fn generate(filenames: Vec<PathBuf>, std_lib: StdLib, build_dir: &Path) {
|
|||||||
render_main_content(interns, module).as_str(),
|
render_main_content(interns, module).as_str(),
|
||||||
);
|
);
|
||||||
|
|
||||||
fs::write(build_dir.join(filename), rendered_module)
|
fs::write(module_dir.join("index.html"), rendered_module)
|
||||||
.expect("TODO gracefully handle failing to write html");
|
.expect("TODO gracefully handle failing to write html");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
www/.gitignore
vendored
Normal file
1
www/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
build
|
16
www/build.sh
16
www/build.sh
@ -1,4 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
# cd into the directory where this script lives.
|
||||||
|
# This allows us to run this script from the root project directory,
|
||||||
|
# which is what Netlify wants to do.
|
||||||
|
SCRIPT_RELATIVE_DIR=$(dirname "${BASH_SOURCE[0]}")
|
||||||
|
cd $SCRIPT_RELATIVE_DIR
|
||||||
|
|
||||||
rm -rf build/
|
rm -rf build/
|
||||||
cp -r public/ build/
|
cp -r public/ build/
|
||||||
|
|
||||||
|
pushd ..
|
||||||
|
echo 'Generating docs...'
|
||||||
|
# We run the CLI with --no-default-features because that way we don't have a LLVM
|
||||||
|
# dependency. (Netlify's build servers have Rust installed, but not LLVM.)
|
||||||
|
cargo run -p roc_cli --no-default-features docs compiler/builtins/docs/Bool.roc
|
||||||
|
mv generated-docs/ www/build/builtins
|
||||||
|
popd
|
||||||
|
Loading…
Reference in New Issue
Block a user