audit LLVM C++ types in ArchiveWrapper and PassWrapper
This commit is contained in:
parent
81df89fc2d
commit
696691e3c4
8 changed files with 275 additions and 114 deletions
|
@ -40,13 +40,9 @@ pub use self::TypeKind::*;
|
||||||
pub use self::AtomicBinOp::*;
|
pub use self::AtomicBinOp::*;
|
||||||
pub use self::AtomicOrdering::*;
|
pub use self::AtomicOrdering::*;
|
||||||
pub use self::SynchronizationScope::*;
|
pub use self::SynchronizationScope::*;
|
||||||
pub use self::FileType::*;
|
|
||||||
pub use self::MetadataType::*;
|
pub use self::MetadataType::*;
|
||||||
pub use self::AsmDialect::*;
|
pub use self::AsmDialect::*;
|
||||||
pub use self::CodeGenOptLevel::*;
|
|
||||||
pub use self::CodeGenOptSize::*;
|
pub use self::CodeGenOptSize::*;
|
||||||
pub use self::RelocMode::*;
|
|
||||||
pub use self::CodeGenModel::*;
|
|
||||||
pub use self::DiagnosticKind::*;
|
pub use self::DiagnosticKind::*;
|
||||||
pub use self::CallConv::*;
|
pub use self::CallConv::*;
|
||||||
pub use self::Visibility::*;
|
pub use self::Visibility::*;
|
||||||
|
@ -75,9 +71,26 @@ pub type Bool = c_uint;
|
||||||
pub const True: Bool = 1 as Bool;
|
pub const True: Bool = 1 as Bool;
|
||||||
pub const False: Bool = 0 as Bool;
|
pub const False: Bool = 0 as Bool;
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
pub enum LLVMRustResult {
|
||||||
|
Success = 0,
|
||||||
|
Failure = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LLVMRustResult {
|
||||||
|
pub fn into_result(self) -> Result<(), ()> {
|
||||||
|
match self {
|
||||||
|
LLVMRustResult::Success => Ok(()),
|
||||||
|
LLVMRustResult::Failure => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Consts for the LLVM CallConv type, pre-cast to usize.
|
// Consts for the LLVM CallConv type, pre-cast to usize.
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
#[repr(C)]
|
||||||
pub enum CallConv {
|
pub enum CallConv {
|
||||||
CCallConv = 0,
|
CCallConv = 0,
|
||||||
FastCallConv = 8,
|
FastCallConv = 8,
|
||||||
|
@ -89,6 +102,7 @@ pub enum CallConv {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
pub enum Visibility {
|
pub enum Visibility {
|
||||||
LLVMDefaultVisibility = 0,
|
LLVMDefaultVisibility = 0,
|
||||||
HiddenVisibility = 1,
|
HiddenVisibility = 1,
|
||||||
|
@ -100,6 +114,7 @@ pub enum Visibility {
|
||||||
// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
|
// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
|
||||||
// they've been removed in upstream LLVM commit r203866.
|
// they've been removed in upstream LLVM commit r203866.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
#[repr(C)]
|
||||||
pub enum Linkage {
|
pub enum Linkage {
|
||||||
ExternalLinkage = 0,
|
ExternalLinkage = 0,
|
||||||
AvailableExternallyLinkage = 1,
|
AvailableExternallyLinkage = 1,
|
||||||
|
@ -337,12 +352,12 @@ pub enum SynchronizationScope {
|
||||||
CrossThread = 1
|
CrossThread = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum FileType {
|
pub enum FileType {
|
||||||
AssemblyFileType = 0,
|
Other,
|
||||||
ObjectFileType = 1
|
AssemblyFile,
|
||||||
|
ObjectFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -371,10 +386,11 @@ pub enum AsmDialect {
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum CodeGenOptLevel {
|
pub enum CodeGenOptLevel {
|
||||||
CodeGenLevelNone = 0,
|
Other,
|
||||||
CodeGenLevelLess = 1,
|
None,
|
||||||
CodeGenLevelDefault = 2,
|
Less,
|
||||||
CodeGenLevelAggressive = 3,
|
Default,
|
||||||
|
Aggressive,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
|
@ -388,21 +404,22 @@ pub enum CodeGenOptSize {
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum RelocMode {
|
pub enum RelocMode {
|
||||||
RelocDefault = 0,
|
Default = 0,
|
||||||
RelocStatic = 1,
|
Static = 1,
|
||||||
RelocPIC = 2,
|
PIC = 2,
|
||||||
RelocDynamicNoPic = 3,
|
DynamicNoPic = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum CodeGenModel {
|
pub enum CodeModel {
|
||||||
CodeModelDefault = 0,
|
Other,
|
||||||
CodeModelJITDefault = 1,
|
Default,
|
||||||
CodeModelSmall = 2,
|
JITDefault,
|
||||||
CodeModelKernel = 3,
|
Small,
|
||||||
CodeModelMedium = 4,
|
Kernel,
|
||||||
CodeModelLarge = 5,
|
Medium,
|
||||||
|
Large,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
|
@ -421,6 +438,7 @@ pub enum DiagnosticKind {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum ArchiveKind {
|
pub enum ArchiveKind {
|
||||||
|
Other,
|
||||||
K_GNU,
|
K_GNU,
|
||||||
K_MIPS64,
|
K_MIPS64,
|
||||||
K_BSD,
|
K_BSD,
|
||||||
|
@ -444,10 +462,10 @@ impl FromStr for ArchiveKind {
|
||||||
/// Represents the different LLVM passes Rust supports
|
/// Represents the different LLVM passes Rust supports
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum SupportedPassKind {
|
pub enum PassKind {
|
||||||
|
Other,
|
||||||
Function,
|
Function,
|
||||||
Module,
|
Module,
|
||||||
Unsupported,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opaque pointer types
|
// Opaque pointer types
|
||||||
|
@ -2021,7 +2039,7 @@ extern {
|
||||||
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
|
pub fn LLVMIsAAllocaInst(value_ref: ValueRef) -> ValueRef;
|
||||||
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
|
pub fn LLVMIsAConstantInt(value_ref: ValueRef) -> ValueRef;
|
||||||
|
|
||||||
pub fn LLVMRustPassKind(Pass: PassRef) -> SupportedPassKind;
|
pub fn LLVMRustPassKind(Pass: PassRef) -> PassKind;
|
||||||
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
|
pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> PassRef;
|
||||||
pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
|
pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
|
||||||
|
|
||||||
|
@ -2031,7 +2049,7 @@ extern {
|
||||||
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
|
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
|
||||||
CPU: *const c_char,
|
CPU: *const c_char,
|
||||||
Features: *const c_char,
|
Features: *const c_char,
|
||||||
Model: CodeGenModel,
|
Model: CodeModel,
|
||||||
Reloc: RelocMode,
|
Reloc: RelocMode,
|
||||||
Level: CodeGenOptLevel,
|
Level: CodeGenOptLevel,
|
||||||
UseSoftFP: bool,
|
UseSoftFP: bool,
|
||||||
|
@ -2057,7 +2075,8 @@ extern {
|
||||||
PM: PassManagerRef,
|
PM: PassManagerRef,
|
||||||
M: ModuleRef,
|
M: ModuleRef,
|
||||||
Output: *const c_char,
|
Output: *const c_char,
|
||||||
FileType: FileType) -> bool;
|
FileType: FileType)
|
||||||
|
-> LLVMRustResult;
|
||||||
pub fn LLVMRustPrintModule(PM: PassManagerRef,
|
pub fn LLVMRustPrintModule(PM: PassManagerRef,
|
||||||
M: ModuleRef,
|
M: ModuleRef,
|
||||||
Output: *const c_char);
|
Output: *const c_char);
|
||||||
|
@ -2123,7 +2142,8 @@ extern {
|
||||||
NumMembers: size_t,
|
NumMembers: size_t,
|
||||||
Members: *const RustArchiveMemberRef,
|
Members: *const RustArchiveMemberRef,
|
||||||
WriteSymbtab: bool,
|
WriteSymbtab: bool,
|
||||||
Kind: ArchiveKind) -> c_int;
|
Kind: ArchiveKind) ->
|
||||||
|
LLVMRustResult;
|
||||||
pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
|
pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
|
||||||
Name: *const c_char,
|
Name: *const c_char,
|
||||||
Child: ArchiveChildRef) -> RustArchiveMemberRef;
|
Child: ArchiveChildRef) -> RustArchiveMemberRef;
|
||||||
|
|
|
@ -293,7 +293,7 @@ impl<'a> ArchiveBuilder<'a> {
|
||||||
members.as_ptr(),
|
members.as_ptr(),
|
||||||
self.should_update_symbols,
|
self.should_update_symbols,
|
||||||
kind);
|
kind);
|
||||||
let ret = if r != 0 {
|
let ret = if r.into_result().is_err() {
|
||||||
let err = llvm::LLVMRustGetLastError();
|
let err = llvm::LLVMRustGetLastError();
|
||||||
let msg = if err.is_null() {
|
let msg = if err.is_null() {
|
||||||
"failed to write archive".to_string()
|
"failed to write archive".to_string()
|
||||||
|
|
|
@ -54,7 +54,7 @@ pub fn write_output_file(
|
||||||
let output_c = path2cstr(output);
|
let output_c = path2cstr(output);
|
||||||
let result = llvm::LLVMRustWriteOutputFile(
|
let result = llvm::LLVMRustWriteOutputFile(
|
||||||
target, pm, m, output_c.as_ptr(), file_type);
|
target, pm, m, output_c.as_ptr(), file_type);
|
||||||
if !result {
|
if result.into_result().is_err() {
|
||||||
llvm_err(handler, format!("could not write output to {}", output.display()));
|
llvm_err(handler, format!("could not write output to {}", output.display()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,11 +138,11 @@ fn target_feature(sess: &Session) -> String {
|
||||||
|
|
||||||
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
|
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
|
||||||
match optimize {
|
match optimize {
|
||||||
config::OptLevel::No => llvm::CodeGenLevelNone,
|
config::OptLevel::No => llvm::CodeGenOptLevel::None,
|
||||||
config::OptLevel::Less => llvm::CodeGenLevelLess,
|
config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
|
||||||
config::OptLevel::Default => llvm::CodeGenLevelDefault,
|
config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
|
||||||
config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive,
|
config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
|
||||||
_ => llvm::CodeGenLevelDefault,
|
_ => llvm::CodeGenOptLevel::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,11 +169,11 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
|
||||||
};
|
};
|
||||||
|
|
||||||
let code_model = match code_model_arg {
|
let code_model = match code_model_arg {
|
||||||
"default" => llvm::CodeModelDefault,
|
"default" => llvm::CodeModel::Default,
|
||||||
"small" => llvm::CodeModelSmall,
|
"small" => llvm::CodeModel::Small,
|
||||||
"kernel" => llvm::CodeModelKernel,
|
"kernel" => llvm::CodeModel::Kernel,
|
||||||
"medium" => llvm::CodeModelMedium,
|
"medium" => llvm::CodeModel::Medium,
|
||||||
"large" => llvm::CodeModelLarge,
|
"large" => llvm::CodeModel::Large,
|
||||||
_ => {
|
_ => {
|
||||||
sess.err(&format!("{:?} is not a valid code model",
|
sess.err(&format!("{:?} is not a valid code model",
|
||||||
sess.opts
|
sess.opts
|
||||||
|
@ -449,9 +449,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
let pass_manager = match llvm::LLVMRustPassKind(pass) {
|
let pass_manager = match llvm::LLVMRustPassKind(pass) {
|
||||||
llvm::SupportedPassKind::Function => fpm,
|
llvm::PassKind::Function => fpm,
|
||||||
llvm::SupportedPassKind::Module => mpm,
|
llvm::PassKind::Module => mpm,
|
||||||
llvm::SupportedPassKind::Unsupported => {
|
llvm::PassKind::Other => {
|
||||||
cgcx.handler.err("Encountered LLVM pass kind we can't handle");
|
cgcx.handler.err("Encountered LLVM pass kind we can't handle");
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
|
@ -579,7 +579,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
};
|
};
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
|
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
|
||||||
llvm::AssemblyFileType);
|
llvm::FileType::AssemblyFile);
|
||||||
});
|
});
|
||||||
if config.emit_obj {
|
if config.emit_obj {
|
||||||
llvm::LLVMDisposeModule(llmod);
|
llvm::LLVMDisposeModule(llmod);
|
||||||
|
@ -588,7 +588,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
|
||||||
|
|
||||||
if write_obj {
|
if write_obj {
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out, llvm::ObjectFileType);
|
write_output_file(cgcx.handler, tm, cpm, llmod, &obj_out,
|
||||||
|
llvm::FileType::ObjectFile);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1078,7 +1079,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
|
||||||
// reasonable defaults and prepare it to actually populate the pass
|
// reasonable defaults and prepare it to actually populate the pass
|
||||||
// manager.
|
// manager.
|
||||||
let builder = llvm::LLVMPassManagerBuilderCreate();
|
let builder = llvm::LLVMPassManagerBuilderCreate();
|
||||||
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenLevelNone);
|
let opt_level = config.opt_level.unwrap_or(llvm::CodeGenOptLevel::None);
|
||||||
let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
|
let opt_size = config.opt_size.unwrap_or(llvm::CodeGenOptSizeNone);
|
||||||
let inline_threshold = config.inline_threshold;
|
let inline_threshold = config.inline_threshold;
|
||||||
|
|
||||||
|
@ -1102,7 +1103,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
|
||||||
(_, _, Some(t)) => {
|
(_, _, Some(t)) => {
|
||||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
|
||||||
}
|
}
|
||||||
(llvm::CodeGenLevelAggressive, _, _) => {
|
(llvm::CodeGenOptLevel::Aggressive, _, _) => {
|
||||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
|
||||||
}
|
}
|
||||||
(_, llvm::CodeGenOptSizeDefault, _) => {
|
(_, llvm::CodeGenOptSizeDefault, _) => {
|
||||||
|
@ -1111,15 +1112,18 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
|
||||||
(_, llvm::CodeGenOptSizeAggressive, _) => {
|
(_, llvm::CodeGenOptSizeAggressive, _) => {
|
||||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
|
||||||
}
|
}
|
||||||
(llvm::CodeGenLevelNone, _, _) => {
|
(llvm::CodeGenOptLevel::None, _, _) => {
|
||||||
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
|
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
|
||||||
}
|
}
|
||||||
(llvm::CodeGenLevelLess, _, _) => {
|
(llvm::CodeGenOptLevel::Less, _, _) => {
|
||||||
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
|
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
|
||||||
}
|
}
|
||||||
(llvm::CodeGenLevelDefault, _, _) => {
|
(llvm::CodeGenOptLevel::Default, _, _) => {
|
||||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
|
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
|
||||||
}
|
}
|
||||||
|
(llvm::CodeGenOptLevel::Other, _, _) => {
|
||||||
|
bug!("CodeGenOptLevel::Other selected")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
f(builder);
|
f(builder);
|
||||||
|
|
|
@ -325,10 +325,10 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
|
||||||
};
|
};
|
||||||
|
|
||||||
match reloc_model_arg {
|
match reloc_model_arg {
|
||||||
"pic" => llvm::RelocPIC,
|
"pic" => llvm::RelocMode::PIC,
|
||||||
"static" => llvm::RelocStatic,
|
"static" => llvm::RelocMode::Static,
|
||||||
"default" => llvm::RelocDefault,
|
"default" => llvm::RelocMode::Default,
|
||||||
"dynamic-no-pic" => llvm::RelocDynamicNoPic,
|
"dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
|
||||||
_ => {
|
_ => {
|
||||||
sess.err(&format!("{:?} is not a valid relocation mode",
|
sess.err(&format!("{:?} is not a valid relocation mode",
|
||||||
sess.opts
|
sess.opts
|
||||||
|
@ -347,7 +347,7 @@ fn is_any_library(sess: &Session) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_pie_binary(sess: &Session) -> bool {
|
pub fn is_pie_binary(sess: &Session) -> bool {
|
||||||
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocPIC
|
!is_any_library(sess) && get_reloc_model(sess) == llvm::RelocMode::PIC
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
|
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
|
||||||
|
|
|
@ -16,24 +16,62 @@
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace llvm::object;
|
using namespace llvm::object;
|
||||||
|
|
||||||
struct LLVMRustArchiveMember {
|
struct RustArchiveMember {
|
||||||
const char *filename;
|
const char *filename;
|
||||||
const char *name;
|
const char *name;
|
||||||
Archive::Child child;
|
Archive::Child child;
|
||||||
|
|
||||||
LLVMRustArchiveMember(): filename(NULL), name(NULL),
|
RustArchiveMember(): filename(NULL), name(NULL),
|
||||||
#if LLVM_VERSION_MINOR >= 8
|
#if LLVM_VERSION_MINOR >= 8
|
||||||
child(NULL, NULL, NULL)
|
child(NULL, NULL, NULL)
|
||||||
#else
|
#else
|
||||||
child(NULL, NULL)
|
child(NULL, NULL)
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
~LLVMRustArchiveMember() {}
|
~RustArchiveMember() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef OwningBinary<Archive> RustArchive;
|
|
||||||
|
|
||||||
extern "C" void*
|
struct RustArchiveIterator {
|
||||||
|
Archive::child_iterator cur;
|
||||||
|
Archive::child_iterator end;
|
||||||
|
#if LLVM_VERSION_MINOR >= 9
|
||||||
|
Error err;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class LLVMRustArchiveKind {
|
||||||
|
Other,
|
||||||
|
GNU,
|
||||||
|
MIPS64,
|
||||||
|
BSD,
|
||||||
|
COFF,
|
||||||
|
};
|
||||||
|
|
||||||
|
static Archive::Kind
|
||||||
|
from_rust(LLVMRustArchiveKind kind)
|
||||||
|
{
|
||||||
|
switch (kind) {
|
||||||
|
case LLVMRustArchiveKind::GNU:
|
||||||
|
return Archive::K_GNU;
|
||||||
|
case LLVMRustArchiveKind::MIPS64:
|
||||||
|
return Archive::K_MIPS64;
|
||||||
|
case LLVMRustArchiveKind::BSD:
|
||||||
|
return Archive::K_BSD;
|
||||||
|
case LLVMRustArchiveKind::COFF:
|
||||||
|
return Archive::K_COFF;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef OwningBinary<Archive> *LLVMRustArchiveRef;
|
||||||
|
typedef RustArchiveMember *LLVMRustArchiveMemberRef;
|
||||||
|
typedef Archive::Child *LLVMRustArchiveChildRef;
|
||||||
|
typedef Archive::Child const *LLVMRustArchiveChildConstRef;
|
||||||
|
typedef RustArchiveIterator *LLVMRustArchiveIteratorRef;
|
||||||
|
|
||||||
|
extern "C" LLVMRustArchiveRef
|
||||||
LLVMRustOpenArchive(char *path) {
|
LLVMRustOpenArchive(char *path) {
|
||||||
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
|
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
|
||||||
-1,
|
-1,
|
||||||
|
@ -66,20 +104,12 @@ LLVMRustOpenArchive(char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustDestroyArchive(RustArchive *ar) {
|
LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
|
||||||
delete ar;
|
delete ar;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RustArchiveIterator {
|
extern "C" LLVMRustArchiveIteratorRef
|
||||||
Archive::child_iterator cur;
|
LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
|
||||||
Archive::child_iterator end;
|
|
||||||
#if LLVM_VERSION_MINOR >= 9
|
|
||||||
Error err;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
extern "C" RustArchiveIterator*
|
|
||||||
LLVMRustArchiveIteratorNew(RustArchive *ra) {
|
|
||||||
Archive *ar = ra->getBinary();
|
Archive *ar = ra->getBinary();
|
||||||
RustArchiveIterator *rai = new RustArchiveIterator();
|
RustArchiveIterator *rai = new RustArchiveIterator();
|
||||||
#if LLVM_VERSION_MINOR <= 8
|
#if LLVM_VERSION_MINOR <= 8
|
||||||
|
@ -95,8 +125,8 @@ LLVMRustArchiveIteratorNew(RustArchive *ra) {
|
||||||
return rai;
|
return rai;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" const Archive::Child*
|
extern "C" LLVMRustArchiveChildConstRef
|
||||||
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
|
LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
|
||||||
#if LLVM_VERSION_MINOR >= 9
|
#if LLVM_VERSION_MINOR >= 9
|
||||||
if (rai->err) {
|
if (rai->err) {
|
||||||
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
|
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
|
||||||
|
@ -122,17 +152,17 @@ LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustArchiveChildFree(Archive::Child *child) {
|
LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
|
||||||
delete child;
|
delete child;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
|
LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
|
||||||
delete rai;
|
delete rai;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" const char*
|
extern "C" const char*
|
||||||
LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
|
LLVMRustArchiveChildName(LLVMRustArchiveChildConstRef child, size_t *size) {
|
||||||
ErrorOr<StringRef> name_or_err = child->getName();
|
ErrorOr<StringRef> name_or_err = child->getName();
|
||||||
if (name_or_err.getError())
|
if (name_or_err.getError())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -142,7 +172,7 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" const char*
|
extern "C" const char*
|
||||||
LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
|
LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
|
||||||
StringRef buf;
|
StringRef buf;
|
||||||
ErrorOr<StringRef> buf_or_err = child->getBuffer();
|
ErrorOr<StringRef> buf_or_err = child->getBuffer();
|
||||||
if (buf_or_err.getError()) {
|
if (buf_or_err.getError()) {
|
||||||
|
@ -154,9 +184,10 @@ LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
|
||||||
return buf.data();
|
return buf.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LLVMRustArchiveMember*
|
extern "C" LLVMRustArchiveMemberRef
|
||||||
LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
|
LLVMRustArchiveMemberNew(char *Filename, char *Name,
|
||||||
LLVMRustArchiveMember *Member = new LLVMRustArchiveMember;
|
LLVMRustArchiveChildRef child) {
|
||||||
|
RustArchiveMember *Member = new RustArchiveMember;
|
||||||
Member->filename = Filename;
|
Member->filename = Filename;
|
||||||
Member->name = Name;
|
Member->name = Name;
|
||||||
if (child)
|
if (child)
|
||||||
|
@ -165,22 +196,23 @@ LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) {
|
LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
|
||||||
delete Member;
|
delete Member;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" int
|
extern "C" LLVMRustResult
|
||||||
LLVMRustWriteArchive(char *Dst,
|
LLVMRustWriteArchive(char *Dst,
|
||||||
size_t NumMembers,
|
size_t NumMembers,
|
||||||
const LLVMRustArchiveMember **NewMembers,
|
const LLVMRustArchiveMemberRef *NewMembers,
|
||||||
bool WriteSymbtab,
|
bool WriteSymbtab,
|
||||||
Archive::Kind Kind) {
|
LLVMRustArchiveKind rust_kind) {
|
||||||
|
|
||||||
#if LLVM_VERSION_MINOR <= 8
|
#if LLVM_VERSION_MINOR <= 8
|
||||||
std::vector<NewArchiveIterator> Members;
|
std::vector<NewArchiveIterator> Members;
|
||||||
#else
|
#else
|
||||||
std::vector<NewArchiveMember> Members;
|
std::vector<NewArchiveMember> Members;
|
||||||
#endif
|
#endif
|
||||||
|
auto Kind = from_rust(rust_kind);
|
||||||
|
|
||||||
for (size_t i = 0; i < NumMembers; i++) {
|
for (size_t i = 0; i < NumMembers; i++) {
|
||||||
auto Member = NewMembers[i];
|
auto Member = NewMembers[i];
|
||||||
|
@ -190,7 +222,7 @@ LLVMRustWriteArchive(char *Dst,
|
||||||
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
|
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
|
||||||
if (!MOrErr) {
|
if (!MOrErr) {
|
||||||
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
||||||
return -1;
|
return LLVMRustResult::Failure;
|
||||||
}
|
}
|
||||||
Members.push_back(std::move(*MOrErr));
|
Members.push_back(std::move(*MOrErr));
|
||||||
#elif LLVM_VERSION_MINOR == 8
|
#elif LLVM_VERSION_MINOR == 8
|
||||||
|
@ -205,7 +237,7 @@ LLVMRustWriteArchive(char *Dst,
|
||||||
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
|
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
|
||||||
if (!MOrErr) {
|
if (!MOrErr) {
|
||||||
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
|
||||||
return -1;
|
return LLVMRustResult::Failure;
|
||||||
}
|
}
|
||||||
Members.push_back(std::move(*MOrErr));
|
Members.push_back(std::move(*MOrErr));
|
||||||
#endif
|
#endif
|
||||||
|
@ -217,7 +249,7 @@ LLVMRustWriteArchive(char *Dst,
|
||||||
auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
|
auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
|
||||||
#endif
|
#endif
|
||||||
if (!pair.second)
|
if (!pair.second)
|
||||||
return 0;
|
return LLVMRustResult::Success;
|
||||||
LLVMRustSetLastError(pair.second.message().c_str());
|
LLVMRustSetLastError(pair.second.message().c_str());
|
||||||
return -1;
|
return LLVMRustResult::Failure;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,41 +54,48 @@ LLVMInitializePasses() {
|
||||||
initializeTarget(Registry);
|
initializeTarget(Registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class LLVMRustPassKind {
|
||||||
enum class SupportedPassKind {
|
Other,
|
||||||
Function,
|
Function,
|
||||||
Module,
|
Module,
|
||||||
Unsupported
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" Pass*
|
static LLVMRustPassKind
|
||||||
|
to_rust(PassKind kind)
|
||||||
|
{
|
||||||
|
switch (kind) {
|
||||||
|
case PT_Function:
|
||||||
|
return LLVMRustPassKind::Function;
|
||||||
|
case PT_Module:
|
||||||
|
return LLVMRustPassKind::Module;
|
||||||
|
default:
|
||||||
|
return LLVMRustPassKind::Other;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" LLVMPassRef
|
||||||
LLVMRustFindAndCreatePass(const char *PassName) {
|
LLVMRustFindAndCreatePass(const char *PassName) {
|
||||||
StringRef SR(PassName);
|
StringRef SR(PassName);
|
||||||
PassRegistry *PR = PassRegistry::getPassRegistry();
|
PassRegistry *PR = PassRegistry::getPassRegistry();
|
||||||
|
|
||||||
const PassInfo *PI = PR->getPassInfo(SR);
|
const PassInfo *PI = PR->getPassInfo(SR);
|
||||||
if (PI) {
|
if (PI) {
|
||||||
return PI->createPass();
|
return wrap(PI->createPass());
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" SupportedPassKind
|
extern "C" LLVMRustPassKind
|
||||||
LLVMRustPassKind(Pass *pass) {
|
LLVMRustPassKind(LLVMPassRef rust_pass) {
|
||||||
assert(pass);
|
assert(rust_pass);
|
||||||
PassKind passKind = pass->getPassKind();
|
Pass *pass = unwrap(rust_pass);
|
||||||
if (passKind == PT_Module) {
|
return to_rust(pass->getPassKind());
|
||||||
return SupportedPassKind::Module;
|
|
||||||
} else if (passKind == PT_Function) {
|
|
||||||
return SupportedPassKind::Function;
|
|
||||||
} else {
|
|
||||||
return SupportedPassKind::Unsupported;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) {
|
LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
|
||||||
assert(pass);
|
assert(rust_pass);
|
||||||
|
Pass *pass = unwrap(rust_pass);
|
||||||
PassManagerBase *pm = unwrap(PM);
|
PassManagerBase *pm = unwrap(PM);
|
||||||
pm->add(pass);
|
pm->add(pass);
|
||||||
}
|
}
|
||||||
|
@ -162,13 +169,69 @@ LLVMRustHasFeature(LLVMTargetMachineRef TM,
|
||||||
return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
|
return (Bits & FeatureEntry->Value) == FeatureEntry->Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class LLVMRustCodeModel {
|
||||||
|
Other,
|
||||||
|
Default,
|
||||||
|
JITDefault,
|
||||||
|
Small,
|
||||||
|
Kernel,
|
||||||
|
Medium,
|
||||||
|
Large,
|
||||||
|
};
|
||||||
|
|
||||||
|
static CodeModel::Model
|
||||||
|
from_rust(LLVMRustCodeModel model)
|
||||||
|
{
|
||||||
|
switch (model) {
|
||||||
|
case LLVMRustCodeModel::Default:
|
||||||
|
return CodeModel::Default;
|
||||||
|
case LLVMRustCodeModel::JITDefault:
|
||||||
|
return CodeModel::JITDefault;
|
||||||
|
case LLVMRustCodeModel::Small:
|
||||||
|
return CodeModel::Small;
|
||||||
|
case LLVMRustCodeModel::Kernel:
|
||||||
|
return CodeModel::Kernel;
|
||||||
|
case LLVMRustCodeModel::Medium:
|
||||||
|
return CodeModel::Medium;
|
||||||
|
case LLVMRustCodeModel::Large:
|
||||||
|
return CodeModel::Large;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class LLVMRustCodeGenOptLevel {
|
||||||
|
Other,
|
||||||
|
None,
|
||||||
|
Less,
|
||||||
|
Default,
|
||||||
|
Aggressive,
|
||||||
|
};
|
||||||
|
|
||||||
|
static CodeGenOpt::Level
|
||||||
|
from_rust(LLVMRustCodeGenOptLevel level)
|
||||||
|
{
|
||||||
|
switch (level) {
|
||||||
|
case LLVMRustCodeGenOptLevel::None:
|
||||||
|
return CodeGenOpt::None;
|
||||||
|
case LLVMRustCodeGenOptLevel::Less:
|
||||||
|
return CodeGenOpt::Less;
|
||||||
|
case LLVMRustCodeGenOptLevel::Default:
|
||||||
|
return CodeGenOpt::Default;
|
||||||
|
case LLVMRustCodeGenOptLevel::Aggressive:
|
||||||
|
return CodeGenOpt::Aggressive;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" LLVMTargetMachineRef
|
extern "C" LLVMTargetMachineRef
|
||||||
LLVMRustCreateTargetMachine(const char *triple,
|
LLVMRustCreateTargetMachine(const char *triple,
|
||||||
const char *cpu,
|
const char *cpu,
|
||||||
const char *feature,
|
const char *feature,
|
||||||
CodeModel::Model CM,
|
LLVMRustCodeModel rust_CM,
|
||||||
LLVMRelocMode Reloc,
|
LLVMRelocMode Reloc,
|
||||||
CodeGenOpt::Level OptLevel,
|
LLVMRustCodeGenOptLevel rust_OptLevel,
|
||||||
bool UseSoftFloat,
|
bool UseSoftFloat,
|
||||||
bool PositionIndependentExecutable,
|
bool PositionIndependentExecutable,
|
||||||
bool FunctionSections,
|
bool FunctionSections,
|
||||||
|
@ -179,6 +242,9 @@ LLVMRustCreateTargetMachine(const char *triple,
|
||||||
#else
|
#else
|
||||||
Optional<Reloc::Model> RM;
|
Optional<Reloc::Model> RM;
|
||||||
#endif
|
#endif
|
||||||
|
auto CM = from_rust(rust_CM);
|
||||||
|
auto OptLevel = from_rust(rust_OptLevel);
|
||||||
|
|
||||||
switch (Reloc){
|
switch (Reloc){
|
||||||
case LLVMRelocStatic:
|
case LLVMRelocStatic:
|
||||||
RM = Reloc::Static;
|
RM = Reloc::Static;
|
||||||
|
@ -251,14 +317,14 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
|
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
|
||||||
CodeGenOpt::Level OptLevel,
|
LLVMRustCodeGenOptLevel OptLevel,
|
||||||
bool MergeFunctions,
|
bool MergeFunctions,
|
||||||
bool SLPVectorize,
|
bool SLPVectorize,
|
||||||
bool LoopVectorize) {
|
bool LoopVectorize) {
|
||||||
// Ignore mergefunc for now as enabling it causes crashes.
|
// Ignore mergefunc for now as enabling it causes crashes.
|
||||||
//unwrap(PMB)->MergeFunctions = MergeFunctions;
|
//unwrap(PMB)->MergeFunctions = MergeFunctions;
|
||||||
unwrap(PMB)->SLPVectorize = SLPVectorize;
|
unwrap(PMB)->SLPVectorize = SLPVectorize;
|
||||||
unwrap(PMB)->OptLevel = OptLevel;
|
unwrap(PMB)->OptLevel = from_rust(OptLevel);
|
||||||
unwrap(PMB)->LoopVectorize = LoopVectorize;
|
unwrap(PMB)->LoopVectorize = LoopVectorize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,13 +380,33 @@ LLVMRustSetLLVMOptions(int Argc, char **Argv) {
|
||||||
cl::ParseCommandLineOptions(Argc, Argv);
|
cl::ParseCommandLineOptions(Argc, Argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" bool
|
enum class LLVMRustFileType {
|
||||||
|
Other,
|
||||||
|
AssemblyFile,
|
||||||
|
ObjectFile,
|
||||||
|
};
|
||||||
|
|
||||||
|
static TargetMachine::CodeGenFileType
|
||||||
|
from_rust(LLVMRustFileType type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case LLVMRustFileType::AssemblyFile:
|
||||||
|
return TargetMachine::CGFT_AssemblyFile;
|
||||||
|
case LLVMRustFileType::ObjectFile:
|
||||||
|
return TargetMachine::CGFT_ObjectFile;
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" LLVMRustResult
|
||||||
LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
|
LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
|
||||||
LLVMPassManagerRef PMR,
|
LLVMPassManagerRef PMR,
|
||||||
LLVMModuleRef M,
|
LLVMModuleRef M,
|
||||||
const char *path,
|
const char *path,
|
||||||
TargetMachine::CodeGenFileType FileType) {
|
LLVMRustFileType rust_FileType) {
|
||||||
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
|
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
|
||||||
|
auto FileType = from_rust(rust_FileType);
|
||||||
|
|
||||||
std::string ErrorInfo;
|
std::string ErrorInfo;
|
||||||
std::error_code EC;
|
std::error_code EC;
|
||||||
|
@ -329,7 +415,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
|
||||||
ErrorInfo = EC.message();
|
ErrorInfo = EC.message();
|
||||||
if (ErrorInfo != "") {
|
if (ErrorInfo != "") {
|
||||||
LLVMRustSetLastError(ErrorInfo.c_str());
|
LLVMRustSetLastError(ErrorInfo.c_str());
|
||||||
return false;
|
return LLVMRustResult::Failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
|
unwrap(Target)->addPassesToEmitFile(*PM, OS, FileType, false);
|
||||||
|
@ -339,7 +425,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
|
||||||
// stream (OS), so the only real safe place to delete this is here? Don't we
|
// stream (OS), so the only real safe place to delete this is here? Don't we
|
||||||
// wish this was written in Rust?
|
// wish this was written in Rust?
|
||||||
delete PM;
|
delete PM;
|
||||||
return true;
|
return LLVMRustResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
|
|
|
@ -1,2 +1,16 @@
|
||||||
This directory currently contains some LLVM support code. This will generally
|
This directory currently contains some LLVM support code. This will generally
|
||||||
be sent upstream to LLVM in time; for now it lives here.
|
be sent upstream to LLVM in time; for now it lives here.
|
||||||
|
|
||||||
|
NOTE: the LLVM C++ ABI is subject to between-version breakage and must *never*
|
||||||
|
be exposed to Rust. To allow for easy auditing of that, all Rust-exposed types
|
||||||
|
must be typedef-ed as "LLVMXyz", or "LLVMRustXyz" if they were defined here.
|
||||||
|
|
||||||
|
Functions that return a failure status and leave the error in
|
||||||
|
the LLVM last error should return an LLVMRustResult rather than an
|
||||||
|
int or anything to avoid confusion.
|
||||||
|
|
||||||
|
When translating enums, add a single `Other` variant as the first
|
||||||
|
one to allow for new variants to be added. It should abort when used
|
||||||
|
as an input.
|
||||||
|
|
||||||
|
All other types must not be typedef-ed as such.
|
||||||
|
|
|
@ -58,6 +58,11 @@
|
||||||
|
|
||||||
void LLVMRustSetLastError(const char*);
|
void LLVMRustSetLastError(const char*);
|
||||||
|
|
||||||
|
enum class LLVMRustResult {
|
||||||
|
Success,
|
||||||
|
Failure
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct OpaqueRustString *RustStringRef;
|
typedef struct OpaqueRustString *RustStringRef;
|
||||||
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
|
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
|
||||||
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
|
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue