Skip to content
This repository has been archived by the owner on Jun 28, 2022. It is now read-only.

Commit

Permalink
Major changes. Working on issue #84, issue #80, issue #71, issue #65,…
Browse files Browse the repository at this point in the history
… issue #63, issue #20.
  • Loading branch information
pgoodman committed Dec 25, 2014
1 parent 8ec4295 commit 89ed6fd
Show file tree
Hide file tree
Showing 95 changed files with 1,185 additions and 2,416 deletions.
16 changes: 7 additions & 9 deletions .gdbinit
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,8 @@ define print-meta-entry
set language c++
set $__i = granary_meta_log_index + GRANARY_META_LOG_LENGTH - $arg0
set $__i = ($__i - 1) % GRANARY_META_LOG_LENGTH
set $__m = (granary::BlockMetaData *) granary_meta_log[$__i].meta
set $__g = (unsigned long) granary_meta_log[$__i].group
printf "Meta-data %p in group %lu:\n", $__m, $__g
set $__m = (granary::BlockMetaData *) granary_meta_log[$__i]
printf "Meta-data %p:\n", $__m
print-block-meta $__m
dont-repeat
end
Expand All @@ -346,7 +345,7 @@ define save-meta-pcs
set logging redirect on
set $__i = 0
while $__i < GRANARY_META_LOG_LENGTH && $__i < granary_meta_log_index
set $__m = (unsigned long *) granary_meta_log[$__i].meta
set $__m = (unsigned long *) granary_meta_log[$__i]
if $__m[1]
x/i $__m[1]
end
Expand Down Expand Up @@ -395,12 +394,11 @@ define find-meta-entry
set $__m = (granary::BlockMetaData *) 0

while $__i < GRANARY_META_LOG_LENGTH
set $__sm = (char *) granary_meta_log[$__i].meta
set $__sm = (char *) granary_meta_log[$__i]
if $__sm
set $__fpc_app = *((granary::AppPC *) &($__sm[8]))
set $__fpc_cache = *((granary::CachePC *) &($__sm[16]))
if $__fpc_app == $__pc || $__fpc_cache == $__pc
set $__g = granary_meta_log[$__i].group
set $__m = (granary::BlockMetaData *) $__sm
set $__i = GRANARY_META_LOG_LENGTH
end
Expand All @@ -409,7 +407,7 @@ define find-meta-entry
end

if $__m
printf "Meta-data %p in group %lu:\n", $__m, $__g
printf "Meta-data %p:\n", $__m
print-block-meta $__m
end
dont-repeat
Expand Down Expand Up @@ -837,11 +835,11 @@ end

# get-next-block
#
# Treat `$arg0` as a pointer to a `BasicBlock`, and update the variable `$__b`
# Treat `$arg0` as a pointer to a `Block`, and update the variable `$__b`
# to point to the next basic block in the list to which `$arg0` belongs.
define get-next-block
set language c++
set $__b = (granary::BasicBlock *) $arg0
set $__b = (granary::Block *) $arg0
if $__b
set $__b = $__b->list.next
end
Expand Down
4 changes: 2 additions & 2 deletions arch/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace granary {

// Forward declarations.
class DecodedBasicBlock;
class DecodedBlock;

namespace arch {

Expand All @@ -39,7 +39,7 @@ class InstructionDecoder {
// mangling might involve adding many new instructions to deal with some
// instruction set peculiarities, and sometimes we only want to speculatively
// decode and instruction and not add these extra instructions to a block.
void Mangle(DecodedBasicBlock *block, Instruction *instr);
void Mangle(DecodedBlock *block, Instruction *instr);

private:
// Internal APIs for decoding instructions. These APIs directly
Expand Down
2 changes: 1 addition & 1 deletion arch/encode.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace granary {

// Forward declarations.
class DecodedBasicBlock;
class DecodedBlock;

namespace arch {

Expand Down
20 changes: 10 additions & 10 deletions arch/x86-64/assemble/0_compile_inline_assembly.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

#include "granary/base/string.h"

#include "granary/cfg/basic_block.h"
#include "granary/cfg/control_flow_graph.h"
#include "granary/cfg/block.h"
#include "granary/cfg/trace.h"
#include "granary/cfg/instruction.h"

#include "granary/code/inline_assembly.h"
Expand Down Expand Up @@ -34,9 +34,9 @@ namespace {
// Granary's inline assembly instructions.
class InlineAssemblyParser {
public:
InlineAssemblyParser(LocalControlFlowGraph *cfg_,
InlineAssemblyParser(Trace *cfg_,
InlineAssemblyScope *scope_,
DecodedBasicBlock *block_,
DecodedBlock *block_,
Instruction *instr_,
const char *ch_)
: op(nullptr),
Expand Down Expand Up @@ -570,12 +570,12 @@ class InlineAssemblyParser {
new_instr = new BranchInstruction(
&data, DynamicCast<LabelInstruction *>(data.ops[0].annotation_instr));
} else if (data.IsFunctionCall()) {
auto bb = new NativeBasicBlock(
auto bb = new NativeBlock(
data.HasIndirectTarget() ? nullptr : data.BranchTargetPC());
cfg->AddBlock(bb);
new_instr = new ControlFlowInstruction(&data, bb);
} else if (data.IsFunctionReturn()) {
auto bb = new ReturnBasicBlock(cfg, nullptr /* no meta-data */);
auto bb = new ReturnBlock(cfg, nullptr /* no meta-data */);
cfg->AddBlock(bb);
new_instr = new ControlFlowInstruction(&data, bb);

Expand Down Expand Up @@ -656,14 +656,14 @@ class InlineAssemblyParser {
arch::Operand *op;

// The control-flow graph; used to materialize basic blocks.
LocalControlFlowGraph *cfg;
Trace *cfg;

// Scope from which local/input variables can be looked up.
InlineAssemblyScope * const scope;

// Basic block into which instructions are being placed. Used to allocate
// new virtual registers.
DecodedBasicBlock * const block;
DecodedBlock * const block;

// Instruction before which all assembly instructions will be placed.
Instruction * const instr;
Expand All @@ -684,8 +684,8 @@ namespace arch {
// `block`. This places the inlined instructions before `instr`, which is
// assumed to be the `AnnotationInstruction` containing the inline assembly
// instructions.
void CompileInlineAssemblyBlock(LocalControlFlowGraph *cfg,
DecodedBasicBlock *block,
void CompileInlineAssemblyBlock(Trace *cfg,
DecodedBlock *block,
granary::Instruction *instr,
InlineAssemblyBlock *asm_block) {
InlineAssemblyParser parser(cfg, asm_block->scope, block,
Expand Down
16 changes: 8 additions & 8 deletions arch/x86-64/assemble/1_mangle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#include "granary/base/base.h"
#include "granary/base/new.h"

#include "granary/cfg/basic_block.h"
#include "granary/cfg/block.h"
#include "granary/cfg/instruction.h"

#include "arch/x86-64/builder.h"
Expand Down Expand Up @@ -192,7 +192,7 @@ void RelativizeDirectCFI(CacheMetaData *meta, NativeInstruction *cfi,
}

// Mangle a tail-call by pushing a return address onto the stack.
void MangleTailCall(DecodedBasicBlock *block, ControlFlowInstruction *cfi) {
void MangleTailCall(DecodedBlock *block, ControlFlowInstruction *cfi) {
Instruction ni;
auto ret_addr_pc = cfi->DecodedPC() + cfi->DecodedLength();
auto ret_addr = reinterpret_cast<uintptr_t>(ret_addr_pc);
Expand All @@ -212,7 +212,7 @@ void MangleTailCall(DecodedBasicBlock *block, ControlFlowInstruction *cfi) {
}

// Mangle a specialized indirect return into an indirect jump.
void MangleIndirectReturn(DecodedBasicBlock *block,
void MangleIndirectReturn(DecodedBlock *block,
ControlFlowInstruction *cfi) {
auto target = block->AllocateVirtualRegister();
Instruction ni;
Expand All @@ -235,7 +235,7 @@ void MangleIndirectReturn(DecodedBasicBlock *block,
}

// Mangle an indirect function call.
static void MangleIndirectCall(DecodedBasicBlock *block,
static void MangleIndirectCall(DecodedBlock *block,
ControlFlowInstruction *cfi,
AnnotationInstruction *ret_address) {
Instruction ni;
Expand All @@ -258,11 +258,11 @@ static void MangleIndirectCall(DecodedBasicBlock *block,

// Performs mangling of an indirect CFI instruction. This ensures that the
// target of any specialized indirect CFI instruction is stored in a register.
void MangleIndirectCFI(DecodedBasicBlock *block, ControlFlowInstruction *cfi,
void MangleIndirectCFI(DecodedBlock *block, ControlFlowInstruction *cfi,
AnnotationInstruction *ret_address) {
if (cfi->IsFunctionReturn()) {
auto target_block = cfi->TargetBlock();
if (auto return_block = DynamicCast<ReturnBasicBlock *>(target_block)) {
if (auto return_block = DynamicCast<ReturnBlock *>(target_block)) {
if (return_block->UsesMetaData()) MangleIndirectReturn(block, cfi);
}
return;
Expand Down Expand Up @@ -302,7 +302,7 @@ void MangleIndirectCFI(DecodedBasicBlock *block, ControlFlowInstruction *cfi,
// Performs mangling of an direct CFI instruction.
//
// Note: This has an architecture-specific implementation.
void MangleDirectCFI(DecodedBasicBlock *, ControlFlowInstruction *cfi,
void MangleDirectCFI(DecodedBlock *, ControlFlowInstruction *cfi,
AppPC target_pc) {
auto &instr(cfi->instruction);
if (IsLoopInstruction(instr.iclass)) {
Expand All @@ -317,7 +317,7 @@ bool AddressNeedsRelativizing(const void *ptr) {

// Relativize a instruction with a memory operand, where the operand loads some
// value from `mem_addr`
void RelativizeMemOp(DecodedBasicBlock *block, NativeInstruction *ninstr,
void RelativizeMemOp(DecodedBlock *block, NativeInstruction *ninstr,
const MemoryOperand &mloc, const void *mem_addr) {
auto &ainstr(ninstr->instruction);
auto op = mloc.UnsafeExtract();
Expand Down
62 changes: 28 additions & 34 deletions arch/x86-64/assemble/6_track_ssa_vars.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,37 +17,37 @@ namespace {

// Look for the pattern `XOR A, A`.
static void UpdateIfClearedByXor(const Operand *arch_ops,
SSAOperandPack &ssa_ops) {
SSAInstruction *instr) {
if (arch_ops[0].reg != arch_ops[1].reg) {
ssa_ops[0].action = SSAOperandAction::kSSAOperandActionReadWrite;
ssa_ops[1].action = SSAOperandAction::kSSAOperandActionRead;
instr->ops[0].action = SSAOperandAction::kSSAOperandActionReadWrite;
instr->ops[1].action = SSAOperandAction::kSSAOperandActionRead;
} else {
ssa_ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
ssa_ops[1].action = SSAOperandAction::kSSAOperandActionCleared;
instr->ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
instr->ops[1].action = SSAOperandAction::kSSAOperandActionCleared;
}
}

// Look for the pattern `SUB A, A`.
static void UpdateIfClearedBySub(const Operand *arch_ops,
SSAOperandPack &ssa_ops) {
SSAInstruction *instr) {
if (arch_ops[0].reg == arch_ops[1].reg) {
ssa_ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
ssa_ops[1].action = SSAOperandAction::kSSAOperandActionCleared;
instr->ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
instr->ops[1].action = SSAOperandAction::kSSAOperandActionCleared;
}
}

// Look for the pattern `AND A, 0`.
static void UpdateIfClearedByAnd(const Operand *arch_ops,
SSAOperandPack &ssa_ops) {
SSAInstruction *instr) {
if (0 == arch_ops[1].imm.as_uint &&
!arch_ops[0].reg.PreservesBytesOnWrite()) {
ssa_ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
instr->ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
}
}

// Look for things like `MOV R, R` and either elide them, or modify the
// source register appropriately.
static void UpdateRegCopy(Instruction *ni, SSAOperandPack &ssa_ops) {
static void UpdateRegCopy(Instruction *ni, SSAInstruction *instr) {
auto dst_reg = ni->ops[0].reg;
auto src_reg = ni->ops[1].reg;

Expand All @@ -62,13 +62,10 @@ static void UpdateRegCopy(Instruction *ni, SSAOperandPack &ssa_ops) {
// MOV A, B <dont_encode>
if (dst_reg != src_reg) return;

auto &ssa_op0(ssa_ops[0]);
auto &ssa_op1(ssa_ops[1]);
auto &ssa_op0(instr->ops[0]);
auto &ssa_op1(instr->ops[1]);
ssa_op0.action = SSAOperandAction::kSSAOperandActionReadWrite;
if (kSSAOperandStateNode == ssa_op0.state) {
GRANARY_ASSERT(ssa_op0.node->reg == ssa_op1.node->reg);
ssa_op0.node->id.Union(ssa_op1.node->id);
}
ssa_op0.reg_web.Union(ssa_op1.reg_web);

if (dst_reg.BitWidth() != src_reg.BitWidth() ||
dst_reg.ByteWidth() != dst_reg.EffectiveWriteWidth()) {
Expand All @@ -81,7 +78,7 @@ static void UpdateRegCopy(Instruction *ni, SSAOperandPack &ssa_ops) {

// Look for the pattern `LEA R, [R]` and make sure that the destination operand
// is treated as a READ_WRITE.
static void UpdateEffectiveAddress(Instruction *ni, SSAOperandPack &ssa_ops) {
static void UpdateEffectiveAddress(Instruction *ni, SSAInstruction *instr) {
GRANARY_ASSERT(2 == ni->num_explicit_ops);
if (ni->ops[1].is_compound) return;
if (ni->ops[1].IsPointer()) return;
Expand All @@ -96,23 +93,19 @@ static void UpdateEffectiveAddress(Instruction *ni, SSAOperandPack &ssa_ops) {
// remain as an LEA so that it is an effective address.
if (!src_reg.IsStackPointer()) {
MOV_GPRv_GPRv_89(ni, dst_reg, src_reg);
ssa_ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
ssa_ops[1].action = SSAOperandAction::kSSAOperandActionRead;
instr->ops[0].action = SSAOperandAction::kSSAOperandActionWrite;
instr->ops[1].action = SSAOperandAction::kSSAOperandActionRead;
}

// `LEA R, [R]`.
} else {
auto &ssa_op0(ssa_ops[0]);
auto &ssa_op1(ssa_ops[1]);
auto &ssa_op0(instr->ops[0]);
auto &ssa_op1(instr->ops[1]);
MOV_GPRv_GPRv_89(ni, dst_reg, dst_reg);
ni->DontEncode(); // This instruction is useless.
ssa_op0.action = SSAOperandAction::kSSAOperandActionReadWrite;
ssa_op1.action = SSAOperandAction::kSSAOperandActionRead;

if (kSSAOperandStateNode == ssa_op0.state) {
GRANARY_ASSERT(ssa_op0.node->reg == ssa_op1.node->reg);
ssa_op0.node->id.Union(ssa_op1.node->id);
}
ssa_op0.reg_web.Union(ssa_op1.reg_web);
}
}

Expand All @@ -121,32 +114,33 @@ static void UpdateEffectiveAddress(Instruction *ni, SSAOperandPack &ssa_ops) {
// Performs architecture-specific conversion of `SSAOperand` actions. The things
// we want to handle here are instructions like `XOR A, A`, that can be seen as
// clearing the value of `A` and not reading it for the sake of reading it.
void ConvertOperandActions(NativeInstruction *instr,
SSAOperandPack &operands) {
void ConvertOperandActions(NativeInstruction *instr) {
auto &ainstr(instr->instruction);
auto ssa_instr = instr->ssa;

switch (ainstr.iform) {
case XED_IFORM_XOR_GPR8_GPR8_30:
case XED_IFORM_XOR_GPR8_GPR8_32:
case XED_IFORM_XOR_GPRv_GPRv_31:
case XED_IFORM_XOR_GPRv_GPRv_33:
UpdateIfClearedByXor(ainstr.ops, operands); return;
UpdateIfClearedByXor(ainstr.ops, ssa_instr); return;
case XED_IFORM_SUB_GPR8_GPR8_28:
case XED_IFORM_SUB_GPR8_GPR8_2A:
case XED_IFORM_SUB_GPRv_GPRv_29:
case XED_IFORM_SUB_GPRv_GPRv_2B:
UpdateIfClearedBySub(ainstr.ops, operands); return;
UpdateIfClearedBySub(ainstr.ops, ssa_instr); return;
case XED_IFORM_AND_GPR8_IMMb_80r4:
case XED_IFORM_AND_GPR8_IMMb_82r4:
case XED_IFORM_AND_GPRv_IMMb:
case XED_IFORM_AND_GPRv_IMMz:
UpdateIfClearedByAnd(ainstr.ops, operands); return;
UpdateIfClearedByAnd(ainstr.ops, ssa_instr); return;
case XED_IFORM_MOV_GPR8_GPR8_88:
case XED_IFORM_MOV_GPR8_GPR8_8A:
case XED_IFORM_MOV_GPRv_GPRv_89:
case XED_IFORM_MOV_GPRv_GPRv_8B:
UpdateRegCopy(&ainstr, operands); return;
UpdateRegCopy(&ainstr, ssa_instr); return;
case XED_IFORM_LEA_GPRv_AGEN:
UpdateEffectiveAddress(&ainstr, operands); return;
UpdateEffectiveAddress(&ainstr, ssa_instr); return;
default: return;
}
}
Expand Down
12 changes: 7 additions & 5 deletions arch/x86-64/assemble/7_propagate_copies.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,15 @@ bool GetCopiedOperand(const NativeInstruction *instr,
// have the wrong value!
if (dst.reg.EffectiveWriteWidth() != dst.reg.ByteWidth()) return nullptr;

*def = &(ssa_instr->operands[0]);
*use0 = &(ssa_instr->operands[1]);
if (3 == ssa_instr->operands.Size()) {
GRANARY_ASSERT(2 == ssa_instr->num_ops);

*def = &(ssa_instr->ops[0]);
*use0 = &(ssa_instr->ops[1]);
if (3 == ssa_instr->num_ops) {
GRANARY_ASSERT(XED_IFORM_LEA_GPRv_AGEN == ainstr.iform);
*use1 = &(ssa_instr->operands[2]);
*use1 = &(ssa_instr->ops[2]);
} else {
GRANARY_ASSERT(2 == ssa_instr->operands.Size());

}
return true;
}
Expand Down
Loading

0 comments on commit 89ed6fd

Please sign in to comment.