Merge branch 'master' into sync_from_rust_2026_01_28
This commit is contained in:
commit
7db4614d46
18 changed files with 1708 additions and 1618 deletions
|
|
@ -18,6 +18,7 @@
|
|||
],
|
||||
"ignorePaths": [
|
||||
"src/intrinsic/archs.rs",
|
||||
"src/intrinsic/old_archs.rs",
|
||||
"src/intrinsic/llvm.rs"
|
||||
],
|
||||
"ignoreRegExpList": [
|
||||
|
|
|
|||
|
|
@ -56,18 +56,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gccjit"
|
||||
version = "3.1.1"
|
||||
version = "3.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff80f4d6d0749eab3a69122210b3a1fdd52edb6162781aadd7c4842e26983683"
|
||||
checksum = "ef03c8ae23826a0755b980999a553a262c61f2f585245e647192d95bf09eee79"
|
||||
dependencies = [
|
||||
"gccjit_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gccjit_sys"
|
||||
version = "1.1.2"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f81d901767ddba371a619fa9bba657066a4d3c5607ee69bbb557c1c5ba9bf85"
|
||||
checksum = "0ff511da413e4a5da6f09607748395ba37525e01ba7d322cbec3efc43095dd60"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ default = ["master"]
|
|||
[dependencies]
|
||||
object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
|
||||
tempfile = "3.20"
|
||||
gccjit = { version = "3.1.1", features = ["dlopen"] }
|
||||
gccjit = { version = "3.2.0", features = ["dlopen"] }
|
||||
#gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] }
|
||||
|
||||
# Local copy.
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ seh = "seh"
|
|||
typ = "typ"
|
||||
|
||||
[files]
|
||||
extend-exclude = ["src/intrinsic/archs.rs"]
|
||||
extend-exclude = ["src/intrinsic/archs.rs", "src/intrinsic/old_archs.rs"]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, internal_features, non_camel_case_types)]
|
||||
#![rustfmt_skip]
|
||||
#![cfg_attr(rustfmt, rustfmt_skip)]
|
||||
|
||||
extern crate mini_core;
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
0081ca6631abdfa02bf42bc85aaf507b8a0e6beb
|
||||
586d798e864fb33b1b4e842c5493a653841a7c02
|
||||
|
|
|
|||
24
src/archive.rs
Normal file
24
src/archive.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use std::path::Path;
|
||||
|
||||
use rustc_codegen_ssa::back::archive::{
|
||||
ArArchiveBuilder, ArchiveBuilder, ArchiveBuilderBuilder, DEFAULT_OBJECT_READER,
|
||||
};
|
||||
use rustc_session::Session;
|
||||
|
||||
pub(crate) struct ArArchiveBuilderBuilder;
|
||||
|
||||
impl ArchiveBuilderBuilder for ArArchiveBuilderBuilder {
|
||||
fn new_archive_builder<'a>(&self, sess: &'a Session) -> Box<dyn ArchiveBuilder + 'a> {
|
||||
Box::new(ArArchiveBuilder::new(sess, &DEFAULT_OBJECT_READER))
|
||||
}
|
||||
|
||||
fn create_dll_import_lib(
|
||||
&self,
|
||||
_sess: &Session,
|
||||
_lib_name: &str,
|
||||
_import_name_and_ordinal_vector: Vec<(String, Option<u16>)>,
|
||||
_output_path: &Path,
|
||||
) {
|
||||
unimplemented!("creating dll imports is not yet supported");
|
||||
}
|
||||
}
|
||||
|
|
@ -575,9 +575,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
|
|||
}
|
||||
if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) {
|
||||
let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
|
||||
let builtin_unreachable: RValue<'gcc> =
|
||||
unsafe { std::mem::transmute(builtin_unreachable) };
|
||||
self.call(self.type_void(), None, None, builtin_unreachable, &[], None, None);
|
||||
self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[]));
|
||||
}
|
||||
|
||||
// Write results to outputs.
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ use rustc_middle::ty::layout::{
|
|||
};
|
||||
use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
#[cfg(feature = "master")]
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi};
|
||||
|
|
@ -145,6 +147,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|||
supports_f64_type: bool,
|
||||
supports_f128_type: bool,
|
||||
) -> Self {
|
||||
#[cfg(feature = "master")]
|
||||
if tcx.sess.opts.debuginfo != DebugInfo::None {
|
||||
context.set_filename(codegen_unit.name().as_str());
|
||||
}
|
||||
|
||||
let create_type = |ctype, rust_type| {
|
||||
let layout = tcx
|
||||
.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(rust_type))
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1061,7 +1061,18 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
|
|||
|
||||
"llvm.x86.xgetbv" => "__builtin_ia32_xgetbv",
|
||||
// NOTE: this doc specifies the equivalent GCC builtins: http://huonw.github.io/llvmint/llvmint/x86/index.html
|
||||
// FIXME: Should handle other targets than `ia32`.
|
||||
"llvm.sqrt.v2f64" => "__builtin_ia32_sqrtpd",
|
||||
// FIXME: Should handle other targets than `ia32`.
|
||||
"llvm.sqrt.v4f32" => "__builtin_ia32_sqrtps",
|
||||
"llvm.sqrt.f32" => {
|
||||
let gcc_name = "__builtin_sqrtf";
|
||||
let func = cx.context.get_builtin_function(gcc_name);
|
||||
cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
|
||||
return func;
|
||||
}
|
||||
// FIXME: Should handle other targets than `ia32`.
|
||||
"llvm.smax.v4i32" => "__builtin_ia32_pmaxsd128",
|
||||
"llvm.x86.avx512.pmul.dq.512" => "__builtin_ia32_pmuldq512_mask",
|
||||
"llvm.x86.avx512.pmulu.dq.512" => "__builtin_ia32_pmuludq512_mask",
|
||||
"llvm.x86.avx512.max.ps.512" => "__builtin_ia32_maxps512_mask",
|
||||
|
|
@ -1604,5 +1615,7 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function
|
|||
func
|
||||
}
|
||||
|
||||
#[cfg(feature = "master")]
|
||||
include!("old_archs.rs");
|
||||
#[cfg(feature = "master")]
|
||||
include!("archs.rs");
|
||||
|
|
|
|||
|
|
@ -69,44 +69,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
|
|||
sym::fabsf64 => "fabs",
|
||||
sym::minnumf32 => "fminf",
|
||||
sym::minnumf64 => "fmin",
|
||||
sym::minimumf32 => "fminimumf",
|
||||
sym::minimumf64 => "fminimum",
|
||||
sym::minimumf128 => {
|
||||
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fminimumf128.html
|
||||
let f128_type = cx.type_f128();
|
||||
return Some(cx.context.new_function(
|
||||
None,
|
||||
FunctionType::Extern,
|
||||
f128_type,
|
||||
&[
|
||||
cx.context.new_parameter(None, f128_type, "a"),
|
||||
cx.context.new_parameter(None, f128_type, "b"),
|
||||
],
|
||||
"fminimumf128",
|
||||
false,
|
||||
));
|
||||
}
|
||||
sym::maxnumf32 => "fmaxf",
|
||||
sym::maxnumf64 => "fmax",
|
||||
sym::maximumf32 => "fmaximumf",
|
||||
sym::maximumf64 => "fmaximum",
|
||||
sym::maximumf128 => {
|
||||
// GCC doesn't have the intrinsic we want so we use the compiler-builtins one
|
||||
// https://docs.rs/compiler_builtins/latest/compiler_builtins/math/full_availability/fn.fmaximumf128.html
|
||||
let f128_type = cx.type_f128();
|
||||
return Some(cx.context.new_function(
|
||||
None,
|
||||
FunctionType::Extern,
|
||||
f128_type,
|
||||
&[
|
||||
cx.context.new_parameter(None, f128_type, "a"),
|
||||
cx.context.new_parameter(None, f128_type, "b"),
|
||||
],
|
||||
"fmaximumf128",
|
||||
false,
|
||||
));
|
||||
}
|
||||
sym::copysignf32 => "copysignf",
|
||||
sym::copysignf64 => "copysign",
|
||||
sym::floorf32 => "floorf",
|
||||
|
|
|
|||
1390
src/intrinsic/old_archs.rs
Normal file
1390
src/intrinsic/old_archs.rs
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -240,6 +240,8 @@ impl CodegenBackend for GccCodegenBackend {
|
|||
|
||||
#[cfg(feature = "master")]
|
||||
{
|
||||
gccjit::set_lang_name(c"GNU Rust");
|
||||
|
||||
let target_cpu = target_cpu(sess);
|
||||
|
||||
// Get the second TargetInfo with the correct CPU features by setting the arch.
|
||||
|
|
|
|||
38
tests/run/call-llvm-intrinsics.rs
Normal file
38
tests/run/call-llvm-intrinsics.rs
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
// FIXME: Remove this test once rustc's `./tests/codegen/riscv-abi/call-llvm-intrinsics.rs`
|
||||
// stops ignoring GCC backend.
|
||||
|
||||
#![feature(link_llvm_intrinsics)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
struct A;
|
||||
|
||||
impl Drop for A {
|
||||
fn drop(&mut self) {
|
||||
println!("A");
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "llvm.sqrt.f32"]
|
||||
fn sqrt(x: f32) -> f32;
|
||||
}
|
||||
|
||||
pub fn do_call() {
|
||||
let _a = A;
|
||||
|
||||
unsafe {
|
||||
// Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them
|
||||
// CHECK: store float 4.000000e+00, float* %{{.}}, align 4
|
||||
// CHECK: call float @llvm.sqrt.f32(float %{{.}}
|
||||
sqrt(4.0);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
do_call();
|
||||
}
|
||||
102
tests/run/simd-ffi.rs
Normal file
102
tests/run/simd-ffi.rs
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
// FIXME: Remove this test once <tests/run-make/simd-ffi/simd.rs> stops
|
||||
// ignoring GCC backend.
|
||||
|
||||
#![allow(internal_features, non_camel_case_types)]
|
||||
// we can compile to a variety of platforms, because we don't need
|
||||
// cross-compiled standard libraries.
|
||||
#![feature(no_core, auto_traits)]
|
||||
#![no_core]
|
||||
#![feature(repr_simd, simd_ffi, link_llvm_intrinsics, lang_items, rustc_attrs)]
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(simd)]
|
||||
pub struct f32x4([f32; 4]);
|
||||
|
||||
extern "C" {
|
||||
#[link_name = "llvm.sqrt.v4f32"]
|
||||
fn vsqrt(x: f32x4) -> f32x4;
|
||||
}
|
||||
|
||||
pub fn foo(x: f32x4) -> f32x4 {
|
||||
unsafe { vsqrt(x) }
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
#[repr(simd)]
|
||||
pub struct i32x4([i32; 4]);
|
||||
|
||||
extern "C" {
|
||||
// _mm_sll_epi32
|
||||
#[cfg(all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"))]
|
||||
#[link_name = "llvm.x86.sse2.psll.d"]
|
||||
fn integer(a: i32x4, b: i32x4) -> i32x4;
|
||||
|
||||
// vmaxq_s32
|
||||
#[cfg(target_arch = "arm")]
|
||||
#[link_name = "llvm.arm.neon.vmaxs.v4i32"]
|
||||
fn integer(a: i32x4, b: i32x4) -> i32x4;
|
||||
// vmaxq_s32
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[link_name = "llvm.aarch64.neon.maxs.v4i32"]
|
||||
fn integer(a: i32x4, b: i32x4) -> i32x4;
|
||||
|
||||
// Use a generic LLVM intrinsic to do type checking on other platforms
|
||||
#[cfg(not(any(
|
||||
all(any(target_arch = "x86", target_arch = "x86-64"), target_feature = "sse2"),
|
||||
target_arch = "arm",
|
||||
target_arch = "aarch64"
|
||||
)))]
|
||||
#[link_name = "llvm.smax.v4i32"]
|
||||
fn integer(a: i32x4, b: i32x4) -> i32x4;
|
||||
}
|
||||
|
||||
pub fn bar(a: i32x4, b: i32x4) -> i32x4 {
|
||||
unsafe { integer(a, b) }
|
||||
}
|
||||
|
||||
#[lang = "pointee_sized"]
|
||||
pub trait PointeeSized {}
|
||||
|
||||
#[lang = "meta_sized"]
|
||||
pub trait MetaSized: PointeeSized {}
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized: MetaSized {}
|
||||
|
||||
#[lang = "copy"]
|
||||
pub trait Copy {}
|
||||
|
||||
impl Copy for f32 {}
|
||||
impl Copy for i32 {}
|
||||
impl Copy for [f32; 4] {}
|
||||
impl Copy for [i32; 4] {}
|
||||
|
||||
pub mod marker {
|
||||
pub use Copy;
|
||||
}
|
||||
|
||||
#[lang = "freeze"]
|
||||
auto trait Freeze {}
|
||||
|
||||
#[macro_export]
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! Copy {
|
||||
() => {};
|
||||
}
|
||||
#[macro_export]
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! derive {
|
||||
() => {};
|
||||
}
|
||||
|
||||
#[lang = "start"]
|
||||
fn start<T>(_main: fn() -> T, _argc: isize, _argv: *const *const u8, _sigpipe: u8) -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
27
tests/run/unreachable-function.rs
Normal file
27
tests/run/unreachable-function.rs
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// Compiler:
|
||||
//
|
||||
// Run-time:
|
||||
// status: 0
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
fn exit_syscall(status: i32) -> ! {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe {
|
||||
asm!(
|
||||
"syscall",
|
||||
in("rax") 60,
|
||||
in("rdi") status,
|
||||
options(noreturn)
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "x86_64"))]
|
||||
std::process::exit(status);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Used to crash with rustc_codegen_gcc.
|
||||
exit_syscall(0);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ def run_command(command, cwd=None):
|
|||
sys.exit(1)
|
||||
|
||||
|
||||
def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None):
|
||||
def clone_repository(repo_name, path, repo_url, sub_paths):
|
||||
if os.path.exists(path):
|
||||
while True:
|
||||
choice = input("There is already a `{}` folder, do you want to update it? [y/N]".format(path))
|
||||
|
|
@ -21,18 +21,15 @@ def clone_repository(repo_name, path, repo_url, branch="master", sub_paths=None)
|
|||
return
|
||||
elif choice.lower() == "y":
|
||||
print("Updating repository...")
|
||||
run_command(["git", "pull", "origin", branch], cwd=path)
|
||||
run_command(["git", "pull", "origin", "main"], cwd=path)
|
||||
return
|
||||
else:
|
||||
print("Didn't understand answer...")
|
||||
print("Cloning {} repository...".format(repo_name))
|
||||
if sub_paths is None:
|
||||
run_command(["git", "clone", repo_url, "--depth", "1", path])
|
||||
else:
|
||||
run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path])
|
||||
run_command(["git", "sparse-checkout", "init"], cwd=path)
|
||||
run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path)
|
||||
run_command(["git", "checkout"], cwd=path)
|
||||
run_command(["git", "clone", repo_url, "--filter=tree:0", "--no-checkout", path])
|
||||
run_command(["git", "sparse-checkout", "init"], cwd=path)
|
||||
run_command(["git", "sparse-checkout", "set", *sub_paths], cwd=path)
|
||||
run_command(["git", "checkout"], cwd=path)
|
||||
|
||||
|
||||
def append_intrinsic(array, intrinsic_name, translation):
|
||||
|
|
@ -45,121 +42,36 @@ def convert_to_string(content):
|
|||
return content
|
||||
|
||||
|
||||
def extract_intrinsics_from_llvm(llvm_path, intrinsics):
|
||||
command = ["llvm-tblgen", "llvm/IR/Intrinsics.td"]
|
||||
def extract_intrinsics_from_llvm(llvm_path):
|
||||
intrinsics = {}
|
||||
command = ["llvm-tblgen", "llvm/IR/Intrinsics.td", "--dump-json"]
|
||||
cwd = os.path.join(llvm_path, "llvm/include")
|
||||
print("=> Running command `{}` from `{}`".format(command, cwd))
|
||||
p = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE)
|
||||
output, err = p.communicate()
|
||||
lines = convert_to_string(output).splitlines()
|
||||
pos = 0
|
||||
while pos < len(lines):
|
||||
line = lines[pos]
|
||||
if not line.startswith("def "):
|
||||
pos += 1
|
||||
content = json.loads(convert_to_string(output))
|
||||
for intrinsic in content:
|
||||
data = content[intrinsic]
|
||||
if not isinstance(data, dict):
|
||||
continue
|
||||
intrinsic = line.split(" ")[1].strip()
|
||||
content = line
|
||||
while pos < len(lines):
|
||||
line = lines[pos].split(" // ")[0].strip()
|
||||
content += line
|
||||
pos += 1
|
||||
if line == "}":
|
||||
break
|
||||
entries = re.findall('string ClangBuiltinName = "(\\w+)";', content)
|
||||
current_arch = re.findall('string TargetPrefix = "(\\w+)";', content)
|
||||
if len(entries) == 1 and len(current_arch) == 1:
|
||||
current_arch = current_arch[0]
|
||||
intrinsic = intrinsic.split("_")
|
||||
if len(intrinsic) < 2 or intrinsic[0] != "int":
|
||||
continue
|
||||
intrinsic[0] = "llvm"
|
||||
intrinsic = ".".join(intrinsic)
|
||||
if current_arch not in intrinsics:
|
||||
intrinsics[current_arch] = []
|
||||
append_intrinsic(intrinsics[current_arch], intrinsic, entries[0])
|
||||
|
||||
|
||||
def append_translation(json_data, p, array):
|
||||
it = json_data["index"][p]
|
||||
content = it["docs"].split('`')
|
||||
if len(content) != 5:
|
||||
return
|
||||
append_intrinsic(array, content[1], content[3])
|
||||
|
||||
|
||||
def extract_intrinsics_from_llvmint(llvmint, intrinsics):
|
||||
archs = [
|
||||
"AMDGPU",
|
||||
"aarch64",
|
||||
"arm",
|
||||
"cuda",
|
||||
"hexagon",
|
||||
"mips",
|
||||
"nvvm",
|
||||
"ppc",
|
||||
"ptx",
|
||||
"x86",
|
||||
"xcore",
|
||||
]
|
||||
|
||||
json_file = os.path.join(llvmint, "target/doc/llvmint.json")
|
||||
# We need to regenerate the documentation!
|
||||
run_command(
|
||||
["cargo", "rustdoc", "--", "-Zunstable-options", "--output-format", "json"],
|
||||
cwd=llvmint,
|
||||
)
|
||||
with open(json_file, "r", encoding="utf8") as f:
|
||||
json_data = json.loads(f.read())
|
||||
for p in json_data["paths"]:
|
||||
it = json_data["paths"][p]
|
||||
if it["crate_id"] != 0:
|
||||
# This is from an external crate.
|
||||
current_arch = data.get("TargetPrefix")
|
||||
builtin_name = data.get("ClangBuiltinName")
|
||||
if current_arch is None or current_arch == "" or builtin_name is None:
|
||||
continue
|
||||
if it["kind"] != "function":
|
||||
# We're only looking for functions.
|
||||
intrinsic = intrinsic.split("_")
|
||||
if len(intrinsic) < 2 or intrinsic[0] != "int":
|
||||
continue
|
||||
# if len(it["path"]) == 2:
|
||||
# # This is a "general" intrinsic, not bound to a specific arch.
|
||||
# append_translation(json_data, p, general)
|
||||
# continue
|
||||
if len(it["path"]) != 3 or it["path"][1] not in archs:
|
||||
continue
|
||||
arch = it["path"][1]
|
||||
if arch not in intrinsics:
|
||||
intrinsics[arch] = []
|
||||
append_translation(json_data, p, intrinsics[arch])
|
||||
intrinsic[0] = "llvm"
|
||||
intrinsic = ".".join(intrinsic)
|
||||
if current_arch not in intrinsics:
|
||||
intrinsics[current_arch] = []
|
||||
append_intrinsic(intrinsics[current_arch], intrinsic, builtin_name)
|
||||
|
||||
return intrinsics
|
||||
|
||||
|
||||
def fill_intrinsics(intrinsics, from_intrinsics, all_intrinsics):
|
||||
for arch in from_intrinsics:
|
||||
if arch not in intrinsics:
|
||||
intrinsics[arch] = []
|
||||
for entry in from_intrinsics[arch]:
|
||||
if entry[0] in all_intrinsics:
|
||||
if all_intrinsics[entry[0]] == entry[1]:
|
||||
# This is a "full" duplicate, both the LLVM instruction and the GCC
|
||||
# translation are the same.
|
||||
continue
|
||||
intrinsics[arch].append((entry[0], entry[1], True))
|
||||
else:
|
||||
intrinsics[arch].append((entry[0], entry[1], False))
|
||||
all_intrinsics[entry[0]] = entry[1]
|
||||
|
||||
|
||||
def update_intrinsics(llvm_path, llvmint, llvmint2):
|
||||
intrinsics_llvm = {}
|
||||
intrinsics_llvmint = {}
|
||||
all_intrinsics = {}
|
||||
|
||||
extract_intrinsics_from_llvm(llvm_path, intrinsics_llvm)
|
||||
extract_intrinsics_from_llvmint(llvmint, intrinsics_llvmint)
|
||||
extract_intrinsics_from_llvmint(llvmint2, intrinsics_llvmint)
|
||||
|
||||
intrinsics = {}
|
||||
# We give priority to translations from LLVM over the ones from llvmint.
|
||||
fill_intrinsics(intrinsics, intrinsics_llvm, all_intrinsics)
|
||||
fill_intrinsics(intrinsics, intrinsics_llvmint, all_intrinsics)
|
||||
def update_intrinsics(llvm_path):
|
||||
intrinsics = extract_intrinsics_from_llvm(llvm_path)
|
||||
|
||||
archs = [arch for arch in intrinsics]
|
||||
archs.sort()
|
||||
|
|
@ -173,33 +85,41 @@ def update_intrinsics(llvm_path, llvmint, llvmint2):
|
|||
# Since all intrinsic names start with "llvm.", we skip that prefix.
|
||||
print("Updating content of `{}`...".format(output_file))
|
||||
with open(output_file, "w", encoding="utf8") as out:
|
||||
out.write("// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`\n")
|
||||
out.write("// DO NOT EDIT IT!\n")
|
||||
out.write("/// Translate a given LLVM intrinsic name to an equivalent GCC one.\n")
|
||||
out.write("fn map_arch_intrinsic(full_name:&str)->&'static str{\n")
|
||||
out.write('let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };\n')
|
||||
out.write('let Some((arch, name)) = name.split_once(\'.\') else { unimplemented!("***** unsupported LLVM intrinsic {}", name) };\n')
|
||||
out.write("match arch {\n")
|
||||
out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py`
|
||||
// DO NOT EDIT IT!
|
||||
/// Translate a given LLVM intrinsic name to an equivalent GCC one.
|
||||
fn map_arch_intrinsic(full_name:&str)-> &'static str {
|
||||
let Some(name) = full_name.strip_prefix("llvm.") else { unimplemented!("***** unsupported LLVM intrinsic {}", full_name) };
|
||||
let Some((arch, name)) = name.split_once('.') else { unimplemented!("***** unsupported LLVM intrinsic llvm.{}", name) };
|
||||
let old_arch_res = old_archs(arch, name);
|
||||
if let ArchCheckResult::Ok(res) = old_arch_res {
|
||||
return res;
|
||||
}
|
||||
match arch {""")
|
||||
for arch in archs:
|
||||
if len(intrinsics[arch]) == 0:
|
||||
continue
|
||||
attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else ""
|
||||
out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch))
|
||||
intrinsics[arch].sort(key=lambda x: (x[0], x[2]))
|
||||
intrinsics[arch].sort(key=lambda x: (x[0], x[1]))
|
||||
out.write(' // {}\n'.format(arch))
|
||||
for entry in intrinsics[arch]:
|
||||
llvm_name = entry[0].removeprefix("llvm.");
|
||||
llvm_name = llvm_name.removeprefix(arch);
|
||||
llvm_name = llvm_name.removeprefix(".");
|
||||
if entry[2] is True: # if it is a duplicate
|
||||
out.write(' // [DUPLICATE]: "{}" => "{}",\n'.format(llvm_name, entry[1]))
|
||||
elif "_round_mask" in entry[1]:
|
||||
if "_round_mask" in entry[1]:
|
||||
out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1]))
|
||||
else:
|
||||
out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1]))
|
||||
out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n')
|
||||
out.write("}} }} {}(name,full_name) }}\n,".format(arch))
|
||||
out.write(' _ => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic:{full_name}"),\n')
|
||||
out.write(""" _ => {
|
||||
match old_arch_res {
|
||||
ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),
|
||||
ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"),
|
||||
ArchCheckResult::Ok(_) => unreachable!(),
|
||||
}
|
||||
}""")
|
||||
out.write("}\n}")
|
||||
subprocess.call(["rustfmt", output_file])
|
||||
print("Done!")
|
||||
|
|
@ -210,35 +130,21 @@ def main():
|
|||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"llvm-project",
|
||||
)
|
||||
llvmint_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"llvmint",
|
||||
)
|
||||
llvmint2_path = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"llvmint-2",
|
||||
)
|
||||
|
||||
# First, we clone the LLVM repository if it's not already here.
|
||||
clone_repository(
|
||||
"llvm-project",
|
||||
llvm_path,
|
||||
"https://github.com/llvm/llvm-project",
|
||||
branch="main",
|
||||
sub_paths=["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"],
|
||||
["llvm/include/llvm/IR", "llvm/include/llvm/CodeGen/"],
|
||||
)
|
||||
clone_repository(
|
||||
"llvmint",
|
||||
llvmint_path,
|
||||
"https://github.com/GuillaumeGomez/llvmint",
|
||||
)
|
||||
clone_repository(
|
||||
"llvmint2",
|
||||
llvmint2_path,
|
||||
"https://github.com/antoyo/llvmint",
|
||||
)
|
||||
update_intrinsics(llvm_path, llvmint_path, llvmint2_path)
|
||||
update_intrinsics(llvm_path)
|
||||
|
||||
# llvm-tblgen can be built with:
|
||||
#
|
||||
# mkdir llvm-tblgen-build && cd llvm-tblgen-build
|
||||
# cmake -G Ninja -DLLVM_ENABLE_PROJECTS="llvm" -DCMAKE_BUILD_TYPE=Release ../llvm
|
||||
# ninja llvm-tblgen
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue