summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml1
-rw-r--r--README.md3
-rw-r--r--appveyor.yml19
-rw-r--r--samples/target_stress_test.toml22
-rw-r--r--samples/test/issue-mrustc-103.rs9
-rw-r--r--samples/test/issue-mrustc-77.rs14
-rw-r--r--samples/test/zst_use.rs12
-rw-r--r--src/ast/expr.hpp1
-rw-r--r--src/expand/derive.cpp1
-rw-r--r--src/expand/proc_macro.cpp2
-rw-r--r--src/hir/expr.hpp1
-rw-r--r--src/hir/expr_ptr.hpp2
-rw-r--r--src/hir_typeck/expr_cs.cpp8
-rw-r--r--src/hir_typeck/helpers.cpp4
-rw-r--r--src/include/span.hpp10
-rw-r--r--src/include/synext_decorator.hpp1
-rw-r--r--src/macro_rules/macro_rules_ptr.hpp2
-rw-r--r--src/macro_rules/mod.cpp6
-rw-r--r--src/macro_rules/parse.cpp1
-rw-r--r--src/main.cpp32
-rw-r--r--src/mir/cleanup.cpp2
-rw-r--r--src/parse/token.cpp1
-rw-r--r--src/parse/tokenstream.cpp2
-rw-r--r--src/rc_string.cpp4
-rw-r--r--src/span.cpp9
-rw-r--r--src/trans/codegen_c.cpp45
-rw-r--r--src/trans/codegen_mmir.cpp20
-rw-r--r--src/trans/target.cpp163
-rw-r--r--src/trans/target.hpp42
-rw-r--r--tools/common/path.h7
-rw-r--r--tools/common/target_detect.h11
-rw-r--r--tools/common/toml.cpp85
-rw-r--r--tools/common/toml.h21
-rw-r--r--tools/minicargo/build.cpp76
-rw-r--r--tools/minicargo/main.cpp4
-rw-r--r--tools/minicargo/manifest.cpp6
-rw-r--r--vsproject/build_std.cmd2
-rw-r--r--vsproject/common_lib/common_lib.vcxproj9
-rw-r--r--vsproject/minicargo/minicargo.vcxproj9
-rw-r--r--vsproject/testrunner/testrunner.vcxproj9
40 files changed, 513 insertions, 165 deletions
diff --git a/.travis.yml b/.travis.yml
index 63a7347f..a44cceff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,7 @@ matrix:
- os: linux
before_install:
- export CC=gcc-6
+ - export CC-x86_64-linux-gnu=gcc-6
- export CXX=g++-6
addons:
apt:
diff --git a/README.md b/README.md
index bbc34fb6..d17ef42b 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,9 @@ Mutabah's Rust Compiler
_In-progress_ alternative rust compiler. Capable of building a fully-working copy of rustc, but not yet suitable for everyday use.
+[![Build Status: windows](https://ci.appveyor.com/api/projects/status/96y4ui20pl8xjm2h/branch/master?svg=true)](https://ci.appveyor.com/project/thepowersgang/mrustc/branch/master)
+[![Build Status: Linux/OSX](https://travis-ci.org/thepowersgang/mrustc.svg?branch=master)](https://travis-ci.org/thepowersgang/mrustc)
+
Intro
===
This project is an attempt at creating a simple rust compiler in C++, with the ultimate goal of being a separate re-implementation.
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 00000000..3f3f52f0
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,19 @@
+version: 1.0.{build}
+
+configuration: Release
+platform: x64
+
+before_build:
+- cmd: nuget restore vsproject/mrustc.sln
+
+build:
+ project: vsproject/mrustc.sln
+ verbosity: minimal
+
+test_script:
+# - Download/extract rust 1.19.0
+- appveyor DownloadFile https://static.rust-lang.org/dist/rustc-1.19.0-src.tar.gz
+- tar xzf rustc-1.19.0-src.tar.gz
+- cmd: cd vsproject
+- cmd: call build_std.cmd
+- cmd: call run_hello.cmd
diff --git a/samples/target_stress_test.toml b/samples/target_stress_test.toml
new file mode 100644
index 00000000..c7630567
--- /dev/null
+++ b/samples/target_stress_test.toml
@@ -0,0 +1,22 @@
+[target]
+family = "fake"
+os-name = "fakest"
+env-name = "faker"
+
+[backend.c]
+variant = "msvc"
+target = "x86_64-linux-msvc"
+compiler-opts = ["/W:1234",]
+linker-opts = ["/K",]
+
+[arch]
+name = "fubar"
+pointer-bits = 128
+is-big-endian = true
+has-atomic-u8 = false
+has-atomic-u16 = false
+has-atomic-u32 = false
+has-atomic-u64 = false
+has-atomic-ptr = false
+alignments = { u16 = 1, u32 = 2, u64 = 4, u128 = 8, f32 = 3, f64 = 5, ptr = 16 }
+
diff --git a/samples/test/issue-mrustc-103.rs b/samples/test/issue-mrustc-103.rs
new file mode 100644
index 00000000..f27fe6de
--- /dev/null
+++ b/samples/test/issue-mrustc-103.rs
@@ -0,0 +1,9 @@
+macro_rules! pat {
+ [$a:expr;$b:expr] => (
+ println!("{} {}", $a, $b);
+ )
+}
+fn main() {
+ pat![4;5];
+}
+
diff --git a/samples/test/issue-mrustc-77.rs b/samples/test/issue-mrustc-77.rs
new file mode 100644
index 00000000..ba916822
--- /dev/null
+++ b/samples/test/issue-mrustc-77.rs
@@ -0,0 +1,14 @@
+// ignore-test
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+pub struct __BindgenBitfieldUnit<Storage, Align>
+where
+ Storage: AsRef<[u8]> + AsMut<[u8]>,
+{
+ storage: Storage,
+ align: [Align; 0],
+}
+
+fn main() {
+}
diff --git a/samples/test/zst_use.rs b/samples/test/zst_use.rs
new file mode 100644
index 00000000..17e75919
--- /dev/null
+++ b/samples/test/zst_use.rs
@@ -0,0 +1,12 @@
+// compile-flags: --test
+
+#[test]
+fn zst_enum_variant() {
+ #[inline(never)]
+ fn takes_fn<F: Fn( () ) -> Option<()>>(f: F) {
+ f( () );
+ }
+
+ takes_fn( Option::Some );
+}
+
diff --git a/src/ast/expr.hpp b/src/ast/expr.hpp
index a9c82efa..6cfda001 100644
--- a/src/ast/expr.hpp
+++ b/src/ast/expr.hpp
@@ -636,6 +636,7 @@ struct ExprNode_UniOp:
class NodeVisitor
{
public:
+ virtual ~NodeVisitor() = default;
inline void visit(const unique_ptr<ExprNode>& cnode) {
if(cnode.get())
cnode->visit(*this);
diff --git a/src/expand/derive.cpp b/src/expand/derive.cpp
index 0ccda406..a14a12a3 100644
--- a/src/expand/derive.cpp
+++ b/src/expand/derive.cpp
@@ -156,6 +156,7 @@ struct DeriveOpts
/// Interface for derive handlers
struct Deriver
{
+ virtual ~Deriver() = default;
virtual const char* trait_name() const = 0;
virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Struct& str) const = 0;
virtual AST::Impl handle_item(Span sp, const DeriveOpts& opts, const AST::GenericParams& p, const TypeRef& type, const AST::Enum& enm) const = 0;
diff --git a/src/expand/proc_macro.cpp b/src/expand/proc_macro.cpp
index 3b23184e..bc882d77 100644
--- a/src/expand/proc_macro.cpp
+++ b/src/expand/proc_macro.cpp
@@ -1008,7 +1008,7 @@ uint64_t ProcMacroInv::recv_v128u()
for(;;)
{
auto b = recv_u8();
- v |= static_cast<uint64_t>(b) << ofs;
+ v |= static_cast<uint64_t>(b & 0x7F) << ofs;
if( (b & 0x80) == 0 )
break;
ofs += 7;
diff --git a/src/hir/expr.hpp b/src/hir/expr.hpp
index 2ca960e3..c87ae3a7 100644
--- a/src/hir/expr.hpp
+++ b/src/hir/expr.hpp
@@ -821,6 +821,7 @@ struct ExprNode_Closure:
class ExprVisitor
{
public:
+ virtual ~ExprVisitor() = default;
virtual void visit_node_ptr(::std::unique_ptr<ExprNode>& node_ptr);
virtual void visit_node(ExprNode& node);
#define NV(nt) virtual void visit(nt& n) = 0;
diff --git a/src/hir/expr_ptr.hpp b/src/hir/expr_ptr.hpp
index 58fa3762..512921eb 100644
--- a/src/hir/expr_ptr.hpp
+++ b/src/hir/expr_ptr.hpp
@@ -12,7 +12,7 @@
#include <mir/mir_ptr.hpp>
-class Span;
+struct Span;
namespace HIR {
diff --git a/src/hir_typeck/expr_cs.cpp b/src/hir_typeck/expr_cs.cpp
index 10cb9407..8a374946 100644
--- a/src/hir_typeck/expr_cs.cpp
+++ b/src/hir_typeck/expr_cs.cpp
@@ -46,6 +46,7 @@ struct Context
class Revisitor
{
public:
+ virtual ~Revisitor() = default;
virtual const Span& span() const = 0;
virtual void fmt(::std::ostream& os) const = 0;
virtual bool revisit(Context& context, bool is_fallback) = 0;
@@ -6667,13 +6668,8 @@ namespace {
if( H::type_is_num(left) && H::type_is_num(right) ) {
DEBUG("- Magic inferrence link for binops on numerics");
context.equate_types(sp, res, left);
- const auto& right = context.get_type(v.params.m_types.at(0));
- context.equate_types_to_shadow(sp, right);
- }
- else
- {
- context.equate_types_to_shadow(sp, right);
}
+ context.equate_types_to_shadow(sp, /*right*/v.params.m_types.at(0)); // RHS, can't use `right` because it might be freed by the above equate.
}
else
{
diff --git a/src/hir_typeck/helpers.cpp b/src/hir_typeck/helpers.cpp
index 08e817de..010df546 100644
--- a/src/hir_typeck/helpers.cpp
+++ b/src/hir_typeck/helpers.cpp
@@ -636,7 +636,7 @@ void HMTypeInferrence::set_ivar_to(unsigned int slot, ::HIR::TypeRef type)
}
else
#endif
- root_ivar.type = box$( mv$(type) );
+ root_ivar.type = box$( type );
}
this->mark_change();
@@ -1648,7 +1648,7 @@ bool TraitResolution::has_associated_type(const ::HIR::TypeRef& input) const
//TRACE_FUNCTION_F(input);
TU_MATCH(::HIR::TypeRef::Data, (input.m_data), (e),
(Infer,
- auto& ty = this->m_ivars.get_type(input);
+ const auto& ty = this->m_ivars.get_type(input);
if( ty != input ) {
return this->has_associated_type(ty);
}
diff --git a/src/include/span.hpp b/src/include/span.hpp
index 51c3440c..970a2ad0 100644
--- a/src/include/span.hpp
+++ b/src/include/span.hpp
@@ -29,9 +29,9 @@ struct ProtoSpan
unsigned int start_line;
unsigned int start_ofs;
};
-class Span
+struct Span
{
-public:
+//public:
::std::shared_ptr<Span> outer_span; // Expansion target for macros
RcString filename;
@@ -47,10 +47,14 @@ public:
end_line(end_line),
end_ofs(end_ofs)
{}
- Span(const Span& x);
+ Span(const Span& x) = default;
+ Span(Span&& x) = default;
Span(const Position& position);
Span();
+ Span& operator=(const Span& x) = default;
+ Span& operator=(Span&& x) = default;
+
void bug(::std::function<void(::std::ostream&)> msg) const;
void error(ErrorType tag, ::std::function<void(::std::ostream&)> msg) const;
void warning(WarningType tag, ::std::function<void(::std::ostream&)> msg) const;
diff --git a/src/include/synext_decorator.hpp b/src/include/synext_decorator.hpp
index c910f6c0..88a6258c 100644
--- a/src/include/synext_decorator.hpp
+++ b/src/include/synext_decorator.hpp
@@ -46,6 +46,7 @@ class ExpandDecorator
{
void unexpected(const Span& sp, const AST::Attribute& mi, const char* loc_str) const;
public:
+ virtual ~ExpandDecorator() = default;
virtual AttrStage stage() const = 0;
virtual void handle(const Span& sp, const AST::Attribute& mi, AST::Crate& crate) const { unexpected(sp, mi, "crate"); }
diff --git a/src/macro_rules/macro_rules_ptr.hpp b/src/macro_rules/macro_rules_ptr.hpp
index fdb01fbe..5dbfd032 100644
--- a/src/macro_rules/macro_rules_ptr.hpp
+++ b/src/macro_rules/macro_rules_ptr.hpp
@@ -14,7 +14,7 @@ class MacroRulesPtr
MacroRules* m_ptr;
public:
MacroRulesPtr(): m_ptr(nullptr) {}
- MacroRulesPtr(MacroRules* p): m_ptr(p) {}
+ MacroRulesPtr(MacroRules* p);
MacroRulesPtr(MacroRulesPtr&& x):
m_ptr(x.m_ptr)
{
diff --git a/src/macro_rules/mod.cpp b/src/macro_rules/mod.cpp
index e9ecb504..2ad325b8 100644
--- a/src/macro_rules/mod.cpp
+++ b/src/macro_rules/mod.cpp
@@ -168,10 +168,16 @@ bool is_token_vis(eTokenType tt) {
}
}
+MacroRulesPtr::MacroRulesPtr(MacroRules* p):
+ m_ptr(p)
+{
+ //::std::cout << "MRP new " << m_ptr << ::std::endl;
+}
MacroRulesPtr::~MacroRulesPtr()
{
if(m_ptr)
{
+ //::std::cout << "MRP delete " << m_ptr << ::std::endl;
delete m_ptr;
m_ptr = nullptr;
}
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp
index 43ffb097..6a476ef1 100644
--- a/src/macro_rules/parse.cpp
+++ b/src/macro_rules/parse.cpp
@@ -265,6 +265,7 @@ MacroRule Parse_MacroRules_Var(TokenStream& lex)
{
case TOK_BRACE_OPEN: close = TOK_BRACE_CLOSE; break;
case TOK_PAREN_OPEN: close = TOK_PAREN_CLOSE; break;
+ case TOK_SQUARE_OPEN: close = TOK_SQUARE_CLOSE; break;
default:
throw ParseError::Unexpected(lex, tok);
}
diff --git a/src/main.cpp b/src/main.cpp
index 0efddc5f..c722bc73 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -38,6 +38,7 @@ TargetVersion gTargetVersion = TargetVersion::Rustc1_29;
void init_debug_list()
{
+ g_debug_disable_map.insert( "Target Load" );
g_debug_disable_map.insert( "Parse" );
g_debug_disable_map.insert( "LoadCrates" );
g_debug_disable_map.insert( "Expand" );
@@ -159,6 +160,9 @@ struct ProgramParams
bool test_harness = false;
+ // NOTE: If populated, nothing happens except for loading the target
+ ::std::string target_saveback;
+
::std::vector<const char*> lib_search_dirs;
::std::vector<const char*> libraries;
::std::map<::std::string, ::std::string> crate_overrides; // --extern name=path
@@ -217,8 +221,21 @@ int main(int argc, char *argv[])
Cfg_SetValueCb("feature", [&params](const ::std::string& s) {
return params.features.count(s) != 0;
});
- Target_SetCfg(params.target);
+ CompilePhaseV("Target Load", [&]() {
+ Target_SetCfg(params.target);
+ });
+ if( params.target_saveback != "")
+ {
+ Target_ExportCurSpec(params.target_saveback);
+ return 0;
+ }
+
+ if( params.infile == "" )
+ {
+ ::std::cerr << "No input file passed" << ::std::endl;
+ return 1;
+ }
if( params.test_harness )
{
@@ -1100,6 +1117,13 @@ ProgramParams::ProgramParams(int argc, char *argv[])
}
this->target = argv[++i];
}
+ else if( strcmp(arg, "--dump-target-spec") == 0 ) {
+ if (i == argc - 1) {
+ ::std::cerr << "Flag " << arg << " requires an argument" << ::std::endl;
+ exit(1);
+ }
+ this->target_saveback = argv[++i];
+ }
else if( strcmp(arg, "--test") == 0 ) {
this->test_harness = true;
}
@@ -1110,12 +1134,6 @@ ProgramParams::ProgramParams(int argc, char *argv[])
}
}
- if (this->infile == "")
- {
- ::std::cerr << "No input file passed" << ::std::endl;
- exit(1);
- }
-
if( const auto* a = getenv("MRUSTC_TARGET_VER") )
{
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index ef2a24aa..6b8bcf79 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -1264,7 +1264,7 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
void MIR_CleanupCrate(::HIR::Crate& crate)
{
- ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, auto& expr_ptr, const auto& args, const auto& ty){
+ ::MIR::OuterVisitor ov { crate, [&](const auto& res, const auto& p, ::HIR::ExprPtr& expr_ptr, const auto& args, const auto& ty){
MIR_Cleanup(res, p, expr_ptr.get_mir_or_error_mut(Span()), args, ty);
} };
ov.visit_crate(crate);
diff --git a/src/parse/token.cpp b/src/parse/token.cpp
index 900108ab..f9ecd028 100644
--- a/src/parse/token.cpp
+++ b/src/parse/token.cpp
@@ -229,6 +229,7 @@ Token Token::clone() const
BUG(m_pos, "Fragment with invalid token type (" << *this << ")");
break;
}
+ assert(rv.m_data.is_Fragment());
)
)
return rv;
diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp
index 957bc673..6f0c57a1 100644
--- a/src/parse/tokenstream.cpp
+++ b/src/parse/tokenstream.cpp
@@ -125,7 +125,7 @@ ProtoSpan TokenStream::start_span() const
Span TokenStream::end_span(ProtoSpan ps) const
{
auto p = this->getPosition();
- auto rv = Span( ps.filename, ps.start_line, ps.start_ofs, p.line, p.ofs );
+ auto rv = Span( ::std::move(ps.filename), ps.start_line, ps.start_ofs, p.line, p.ofs );
rv.outer_span = this->outerSpan();
return rv;
}
diff --git a/src/rc_string.cpp b/src/rc_string.cpp
index 260ba90a..b56f2e62 100644
--- a/src/rc_string.cpp
+++ b/src/rc_string.cpp
@@ -23,6 +23,8 @@ RcString::RcString(const char* s, unsigned int len):
for(unsigned int j = 0; j < len; j ++ )
data_mut[j] = s[j];
data_mut[len] = '\0';
+
+ //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " (creation)" << ::std::endl;
}
}
RcString::~RcString()
@@ -30,7 +32,7 @@ RcString::~RcString()
if(m_ptr)
{
*m_ptr -= 1;
- //::std::cout << "RcString(\"" << *this << "\") - " << *m_ptr << " refs left" << ::std::endl;
+ //::std::cout << "RcString(" << m_ptr << " \"" << *this << "\") - " << *m_ptr << " refs left (drop)" << ::std::endl;
if( *m_ptr == 0 )
{
delete[] m_ptr;
diff --git a/src/span.cpp b/src/span.cpp
index 035258d6..7e3968d1 100644
--- a/src/span.cpp
+++ b/src/span.cpp
@@ -11,15 +11,6 @@
#include <parse/lex.hpp>
#include <common.hpp>
-Span::Span(const Span& x):
- outer_span(x.outer_span),
- filename(x.filename),
- start_line(x.start_line),
- start_ofs(x.start_ofs),
- end_line(x.end_line),
- end_ofs(x.end_ofs)
-{
-}
Span::Span(const Position& pos):
outer_span(),
filename(pos.filename),
diff --git a/src/trans/codegen_c.cpp b/src/trans/codegen_c.cpp
index 8ecf988a..8a392f86 100644
--- a/src/trans/codegen_c.cpp
+++ b/src/trans/codegen_c.cpp
@@ -200,20 +200,23 @@ namespace {
m_outfile_path_c(outfile + ".c"),
m_of(m_outfile_path_c)
{
+ m_options.emulated_i128 = Target_GetCurSpec().m_backend_c.m_emulated_i128;
switch(Target_GetCurSpec().m_backend_c.m_codegen_mode)
{
case CodegenMode::Gnu11:
m_compiler = Compiler::Gcc;
- m_options.emulated_i128 = false;
- if( Target_GetCurSpec().m_arch.m_pointer_bits < 64 )
+ if( Target_GetCurSpec().m_arch.m_pointer_bits < 64 && !m_options.emulated_i128 )
{
- m_options.emulated_i128 = true;
+ WARNING(Span(), W0000, "Potentially misconfigured target, 32-bit targets require i128 emulation");
}
m_options.disallow_empty_structs = true;
break;
case CodegenMode::Msvc:
m_compiler = Compiler::Msvc;
- m_options.emulated_i128 = true;
+ if( !m_options.emulated_i128 )
+ {
+ WARNING(Span(), W0000, "Potentially misconfigured target, MSVC requires i128 emulation");
+ }
m_options.disallow_empty_structs = true;
break;
}
@@ -297,7 +300,7 @@ namespace {
// 64-bit bit ops (gcc intrinsics)
m_of
<< "static inline uint64_t __builtin_clz64(uint64_t v) {\n"
- << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n"
+ << "\treturn ( (v >> 32) != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n"
<< "}\n"
<< "static inline uint64_t __builtin_ctz64(uint64_t v) {\n"
<< "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n"
@@ -322,10 +325,10 @@ namespace {
<< "static inline uint64_t __builtin_popcount(uint64_t v) {\n"
<< "\treturn (v >> 32 != 0 ? __popcnt64(v>>32) : 32 + __popcnt64(v));\n"
<< "}\n"
- << "static inline int __builtin_ctz(uint32_t v) { int rv; _BitScanReverse(&rv, v); return rv; }\n"
- << "static inline int __builtin_clz(uint32_t v) { int rv; _BitScanForward(&rv, v); return rv; }\n"
+ << "static inline int __builtin_ctz(uint32_t v) { int rv; _BitScanForward(&rv, v); return rv; }\n"
+ << "static inline int __builtin_clz(uint32_t v) { int rv; _BitScanReverse(&rv, v); return 31 - rv; }\n"
<< "static inline uint64_t __builtin_clz64(uint64_t v) {\n"
- << "\treturn (v >> 32 != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v));\n"
+ << "\treturn ( (v >> 32) != 0 ? __builtin_clz(v>>32) : 32 + __builtin_clz(v) );\n"
<< "}\n"
<< "static inline uint64_t __builtin_ctz64(uint64_t v) {\n"
<< "\treturn ((v&0xFFFFFFFF) == 0 ? __builtin_ctz(v>>32) + 32 : __builtin_ctz(v));\n"
@@ -776,13 +779,14 @@ namespace {
if( getenv(varname.c_str()) ) {
args.push_back( getenv(varname.c_str()) );
}
+ else if (system(("which " + Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" + " >/dev/null 2>&1").c_str()) == 0) {
+ args.push_back( Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" );
+ }
else if( getenv("CC") ) {
args.push_back( getenv("CC") );
}
else {
- // TODO: Determine if the compiler can't be found, and fall back to `gcc` if that's the case
- args.push_back( Target_GetCurSpec().m_backend_c.m_c_compiler + "-gcc" );
- //args.push_back( "gcc" );
+ args.push_back("gcc");
}
}
for( const auto& a : Target_GetCurSpec().m_backend_c.m_compiler_opts )
@@ -1561,7 +1565,7 @@ namespace {
assert(1 + union_fields.size() + 1 >= repr->fields.size());
// Make the union!
// NOTE: The way the structure generation works is that enum variants are always first, so the field index = the variant index
- // TODO:
+ // TODO:
if( !this->type_is_bad_zst(repr->fields[0].ty) || ::std::any_of(union_fields.begin(), union_fields.end(), [this,repr](auto x){ return !this->type_is_bad_zst(repr->fields[x].ty); }) )
{
m_of << "\tunion {\n";
@@ -2176,7 +2180,11 @@ namespace {
(String,
m_of << "{ ";
this->print_escaped_string(e);
- m_of << ", " << e.size() << "}";
+ // TODO: Better type checking?
+ if( !ty.m_data.is_Array() ) {
+ m_of << ", " << e.size();
+ }
+ m_of << "}";
)
)
}
@@ -2219,9 +2227,8 @@ namespace {
m_of << "\\x0" << (unsigned int)static_cast<uint8_t>(v);
else
m_of << "\\x" << (unsigned int)static_cast<uint8_t>(v);
- // If the next character is a hex digit,
- // close/reopen the string.
- if( isxdigit(*(&v+1)) )
+ // If the next character is a hex digit, close/reopen the string.
+ if( &v < &s.back() && isxdigit(*(&v+1)) )
m_of << "\"\"";
}
}
@@ -3927,7 +3934,7 @@ namespace {
m_of << "(";
for(unsigned int j = 0; j < e.args.size(); j ++) {
if(j != 0) m_of << ",";
- m_of << " ";
+ m_of << " ";
if( m_options.disallow_empty_structs && TU_TEST1(e.args[j], LValue, .is_Field()) )
{
::HIR::TypeRef tmp;
@@ -4176,7 +4183,7 @@ namespace {
void emit_intrinsic_call(const RcString& name, const ::HIR::PathParams& params, const ::MIR::Terminator::Data_Call& e)
{
const auto& mir_res = *m_mir_res;
- enum class Ordering
+ enum class Ordering
{
SeqCst,
Acquire,
@@ -4341,7 +4348,7 @@ namespace {
m_of << "*(volatile uint8_t*)";
else
m_of << "*(volatile int8_t*)";
- emit_param(e.args.at(0));
+ emit_param(e.args.at(0));
switch(op)
{
case AtomicOp::Add: m_of << " += "; break;
diff --git a/src/trans/codegen_mmir.cpp b/src/trans/codegen_mmir.cpp
index 97ac00eb..58739805 100644
--- a/src/trans/codegen_mmir.cpp
+++ b/src/trans/codegen_mmir.cpp
@@ -20,6 +20,14 @@ namespace
{
size_t PTR_BASE = 0x1000; // See matching value in standalone_miri value.hpp
+ size_t Target_GetSizeOf_Required(const Span& sp, const StaticTraitResolve& resolve, const ::HIR::TypeRef& ty)
+ {
+ size_t size;
+ bool type_has_size = Target_GetSizeOf(sp, resolve, ty, size);
+ ASSERT_BUG(sp, type_has_size, "Attempting to get the size of a unsized type");
+ return size;
+ }
+
template<typename T>
struct Fmt
{
@@ -874,8 +882,7 @@ namespace
cur_ofs ++;
}
emit_literal_as_bytes(le[i], repr->fields[i].ty, out_relocations, base_ofs + cur_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, repr->fields[i].ty, size));
+ size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[i].ty);
cur_ofs += size;
}
while(cur_ofs < repr->size)
@@ -898,8 +905,7 @@ namespace
emit_literal_as_bytes(*le.val, repr->fields[le.idx].ty, out_relocations, base_ofs + cur_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, repr->fields[le.idx].ty, size));
+ size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[le.idx].ty);
cur_ofs += size;
}
@@ -914,8 +920,7 @@ namespace
auto v = ::HIR::Literal::make_Integer(le.idx);
emit_literal_as_bytes(v, repr->fields[ve->field.index].ty, out_relocations, base_ofs + cur_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, repr->fields[ve->field.index].ty, size));
+ size_t size = Target_GetSizeOf_Required(sp, m_resolve, repr->fields[ve->field.index].ty);
cur_ofs += size;
}
// TODO: Nonzero?
@@ -989,8 +994,7 @@ namespace
for(const auto& v : lit.as_List())
{
emit_literal_as_bytes(v, *te.inner, out_relocations, base_ofs);
- size_t size;
- assert(Target_GetSizeOf(sp, m_resolve, *te.inner, size));
+ size_t size = Target_GetSizeOf(sp, m_resolve, *te.inner, size);
base_ofs += size;
}
} break;
diff --git a/src/trans/target.cpp b/src/trans/target.cpp
index 5f52912e..9172481a 100644
--- a/src/trans/target.cpp
+++ b/src/trans/target.cpp
@@ -17,22 +17,32 @@
const TargetArch ARCH_X86_64 = {
"x86_64",
64, false,
- { /*atomic(u8)=*/true, false, true, true, true }
+ TargetArch::Atomics(/*atomic(u8)=*/true, false, true, true, true),
+ TargetArch::Alignments(2, 4, 8, 16, 4, 8, 8)
};
const TargetArch ARCH_X86 = {
"x86",
32, false,
- { /*atomic(u8)=*/true, false, true, false, true }
+ { /*atomic(u8)=*/true, false, true, false, true },
+ TargetArch::Alignments(2, 4, /*u64*/4, /*u128*/4, 4, 4, /*ptr*/4) // u128 has the same alignment as u64, which is u32's alignment. And f64 is 4 byte aligned
};
const TargetArch ARCH_ARM64 = {
"aarch64",
64, false,
- { /*atomic(u8)=*/true, true, true, true, true }
+ { /*atomic(u8)=*/true, true, true, true, true },
+ TargetArch::Alignments(2, 4, 8, 16, 4, 8, 8)
};
const TargetArch ARCH_ARM32 = {
"arm",
32, false,
- { /*atomic(u8)=*/true, false, true, false, true }
+ { /*atomic(u8)=*/true, false, true, false, true },
+ TargetArch::Alignments(2, 4, 8, 16, 4, 8, 4) // Note, all types are natively aligned (but i128 will be emulated)
+};
+const TargetArch ARCH_M68K = {
+ "m68k",
+ 32, true,
+ { /*atomic(u8)=*/true, false, true, false, true },
+ TargetArch::Alignments(2, 2, 2, 2, 2, 2, 2)
};
TargetSpec g_target;
@@ -108,6 +118,10 @@ namespace
{
rv.m_arch = ARCH_X86_64;
}
+ else if( key_val.value.as_string() == ARCH_M68K.m_name )
+ {
+ rv.m_arch = ARCH_M68K;
+ }
else
{
// Error.
@@ -150,6 +164,11 @@ namespace
check_path_length(key_val, 3);
rv.m_backend_c.m_c_compiler = key_val.value.as_string();
}
+ else if( key_val.path[2] == "emulate-i128" )
+ {
+ check_path_length(key_val, 3);
+ rv.m_backend_c.m_emulated_i128 = key_val.value.as_bool();
+ }
else if( key_val.path[2] == "compiler-opts" )
{
check_path_length(key_val, 3);
@@ -224,6 +243,42 @@ namespace
check_path_length(key_val, 2);
rv.m_arch.m_atomics.ptr = key_val.value.as_bool();
}
+ else if( key_val.path[1] == "alignments" )
+ {
+ check_path_length(key_val, 3);
+ if( key_val.path[2] == "u16" )
+ {
+ rv.m_arch.m_alignments.u16 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "u32" )
+ {
+ rv.m_arch.m_alignments.u32 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "u64" )
+ {
+ rv.m_arch.m_alignments.u64 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "u128" )
+ {
+ rv.m_arch.m_alignments.u128 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "f32" )
+ {
+ rv.m_arch.m_alignments.f32 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "f64" )
+ {
+ rv.m_arch.m_alignments.f64 = key_val.value.as_int();
+ }
+ else if( key_val.path[2] == "ptr" )
+ {
+ rv.m_arch.m_alignments.ptr = key_val.value.as_int();
+ }
+ else
+ {
+ ::std::cerr << "WARNING: Unknown field arch.alignments." << key_val.path[1] << " in " << filename << ::std::endl;
+ }
+ }
else
{
::std::cerr << "WARNING: Unknown field arch." << key_val.path[1] << " in " << filename << ::std::endl;
@@ -281,10 +336,10 @@ namespace
<< "[backend.c]\n"
<< "variant = \"" << H::c_variant_name(spec.m_backend_c.m_codegen_mode) << "\"\n"
<< "target = \"" << spec.m_backend_c.m_c_compiler << "\"\n"
- << "compiler-opts = [" << spec.m_backend_c.m_compiler_opts << "]\n"
- << "linker-opts = [" << spec.m_backend_c.m_linker_opts << "]\n"
+ << "compiler-opts = ["; for(const auto& s : spec.m_backend_c.m_compiler_opts) of << "\"" << s << "\","; of << "]\n"
+ << "linker-opts = ["; for(const auto& s : spec.m_backend_c.m_linker_opts) of << "\"" << s << "\","; of << "]\n"
<< "\n"
- << "[arch]"
+ << "[arch]\n"
<< "name = \"" << spec.m_arch.m_name << "\"\n"
<< "pointer-bits = " << spec.m_arch.m_pointer_bits << "\n"
<< "is-big-endian = " << H::tfstr(spec.m_arch.m_big_endian) << "\n"
@@ -293,6 +348,16 @@ namespace
<< "has-atomic-u32 = " << H::tfstr(spec.m_arch.m_atomics.u32) << "\n"
<< "has-atomic-u64 = " << H::tfstr(spec.m_arch.m_atomics.u64) << "\n"
<< "has-atomic-ptr = " << H::tfstr(spec.m_arch.m_atomics.ptr) << "\n"
+ << "alignments = {"
+ << " u16 = " << static_cast<int>(spec.m_arch.m_alignments.u16 ) << ","
+ << " u32 = " << static_cast<int>(spec.m_arch.m_alignments.u32 ) << ","
+ << " u64 = " << static_cast<int>(spec.m_arch.m_alignments.u64 ) << ","
+ << " u128 = " << static_cast<int>(spec.m_arch.m_alignments.u128) << ","
+ << " f32 = " << static_cast<int>(spec.m_arch.m_alignments.f32 ) << ","
+ << " f64 = " << static_cast<int>(spec.m_arch.m_alignments.f64 ) << ","
+ << " ptr = " << static_cast<int>(spec.m_arch.m_alignments.ptr )
+ << " }\n"
+ << "\n"
;
}
TargetSpec init_from_spec_name(const ::std::string& target_name)
@@ -307,42 +372,49 @@ namespace
else if(target_name == "i586-linux-gnu")
{
return TargetSpec {
- "unix", "linux", "gnu", {CodegenMode::Gnu11, "i586-linux-gnu", BACKEND_C_OPTS_GNU},
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "i586-linux-gnu", BACKEND_C_OPTS_GNU},
ARCH_X86
};
}
else if(target_name == "x86_64-linux-gnu")
{
return TargetSpec {
- "unix", "linux", "gnu", {CodegenMode::Gnu11, "x86_64-linux-gnu", BACKEND_C_OPTS_GNU},
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, false, "x86_64-linux-gnu", BACKEND_C_OPTS_GNU},
ARCH_X86_64
};
}
else if(target_name == "arm-linux-gnu")
{
return TargetSpec {
- "unix", "linux", "gnu", {CodegenMode::Gnu11, "arm-elf-eabi", BACKEND_C_OPTS_GNU},
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "arm-elf-eabi", BACKEND_C_OPTS_GNU},
ARCH_ARM32
};
}
else if(target_name == "aarch64-linux-gnu")
{
return TargetSpec {
- "unix", "linux", "gnu", {CodegenMode::Gnu11, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU},
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, false, "aarch64-linux-gnu", BACKEND_C_OPTS_GNU},
ARCH_ARM64
};
}
+ else if(target_name == "m68k-linux-gnu")
+ {
+ return TargetSpec {
+ "unix", "linux", "gnu", {CodegenMode::Gnu11, true, "m68k-linux-gnu", BACKEND_C_OPTS_GNU},
+ ARCH_M68K
+ };
+ }
else if(target_name == "i586-windows-gnu")
{
return TargetSpec {
- "windows", "windows", "gnu", {CodegenMode::Gnu11, "mingw32", BACKEND_C_OPTS_GNU},
+ "windows", "windows", "gnu", {CodegenMode::Gnu11, true, "mingw32", BACKEND_C_OPTS_GNU},
ARCH_X86
};
}
else if(target_name == "x86_64-windows-gnu")
{
return TargetSpec {
- "windows", "windows", "gnu", {CodegenMode::Gnu11, "x86_64-w64-mingw32", BACKEND_C_OPTS_GNU},
+ "windows", "windows", "gnu", {CodegenMode::Gnu11, false, "x86_64-w64-mingw32", BACKEND_C_OPTS_GNU},
ARCH_X86_64
};
}
@@ -350,84 +422,84 @@ namespace
{
// TODO: Should this include the "kernel32.lib" inclusion?
return TargetSpec {
- "windows", "windows", "msvc", {CodegenMode::Msvc, "x86", {}, {}},
+ "windows", "windows", "msvc", {CodegenMode::Msvc, true, "x86", {}, {}},
ARCH_X86
};
}
else if (target_name == "x86_64-windows-msvc")
{
return TargetSpec {
- "windows", "windows", "msvc", {CodegenMode::Msvc, "amd64", {}, {}},
+ "windows", "windows", "msvc", {CodegenMode::Msvc, true, "amd64", {}, {}},
ARCH_X86_64
};
}
else if(target_name == "i686-unknown-freebsd")
{
return TargetSpec {
- "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "i686-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, true, "i686-unknown-freebsd", BACKEND_C_OPTS_GNU},
ARCH_X86
};
}
else if(target_name == "x86_64-unknown-freebsd")
{
return TargetSpec {
- "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-freebsd", BACKEND_C_OPTS_GNU},
ARCH_X86_64
};
}
else if(target_name == "arm-unknown-freebsd")
{
return TargetSpec {
- "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "arm-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-freebsd", BACKEND_C_OPTS_GNU},
ARCH_ARM32
};
}
else if(target_name == "aarch64-unknown-freebsd")
{
return TargetSpec {
- "unix", "freebsd", "gnu", {CodegenMode::Gnu11, "aarch64-unknown-freebsd", BACKEND_C_OPTS_GNU},
+ "unix", "freebsd", "gnu", {CodegenMode::Gnu11, false, "aarch64-unknown-freebsd", BACKEND_C_OPTS_GNU},
ARCH_ARM64
};
}
else if(target_name == "x86_64-unknown-netbsd")
{
return TargetSpec {
- "unix", "netbsd", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-netbsd", BACKEND_C_OPTS_GNU},
+ "unix", "netbsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-netbsd", BACKEND_C_OPTS_GNU},
ARCH_X86_64
};
}
else if(target_name == "i686-unknown-openbsd")
{
return TargetSpec {
- "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "i686-unknown-openbsd", BACKEND_C_OPTS_GNU},
+ "unix", "openbsd", "gnu", {CodegenMode::Gnu11, true, "i686-unknown-openbsd", BACKEND_C_OPTS_GNU},
ARCH_X86
};
}
else if(target_name == "x86_64-unknown-openbsd")
{
return TargetSpec {
- "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-openbsd", BACKEND_C_OPTS_GNU},
+ "unix", "openbsd", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-openbsd", BACKEND_C_OPTS_GNU},
ARCH_X86_64
};
}
else if(target_name == "arm-unknown-openbsd")
{
return TargetSpec {
- "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "arm-unknown-openbsd", BACKEND_C_OPTS_GNU},
+ "unix", "openbsd", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-openbsd", BACKEND_C_OPTS_GNU},
ARCH_ARM32
};
}
else if(target_name == "aarch64-unknown-openbsd")
{
return TargetSpec {
- "unix", "openbsd", "gnu", {CodegenMode::Gnu11, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU},
+ "unix", "openbsd", "gnu", {CodegenMode::Gnu11, false, "aarch64-unknown-openbsd", BACKEND_C_OPTS_GNU},
ARCH_ARM64
};
}
else if(target_name == "x86_64-unknown-dragonfly")
{
return TargetSpec {
- "unix", "dragonfly", "gnu", {CodegenMode::Gnu11, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU},
+ "unix", "dragonfly", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-dragonfly", BACKEND_C_OPTS_GNU},
ARCH_X86_64
};
}
@@ -435,7 +507,21 @@ namespace
{
// NOTE: OSX uses Mach-O binaries, which don't fully support the defaults used for GNU targets
return TargetSpec {
- "unix", "macos", "gnu", {CodegenMode::Gnu11, "x86_64-apple-darwin", {}, {}},
+ "unix", "macos", "gnu", {CodegenMode::Gnu11, false, "x86_64-apple-darwin", {}, {}},
+ ARCH_X86_64
+ };
+ }
+ else if(target_name == "arm-unknown-haiku")
+ {
+ return TargetSpec {
+ "unix", "haiku", "gnu", {CodegenMode::Gnu11, true, "arm-unknown-haiku", {}, {}},
+ ARCH_ARM32
+ };
+ }
+ else if(target_name == "x86_64-unknown-haiku")
+ {
+ return TargetSpec {
+ "unix", "haiku", "gnu", {CodegenMode::Gnu11, false, "x86_64-unknown-haiku", {}, {}},
ARCH_X86_64
};
}
@@ -536,48 +622,45 @@ bool Target_GetSizeAndAlignOf(const Span& sp, const StaticTraitResolve& resolve,
case ::HIR::CoreType::U8:
case ::HIR::CoreType::I8:
out_size = 1;
- out_align = 1;
+ out_align = 1; // u8 is always 1 aligned
return true;
case ::HIR::CoreType::U16:
case ::HIR::CoreType::I16:
out_size = 2;
- out_align = 2;
+ out_align = g_target.m_arch.m_alignments.u16;
return true;
case ::HIR::CoreType::U32:
case ::HIR::CoreType::I32:
case ::HIR::CoreType::Char:
out_size = 4;
- out_align = 4;
+ out_align = g_target.m_arch.m_alignments.u32;
return true;
case ::HIR::CoreType::U64:
case ::HIR::CoreType::I64:
out_size = 8;
- // TODO: on x86, u64/i64 has an alignment of 4, while x86_64 has 8. What do other platforms have?
- out_align = g_target.m_arch.m_name == "x86" ? 4 : 8;
+ out_align = g_target.m_arch.m_alignments.u64;
return true;
case ::HIR::CoreType::U128:
case ::HIR::CoreType::I128:
out_size = 16;
// TODO: If i128 is emulated, this can be 8 (as it is on x86, where it's actually 4 due to the above comment)
- if( g_target.m_arch.m_name == "x86" )
- out_align = 4;
- else if( /*g_target.m_arch.m_name == "x86_64" && */g_target.m_backend_c.m_codegen_mode == CodegenMode::Msvc )
- out_align = 8;
- else
- out_align = 16;
+ if( g_target.m_backend_c.m_emulated_i128 )
+ out_align = g_target.m_arch.m_alignments.u64;
+ else
+ out_align = g_target.m_arch.m_alignments.u128;
return true;
case ::HIR::CoreType::Usize:
case ::HIR::CoreType::Isize:
out_size = g_target.m_arch.m_pointer_bits / 8;
- out_align = g_target.m_arch.m_pointer_bits / 8;
+ out_align = g_target.m_arch.m_alignments.ptr;
return true;
case ::HIR::CoreType::F32:
out_size = 4;
- out_align = 4;
+ out_align = g_target.m_arch.m_alignments.f32;
return true;
case ::HIR::CoreType::F64:
out_size = 8;
- out_align = g_target.m_arch.m_name == "x86" ? 4 : 8;
+ out_align = g_target.m_arch.m_alignments.f64;
return true;
case ::HIR::CoreType::Str:
DEBUG("sizeof on a `str` - unsized");
diff --git a/src/trans/target.hpp b/src/trans/target.hpp
index 107d19e1..3433483b 100644
--- a/src/trans/target.hpp
+++ b/src/trans/target.hpp
@@ -17,23 +17,53 @@ enum class CodegenMode
Msvc,
};
+// NOTE: The default architecture is an unnamed 32-bit little-endian arch with all types natively aligned
struct TargetArch
{
::std::string m_name;
unsigned m_pointer_bits;
bool m_big_endian;
- struct {
- bool u8;
- bool u16;
- bool u32;
- bool u64;
- bool ptr;
+ struct Atomics {
+ bool u8 = true;
+ bool u16 = true;
+ bool u32 = true;
+ bool u64 = false;
+ bool ptr = true;
+ Atomics(bool u8 = true, bool u16 = true, bool u32 = true, bool u64 = false, bool ptr = true)
+ :u8(u8)
+ ,u16(u16)
+ ,u32(u32)
+ ,u64(u64)
+ ,ptr(ptr)
+ {
+ }
} m_atomics;
+
+ struct Alignments {
+ uint8_t u16;
+ uint8_t u32;
+ uint8_t u64;
+ uint8_t u128;
+ uint8_t f32;
+ uint8_t f64;
+ uint8_t ptr;
+ Alignments(uint8_t u16 = 2, uint8_t u32 = 4, uint8_t u64 = 8, uint8_t u128 = 16, uint8_t f32 = 4, uint8_t f64 = 8, uint8_t ptr = 4)
+ :u16 (u16)
+ ,u32 (u32 )
+ ,u64 (u64 )
+ ,u128(u128)
+ ,f32 (f32 )
+ ,f64 (f64 )
+ ,ptr (ptr )
+ {
+ }
+ } m_alignments;
};
struct BackendOptsC
{
CodegenMode m_codegen_mode;
+ bool m_emulated_i128; // Influences the chosen alignment for i128/u128
::std::string m_c_compiler; // MSVC arch / GNU triplet
::std::vector< ::std::string> m_compiler_opts;
::std::vector< ::std::string> m_linker_opts;
diff --git a/tools/common/path.h b/tools/common/path.h
index eae4951f..1ad6f506 100644
--- a/tools/common/path.h
+++ b/tools/common/path.h
@@ -38,6 +38,13 @@ public:
return m_str != "";
}
+ bool operator==(const path& p) const {
+ return m_str == p.m_str;
+ }
+ bool operator!=(const path& p) const {
+ return m_str != p.m_str;
+ }
+
path& operator/=(const path& p)
{
if(!p.is_valid())
diff --git a/tools/common/target_detect.h b/tools/common/target_detect.h
index a4c44ba4..1bfc7dd9 100644
--- a/tools/common/target_detect.h
+++ b/tools/common/target_detect.h
@@ -24,6 +24,8 @@
# define DEFAULT_TARGET_NAME "arm-linux-gnu"
# elif defined(__i386__)
# define DEFAULT_TARGET_NAME "i586-linux-gnu"
+# elif defined(__m68k__)
+# define DEFAULT_TARGET_NAME "m68k-linux-gnu"
# else
# warning "Unable to detect a suitable default target (linux-gnu)"
# endif
@@ -73,6 +75,15 @@
// - Apple devices
#elif defined(__APPLE__)
# define DEFAULT_TARGET_NAME "x86_64-apple-macosx"
+// - Haiku
+#elif defined(__HAIKU__)
+# if defined(__x86_64__)
+# define DEFAULT_TARGET_NAME "x86_64-unknown-haiku"
+# elif defined(__arm__)
+# define DEFAULT_TARGET_NAME "arm-unknown-haiku"
+# else
+# warning "Unable to detect a suitable default target (Haiku)"
+# endif
// - Unknown
#else
# warning "Unable to detect a suitable default target"
diff --git a/tools/common/toml.cpp b/tools/common/toml.cpp
index 7e24b610..4e8e6da6 100644
--- a/tools/common/toml.cpp
+++ b/tools/common/toml.cpp
@@ -80,11 +80,8 @@ struct Token
};
TomlFile::TomlFile(const ::std::string& filename):
- m_if(filename)
+ m_lexer(filename)
{
- if( !m_if.is_open() ) {
- throw ::std::runtime_error("Unable to open file '" + filename + "'");
- }
}
TomlFileIter TomlFile::begin()
{
@@ -99,12 +96,14 @@ TomlFileIter TomlFile::end()
TomlKeyValue TomlFile::get_next_value()
{
- auto t = Token::lex_from(m_if);
+ auto t = m_lexer.get_token();
if(m_current_composite.empty())
{
while( t.m_type == Token::Type::Newline )
- t = Token::lex_from(m_if);
+ {
+ t = m_lexer.get_token();
+ }
// Expect '[', a string, or an identifier
switch(t.m_type)
@@ -116,32 +115,32 @@ TomlKeyValue TomlFile::get_next_value()
m_current_block.clear();
do
{
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
bool is_array = false;
if(t.m_type == Token::Type::SquareOpen)
{
is_array = true;
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
}
assert(t.m_type == Token::Type::Ident || t.m_type == Token::Type::String);
m_current_block.push_back(t.as_string());
if(is_array)
{
m_current_block.push_back(::format(m_array_counts[t.as_string()]++));
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
assert(t.m_type == Token::Type::SquareClose);
}
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
} while(t.m_type == Token::Type::Dot);
if( t.m_type != Token::Type::SquareClose )
{
- throw ::std::runtime_error(::format("Unexpected token in block header - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in block header - ", t));
}
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
if (t.m_type != Token::Type::Newline)
{
- throw ::std::runtime_error(::format("Unexpected token after block block - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after block block - ", t));
}
DEBUG("Start block " << m_current_block);
// Recurse!
@@ -156,7 +155,7 @@ TomlKeyValue TomlFile::get_next_value()
if( t.m_type == Token::Type::Eof )
{
// EOF isn't allowed here
- throw ::std::runtime_error(::format("Unexpected EOF in composite"));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected EOF in composite"));
}
}
switch (t.m_type)
@@ -165,14 +164,14 @@ TomlKeyValue TomlFile::get_next_value()
case Token::Type::Ident:
break;
default:
- throw ::std::runtime_error(::format("Unexpected token for key - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token for key - ", t));
}
::std::string key_name = t.as_string();
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
if(t.m_type != Token::Type::Assign)
- throw ::std::runtime_error(::format("Unexpected token after key - ", t));
- t = Token::lex_from(m_if);
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after key - ", t));
+ t = m_lexer.get_token();
// --- Value ---
TomlKeyValue rv;
@@ -193,10 +192,12 @@ TomlKeyValue TomlFile::get_next_value()
rv.path.push_back(key_name);
rv.value.m_type = TomlValue::Type::List;
- while( (t = Token::lex_from(m_if)).m_type != Token::Type::SquareClose )
+ while( (t = m_lexer.get_token()).m_type != Token::Type::SquareClose )
{
while( t.m_type == Token::Type::Newline )
- t = Token::lex_from(m_if);
+ {
+ t = m_lexer.get_token();
+ }
if( t.m_type == Token::Type::SquareClose )
break;
@@ -208,15 +209,15 @@ TomlKeyValue TomlFile::get_next_value()
rv.value.m_sub_values.push_back(TomlValue { t.as_string() });
break;
default:
- throw ::std::runtime_error(::format("Unexpected token in array value position - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in array value position - ", t));
}
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
if(t.m_type != Token::Type::Comma)
break;
}
if(t.m_type != Token::Type::SquareClose)
- throw ::std::runtime_error(::format("Unexpected token after array - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token after array - ", t));
break;
case Token::Type::BraceOpen:
m_current_composite.push_back(key_name);
@@ -228,7 +229,7 @@ TomlKeyValue TomlFile::get_next_value()
rv.path.insert(rv.path.end(), m_current_composite.begin(), m_current_composite.end());
rv.path.push_back(key_name);
rv.value = TomlValue { t.m_intval };
- return rv;
+ break;
case Token::Type::Ident:
if( t.m_data == "true" )
{
@@ -247,33 +248,57 @@ TomlKeyValue TomlFile::get_next_value()
}
else
{
- throw ::std::runtime_error(::format("Unexpected identifier in value position - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected identifier in value position - ", t));
}
break;
default:
- throw ::std::runtime_error(::format("Unexpected token in value position - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in value position - ", t));
}
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
while (!m_current_composite.empty() && t.m_type == Token::Type::BraceClose)
{
DEBUG("Leave composite block " << m_current_block << ", " << m_current_composite);
m_current_composite.pop_back();
- t = Token::lex_from(m_if);
+ t = m_lexer.get_token();
}
if( m_current_composite.empty() )
{
if(t.m_type != Token::Type::Newline && t.m_type != Token::Type::Eof)
- throw ::std::runtime_error(::format("Unexpected token in TOML file after entry - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in TOML file after entry - ", t));
}
else
{
if( t.m_type != Token::Type::Comma )
- throw ::std::runtime_error(::format("Unexpected token in TOML file after composite entry - ", t));
+ throw ::std::runtime_error(::format(m_lexer, ": Unexpected token in TOML file after composite entry - ", t));
}
return rv;
}
+TomlLexer::TomlLexer(const ::std::string& filename)
+ :m_if(filename)
+ ,m_filename(filename)
+ ,m_line(1)
+{
+ if( !m_if.is_open() ) {
+ throw ::std::runtime_error("Unable to open file '" + filename + "'");
+ }
+}
+Token TomlLexer::get_token()
+{
+ auto rv = Token::lex_from(m_if);
+ if( rv.m_type == Token::Type::Newline )
+ {
+ m_line ++;
+ }
+ return rv;
+}
+::std::ostream& operator<<(::std::ostream& os, const TomlLexer& x)
+{
+ os << x.m_filename << ":" << x.m_line;
+ return os;
+}
+
Token Token::lex_from(::std::ifstream& is)
{
auto rv = Token::lex_from_inner(is);
diff --git a/tools/common/toml.h b/tools/common/toml.h
index 4c97e7f2..17e05142 100644
--- a/tools/common/toml.h
+++ b/tools/common/toml.h
@@ -15,11 +15,28 @@
class TomlFileIter;
struct TomlKeyValue;
-class TomlFile
+struct Token;
+class TomlLexer
{
+ friend class TomlFile;
/// Input file stream
::std::ifstream m_if;
+ ::std::string m_filename;
+ unsigned m_line;
+protected:
+ TomlLexer(const ::std::string& filename);
+ Token get_token();
+
+public:
+ friend ::std::ostream& operator<<(::std::ostream& os, const TomlLexer& x);
+};
+
+class TomlFile
+{
+ /// Input file stream
+ TomlLexer m_lexer;
+
/// Name of the current `[]` block
::std::vector<::std::string> m_current_block;
@@ -40,6 +57,8 @@ public:
// Obtain the next value in the file
TomlKeyValue get_next_value();
+
+ const TomlLexer& lexer() const;
};
struct TomlValue
diff --git a/tools/minicargo/build.cpp b/tools/minicargo/build.cpp
index 04a9a507..5eb07104 100644
--- a/tools/minicargo/build.cpp
+++ b/tools/minicargo/build.cpp
@@ -31,6 +31,7 @@ extern int _putenv_s(const char*, const char*);
# include <mutex>
# include <condition_variable>
#endif
+#include <fstream>
#include <climits>
#include <cassert>
#ifdef _WIN32
@@ -67,6 +68,9 @@ class Builder
::helpers::path m_compiler_path;
size_t m_total_targets;
mutable size_t m_targets_built;
+#ifndef _WIN32
+ mutable ::std::mutex chdir_mutex;
+#endif
public:
Builder(const BuildOptions& opts, size_t total_targets);
@@ -78,7 +82,7 @@ public:
private:
::helpers::path get_crate_path(const PackageManifest& manifest, const PackageTarget& target, bool is_for_host, const char** crate_type, ::std::string* out_crate_suffix) const;
bool spawn_process_mrustc(const StringList& args, StringListKV env, const ::helpers::path& logfile) const;
- bool spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile) const;
+ bool spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile, const ::helpers::path& working_directory={}) const;
::helpers::path build_and_run_script(const PackageManifest& manifest, bool is_for_host) const;
@@ -566,6 +570,11 @@ Builder::Builder(const BuildOptions& opts, size_t total_targets):
m_total_targets(total_targets),
m_targets_built(0)
{
+ if( const char* override_path = getenv("MRUSTC_PATH") ) {
+ m_compiler_path = override_path;
+ return ;
+ }
+ // TODO: Clean this stuff up
#ifdef _WIN32
char buf[1024];
size_t s = GetModuleFileName(NULL, buf, sizeof(buf)-1);
@@ -1000,6 +1009,10 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget&
args.push_back("--crate-type"); args.push_back("bin");
args.push_back("-o"); args.push_back(outfile);
args.push_back("-L"); args.push_back(this->get_output_dir(true).str()); // NOTE: Forces `is_for_host` to true here.
+ if( true )
+ {
+ args.push_back("-g");
+ }
for(const auto& d : m_opts.lib_search_dirs)
{
args.push_back("-L");
@@ -1102,23 +1115,31 @@ bool Builder::build_target(const PackageManifest& manifest, const PackageTarget&
}
//auto _ = ScopedChdir { manifest.directory() };
- #if _WIN32
- #else
- auto fd_cwd = open(".", O_DIRECTORY);
- chdir(manifest.directory().str().c_str());
- #endif
- if( !this->spawn_process(script_exe_abs.str().c_str(), {}, env, out_file) )
+ if( !this->spawn_process(script_exe_abs.str().c_str(), {}, env, out_file, /*working_directory=*/manifest.directory()) )
{
- rename(out_file.str().c_str(), (out_file+"_failed").str().c_str());
+ auto failed_filename = out_file+"_failed.txt";
+ remove(failed_filename.str().c_str());
+ rename(out_file.str().c_str(), failed_filename.str().c_str());
+
+ ::std::cerr << "Calling " << script_exe_abs << " failed" << ::std::endl;
+ {
+ ::std::ifstream ifs(failed_filename);
+ char linebuf[1024];
+ while( ifs.good() && !ifs.eof() )
+ {
+ ifs.getline(linebuf, sizeof(linebuf)-1);
+ if( strncmp(linebuf, "cargo:", 6) == 0 ) {
+ continue;
+ }
+ ::std::cerr << "> " << linebuf << ::std::endl;
+ }
+ }
+
// Build failed, return an invalid path
- return ::helpers::path();;
+ return ::helpers::path();
}
- #if _WIN32
- #else
- fchdir(fd_cwd);
- #endif
}
-
+
return out_file;
}
bool Builder::build_library(const PackageManifest& manifest, bool is_for_host, size_t index) const
@@ -1154,7 +1175,7 @@ bool Builder::spawn_process_mrustc(const StringList& args, StringListKV env, con
//env.push_back("MRUSTC_DEBUG", "");
return spawn_process(m_compiler_path.str().c_str(), args, env, logfile);
}
-bool Builder::spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile) const
+bool Builder::spawn_process(const char* exe_name, const StringList& args, const StringListKV& env, const ::helpers::path& logfile, const ::helpers::path& working_directory/*={}*/) const
{
#ifdef _WIN32
::std::stringstream cmdline;
@@ -1206,14 +1227,14 @@ bool Builder::spawn_process(const char* exe_name, const StringList& args, const
WriteFile(si.hStdOutput, "\n", 1, &tmp, NULL);
}
PROCESS_INFORMATION pi = { 0 };
- CreateProcessA(exe_name, (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
+ CreateProcessA(exe_name, (LPSTR)cmdline_str.c_str(), NULL, NULL, TRUE, 0, NULL, (working_directory != ::helpers::path() ? working_directory.str().c_str() : NULL), &si, &pi);
CloseHandle(si.hStdOutput);
WaitForSingleObject(pi.hProcess, INFINITE);
DWORD status = 1;
GetExitCodeProcess(pi.hProcess, &status);
if (status != 0)
{
- DEBUG("Compiler exited with non-zero exit status " << status);
+ DEBUG("Process exited with non-zero exit status " << status);
return false;
}
#else
@@ -1270,12 +1291,23 @@ bool Builder::spawn_process(const char* exe_name, const StringList& args, const
// });
envp.push_back(nullptr);
- if( posix_spawn(&pid, exe_name, &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.get_vec().data()) != 0 )
+ // TODO: Acquire a lock
{
- ::std::cerr << "Unable to run process '" << exe_name << "' - " << strerror(errno) << ::std::endl;
- DEBUG("Unable to spawn executable");
- posix_spawn_file_actions_destroy(&fa);
- return false;
+ ::std::lock_guard<::std::mutex> lh { this->chdir_mutex };
+ auto fd_cwd = open(".", O_DIRECTORY);
+ if( working_directory != ::helpers::path() ) {
+ chdir(working_directory.str().c_str());
+ }
+ if( posix_spawn(&pid, exe_name, &fa, /*attr=*/nullptr, (char* const*)argv.data(), (char* const*)envp.get_vec().data()) != 0 )
+ {
+ ::std::cerr << "Unable to run process '" << exe_name << "' - " << strerror(errno) << ::std::endl;
+ DEBUG("Unable to spawn executable");
+ posix_spawn_file_actions_destroy(&fa);
+ return false;
+ }
+ if( working_directory != ::helpers::path() ) {
+ fchdir(fd_cwd);
+ }
}
posix_spawn_file_actions_destroy(&fa);
int status = -1;
diff --git a/tools/minicargo/main.cpp b/tools/minicargo/main.cpp
index 7065b7f5..4e929653 100644
--- a/tools/minicargo/main.cpp
+++ b/tools/minicargo/main.cpp
@@ -9,9 +9,9 @@
#include <iostream>
#include <cstring> // strcmp
#include <map>
-#include "debug.h"
+#include <debug.h>
#include "manifest.h"
-#include "helpers.h"
+#include <helpers.h>
#include "repository.h"
#include "build.h"
diff --git a/tools/minicargo/manifest.cpp b/tools/minicargo/manifest.cpp
index 8c0a7f44..edebd71a 100644
--- a/tools/minicargo/manifest.cpp
+++ b/tools/minicargo/manifest.cpp
@@ -317,7 +317,7 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
rv.m_targets.push_back(PackageTarget { PackageTarget::Type::Lib });
}
}
- // - If there's no binary section, but src/main.rs exists, add one
+ // - If there's no binary section, but src/main.rs exists, add as a binary
if( ! ::std::any_of(rv.m_targets.begin(), rv.m_targets.end(), [](const auto& x){ return x.m_type == PackageTarget::Type::Bin; }) )
{
// No library, add one pointing to lib.rs
@@ -327,6 +327,10 @@ PackageManifest PackageManifest::load_from_toml(const ::std::string& path)
rv.m_targets.push_back(PackageTarget { PackageTarget::Type::Bin });
}
}
+ if( rv.m_targets.empty() )
+ {
+ throw ::std::runtime_error(format("Manifest file ", path, " didn't specify any targets (and src/{main,lib}.rs doesn't exist)"));
+ }
// Default target names
for(auto& tgt : rv.m_targets)
diff --git a/vsproject/build_std.cmd b/vsproject/build_std.cmd
index a9d6b45d..0a360614 100644
--- a/vsproject/build_std.cmd
+++ b/vsproject/build_std.cmd
@@ -5,3 +5,5 @@ x64\Release\minicargo.exe ..\rustc-1.19.0-src\src\libpanic_unwind --script-overr
if %errorlevel% neq 0 exit /b %errorlevel%
x64\Release\minicargo.exe ..\rustc-1.19.0-src\src\libtest --script-overrides ..\script-overrides\stable-1.19.0
if %errorlevel% neq 0 exit /b %errorlevel%
+x64\Release\minicargo.exe ..\lib\libproc_macro
+if %errorlevel% neq 0 exit /b %errorlevel%
diff --git a/vsproject/common_lib/common_lib.vcxproj b/vsproject/common_lib/common_lib.vcxproj
index 09789501..4f861999 100644
--- a/vsproject/common_lib/common_lib.vcxproj
+++ b/vsproject/common_lib/common_lib.vcxproj
@@ -69,7 +69,14 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
diff --git a/vsproject/minicargo/minicargo.vcxproj b/vsproject/minicargo/minicargo.vcxproj
index c632cee2..b62aad66 100644
--- a/vsproject/minicargo/minicargo.vcxproj
+++ b/vsproject/minicargo/minicargo.vcxproj
@@ -68,7 +68,14 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
diff --git a/vsproject/testrunner/testrunner.vcxproj b/vsproject/testrunner/testrunner.vcxproj
index 94d365f0..550614ac 100644
--- a/vsproject/testrunner/testrunner.vcxproj
+++ b/vsproject/testrunner/testrunner.vcxproj
@@ -68,7 +68,14 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
- <PropertyGroup />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir>
+ <IntDir>$(Platform)\$(Configuration)\</IntDir>
+ </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>