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
|
||||
const uint32_t crf = i.X.RT >> 2;
|
||||
// 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;
|
||||
}
|
||||
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) {
|
||||
|
|
|
@ -44,6 +44,41 @@ void FunctionBuilder::Reset() {
|
|||
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) {
|
||||
if (value->IsConstant()) {
|
||||
switch (value->type) {
|
||||
|
@ -186,14 +221,16 @@ Label* FunctionBuilder::NewLabel() {
|
|||
return label;
|
||||
}
|
||||
|
||||
void FunctionBuilder::MarkLabel(Label* label) {
|
||||
if (current_block_ && current_block_->instr_tail) {
|
||||
EndBlock();
|
||||
void FunctionBuilder::MarkLabel(Label* label, Block* block) {
|
||||
if (!block) {
|
||||
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->prev = block->label_tail;
|
||||
label->next = NULL;
|
||||
|
@ -299,6 +336,18 @@ void FunctionBuilder::EndBlock() {
|
|||
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(
|
||||
const OpcodeInfo& opcode_info, uint16_t flags, Value* dest) {
|
||||
if (!current_block_) {
|
||||
|
@ -489,6 +538,15 @@ void FunctionBuilder::Branch(Label* label, uint32_t branch_flags) {
|
|||
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(
|
||||
Value* cond, Label* label, uint32_t branch_flags) {
|
||||
if (cond->IsConstant()) {
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
virtual ~FunctionBuilder();
|
||||
|
||||
virtual void Reset();
|
||||
virtual int Finalize();
|
||||
|
||||
void Dump(StringBuffer* str);
|
||||
|
||||
|
@ -44,7 +45,7 @@ public:
|
|||
Instr* last_instr() const;
|
||||
|
||||
Label* NewLabel();
|
||||
void MarkLabel(Label* label);
|
||||
void MarkLabel(Label* label, Block* block = 0);
|
||||
void InsertLabel(Label* label, Instr* prev_instr);
|
||||
|
||||
// static allocations:
|
||||
|
@ -75,6 +76,7 @@ public:
|
|||
void SetReturnAddress(Value* value);
|
||||
|
||||
void Branch(Label* label, uint32_t branch_flags = 0);
|
||||
void Branch(Block* block, uint32_t branch_flags = 0);
|
||||
void BranchTrue(Value* cond, Label* label,
|
||||
uint32_t branch_flags = 0);
|
||||
void BranchFalse(Value* cond, Label* label,
|
||||
|
@ -205,6 +207,7 @@ protected:
|
|||
private:
|
||||
Block* AppendBlock();
|
||||
void EndBlock();
|
||||
bool IsUnconditionalJump(Instr* instr);
|
||||
Instr* AppendInstr(const OpcodeInfo& opcode, uint16_t flags,
|
||||
Value* dest = 0);
|
||||
Value* CompareXX(const OpcodeInfo& opcode, Value* value1, Value* value2);
|
||||
|
|
Loading…
Reference in New Issue