Skip to content

Commit 58ce594

Browse files
committed
Move C bindings to tblgen crate
1 parent 3068313 commit 58ce594

17 files changed

+887
-17
lines changed

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ license = "MIT OR Apache-2.0"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10-
tablegen-sys = { path = "../tablegen-sys" }
1110
thiserror = "1"
1211
paste = "1"
12+
13+
[build-dependencies]
14+
bindgen = "0.66"
15+
cc = "1.0"

build.rs

+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
use std::{
2+
env,
3+
error::Error,
4+
path::Path,
5+
process::{exit, Command},
6+
str,
7+
};
8+
9+
const LLVM_MAJOR_VERSION: usize = 17;
10+
11+
fn main() {
12+
if let Err(error) = run() {
13+
eprintln!("{}", error);
14+
exit(1);
15+
}
16+
}
17+
18+
fn run() -> Result<(), Box<dyn Error>> {
19+
let version = llvm_config("--version")?;
20+
21+
if !version.starts_with(&format!("{}.", LLVM_MAJOR_VERSION)) {
22+
return Err(format!(
23+
"failed to find correct version ({}.x.x) of llvm-config (found {})",
24+
LLVM_MAJOR_VERSION, version
25+
)
26+
.into());
27+
}
28+
29+
println!("cargo:rerun-if-changed=wrapper.h");
30+
println!("cargo:rerun-if-changed=cc");
31+
println!("cargo:rustc-link-search={}", llvm_config("--libdir")?);
32+
println!("cargo:rustc-link-lib=static={}", "LLVMCore");
33+
println!("cargo:rustc-link-lib=static={}", "LLVMSupport");
34+
println!("cargo:rustc-link-lib=static={}", "LLVMTableGen");
35+
36+
for name in llvm_config("--libnames")?.trim().split(' ') {
37+
if let Some(name) = trim_library_name(name) {
38+
println!("cargo:rustc-link-lib={}", name);
39+
}
40+
}
41+
42+
for flag in llvm_config("--system-libs")?.trim().split(' ') {
43+
let flag = flag.trim_start_matches("-l");
44+
45+
if flag.starts_with('/') {
46+
// llvm-config returns absolute paths for dynamically linked libraries.
47+
let path = Path::new(flag);
48+
49+
println!(
50+
"cargo:rustc-link-search={}",
51+
path.parent().unwrap().display()
52+
);
53+
println!(
54+
"cargo:rustc-link-lib={}",
55+
path.file_name()
56+
.unwrap()
57+
.to_str()
58+
.unwrap()
59+
.split_once('.')
60+
.unwrap()
61+
.0
62+
.trim_start_matches("lib")
63+
);
64+
} else {
65+
println!("cargo:rustc-link-lib={}", flag);
66+
}
67+
}
68+
69+
if let Some(name) = get_system_libcpp() {
70+
println!("cargo:rustc-link-lib={}", name);
71+
}
72+
73+
std::env::set_var("CXXFLAGS", llvm_config("--cxxflags")?);
74+
std::env::set_var("CFLAGS", llvm_config("--cflags")?);
75+
println!("cargo:rustc-link-search={}", &env::var("OUT_DIR")?);
76+
77+
cc::Build::new()
78+
.files(
79+
std::fs::read_dir("cc")?
80+
.into_iter()
81+
.filter(|r| r.is_ok())
82+
.map(|r| r.unwrap().path())
83+
.filter(|r| r.is_file() && r.extension().unwrap() == "cc"),
84+
)
85+
.cpp(true)
86+
.include("cc")
87+
.include(llvm_config("--includedir")?)
88+
.opt_level(3)
89+
.compile("CTableGen");
90+
91+
println!("cargo:rustc-link-lib=static={}", "CTableGen");
92+
93+
bindgen::builder()
94+
.header("wrapper.h")
95+
.clang_arg(format!("-I{}", "cc"))
96+
.clang_arg(format!("-I{}", llvm_config("--includedir")?))
97+
.default_enum_style(bindgen::EnumVariation::ModuleConsts)
98+
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
99+
.generate()
100+
.unwrap()
101+
.write_to_file(Path::new(&env::var("OUT_DIR")?).join("bindings.rs"))?;
102+
103+
Ok(())
104+
}
105+
106+
fn get_system_libcpp() -> Option<&'static str> {
107+
if cfg!(target_env = "msvc") {
108+
None
109+
} else if cfg!(target_os = "macos") {
110+
Some("c++")
111+
} else {
112+
Some("stdc++")
113+
}
114+
}
115+
116+
fn llvm_config(argument: &str) -> Result<String, Box<dyn Error>> {
117+
let prefix = env::var(format!("TABLEGEN_SYS_{}0_PREFIX", LLVM_MAJOR_VERSION))
118+
.map(|path| Path::new(&path).join("bin"))
119+
.unwrap_or_default();
120+
let call = format!(
121+
"{} --link-static {}",
122+
prefix.join("llvm-config").display(),
123+
argument
124+
);
125+
126+
Ok(str::from_utf8(
127+
&if cfg!(target_os = "windows") {
128+
Command::new("cmd").args(["/C", &call]).output()?
129+
} else {
130+
Command::new("sh").arg("-c").arg(&call).output()?
131+
}
132+
.stdout,
133+
)?
134+
.trim()
135+
.to_string())
136+
}
137+
138+
fn trim_library_name(name: &str) -> Option<&str> {
139+
if let Some(name) = name.strip_prefix("lib") {
140+
name.strip_suffix(".a")
141+
} else {
142+
None
143+
}
144+
}

cc/Record.cc

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Original work Copyright 2016 Alexander Stocko <[email protected]>.
2+
// Modified work Copyright 2023 Daan Vanoverloop
3+
// See the COPYRIGHT file at the top-level directory of this distribution.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include "TableGen.hpp"
12+
#include "Types.h"
13+
14+
using ctablegen::tableGenFromRecType;
15+
16+
TableGenRecordKeeperRef tableGenRecordGetRecords(TableGenRecordRef record_ref) {
17+
return wrap(&unwrap(record_ref)->getRecords());
18+
}
19+
20+
const char *tableGenRecordGetName(TableGenRecordRef record_ref) {
21+
return unwrap(record_ref)->getName().data();
22+
}
23+
24+
const char *tableGenRecordAsNewString(TableGenRecordRef record_ref) {
25+
auto record = unwrap(record_ref);
26+
auto name = record->getNameInitAsString();
27+
28+
auto sz = name.size() + 1;
29+
auto str = new char[sz];
30+
name.copy(str, name.size(), 0);
31+
str[sz - 1] = '\0';
32+
return str;
33+
}
34+
35+
TableGenRecordValRef tableGenRecordGetValue(TableGenRecordRef record_ref,
36+
const char *name) {
37+
return wrap(unwrap(record_ref)->getValue(StringRef(name)));
38+
}
39+
40+
TableGenRecTyKind tableGenRecordGetFieldType(TableGenRecordRef record_ref,
41+
const char *name) {
42+
auto value = unwrap(record_ref)->getValue(StringRef(name));
43+
if (!value)
44+
return TableGenInvalidRecTyKind;
45+
return tableGenFromRecType(value->getType());
46+
}
47+
48+
TableGenRecordValRef tableGenRecordGetFirstValue(TableGenRecordRef record_ref) {
49+
return wrap(unwrap(record_ref)->getValues().begin());
50+
}
51+
52+
TableGenRecordValRef tableGenRecordValNext(TableGenRecordRef record,
53+
TableGenRecordValRef current) {
54+
auto next = std::next(ArrayRef<RecordVal>::iterator(unwrap(current)));
55+
if (next == unwrap(record)->getValues().end()) {
56+
return nullptr;
57+
}
58+
return wrap(next);
59+
}
60+
61+
TableGenBool tableGenRecordIsAnonymous(TableGenRecordRef record_ref) {
62+
return unwrap(record_ref)->isAnonymous();
63+
}
64+
65+
TableGenBool tableGenRecordIsSubclassOf(TableGenRecordRef record_ref, const char *name) {
66+
return unwrap(record_ref)->isSubClassOf(StringRef(name));
67+
}
68+
69+
// tablegenBool TableGenRecordIsResolveFirst(TableGenRecordRef record_ref) {
70+
// CHECK_REF(record_ref, false);
71+
// auto record = AS_TYPE(Record *, record_ref);
72+
// return record->isResolveFirst();
73+
// }

cc/RecordKeeper.cc

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Original work Copyright 2016 Alexander Stocko <[email protected]>.
2+
// Modified work Copyright 2023 Daan Vanoverloop
3+
// See the COPYRIGHT file at the top-level directory of this distribution.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include "TableGen.hpp"
12+
#include "Types.h"
13+
14+
using ctablegen::RecordMap;
15+
16+
TableGenRecordMapRef
17+
tableGenRecordKeeperGetClasses(TableGenRecordKeeperRef rk_ref) {
18+
return wrap(&unwrap(rk_ref)->getClasses());
19+
}
20+
21+
TableGenRecordMapRef
22+
tableGenRecordKeeperGetDefs(TableGenRecordKeeperRef rk_ref) {
23+
return wrap(&unwrap(rk_ref)->getDefs());
24+
}
25+
26+
TableGenRecordRef tableGenRecordKeeperGetClass(TableGenRecordKeeperRef rk_ref,
27+
const char *name) {
28+
return wrap(unwrap(rk_ref)->getClass(std::string(name)));
29+
}
30+
31+
TableGenRecordRef tableGenRecordKeeperGetDef(TableGenRecordKeeperRef rk_ref,
32+
const char *name) {
33+
return wrap(unwrap(rk_ref)->getDef(std::string(name)));
34+
}
35+
36+
TableGenRecordVectorRef
37+
tableGenRecordKeeperGetAllDerivedDefinitions(TableGenRecordKeeperRef rk_ref,
38+
const char *className) {
39+
return wrap(new ctablegen::RecordVector(
40+
std::move(unwrap(rk_ref)->getAllDerivedDefinitions(className))));
41+
}
42+
43+
TableGenRecordRef tableGenRecordVectorGet(TableGenRecordVectorRef vec_ref,
44+
size_t index) {
45+
auto *vec = unwrap(vec_ref);
46+
if (index < vec->size())
47+
return wrap(((*vec)[index]));
48+
return nullptr;
49+
}
50+
51+
void tableGenRecordVectorFree(TableGenRecordVectorRef vec_ref) {
52+
delete unwrap(vec_ref);
53+
}

cc/RecordMap.cc

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Original work Copyright 2016 Alexander Stocko <[email protected]>.
2+
// Modified work Copyright 2023 Daan Vanoverloop
3+
// See the COPYRIGHT file at the top-level directory of this distribution.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include "TableGen.hpp"
12+
13+
using ctablegen::RecordMap;
14+
15+
TableGenRecordRef tableGenRecordMapGetFirst(TableGenRecordMapRef rm_ref) {
16+
return wrap(unwrap(rm_ref)->begin()->second.get());
17+
}
18+
19+
TableGenRecordRef tableGenRecordMapGet(TableGenRecordMapRef rm_ref,
20+
const char *name) {
21+
auto rm = unwrap(rm_ref);
22+
auto val = rm->find(name);
23+
if (val != rm->end()) {
24+
return wrap(rm->find(name)->second.get());
25+
}
26+
return nullptr;
27+
}
28+
29+
const char **tableGenRecordMapGetKeys(TableGenRecordMapRef rm_ref,
30+
size_t *len) {
31+
auto rm = unwrap(rm_ref);
32+
auto sz = rm->size();
33+
auto str_array = new const char *[sz];
34+
*len = sz;
35+
size_t idx = 0;
36+
37+
for (auto &i : *rm) {
38+
str_array[idx++] = i.first.c_str();
39+
}
40+
41+
return str_array;
42+
}

cc/RecordVal.cc

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Original work Copyright 2016 Alexander Stocko <[email protected]>.
2+
// Modified work Copyright 2023 Daan Vanoverloop
3+
// See the COPYRIGHT file at the top-level directory of this distribution.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#include "TableGen.h"
12+
#include "TableGen.hpp"
13+
#include "Types.h"
14+
15+
const char *tableGenRecordValGetName(TableGenRecordValRef rv_ref) {
16+
return unwrap(rv_ref)->getName().data();
17+
}
18+
19+
TableGenRecTyKind tableGenRecordValGetType(TableGenRecordValRef rv_ref) {
20+
return ctablegen::tableGenFromRecType(unwrap(rv_ref)->getType());
21+
}
22+
23+
TableGenTypedInitRef tableGenRecordValGetValue(TableGenRecordValRef rv_ref) {
24+
return wrap(dyn_cast<TypedInit>(unwrap(rv_ref)->getValue()));
25+
}
26+
27+
char *tableGenRecordValGetValAsNewString(TableGenRecordValRef rv_ref) {
28+
return tableGenStringInitGetValueNewString(
29+
wrap(dyn_cast<TypedInit>(unwrap(rv_ref)->getValue())));
30+
}
31+
32+
TableGenBool tableGenRecordValGetValAsBit(TableGenRecordValRef rv_ref,
33+
int8_t *bit) {
34+
return tableGenBitInitGetValue(
35+
wrap(dyn_cast<TypedInit>(unwrap(rv_ref)->getValue())), bit);
36+
}
37+
38+
int8_t *tableGenRecordValGetValAsBits(TableGenRecordValRef rv_ref,
39+
size_t *len) {
40+
return tableGenBitsInitGetValue(
41+
wrap(dyn_cast<TypedInit>(unwrap(rv_ref)->getValue())), len);
42+
}
43+
44+
TableGenBool tableGenRecordValGetValAsInt(TableGenRecordValRef rv_ref,
45+
int64_t *integer) {
46+
return tableGenIntInitGetValue(
47+
wrap(dyn_cast<TypedInit>(unwrap(rv_ref)->getValue())), integer);
48+
}
49+
50+
TableGenRecordRef
51+
tableGenRecordValGetValAsDefRecord(TableGenRecordValRef rv_ref) {
52+
return tableGenDefInitGetValue(
53+
wrap(dyn_cast<TypedInit>(unwrap(rv_ref)->getValue())));
54+
}

0 commit comments

Comments
 (0)