Skip to content
Merged
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: 5 additions & 2 deletions .github/workflows/macos_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ name: build-and-test-macos
on: ["push", "pull_request"]
jobs:
build-and-test:
# Ref: https://github.com/actions/virtual-environments/blob/main/images/macos/macos-12-Readme.md
runs-on: macos-12
# Ref: https://github.com/actions/runner-images/tree/main/images/macos
strategy:
matrix:
os: [macos-10.15, macos-11, macos-12]
runs-on: ${{ matrix.os }}
steps:
- name: Git checkout
uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ubuntu_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: build-and-test-ubuntu
on: ["push", "pull_request"]
jobs:
build-and-test:
# Ref: https://github.com/actions/runner-images/tree/main/images/linux
name: Test
runs-on: ubuntu-latest
container:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,7 @@ _a.out_*.*

# Compiler_base
.compiler_base

# LLVM
llvm*
llvm-*
3 changes: 3 additions & 0 deletions kclvm/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions kclvm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ name = "kclvm_cli_cdylib"
path = "src/main.rs"
name = "kclvm_cli"

[build-dependencies]
cc = "1.0"

[dependencies]
clap = "3.2.22"
serde_json = "1.0"
Expand Down
49 changes: 41 additions & 8 deletions kclvm/compiler/src/codegen/llvm/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use indexmap::IndexMap;
use inkwell::basic_block::BasicBlock;
use inkwell::builder::Builder;
use inkwell::context::Context;
use inkwell::memory_buffer::MemoryBuffer;
use inkwell::module::{Linkage, Module};
use inkwell::support::LLVMString;
use inkwell::targets::{CodeModel, FileType, RelocMode};
use inkwell::types::{BasicMetadataTypeEnum, BasicType, BasicTypeEnum, FunctionType};
use inkwell::values::{
BasicMetadataValueEnum, BasicValueEnum, FunctionValue, IntValue, PointerValue,
Expand All @@ -14,6 +17,7 @@ use phf::{phf_map, Map};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::path::Path;
use std::rc::Rc;
use std::str;

Expand All @@ -34,7 +38,7 @@ use crate::codegen::{
use crate::pkgpath_without_prefix;
use crate::value;

use super::LL_FILE_SUFFIX;
use super::OBJECT_FILE_SUFFIX;

/// Float type string width mapping
pub const FLOAT_TYPE_WIDTH_MAPPING: Map<&str, usize> = phf_map! {
Expand Down Expand Up @@ -1238,22 +1242,51 @@ impl<'ctx> LLVMCodeGenContext<'ctx> {
let modules = self.modules.borrow_mut();
for (index, (_, module)) in modules.iter().enumerate() {
let path = if modules.len() == 1 {
format!("{}{}", path_str, LL_FILE_SUFFIX)
format!("{}{}", path_str, OBJECT_FILE_SUFFIX)
} else {
format!("{}_{}{}", path_str, index, LL_FILE_SUFFIX)
format!("{}_{}{}", path_str, index, OBJECT_FILE_SUFFIX)
};
let path = std::path::Path::new(&path);
// Emit LLVM ll file
module.borrow_mut().print_to_file(path)?;
// Build LLVM module to a `.o` object file.
self.build_object_file(&module.borrow(), path)?;
}
} else {
self.module
.print_to_file(path)
.expect(kcl_error::CODE_GEN_ERROR_MSG);
// Build LLVM module to a `.o` object file.
self.build_object_file(&self.module, path)?;
}
}
Ok(())
}

/// Build LLVM module to a `.o` object file.
///
/// TODO: WASM and cross platform build.
fn build_object_file(
self: &LLVMCodeGenContext<'ctx>,
module: &Module,
path: &Path,
) -> Result<(), LLVMString> {
let triple = inkwell::targets::TargetMachine::get_default_triple();
let target = inkwell::targets::Target::from_triple(&triple)?;
// Convert LLVM module to ll file.
module.print_to_file(path)?;
let buf = MemoryBuffer::create_from_file(path)?;
let module = self.context.create_module_from_ir(buf)?;
// Read ll file and use target machine to generate native object file.
let target_machine = target
.create_target_machine(
&triple,
"",
"",
// We do not enable any optimization, so that
// the sum of compile time and run time is as small as possible
inkwell::OptimizationLevel::None,
RelocMode::PIC,
CodeModel::Default,
)
.expect(kcl_error::CODE_GEN_ERROR_MSG);
target_machine.write_to_file(&module, FileType::Object, path)
}
}

impl<'ctx> LLVMCodeGenContext<'ctx> {
Expand Down
4 changes: 4 additions & 0 deletions kclvm/compiler/src/codegen/llvm/emit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ pub fn emit_code(
) -> Result<(), Box<dyn error::Error>> {
// Init LLVM targets
LLVM_INIT.get_or_init(|| {
// TODO: linux arm and WASM target.
#[cfg(target_os = "linux")]
inkwell::targets::Target::initialize_x86(&Default::default());
#[cfg(not(target_os = "linux"))]
inkwell::targets::Target::initialize_all(&Default::default());
});
// Create a LLVM context
Expand Down
4 changes: 4 additions & 0 deletions kclvm/runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[build-dependencies]
cc = "1.0"

[dependencies]
serde_json = "1.0"
serde = { version = "1", features = ["derive"] }
Expand All @@ -18,6 +21,7 @@ threadpool = "1.0"
chrono = "0.4.19"
tempfile = "3.3.0"
anyhow = "1.0"
once_cell = "1.10"

kclvm-ast = {path = "../ast", version = "0.1.0"}
kclvm-parser = {path = "../parser", version = "0.1.0"}
Expand Down
71 changes: 71 additions & 0 deletions kclvm/runner/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//! Using `cc` crate to package LLVM `lld` static libraries into
//! the KCLVM CLI.
//!
//! Ref: https://github.com/hyperledger/solang/blob/main/build.rs

fn main() {
stack_link_lld();
}

/// Using `cc` crate to package `lld` static libraries into the KCLVM CLI.
fn stack_link_lld() {
use std::process::Command;

let cxxflags = Command::new("llvm-config")
.args(&["--cxxflags"])
.output()
.expect("could not execute llvm-config");

let cxxflags = String::from_utf8(cxxflags.stdout).unwrap();

let mut build = cc::Build::new();

build.file("src/linker.cpp").cpp(true);

if !cfg!(target_os = "windows") {
build.flag("-Wno-unused-parameter");
}

for flag in cxxflags.split_whitespace() {
build.flag(flag);
}

build.compile("liblinker.a");

let libdir = Command::new("llvm-config")
.args(&["--libdir"])
.output()
.unwrap();
let libdir = String::from_utf8(libdir.stdout).unwrap();

println!("cargo:libdir={}", libdir);
for lib in &[
"lldMachO",
"lldELF",
"lldMinGW",
"lldCOFF",
"lldDriver",
"lldCore",
"lldCommon",
"lldWasm",
] {
println!("cargo:rustc-link-lib=static={}", lib);
}

// Add all the symbols were not using, needed by Windows and debug builds
for lib in &["lldReaderWriter", "lldYAML"] {
println!("cargo:rustc-link-lib=static={}", lib);
}

let output = Command::new("git")
.args(&["describe", "--tags"])
.output()
.unwrap();
let git_hash = String::from_utf8(output.stdout).unwrap();
println!("cargo:rustc-env=GIT_HASH={}", git_hash);

// Make sure we have an 8MiB stack on Windows. Windows defaults to a 1MB
// stack, which is not big enough for debug builds
#[cfg(windows)]
println!("cargo:rustc-link-arg=/STACK:8388608");
}
Loading