summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2016-12-29 17:05:36 +1100
committerJohn Hodge <tpg@mutabah.net>2016-12-29 17:05:36 +1100
commit27985de4e5c26a53fa330dcb8ed8dc6342681d31 (patch)
tree8aa6e242c5340314d188ad614cc785353ebf4eb9 /src
parentdd89eb7acb16234a7a9f2b6e0aee4788024c0df6 (diff)
downloadmrust-27985de4e5c26a53fa330dcb8ed8dc6342681d31.tar.gz
MIR - Inline assembly in MIR
Diffstat (limited to 'src')
-rw-r--r--src/hir/deserialise.cpp8
-rw-r--r--src/hir/serialise.cpp8
-rw-r--r--src/mir/check.cpp21
-rw-r--r--src/mir/cleanup.cpp6
-rw-r--r--src/mir/dump.cpp16
-rw-r--r--src/mir/from_hir.cpp17
-rw-r--r--src/mir/from_hir.hpp2
-rw-r--r--src/mir/mir.hpp16
-rw-r--r--src/mir/mir_builder.cpp11
-rw-r--r--src/trans/enumerate.cpp6
10 files changed, 105 insertions, 6 deletions
diff --git a/src/hir/deserialise.cpp b/src/hir/deserialise.cpp
index de0d13da..d7dd74fe 100644
--- a/src/hir/deserialise.cpp
+++ b/src/hir/deserialise.cpp
@@ -963,6 +963,14 @@ namespace {
m_in.read_bool() ? ::MIR::eDropKind::DEEP : ::MIR::eDropKind::SHALLOW,
deserialise_mir_lvalue()
});
+ case 2:
+ return ::MIR::Statement::make_Asm({
+ m_in.read_string(),
+ deserialise_vec< ::std::pair< ::std::string, ::MIR::LValue> >(),
+ deserialise_vec< ::std::pair< ::std::string, ::MIR::LValue> >(),
+ deserialise_vec< ::std::string>(),
+ deserialise_vec< ::std::string>()
+ });
default:
::std::cerr << "Bad tag for a MIR Statement" << ::std::endl;
throw "";
diff --git a/src/hir/serialise.cpp b/src/hir/serialise.cpp
index 0dfb9b01..4feece50 100644
--- a/src/hir/serialise.cpp
+++ b/src/hir/serialise.cpp
@@ -474,6 +474,14 @@ namespace {
assert(e.kind == ::MIR::eDropKind::DEEP || e.kind == ::MIR::eDropKind::SHALLOW);
m_out.write_bool(e.kind == ::MIR::eDropKind::DEEP);
serialise(e.slot);
+ ),
+ (Asm,
+ m_out.write_tag(2);
+ m_out.write_string(e.tpl);
+ serialise_vec(e.inputs);
+ serialise_vec(e.outputs);
+ serialise_vec(e.clobbers);
+ serialise_vec(e.flags);
)
)
}
diff --git a/src/mir/check.cpp b/src/mir/check.cpp
index 0c428c64..e867c822 100644
--- a/src/mir/check.cpp
+++ b/src/mir/check.cpp
@@ -260,15 +260,22 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
const auto& stmt = bb.statements[stmt_idx];
state.set_cur_stmt(block, stmt_idx);
- if( stmt.is_Drop() )
+ switch( stmt.tag() )
{
+ case ::MIR::Statement::TAGDEAD:
+ throw "";
+ case ::MIR::Statement::TAG_Drop:
// Invalidate the slot
val_state.ensure_valid(state, stmt.as_Drop().slot);
val_state.mark_validity( state, stmt.as_Drop().slot, false );
- }
- else
- {
- assert( stmt.is_Assign() );
+ break;
+ case ::MIR::Statement::TAG_Asm:
+ for(const auto& v : stmt.as_Asm().inputs)
+ val_state.ensure_valid(state, v.second);
+ for(const auto& v : stmt.as_Asm().outputs)
+ val_state.mark_validity( state, v.second, true );
+ break;
+ case ::MIR::Statement::TAG_Assign:
// Check source (and invalidate sources)
TU_MATCH( ::MIR::RValue, (stmt.as_Assign().src), (se),
(Use,
@@ -323,6 +330,7 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
)
// Mark destination as valid
val_state.mark_validity( state, stmt.as_Assign().dst, true );
+ break;
}
}
@@ -557,6 +565,9 @@ void MIR_Validate(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path
)
)
} break;
+ case ::MIR::Statement::TAG_Asm:
+ // TODO: Ensure that values are all thin pointers or integers?
+ break;
case ::MIR::Statement::TAG_Drop:
// TODO: Anything need checking here?
break;
diff --git a/src/mir/cleanup.cpp b/src/mir/cleanup.cpp
index 5744a033..27410462 100644
--- a/src/mir/cleanup.cpp
+++ b/src/mir/cleanup.cpp
@@ -817,6 +817,12 @@ void MIR_Cleanup(const StaticTraitResolve& resolve, const ::HIR::ItemPath& path,
(Drop,
MIR_Cleanup_LValue(state, mutator, se.slot);
),
+ (Asm,
+ for(auto& v : se.inputs)
+ MIR_Cleanup_LValue(state, mutator, v.second);
+ for(auto& v : se.outputs)
+ MIR_Cleanup_LValue(state, mutator, v.second);
+ ),
(Assign,
MIR_Cleanup_LValue(state, mutator, se.dst);
TU_MATCHA( (se.src), (re),
diff --git a/src/mir/dump.cpp b/src/mir/dump.cpp
index d143c2c9..e10856bf 100644
--- a/src/mir/dump.cpp
+++ b/src/mir/dump.cpp
@@ -163,6 +163,22 @@ namespace {
DEBUG("- Assign " << e.dst << " = " << e.src);
m_os << FMT_M(e.dst) << " = " << FMT_M(e.src) << ";\n";
),
+ (Asm,
+ DEBUG("- Asm");
+ m_os << "(";
+ for(const auto& v : e.outputs)
+ m_os << FMT_M(v.second) << ",";
+ m_os << ") = asm!";
+ m_os << "(";
+ for(const auto& v : e.inputs)
+ m_os << FMT_M(v.second) << ",";
+ m_os << " : ";
+ for(const auto& v : e.clobbers)
+ m_os << "\"" << v << "\",";
+ m_os << ")";
+ for(const auto& v : e.flags)
+ m_os << " \"" << v << "\"";
+ ),
(Drop,
DEBUG("- DROP " << e.slot);
m_os << "drop(" << FMT_M(e.slot);
diff --git a/src/mir/from_hir.cpp b/src/mir/from_hir.cpp
index 3cfc8cac..a6a5aa32 100644
--- a/src/mir/from_hir.cpp
+++ b/src/mir/from_hir.cpp
@@ -451,7 +451,22 @@ namespace {
{
TRACE_FUNCTION_F("_Asm");
- TODO(node.span(), "asm!");
+ ::std::vector< ::std::pair< ::std::string, ::MIR::LValue> > inputs;
+ for(auto& v : node.m_inputs) {
+ this->visit_node_ptr(v.value);
+ auto lv = m_builder.get_result_in_lvalue(v.value->span(), v.value->m_res_type);
+ inputs.push_back( ::std::make_pair(v.spec, mv$(lv)) );
+ }
+
+ ::std::vector< ::std::pair< ::std::string, ::MIR::LValue> > outputs;
+ for(auto& v : node.m_outputs) {
+ this->visit_node_ptr(v.value);
+ auto lv = m_builder.get_result_unwrap_lvalue(v.value->span());
+ outputs.push_back( ::std::make_pair(v.spec, mv$(lv)) );
+ }
+
+ m_builder.push_stmt_asm( node.span(), { node.m_template, mv$(outputs), mv$(inputs), node.m_clobbers, node.m_flags } );
+ m_builder.set_result(node.span(), ::MIR::RValue::make_Tuple({}));
}
void visit(::HIR::ExprNode_Return& node) override
{
diff --git a/src/mir/from_hir.hpp b/src/mir/from_hir.hpp
index 405d4ffd..dc11232e 100644
--- a/src/mir/from_hir.hpp
+++ b/src/mir/from_hir.hpp
@@ -174,6 +174,8 @@ public:
void push_stmt_drop(const Span& sp, ::MIR::LValue val);
// Push a shallow drop (for Box)
void push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val);
+ // Push an inline assembly statement (NOTE: inputs aren't marked as moved)
+ void push_stmt_asm(const Span& sp, ::MIR::Statement::Data_Asm data);
// - Block management
bool block_active() const {
diff --git a/src/mir/mir.hpp b/src/mir/mir.hpp
index 5a6b83de..6bd371b5 100644
--- a/src/mir/mir.hpp
+++ b/src/mir/mir.hpp
@@ -200,11 +200,27 @@ enum class eDropKind {
DEEP,
};
TAGGED_UNION(Statement, Assign,
+ // Value assigment
(Assign, struct {
LValue dst;
RValue src;
}),
+ // Inline assembly
+ (Asm, struct {
+ ::std::string tpl;
+ ::std::vector< ::std::pair<::std::string,LValue> > outputs;
+ ::std::vector< ::std::pair<::std::string,LValue> > inputs;
+ ::std::vector< ::std::string> clobbers;
+ ::std::vector< ::std::string> flags;
+ }),
+ // Update the state of a drop flag
+ //(SetDropFlag, struct {
+ // unsigned int idx;
+ // bool new_val;
+ // }),
+ // Drop a value
(Drop, struct {
+ //unsigned int flag_idx; // Valid if != ~0u
eDropKind kind; // NOTE: For the `box` primitive
LValue slot;
})
diff --git a/src/mir/mir_builder.cpp b/src/mir/mir_builder.cpp
index 17cf79ec..6df64a0e 100644
--- a/src/mir/mir_builder.cpp
+++ b/src/mir/mir_builder.cpp
@@ -280,6 +280,17 @@ void MirBuilder::push_stmt_drop_shallow(const Span& sp, ::MIR::LValue val)
DEBUG("DROP shallow " << val);
m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Drop({ ::MIR::eDropKind::SHALLOW, mv$(val) }) );
}
+void MirBuilder::push_stmt_asm(const Span& sp, ::MIR::Statement::Data_Asm data)
+{
+ ASSERT_BUG(sp, m_block_active, "Pushing statement with no active block");
+
+ // 1. Mark outputs as valid
+ for(const auto& v : data.outputs)
+ mark_value_assigned(sp, v.second);
+
+ // 2. Push
+ m_output.blocks.at(m_current_block).statements.push_back( ::MIR::Statement::make_Asm( mv$(data) ) );
+}
void MirBuilder::mark_value_assigned(const Span& sp, const ::MIR::LValue& dst)
{
diff --git a/src/trans/enumerate.cpp b/src/trans/enumerate.cpp
index 81b02199..7462a2d9 100644
--- a/src/trans/enumerate.cpp
+++ b/src/trans/enumerate.cpp
@@ -749,6 +749,12 @@ void Trans_Enumerate_FillFrom_MIR(TransList& out, const ::HIR::Crate& crate, con
)
)
),
+ (Asm,
+ for(const auto& v : se.inputs)
+ Trans_Enumerate_FillFrom_MIR_LValue(out,crate, v.second, pp);
+ for(const auto& v : se.outputs)
+ Trans_Enumerate_FillFrom_MIR_LValue(out,crate, v.second, pp);
+ ),
(Drop,
Trans_Enumerate_FillFrom_MIR_LValue(out,crate, se.slot, pp);
// TODO: Ensure that the drop glue for this type is generated