Oh my. Basic CFA/DFA, local variable support, misc fixes, etc.

This commit is contained in:
Ben Vanik
2014-02-02 00:33:57 -08:00
parent b29276e167
commit bca349b302
37 changed files with 3048 additions and 28 deletions

View File

@@ -12,15 +12,37 @@
#include <alloy/core.h>
XEDECLARECLASS1(llvm, BitVector);
namespace alloy {
namespace hir {
class Block;
class HIRBuilder;
class Instr;
class Label;
class Edge {
public:
enum EdgeFlags {
UNCONDITIONAL = (1 << 0),
DOMINATES = (1 << 1),
};
public:
Edge* outgoing_next;
Edge* outgoing_prev;
Edge* incoming_next;
Edge* incoming_prev;
Block* src;
Block* dest;
uint32_t flags;
};
class Block {
public:
Arena* arena;
@@ -28,6 +50,10 @@ public:
Block* next;
Block* prev;
Edge* incoming_edge_head;
Edge* outgoing_edge_head;
llvm::BitVector* incoming_values;
Label* label_head;
Label* label_tail;

View File

@@ -41,6 +41,7 @@ void HIRBuilder::Reset() {
attributes_ = 0;
next_label_id_ = 0;
next_value_ordinal_ = 0;
locals_.clear();
block_head_ = block_tail_ = NULL;
current_block_ = NULL;
#if XE_DEBUG
@@ -141,6 +142,13 @@ void HIRBuilder::Dump(StringBuffer* str) {
str->Append("; attributes = %.8X\n", attributes_);
}
for (auto it = locals_.begin(); it != locals_.end(); ++it) {
auto local = *it;
str->Append(" ; local ");
DumpValue(str, local);
str->Append("\n");
}
uint32_t block_ordinal = 0;
Block* block = block_head_;
while (block) {
@@ -161,6 +169,39 @@ void HIRBuilder::Dump(StringBuffer* str) {
label = label->next;
}
Edge* incoming_edge = block->incoming_edge_head;
while (incoming_edge) {
auto src_label = incoming_edge->src->label_head;
if (src_label && src_label->name) {
str->Append(" ; in: %s", src_label->name);
} else if (src_label) {
str->Append(" ; in: label%d", src_label->id);
} else {
str->Append(" ; in: <block%d>",
incoming_edge->src->ordinal);
}
str->Append(", dom:%d, uncond:%d\n",
(incoming_edge->flags & Edge::DOMINATES) ? 1 : 0,
(incoming_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0);
incoming_edge = incoming_edge->incoming_next;
}
Edge* outgoing_edge = block->outgoing_edge_head;
while (outgoing_edge) {
auto dest_label = outgoing_edge->dest->label_head;
if (dest_label && dest_label->name) {
str->Append(" ; out: %s", dest_label->name);
} else if (dest_label) {
str->Append(" ; out: label%d", dest_label->id);
} else {
str->Append(" ; out: <block%d>",
outgoing_edge->dest->ordinal);
}
str->Append(", dom:%d, uncond:%d\n",
(outgoing_edge->flags & Edge::DOMINATES) ? 1 : 0,
(outgoing_edge->flags & Edge::UNCONDITIONAL) ? 1 : 0);
outgoing_edge = outgoing_edge->outgoing_next;
}
Instr* i = block->instr_head;
while (i) {
if (i->opcode->flags & OPCODE_FLAG_HIDE) {
@@ -303,6 +344,7 @@ void HIRBuilder::InsertLabel(Label* label, Instr* prev_instr) {
block_tail_ = new_block;
}
new_block->label_head = new_block->label_tail = label;
new_block->incoming_edge_head = new_block->outgoing_edge_head = NULL;
label->block = new_block;
label->prev = label->next = NULL;
@@ -319,8 +361,7 @@ void HIRBuilder::InsertLabel(Label* label, Instr* prev_instr) {
new_block->instr_tail = old_prev_tail;
}
for (auto instr = new_block->instr_head; instr != new_block->instr_tail;
instr = instr->next) {
for (auto instr = new_block->instr_head; instr; instr = instr->next) {
instr->block = new_block;
}
@@ -342,6 +383,19 @@ void HIRBuilder::ResetLabelTags() {
}
}
void HIRBuilder::AddEdge(Block* src, Block* dest, uint32_t flags) {
Edge* edge = arena_->Alloc<Edge>();
edge->src = src;
edge->dest = dest;
edge->flags = flags;
edge->outgoing_prev = NULL;
edge->outgoing_next = src->outgoing_edge_head;
src->outgoing_edge_head = edge;
edge->incoming_prev = NULL;
edge->incoming_next = dest->incoming_edge_head;
dest->incoming_edge_head = edge;
}
Block* HIRBuilder::AppendBlock() {
Block* block = arena_->Alloc<Block>();
block->arena = arena_;
@@ -356,6 +410,7 @@ Block* HIRBuilder::AppendBlock() {
}
current_block_ = block;
block->label_head = block->label_tail = NULL;
block->incoming_edge_head = block->outgoing_edge_head = NULL;
block->instr_head = block->instr_tail = NULL;
return block;
}
@@ -420,6 +475,7 @@ Value* HIRBuilder::AllocValue(TypeName type) {
value->def = NULL;
value->use_head = NULL;
value->last_use = NULL;
value->local_slot = NULL;
value->tag = NULL;
value->reg = -1;
return value;
@@ -434,6 +490,7 @@ Value* HIRBuilder::CloneValue(Value* source) {
value->def = NULL;
value->use_head = NULL;
value->last_use = NULL;
value->local_slot = NULL;
value->tag = NULL;
value->reg = -1;
return value;
@@ -877,6 +934,28 @@ Value* HIRBuilder::LoadClock() {
return i->dest;
}
Value* HIRBuilder::AllocLocal(TypeName type) {
Value* slot = AllocValue(type);
locals_.push_back(slot);
return slot;
}
Value* HIRBuilder::LoadLocal(Value* slot) {
Instr* i = AppendInstr(
OPCODE_LOAD_LOCAL_info, 0,
AllocValue(slot->type));
i->set_src1(slot);
i->src2.value = i->src3.value = NULL;
return i->dest;
}
void HIRBuilder::StoreLocal(Value* slot, Value* value) {
Instr* i = AppendInstr(OPCODE_STORE_LOCAL_info, 0);
i->set_src1(slot);
i->set_src2(value);
i->src3.value = NULL;
}
Value* HIRBuilder::LoadContext(size_t offset, TypeName type) {
Instr* i = AppendInstr(
OPCODE_LOAD_CONTEXT_info, 0,

View File

@@ -41,7 +41,12 @@ public:
uint32_t attributes() const { return attributes_; }
void set_attributes(uint32_t value) { attributes_ = value; }
std::vector<Value*>& locals() { return locals_; }
uint32_t max_value_ordinal() const { return next_value_ordinal_; }
Block* first_block() const { return block_head_; }
Block* last_block() const { return block_tail_; }
Block* current_block() const;
Instr* last_instr() const;
@@ -50,12 +55,11 @@ public:
void InsertLabel(Label* label, Instr* prev_instr);
void ResetLabelTags();
void AddEdge(Block* src, Block* dest, uint32_t flags);
// static allocations:
// Value* AllocStatic(size_t length);
// stack allocations:
// Value* AllocLocal(TypeName type);
void Comment(const char* format, ...);
void Nop();
@@ -116,6 +120,10 @@ public:
Value* LoadClock();
Value* AllocLocal(TypeName type);
Value* LoadLocal(Value* slot);
void StoreLocal(Value* slot, Value* value);
Value* LoadContext(size_t offset, TypeName type);
void StoreContext(size_t offset, Value* value);
@@ -230,6 +238,8 @@ protected:
uint32_t next_label_id_;
uint32_t next_value_ordinal_;
std::vector<Value*> locals_;
Block* block_head_;
Block* block_tail_;
Block* current_block_;

View File

@@ -61,6 +61,36 @@ bool Instr::Match(SignatureType dest_req,
((src3_req == SIG_TYPE_IGNORE) || (src3_req == TO_SIG_TYPE(src3.value)));
}
void Instr::MoveBefore(Instr* other) {
if (next == other) {
return;
}
// Remove from current location.
if (prev) {
prev->next = next;
} else {
block->instr_head = next;
}
if (next) {
next->prev = prev;
} else {
block->instr_tail = prev;
}
// Insert into new location.
block = other->block;
next = other;
prev = other->prev;
other->prev = this;
if (prev) {
prev->next = this;
}
if (other == block->instr_head) {
block->instr_head = this;
}
}
void Instr::Replace(const OpcodeInfo* opcode, uint16_t flags) {
this->opcode = opcode;
this->flags = flags;

View File

@@ -79,6 +79,7 @@ public:
SignatureType src2 = SIG_TYPE_X,
SignatureType src3 = SIG_TYPE_X) const;
void MoveBefore(Instr* other);
void Replace(const OpcodeInfo* opcode, uint16_t flags);
void Remove();
};

View File

@@ -117,6 +117,9 @@ enum Opcode {
OPCODE_LOAD_CLOCK,
OPCODE_LOAD_LOCAL,
OPCODE_STORE_LOCAL,
OPCODE_LOAD_CONTEXT,
OPCODE_STORE_CONTEXT,
@@ -202,6 +205,7 @@ enum OpcodeFlags {
OPCODE_FLAG_VOLATILE = (1 << 4),
OPCODE_FLAG_IGNORE = (1 << 5),
OPCODE_FLAG_HIDE = (1 << 6),
OPCODE_FLAG_PAIRED_PREV = (1 << 7),
};
enum OpcodeSignatureType {

View File

@@ -182,6 +182,18 @@ DEFINE_OPCODE(
OPCODE_SIG_V,
0);
DEFINE_OPCODE(
OPCODE_LOAD_LOCAL,
"load_local",
OPCODE_SIG_V_V,
0);
DEFINE_OPCODE(
OPCODE_STORE_LOCAL,
"store_local",
OPCODE_SIG_X_V_V,
0);
DEFINE_OPCODE(
OPCODE_LOAD_CONTEXT,
"load_context",
@@ -297,17 +309,17 @@ DEFINE_OPCODE(
OPCODE_DID_CARRY,
"did_carry",
OPCODE_SIG_V_V,
0);
OPCODE_FLAG_PAIRED_PREV);
DEFINE_OPCODE(
OPCODE_DID_OVERFLOW,
"did_overflow",
OPCODE_SIG_V_V,
0);
OPCODE_FLAG_PAIRED_PREV);
DEFINE_OPCODE(
OPCODE_DID_SATURATE,
"did_saturate",
OPCODE_SIG_V_V,
0);
OPCODE_FLAG_PAIRED_PREV);
DEFINE_OPCODE(
OPCODE_VECTOR_COMPARE_EQ,

View File

@@ -42,6 +42,25 @@ static bool IsFloatType(TypeName type_name) {
static bool IsVecType(TypeName type_name) {
return type_name == VEC128_TYPE;
}
static size_t GetTypeSize(TypeName type_name) {
switch (type_name) {
case INT8_TYPE:
return 1;
case INT16_TYPE:
return 2;
case INT32_TYPE:
return 4;
case INT64_TYPE:
return 8;
case FLOAT32_TYPE:
return 4;
case FLOAT64_TYPE:
return 8;
default:
case VEC128_TYPE:
return 16;
}
}
enum ValueFlags {
VALUE_IS_CONSTANT = (1 << 1),
@@ -78,6 +97,7 @@ public:
Use* use_head;
// NOTE: for performance reasons this is not maintained during construction.
Instr* last_use;
Value* local_slot;
// TODO(benvanik): remove to shrink size.
void* tag;