audit LLVM C++ types in ArchiveWrapper and PassWrapper

This commit is contained in:
Ariel Ben-Yehuda 2016-08-02 00:16:16 +03:00 committed by Ariel Ben-Yehuda
parent 81df89fc2d
commit 696691e3c4
8 changed files with 275 additions and 114 deletions

View File

@ -40,13 +40,9 @@ pub use self::TypeKind::*;
pub use self::AtomicBinOp::*;
pub use self::AtomicOrdering::*;
pub use self::SynchronizationScope::*;
pub use self::FileType::*;
pub use self::MetadataType::*;
pub use self::AsmDialect::*;
pub use self::CodeGenOptLevel::*;
pub use self::CodeGenOptSize::*;
pub use self::RelocMode::*;
pub use self::CodeGenModel::*;
pub use self::DiagnosticKind::*;
pub use self::CallConv::*;
pub use self::Visibility::*;
@ -75,9 +71,26 @@ pub type Bool = c_uint;
pub const True: Bool = 1 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.
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CallConv {
CCallConv = 0,
FastCallConv = 8,
@ -89,6 +102,7 @@ pub enum CallConv {
}
#[derive(Copy, Clone)]
#[repr(C)]
pub enum Visibility {
LLVMDefaultVisibility = 0,
HiddenVisibility = 1,
@ -100,6 +114,7 @@ pub enum Visibility {
// LinkerPrivateLinkage and LinkerPrivateWeakLinkage are not included either;
// they've been removed in upstream LLVM commit r203866.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
#[repr(C)]
pub enum Linkage {
ExternalLinkage = 0,
AvailableExternallyLinkage = 1,
@ -337,12 +352,12 @@ pub enum SynchronizationScope {
CrossThread = 1
}
// Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
#[repr(C)]
#[derive(Copy, Clone)]
pub enum FileType {
AssemblyFileType = 0,
ObjectFileType = 1
Other,
AssemblyFile,
ObjectFile,
}
#[derive(Copy, Clone)]
@ -371,10 +386,11 @@ pub enum AsmDialect {
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum CodeGenOptLevel {
CodeGenLevelNone = 0,
CodeGenLevelLess = 1,
CodeGenLevelDefault = 2,
CodeGenLevelAggressive = 3,
Other,
None,
Less,
Default,
Aggressive,
}
#[derive(Copy, Clone, PartialEq)]
@ -388,21 +404,22 @@ pub enum CodeGenOptSize {
#[derive(Copy, Clone, PartialEq)]
#[repr(C)]
pub enum RelocMode {
RelocDefault = 0,
RelocStatic = 1,
RelocPIC = 2,
RelocDynamicNoPic = 3,
Default = 0,
Static = 1,
PIC = 2,
DynamicNoPic = 3,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub enum CodeGenModel {
CodeModelDefault = 0,
CodeModelJITDefault = 1,
CodeModelSmall = 2,
CodeModelKernel = 3,
CodeModelMedium = 4,
CodeModelLarge = 5,
pub enum CodeModel {
Other,
Default,
JITDefault,
Small,
Kernel,
Medium,
Large,
}
#[repr(C)]
@ -421,6 +438,7 @@ pub enum DiagnosticKind {
#[repr(C)]
#[derive(Copy, Clone)]
pub enum ArchiveKind {
Other,
K_GNU,
K_MIPS64,
K_BSD,
@ -444,10 +462,10 @@ impl FromStr for ArchiveKind {
/// Represents the different LLVM passes Rust supports
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(C)]
pub enum SupportedPassKind {
pub enum PassKind {
Other,
Function,
Module,
Unsupported,
}
// Opaque pointer types
@ -2021,7 +2039,7 @@ extern {
pub fn LLVMIsAAllocaInst(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 LLVMRustAddPass(PM: PassManagerRef, Pass: PassRef);
@ -2031,7 +2049,7 @@ extern {
pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
CPU: *const c_char,
Features: *const c_char,
Model: CodeGenModel,
Model: CodeModel,
Reloc: RelocMode,
Level: CodeGenOptLevel,
UseSoftFP: bool,
@ -2057,7 +2075,8 @@ extern {
PM: PassManagerRef,
M: ModuleRef,
Output: *const c_char,
FileType: FileType) -> bool;
FileType: FileType)
-> LLVMRustResult;
pub fn LLVMRustPrintModule(PM: PassManagerRef,
M: ModuleRef,
Output: *const c_char);
@ -2123,7 +2142,8 @@ extern {
NumMembers: size_t,
Members: *const RustArchiveMemberRef,
WriteSymbtab: bool,
Kind: ArchiveKind) -> c_int;
Kind: ArchiveKind) ->
LLVMRustResult;
pub fn LLVMRustArchiveMemberNew(Filename: *const c_char,
Name: *const c_char,
Child: ArchiveChildRef) -> RustArchiveMemberRef;

View File

@ -293,7 +293,7 @@ impl<'a> ArchiveBuilder<'a> {
members.as_ptr(),
self.should_update_symbols,
kind);
let ret = if r != 0 {
let ret = if r.into_result().is_err() {
let err = llvm::LLVMRustGetLastError();
let msg = if err.is_null() {
"failed to write archive".to_string()

View File

@ -54,7 +54,7 @@ pub fn write_output_file(
let output_c = path2cstr(output);
let result = llvm::LLVMRustWriteOutputFile(
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()));
}
}
@ -138,11 +138,11 @@ fn target_feature(sess: &Session) -> String {
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
match optimize {
config::OptLevel::No => llvm::CodeGenLevelNone,
config::OptLevel::Less => llvm::CodeGenLevelLess,
config::OptLevel::Default => llvm::CodeGenLevelDefault,
config::OptLevel::Aggressive => llvm::CodeGenLevelAggressive,
_ => llvm::CodeGenLevelDefault,
config::OptLevel::No => llvm::CodeGenOptLevel::None,
config::OptLevel::Less => llvm::CodeGenOptLevel::Less,
config::OptLevel::Default => llvm::CodeGenOptLevel::Default,
config::OptLevel::Aggressive => llvm::CodeGenOptLevel::Aggressive,
_ => llvm::CodeGenOptLevel::Default,
}
}
@ -169,11 +169,11 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
};
let code_model = match code_model_arg {
"default" => llvm::CodeModelDefault,
"small" => llvm::CodeModelSmall,
"kernel" => llvm::CodeModelKernel,
"medium" => llvm::CodeModelMedium,
"large" => llvm::CodeModelLarge,
"default" => llvm::CodeModel::Default,
"small" => llvm::CodeModel::Small,
"kernel" => llvm::CodeModel::Kernel,
"medium" => llvm::CodeModel::Medium,
"large" => llvm::CodeModel::Large,
_ => {
sess.err(&format!("{:?} is not a valid code model",
sess.opts
@ -449,9 +449,9 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
return false;
}
let pass_manager = match llvm::LLVMRustPassKind(pass) {
llvm::SupportedPassKind::Function => fpm,
llvm::SupportedPassKind::Module => mpm,
llvm::SupportedPassKind::Unsupported => {
llvm::PassKind::Function => fpm,
llvm::PassKind::Module => mpm,
llvm::PassKind::Other => {
cgcx.handler.err("Encountered LLVM pass kind we can't handle");
return true
},
@ -579,7 +579,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
};
with_codegen(tm, llmod, config.no_builtins, |cpm| {
write_output_file(cgcx.handler, tm, cpm, llmod, &path,
llvm::AssemblyFileType);
llvm::FileType::AssemblyFile);
});
if config.emit_obj {
llvm::LLVMDisposeModule(llmod);
@ -588,7 +588,8 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext,
if write_obj {
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
// manager.
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 inline_threshold = config.inline_threshold;
@ -1102,7 +1103,7 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
(_, _, Some(t)) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
}
(llvm::CodeGenLevelAggressive, _, _) => {
(llvm::CodeGenOptLevel::Aggressive, _, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
}
(_, llvm::CodeGenOptSizeDefault, _) => {
@ -1111,15 +1112,18 @@ pub unsafe fn with_llvm_pmb(llmod: ModuleRef,
(_, llvm::CodeGenOptSizeAggressive, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25);
}
(llvm::CodeGenLevelNone, _, _) => {
(llvm::CodeGenOptLevel::None, _, _) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, false);
}
(llvm::CodeGenLevelLess, _, _) => {
(llvm::CodeGenOptLevel::Less, _, _) => {
llvm::LLVMRustAddAlwaysInlinePass(builder, true);
}
(llvm::CodeGenLevelDefault, _, _) => {
(llvm::CodeGenOptLevel::Default, _, _) => {
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225);
}
(llvm::CodeGenOptLevel::Other, _, _) => {
bug!("CodeGenOptLevel::Other selected")
}
}
f(builder);

View File

@ -325,10 +325,10 @@ pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
};
match reloc_model_arg {
"pic" => llvm::RelocPIC,
"static" => llvm::RelocStatic,
"default" => llvm::RelocDefault,
"dynamic-no-pic" => llvm::RelocDynamicNoPic,
"pic" => llvm::RelocMode::PIC,
"static" => llvm::RelocMode::Static,
"default" => llvm::RelocMode::Default,
"dynamic-no-pic" => llvm::RelocMode::DynamicNoPic,
_ => {
sess.err(&format!("{:?} is not a valid relocation mode",
sess.opts
@ -347,7 +347,7 @@ fn is_any_library(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) {

View File

@ -16,24 +16,62 @@
using namespace llvm;
using namespace llvm::object;
struct LLVMRustArchiveMember {
struct RustArchiveMember {
const char *filename;
const char *name;
Archive::Child child;
LLVMRustArchiveMember(): filename(NULL), name(NULL),
RustArchiveMember(): filename(NULL), name(NULL),
#if LLVM_VERSION_MINOR >= 8
child(NULL, NULL, NULL)
#else
child(NULL, NULL)
#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) {
ErrorOr<std::unique_ptr<MemoryBuffer>> buf_or = MemoryBuffer::getFile(path,
-1,
@ -66,20 +104,12 @@ LLVMRustOpenArchive(char *path) {
}
extern "C" void
LLVMRustDestroyArchive(RustArchive *ar) {
LLVMRustDestroyArchive(LLVMRustArchiveRef ar) {
delete ar;
}
struct RustArchiveIterator {
Archive::child_iterator cur;
Archive::child_iterator end;
#if LLVM_VERSION_MINOR >= 9
Error err;
#endif
};
extern "C" RustArchiveIterator*
LLVMRustArchiveIteratorNew(RustArchive *ra) {
extern "C" LLVMRustArchiveIteratorRef
LLVMRustArchiveIteratorNew(LLVMRustArchiveRef ra) {
Archive *ar = ra->getBinary();
RustArchiveIterator *rai = new RustArchiveIterator();
#if LLVM_VERSION_MINOR <= 8
@ -95,8 +125,8 @@ LLVMRustArchiveIteratorNew(RustArchive *ra) {
return rai;
}
extern "C" const Archive::Child*
LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
extern "C" LLVMRustArchiveChildConstRef
LLVMRustArchiveIteratorNext(LLVMRustArchiveIteratorRef rai) {
#if LLVM_VERSION_MINOR >= 9
if (rai->err) {
LLVMRustSetLastError(toString(std::move(rai->err)).c_str());
@ -122,17 +152,17 @@ LLVMRustArchiveIteratorNext(RustArchiveIterator *rai) {
}
extern "C" void
LLVMRustArchiveChildFree(Archive::Child *child) {
LLVMRustArchiveChildFree(LLVMRustArchiveChildRef child) {
delete child;
}
extern "C" void
LLVMRustArchiveIteratorFree(RustArchiveIterator *rai) {
LLVMRustArchiveIteratorFree(LLVMRustArchiveIteratorRef rai) {
delete rai;
}
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();
if (name_or_err.getError())
return NULL;
@ -142,7 +172,7 @@ LLVMRustArchiveChildName(const Archive::Child *child, size_t *size) {
}
extern "C" const char*
LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
LLVMRustArchiveChildData(LLVMRustArchiveChildRef child, size_t *size) {
StringRef buf;
ErrorOr<StringRef> buf_or_err = child->getBuffer();
if (buf_or_err.getError()) {
@ -154,9 +184,10 @@ LLVMRustArchiveChildData(Archive::Child *child, size_t *size) {
return buf.data();
}
extern "C" LLVMRustArchiveMember*
LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
LLVMRustArchiveMember *Member = new LLVMRustArchiveMember;
extern "C" LLVMRustArchiveMemberRef
LLVMRustArchiveMemberNew(char *Filename, char *Name,
LLVMRustArchiveChildRef child) {
RustArchiveMember *Member = new RustArchiveMember;
Member->filename = Filename;
Member->name = Name;
if (child)
@ -165,22 +196,23 @@ LLVMRustArchiveMemberNew(char *Filename, char *Name, Archive::Child *child) {
}
extern "C" void
LLVMRustArchiveMemberFree(LLVMRustArchiveMember *Member) {
LLVMRustArchiveMemberFree(LLVMRustArchiveMemberRef Member) {
delete Member;
}
extern "C" int
extern "C" LLVMRustResult
LLVMRustWriteArchive(char *Dst,
size_t NumMembers,
const LLVMRustArchiveMember **NewMembers,
const LLVMRustArchiveMemberRef *NewMembers,
bool WriteSymbtab,
Archive::Kind Kind) {
LLVMRustArchiveKind rust_kind) {
#if LLVM_VERSION_MINOR <= 8
std::vector<NewArchiveIterator> Members;
#else
std::vector<NewArchiveMember> Members;
#endif
auto Kind = from_rust(rust_kind);
for (size_t i = 0; i < NumMembers; i++) {
auto Member = NewMembers[i];
@ -190,7 +222,7 @@ LLVMRustWriteArchive(char *Dst,
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getFile(Member->filename, true);
if (!MOrErr) {
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
return -1;
return LLVMRustResult::Failure;
}
Members.push_back(std::move(*MOrErr));
#elif LLVM_VERSION_MINOR == 8
@ -205,7 +237,7 @@ LLVMRustWriteArchive(char *Dst,
Expected<NewArchiveMember> MOrErr = NewArchiveMember::getOldMember(Member->child, true);
if (!MOrErr) {
LLVMRustSetLastError(toString(MOrErr.takeError()).c_str());
return -1;
return LLVMRustResult::Failure;
}
Members.push_back(std::move(*MOrErr));
#endif
@ -217,7 +249,7 @@ LLVMRustWriteArchive(char *Dst,
auto pair = writeArchive(Dst, Members, WriteSymbtab, Kind, true);
#endif
if (!pair.second)
return 0;
return LLVMRustResult::Success;
LLVMRustSetLastError(pair.second.message().c_str());
return -1;
return LLVMRustResult::Failure;
}

View File

@ -54,41 +54,48 @@ LLVMInitializePasses() {
initializeTarget(Registry);
}
enum class SupportedPassKind {
enum class LLVMRustPassKind {
Other,
Function,
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) {
StringRef SR(PassName);
PassRegistry *PR = PassRegistry::getPassRegistry();
const PassInfo *PI = PR->getPassInfo(SR);
if (PI) {
return PI->createPass();
return wrap(PI->createPass());
}
return NULL;
}
extern "C" SupportedPassKind
LLVMRustPassKind(Pass *pass) {
assert(pass);
PassKind passKind = pass->getPassKind();
if (passKind == PT_Module) {
return SupportedPassKind::Module;
} else if (passKind == PT_Function) {
return SupportedPassKind::Function;
} else {
return SupportedPassKind::Unsupported;
}
extern "C" LLVMRustPassKind
LLVMRustPassKind(LLVMPassRef rust_pass) {
assert(rust_pass);
Pass *pass = unwrap(rust_pass);
return to_rust(pass->getPassKind());
}
extern "C" void
LLVMRustAddPass(LLVMPassManagerRef PM, Pass *pass) {
assert(pass);
LLVMRustAddPass(LLVMPassManagerRef PM, LLVMPassRef rust_pass) {
assert(rust_pass);
Pass *pass = unwrap(rust_pass);
PassManagerBase *pm = unwrap(PM);
pm->add(pass);
}
@ -162,13 +169,69 @@ LLVMRustHasFeature(LLVMTargetMachineRef TM,
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
LLVMRustCreateTargetMachine(const char *triple,
const char *cpu,
const char *feature,
CodeModel::Model CM,
LLVMRustCodeModel rust_CM,
LLVMRelocMode Reloc,
CodeGenOpt::Level OptLevel,
LLVMRustCodeGenOptLevel rust_OptLevel,
bool UseSoftFloat,
bool PositionIndependentExecutable,
bool FunctionSections,
@ -179,6 +242,9 @@ LLVMRustCreateTargetMachine(const char *triple,
#else
Optional<Reloc::Model> RM;
#endif
auto CM = from_rust(rust_CM);
auto OptLevel = from_rust(rust_OptLevel);
switch (Reloc){
case LLVMRelocStatic:
RM = Reloc::Static;
@ -251,14 +317,14 @@ LLVMRustAddAnalysisPasses(LLVMTargetMachineRef TM,
extern "C" void
LLVMRustConfigurePassManagerBuilder(LLVMPassManagerBuilderRef PMB,
CodeGenOpt::Level OptLevel,
LLVMRustCodeGenOptLevel OptLevel,
bool MergeFunctions,
bool SLPVectorize,
bool LoopVectorize) {
// Ignore mergefunc for now as enabling it causes crashes.
//unwrap(PMB)->MergeFunctions = MergeFunctions;
unwrap(PMB)->SLPVectorize = SLPVectorize;
unwrap(PMB)->OptLevel = OptLevel;
unwrap(PMB)->OptLevel = from_rust(OptLevel);
unwrap(PMB)->LoopVectorize = LoopVectorize;
}
@ -314,13 +380,33 @@ LLVMRustSetLLVMOptions(int Argc, char **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,
LLVMPassManagerRef PMR,
LLVMModuleRef M,
const char *path,
TargetMachine::CodeGenFileType FileType) {
LLVMRustFileType rust_FileType) {
llvm::legacy::PassManager *PM = unwrap<llvm::legacy::PassManager>(PMR);
auto FileType = from_rust(rust_FileType);
std::string ErrorInfo;
std::error_code EC;
@ -329,7 +415,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target,
ErrorInfo = EC.message();
if (ErrorInfo != "") {
LLVMRustSetLastError(ErrorInfo.c_str());
return false;
return LLVMRustResult::Failure;
}
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
// wish this was written in Rust?
delete PM;
return true;
return LLVMRustResult::Success;
}
extern "C" void

View File

@ -1,2 +1,16 @@
This directory currently contains some LLVM support code. This will generally
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.

View File

@ -58,6 +58,11 @@
void LLVMRustSetLastError(const char*);
enum class LLVMRustResult {
Success,
Failure
};
typedef struct OpaqueRustString *RustStringRef;
typedef struct LLVMOpaqueTwine *LLVMTwineRef;
typedef struct LLVMOpaqueDebugLoc *LLVMDebugLocRef;