Adding implicit branches to ensure flow control remains legit.
This commit is contained in:
parent
aa021d22dd
commit
7002a3bd57
|
@ -407,7 +407,7 @@ int InstrEmit_fcmpx_(PPCFunctionBuilder& f, InstrData& i, bool ordered) {
|
||||||
// TODO(benvanik): update VXSNAN
|
// TODO(benvanik): update VXSNAN
|
||||||
const uint32_t crf = i.X.RT >> 2;
|
const uint32_t crf = i.X.RT >> 2;
|
||||||
// f.UpdateFPRF(v);
|
// f.UpdateFPRF(v);
|
||||||
f.UpdateCR(crf, f.LoadFPR(i.X.RA), f.LoadFPR(i.X.RB), true);
|
f.UpdateCR(crf, f.LoadFPR(i.X.RA), f.LoadFPR(i.X.RB), false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
XEEMITTER(fcmpo, 0xFC000040, X )(PPCFunctionBuilder& f, InstrData& i) {
|
XEEMITTER(fcmpo, 0xFC000040, X )(PPCFunctionBuilder& f, InstrData& i) {
|
||||||
|
|
|
@ -138,7 +138,7 @@ int PPCFunctionBuilder::Emit(FunctionInfo* symbol_info) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return Finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPCFunctionBuilder::AnnotateLabel(uint64_t address, Label* label) {
|
void PPCFunctionBuilder::AnnotateLabel(uint64_t address, Label* label) {
|
||||||
|
|
|
@ -44,6 +44,41 @@ void FunctionBuilder::Reset() {
|
||||||
current_block_ = NULL;
|
current_block_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FunctionBuilder::Finalize() {
|
||||||
|
// Scan blocks in order and add fallthrough branches. These are needed for
|
||||||
|
// analysis passes to work. We may have also added blocks out of order and
|
||||||
|
// need to ensure they fall through in the right order.
|
||||||
|
for (auto block = block_head_; block != NULL; block = block->next) {
|
||||||
|
bool needs_branch = false;
|
||||||
|
if (block->instr_tail) {
|
||||||
|
if (!IsUnconditionalJump(block->instr_tail)) {
|
||||||
|
// Add tail branch to block that falls through.
|
||||||
|
needs_branch = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Add tail branch to block with no instructions.
|
||||||
|
// Hopefully an optimization pass will clean this up later.
|
||||||
|
needs_branch = true;
|
||||||
|
}
|
||||||
|
if (needs_branch) {
|
||||||
|
current_block_ = block;
|
||||||
|
if (!block->next) {
|
||||||
|
// No following block.
|
||||||
|
// Sometimes VC++ generates functions with bl at the end even if they
|
||||||
|
// will never return. Just add a return to satisfy things.
|
||||||
|
XELOGW("Fall-through out of the function.");
|
||||||
|
Return();
|
||||||
|
current_block_ = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Add branch.
|
||||||
|
Branch(block->next, BRANCH_LIKELY);
|
||||||
|
current_block_ = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void FunctionBuilder::DumpValue(StringBuffer* str, Value* value) {
|
void FunctionBuilder::DumpValue(StringBuffer* str, Value* value) {
|
||||||
if (value->IsConstant()) {
|
if (value->IsConstant()) {
|
||||||
switch (value->type) {
|
switch (value->type) {
|
||||||
|
@ -186,14 +221,16 @@ Label* FunctionBuilder::NewLabel() {
|
||||||
return label;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionBuilder::MarkLabel(Label* label) {
|
void FunctionBuilder::MarkLabel(Label* label, Block* block) {
|
||||||
if (current_block_ && current_block_->instr_tail) {
|
if (!block) {
|
||||||
EndBlock();
|
if (current_block_ && current_block_->instr_tail) {
|
||||||
|
EndBlock();
|
||||||
|
}
|
||||||
|
if (!current_block_) {
|
||||||
|
AppendBlock();
|
||||||
|
}
|
||||||
|
block = current_block_;
|
||||||
}
|
}
|
||||||
if (!current_block_) {
|
|
||||||
AppendBlock();
|
|
||||||
}
|
|
||||||
Block* block = current_block_;
|
|
||||||
label->block = block;
|
label->block = block;
|
||||||
label->prev = block->label_tail;
|
label->prev = block->label_tail;
|
||||||
label->next = NULL;
|
label->next = NULL;
|
||||||
|
@ -299,6 +336,18 @@ void FunctionBuilder::EndBlock() {
|
||||||
current_block_ = NULL;
|
current_block_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FunctionBuilder::IsUnconditionalJump(Instr* instr) {
|
||||||
|
if (instr->opcode == &OPCODE_CALL_info ||
|
||||||
|
instr->opcode == &OPCODE_CALL_INDIRECT_info) {
|
||||||
|
return (instr->flags & CALL_TAIL) != 0;
|
||||||
|
} else if (instr->opcode == &OPCODE_BRANCH_info) {
|
||||||
|
return true;
|
||||||
|
} else if (instr->opcode == &OPCODE_RETURN_info) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Instr* FunctionBuilder::AppendInstr(
|
Instr* FunctionBuilder::AppendInstr(
|
||||||
const OpcodeInfo& opcode_info, uint16_t flags, Value* dest) {
|
const OpcodeInfo& opcode_info, uint16_t flags, Value* dest) {
|
||||||
if (!current_block_) {
|
if (!current_block_) {
|
||||||
|
@ -489,6 +538,15 @@ void FunctionBuilder::Branch(Label* label, uint32_t branch_flags) {
|
||||||
EndBlock();
|
EndBlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FunctionBuilder::Branch(Block* block, uint32_t branch_flags) {
|
||||||
|
if (!block->label_head) {
|
||||||
|
// Block needs a label.
|
||||||
|
Label* label = NewLabel();
|
||||||
|
MarkLabel(label, block);
|
||||||
|
}
|
||||||
|
Branch(block->label_head, branch_flags);
|
||||||
|
}
|
||||||
|
|
||||||
void FunctionBuilder::BranchTrue(
|
void FunctionBuilder::BranchTrue(
|
||||||
Value* cond, Label* label, uint32_t branch_flags) {
|
Value* cond, Label* label, uint32_t branch_flags) {
|
||||||
if (cond->IsConstant()) {
|
if (cond->IsConstant()) {
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
virtual ~FunctionBuilder();
|
virtual ~FunctionBuilder();
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
|
virtual int Finalize();
|
||||||
|
|
||||||
void Dump(StringBuffer* str);
|
void Dump(StringBuffer* str);
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public:
|
||||||
Instr* last_instr() const;
|
Instr* last_instr() const;
|
||||||
|
|
||||||
Label* NewLabel();
|
Label* NewLabel();
|
||||||
void MarkLabel(Label* label);
|
void MarkLabel(Label* label, Block* block = 0);
|
||||||
void InsertLabel(Label* label, Instr* prev_instr);
|
void InsertLabel(Label* label, Instr* prev_instr);
|
||||||
|
|
||||||
// static allocations:
|
// static allocations:
|
||||||
|
@ -75,6 +76,7 @@ public:
|
||||||
void SetReturnAddress(Value* value);
|
void SetReturnAddress(Value* value);
|
||||||
|
|
||||||
void Branch(Label* label, uint32_t branch_flags = 0);
|
void Branch(Label* label, uint32_t branch_flags = 0);
|
||||||
|
void Branch(Block* block, uint32_t branch_flags = 0);
|
||||||
void BranchTrue(Value* cond, Label* label,
|
void BranchTrue(Value* cond, Label* label,
|
||||||
uint32_t branch_flags = 0);
|
uint32_t branch_flags = 0);
|
||||||
void BranchFalse(Value* cond, Label* label,
|
void BranchFalse(Value* cond, Label* label,
|
||||||
|
@ -205,6 +207,7 @@ protected:
|
||||||
private:
|
private:
|
||||||
Block* AppendBlock();
|
Block* AppendBlock();
|
||||||
void EndBlock();
|
void EndBlock();
|
||||||
|
bool IsUnconditionalJump(Instr* instr);
|
||||||
Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags,
|
Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags,
|
||||||
Value* dest = 0);
|
Value* dest = 0);
|
||||||
Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2);
|
Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2);
|
||||||
|
|
Loading…
Reference in New Issue