diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..4fbc0043 --- /dev/null +++ b/.clang-format @@ -0,0 +1,3 @@ +--- +BasedOnStyle: LLVM +IndentWidth: 4 diff --git a/ffi/assembly.cpp b/ffi/assembly.cpp index 4ab705c6..b193d692 100644 --- a/ffi/assembly.cpp +++ b/ffi/assembly.cpp @@ -15,21 +15,21 @@ extern "C" { API_EXPORT(LLVMModuleRef) LLVMPY_ParseAssembly(LLVMContextRef context, const char *ir, const char **outmsg) { - using namespace llvm; + using namespace llvm; - SMDiagnostic error; + SMDiagnostic error; - Module *m = parseAssemblyString(ir, error, *unwrap(context)).release(); - if (!m) { - // Error occurred - std::string osbuf; - raw_string_ostream os(osbuf); - error.print("", os); - os.flush(); - *outmsg = LLVMPY_CreateString(os.str().c_str()); - return NULL; - } - return wrap(m); + Module *m = parseAssemblyString(ir, error, *unwrap(context)).release(); + if (!m) { + // Error occurred + std::string osbuf; + raw_string_ostream os(osbuf); + error.print("", os); + os.flush(); + *outmsg = LLVMPY_CreateString(os.str().c_str()); + return NULL; + } + return wrap(m); } } // end extern "C" diff --git a/ffi/bitcode.cpp b/ffi/bitcode.cpp index 4b707ae1..55e2f2a0 100644 --- a/ffi/bitcode.cpp +++ b/ffi/bitcode.cpp @@ -8,23 +8,23 @@ extern "C" { API_EXPORT(void) LLVMPY_WriteBitcodeToString(LLVMModuleRef M, const char **outbuf, size_t *outlen) { - LLVMMemoryBufferRef MB = LLVMWriteBitcodeToMemoryBuffer(M); - *outlen = LLVMGetBufferSize(MB); - *outbuf = LLVMPY_CreateByteString(LLVMGetBufferStart(MB), *outlen); - LLVMDisposeMemoryBuffer(MB); + LLVMMemoryBufferRef MB = LLVMWriteBitcodeToMemoryBuffer(M); + *outlen = LLVMGetBufferSize(MB); + *outbuf = LLVMPY_CreateByteString(LLVMGetBufferStart(MB), *outlen); + LLVMDisposeMemoryBuffer(MB); } API_EXPORT(LLVMModuleRef) LLVMPY_ParseBitcode(LLVMContextRef context, const char *bitcode, size_t bitcodelen, char **outmsg) { - LLVMModuleRef ref; - LLVMMemoryBufferRef mem = LLVMCreateMemoryBufferWithMemoryRange( - bitcode, bitcodelen, "" /* BufferName*/, 0 /* RequiresNullTerminator*/ - ); + LLVMModuleRef ref; + LLVMMemoryBufferRef mem = LLVMCreateMemoryBufferWithMemoryRange( + bitcode, bitcodelen, "" /* BufferName*/, 0 /* RequiresNullTerminator*/ + ); - LLVMParseBitcodeInContext(context, mem, &ref, outmsg); - LLVMDisposeMemoryBuffer(mem); - return ref; + LLVMParseBitcodeInContext(context, mem, &ref, outmsg); + LLVMDisposeMemoryBuffer(mem); + return ref; } } // end extern "C" diff --git a/ffi/core.cpp b/ffi/core.cpp index f8df5c71..4afc7f7f 100644 --- a/ffi/core.cpp +++ b/ffi/core.cpp @@ -9,12 +9,12 @@ LLVMPY_CreateString(const char *msg) { return strdup(msg); } API_EXPORT(const char *) LLVMPY_CreateByteString(const char *buf, size_t len) { - char *dest = (char *)malloc(len + 1); - if (dest != NULL) { - memcpy(dest, buf, len); - dest[len] = '\0'; - } - return dest; + char *dest = (char *)malloc(len + 1); + if (dest != NULL) { + memcpy(dest, buf, len); + dest[len] = '\0'; + } + return dest; } API_EXPORT(void) @@ -28,13 +28,13 @@ LLVMPY_ContextCreate() { return LLVMContextCreate(); } API_EXPORT(void) LLVMPY_ContextDispose(LLVMContextRef context) { - return LLVMContextDispose(context); + return LLVMContextDispose(context); } API_EXPORT(void) LLVMPY_SetCommandLine(const char *name, const char *option) { - const char *argv[] = {name, option}; - LLVMParseCommandLineOptions(2, argv, NULL); + const char *argv[] = {name, option}; + LLVMParseCommandLineOptions(2, argv, NULL); } } // end extern "C" diff --git a/ffi/custom_passes.cpp b/ffi/custom_passes.cpp index 483dc9a2..21e0bbcf 100644 --- a/ffi/custom_passes.cpp +++ b/ffi/custom_passes.cpp @@ -40,8 +40,8 @@ void initializeRefPrunePassPass(PassRegistry &Registry); * - true if call_inst is an incref, false otherwise */ bool IsIncRef(CallInst *call_inst) { - Value *callee = call_inst->getCalledOperand(); - return callee->getName() == "NRT_incref"; + Value *callee = call_inst->getCalledOperand(); + return callee->getName() == "NRT_incref"; } /** @@ -54,8 +54,8 @@ bool IsIncRef(CallInst *call_inst) { * - true if call_inst is an decref, false otherwise */ bool IsDecRef(CallInst *call_inst) { - Value *callee = call_inst->getCalledOperand(); - return callee->getName() == "NRT_decref"; + Value *callee = call_inst->getCalledOperand(); + return callee->getName() == "NRT_decref"; } /** @@ -68,13 +68,13 @@ bool IsDecRef(CallInst *call_inst) { * - the instruction ii, if it is a "refop", NULL otherwise */ CallInst *GetRefOpCall(Instruction *ii) { - if (ii->getOpcode() == Instruction::Call) { - CallInst *call_inst = dyn_cast(ii); - if (IsIncRef(call_inst) || IsDecRef(call_inst)) { - return call_inst; + if (ii->getOpcode() == Instruction::Call) { + CallInst *call_inst = dyn_cast(ii); + if (IsIncRef(call_inst) || IsDecRef(call_inst)) { + return call_inst; + } } - } - return NULL; + return NULL; } /** @@ -84,20 +84,20 @@ CallInst *GetRefOpCall(Instruction *ii) { * - the type of the stack */ template struct raiiStack { - Tstack &stack; + Tstack &stack; - typedef typename Tstack::value_type value_type; + typedef typename Tstack::value_type value_type; - /** - * ctor pushes `elem` onto `stack` - */ - raiiStack(Tstack &stack, value_type &elem) : stack(stack) { - stack.push_back(elem); - } - /** - * dtor pops back of `stack` - */ - ~raiiStack() { stack.pop_back(); } + /** + * ctor pushes `elem` onto `stack` + */ + raiiStack(Tstack &stack, value_type &elem) : stack(stack) { + stack.push_back(elem); + } + /** + * dtor pops back of `stack` + */ + ~raiiStack() { stack.pop_back(); } }; /** @@ -105,1037 +105,1046 @@ template struct raiiStack { * logically after increfs. This is a pre-requisite pass to the pruner passes. */ struct RefNormalizePass : public FunctionPass { - static char ID; - RefNormalizePass() : FunctionPass(ID) { - initializeRefNormalizePassPass(*PassRegistry::getPassRegistry()); - } - - bool runOnFunction(Function &F) override { - bool mutated = false; - // For each basic block in F - for (BasicBlock &bb : F) { - // This find a incref in the basic block - - bool has_incref = false; - // check the instructions in the basic block - for (Instruction &ii : bb) { - // see if it is a refop - CallInst *refop = GetRefOpCall(&ii); - // if it is a refop and it is an incref, set flag and break - if (refop != NULL && IsIncRef(refop)) { - has_incref = true; - break; - } - } - - // block has an incref - if (has_incref) { - // This moves decrefs to the back just before the terminator. - - SmallVector to_be_moved; - // walk the instructions in the block - for (Instruction &ii : bb) { - // query the instruction, if its a refop store to refop - // if not store NULL to refop - CallInst *refop = GetRefOpCall(&ii); - // if the refop is not NULL and it is also a decref then - // shove it into the to_be_moved vector - if (refop != NULL && IsDecRef(refop)) { - to_be_moved.push_back(refop); - } - } - // Walk the to_be_moved vector of instructions, these are all - // decrefs by construction. - for (CallInst *decref : to_be_moved) { - // move the decref to a location prior to the block - // terminator and set mutated. - decref->moveBefore(bb.getTerminator()); - mutated |= true; - } - } + static char ID; + RefNormalizePass() : FunctionPass(ID) { + initializeRefNormalizePassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &F) override { + bool mutated = false; + // For each basic block in F + for (BasicBlock &bb : F) { + // This find a incref in the basic block + + bool has_incref = false; + // check the instructions in the basic block + for (Instruction &ii : bb) { + // see if it is a refop + CallInst *refop = GetRefOpCall(&ii); + // if it is a refop and it is an incref, set flag and break + if (refop != NULL && IsIncRef(refop)) { + has_incref = true; + break; + } + } + + // block has an incref + if (has_incref) { + // This moves decrefs to the back just before the terminator. + + SmallVector to_be_moved; + // walk the instructions in the block + for (Instruction &ii : bb) { + // query the instruction, if its a refop store to refop + // if not store NULL to refop + CallInst *refop = GetRefOpCall(&ii); + // if the refop is not NULL and it is also a decref then + // shove it into the to_be_moved vector + if (refop != NULL && IsDecRef(refop)) { + to_be_moved.push_back(refop); + } + } + // Walk the to_be_moved vector of instructions, these are all + // decrefs by construction. + for (CallInst *decref : to_be_moved) { + // move the decref to a location prior to the block + // terminator and set mutated. + decref->moveBefore(bb.getTerminator()); + mutated |= true; + } + } + } + return mutated; } - return mutated; - } }; struct RefPrunePass : public FunctionPass { - static char ID; - static size_t stats_per_bb; - static size_t stats_diamond; - static size_t stats_fanout; - static size_t stats_fanout_raise; + static char ID; + static size_t stats_per_bb; + static size_t stats_diamond; + static size_t stats_fanout; + static size_t stats_fanout_raise; - // Fixed size for how deep to recurse in the fanout case prior to giving up. - static const size_t FANOUT_RECURSE_DEPTH = 15; - typedef SmallSet SmallBBSet; + // Fixed size for how deep to recurse in the fanout case prior to giving up. + static const size_t FANOUT_RECURSE_DEPTH = 15; + typedef SmallSet SmallBBSet; - // The maximum number of nodes that the fanout pruners will look at. - size_t subgraph_limit; + // The maximum number of nodes that the fanout pruners will look at. + size_t subgraph_limit; - /** - * Enum for setting which subpasses to run, there is no interdependence. - */ - enum Subpasses { - None = 0b0000, - PerBasicBlock = 0b0001, - Diamond = 0b0010, - Fanout = 0b0100, - FanoutRaise = 0b1000, - All = PerBasicBlock | Diamond | Fanout | FanoutRaise - } flags; + /** + * Enum for setting which subpasses to run, there is no interdependence. + */ + enum Subpasses { + None = 0b0000, + PerBasicBlock = 0b0001, + Diamond = 0b0010, + Fanout = 0b0100, + FanoutRaise = 0b1000, + All = PerBasicBlock | Diamond | Fanout | FanoutRaise + } flags; - RefPrunePass(Subpasses flags = Subpasses::All, size_t subgraph_limit = -1) - : FunctionPass(ID), flags(flags), subgraph_limit(subgraph_limit) { - initializeRefPrunePassPass(*PassRegistry::getPassRegistry()); - } - - bool isSubpassEnabledFor(Subpasses expected) { - return (flags & expected) == expected; - } - - bool runOnFunction(Function &F) override { - // state for LLVM function pass mutated IR - bool mutated = false; - - // local state for capturing mutation by any selected pass, any mutation - // at all propagates into mutated for return. - bool local_mutated; - do { - local_mutated = false; - if (isSubpassEnabledFor(Subpasses::PerBasicBlock)) - local_mutated |= runPerBasicBlockPrune(F); - if (isSubpassEnabledFor(Subpasses::Diamond)) - local_mutated |= runDiamondPrune(F); - if (isSubpassEnabledFor(Subpasses::Fanout)) - local_mutated |= runFanoutPrune(F, /*prune_raise*/ false); - if (isSubpassEnabledFor(Subpasses::FanoutRaise)) - local_mutated |= runFanoutPrune(F, /*prune_raise*/ true); - mutated |= local_mutated; - } while (local_mutated); - - return mutated; - } - - /** - * Per BasicBlock pruning pass. - * - * Assumes all increfs are before all decrefs. - * Cleans up all refcount operations on NULL pointers. - * Cleans up all redundant incref/decref pairs. - * - * This pass works on a block at a time and does not change the CFG. - * Incref/Decref removal is restricted to the basic block. - * - * General idea is to be able to prune within a block as follows: - * - * ┌─────────────┐ - * │ Block entry │ - * | Instruction │ - * | Incref(A) │ ──> No match, cannot remove. - * | Incref(B) │ ──┐ - * | Instruction │ │ Matching pair, can be removed. - * | Instruction │ │ - * | Decref(B) │ <─┘ - * | Instruction │ - * | Decref(NULL)│ ──> Decref on NULL, can be removed. - * | Terminator │ - * └─────────────┘ - * Parameters: - * - F a Function - * - * Returns: - * - true if pruning took place, false otherwise - * - */ - bool runPerBasicBlockPrune(Function &F) { - bool mutated = false; - - // walk the basic blocks in Function F. - for (BasicBlock &bb : F) { - // allocate some buffers - SmallVector incref_list, decref_list, null_list; - - // This is a scanning phase looking to classify instructions into - // inrefs, decrefs and operations on already NULL pointers. - // walk the instructions in the current basic block - for (Instruction &ii : bb) { - // If the instruction is a refop - CallInst *ci; - if ((ci = GetRefOpCall(&ii))) { - if (!isNonNullFirstArg(ci)) { - // Drop refops on NULL pointers - null_list.push_back(ci); - } else if (IsIncRef(ci)) { - incref_list.push_back(ci); - } else if (IsDecRef(ci)) { - decref_list.push_back(ci); - } - } - } - - // First: Remove refops on NULL - for (CallInst *ci : null_list) { - ci->eraseFromParent(); - mutated = true; - - // Do we care about differentiating between prunes of NULL - // and prunes of pairs? - stats_per_bb += 1; - } - - // Second: Find matching pairs of incref decref - while (incref_list.size() > 0) { - // get an incref - CallInst *incref = incref_list.pop_back_val(); - // walk decrefs - for (size_t i = 0; i < decref_list.size(); ++i) { - CallInst *decref = decref_list[i]; - // is this instruction a decref thats non-NULL and - // the decref related to the incref? - if (decref && isRelatedDecref(incref, decref)) { - if (DEBUG_PRINT) { - errs() << "Prune: matching pair in BB:\n"; - incref->dump(); - decref->dump(); - incref->getParent()->dump(); - } - // strip incref and decref from blck - incref->eraseFromParent(); - decref->eraseFromParent(); - - // set stripped decref to null - decref_list[i] = NULL; - // set mutated bit and update prune stats - mutated = true; - stats_per_bb += 2; - break; - } - } - } + RefPrunePass(Subpasses flags = Subpasses::All, size_t subgraph_limit = -1) + : FunctionPass(ID), flags(flags), subgraph_limit(subgraph_limit) { + initializeRefPrunePassPass(*PassRegistry::getPassRegistry()); } - return mutated; - } - /** - * "Diamond" pruning pass. - * - * Looks to prune across basic blocks in cases where incref/decref pairs - * appear in a "diamond" shape CFG structure. For example: - * - * ┌────────────┐ - * │ incref (A) │ - * └────────────┘ - * / \ - * / \ - * / \ - * . . - * . . - * ┌────────────┐ ┌────────────┐ - * │ MORE CFG │ │ MORE CFG │ - * └────────────┘ └────────────┘ - * . . - * . . - * \ / - * \ / - * \ / - * \ / - * ┌────────────┐ - * │ decref (A) │ - * └────────────┘ - * - * Condition for prune is that, in an incref/decref pair: - * - the incref dominates the decref. - * - the decref postdominates the incref. - * - in the blocks in the CFG between the basic blocks containing the - * incref/decref pair there's no other decref present (this is - * conservative and is to handle aliasing of references). - * - that the decref is not in a cycle dominated by the incref (i.e. decref - * in a loop). - * - * Parameters: - * - F a Function - * - * Returns: - * - true if pruning took place, false otherwise - * - */ - bool runDiamondPrune(Function &F) { - bool mutated = false; - // gets the dominator tree - auto &domtree = getAnalysis().getDomTree(); - // gets the post-dominator tree - auto &postdomtree = - getAnalysis().getPostDomTree(); - - // Find all increfs and decrefs in the Function and store them in - // incref_list and decref_list respectively. - std::vector incref_list, decref_list; - listRefOps(F, IsIncRef, incref_list); - listRefOps(F, IsDecRef, decref_list); - - // Walk the incref list - for (CallInst *&incref : incref_list) { - // NULL is the token for already erased, skip on it - if (incref == NULL) - continue; - - // Walk the decref_list - for (CallInst *&decref : decref_list) { - // NULL is the token for already erased, skip on it - if (decref == NULL) - continue; - - // Diamond prune is for refops not in the same BB - if (incref->getParent() == decref->getParent()) - continue; - - // If the refops are unrelated, skip - if (!isRelatedDecref(incref, decref)) - continue; - - // incref DOM decref && decref POSTDOM incref - if (domtree.dominates(incref, decref) && - postdomtree.dominates(decref, incref)) { - // check that the decref cannot be executed multiple times - SmallBBSet tail_nodes; - tail_nodes.insert(decref->getParent()); - if (!verifyFanoutBackward(incref, incref->getParent(), &tail_nodes)) - continue; - - // scan the CFG between the incref and decref BBs, if there's a decref - // present then skip, this is conservative. - if (hasDecrefBetweenGraph(incref->getParent(), decref->getParent())) { - continue; - } else { - - if (DEBUG_PRINT) { - errs() << F.getName() << "-------------\n"; - errs() << incref->getParent()->getName() << "\n"; - incref->dump(); - errs() << decref->getParent()->getName() << "\n"; - decref->dump(); - } - - // erase instruction from block and set NULL marker for - // bookkeeping purposes - incref->eraseFromParent(); - decref->eraseFromParent(); - incref = NULL; - decref = NULL; - - stats_diamond += 2; - } - // mark mutated - mutated = true; - break; - } - } + bool isSubpassEnabledFor(Subpasses expected) { + return (flags & expected) == expected; } - return mutated; - } - /** - * "Fan-out" pruning passes. - * - * Prunes "fan-out"s, this is where control flow from a block containing an - * incref "fans out" into blocks that contain corresponding decrefs. - * - * There are two supported fan-out shape CFG structures. - * - * Supported case 1, simple "fan-out" with no raise, prune occurs when the - * incref dominates the predecessor blocks containing associated decrefs. - * - * ┌────────────┐ - * │ incref (A) │ - * └────────────┘ - * / \ - * / \ - * / \ - * . . - * . . - * ┌────────────┐ ┌────────────┐ - * │ MORE CFG │ │ MORE CFG │ - * └────────────┘ └────────────┘ - * . . - * . . - * ┌────────────┐ ┌────────────┐ - * │ decref (A) │ │ decref (A) │ - * └────────────┘ └────────────┘ - * . . - * . . - * . . - * - * - * Supported case 2, simple "fan-out" with raise, prune occurs when the - * incref dominates the predecessor blocks containing associated decrefs - * with the exception of the raise block (this is to "forgive" the - * occasional missing decref in a raise block). - * - * ┌────────────┐ - * │ incref (A) │ - * └────────────┘ - * / \ - * / \ - * / \ - * . . - * . . - * ┌────────────┐ ┌────────────┐ - * │ MORE CFG │ │ MORE CFG │ - * └────────────┘ └────────────┘ - * . . - * . . - * ┌────────────┐ ┌────────────┐ - * │ decref (A) │ │ raise │ - * └────────────┘ └────────────┘ - * . - * . - * ┌────────────┐ - * │ MORE CFG │ - * └────────────┘ - * - * Parameters: - * - F a Function - * - prune_raise_exit, if false case 1 is considered, if true case 2 is - * considered. - * - * Returns: - * - true if pruning took place, false otherwise - */ - bool runFanoutPrune(Function &F, bool prune_raise_exit) { - bool mutated = false; + bool runOnFunction(Function &F) override { + // state for LLVM function pass mutated IR + bool mutated = false; - // Find all Increfs and store them in incref_list - std::vector incref_list; - listRefOps(F, IsIncRef, incref_list); + // local state for capturing mutation by any selected pass, any mutation + // at all propagates into mutated for return. + bool local_mutated; + do { + local_mutated = false; + if (isSubpassEnabledFor(Subpasses::PerBasicBlock)) + local_mutated |= runPerBasicBlockPrune(F); + if (isSubpassEnabledFor(Subpasses::Diamond)) + local_mutated |= runDiamondPrune(F); + if (isSubpassEnabledFor(Subpasses::Fanout)) + local_mutated |= runFanoutPrune(F, /*prune_raise*/ false); + if (isSubpassEnabledFor(Subpasses::FanoutRaise)) + local_mutated |= runFanoutPrune(F, /*prune_raise*/ true); + mutated |= local_mutated; + } while (local_mutated); - // Remember incref-blocks that will always fail. - SmallBBSet bad_blocks; - // walk the incref_list - for (CallInst *incref : incref_list) { - // Skip blocks that will always fail. - if (bad_blocks.count(incref->getParent())) { - continue; // skip - } + return mutated; + } - // Is there *any* decref in the parent node of the incref? - // If so skip this incref (considering that aliases may exist). - if (hasAnyDecrefInNode(incref->getParent())) { - // be careful of potential alias - continue; // skip - } + /** + * Per BasicBlock pruning pass. + * + * Assumes all increfs are before all decrefs. + * Cleans up all refcount operations on NULL pointers. + * Cleans up all redundant incref/decref pairs. + * + * This pass works on a block at a time and does not change the CFG. + * Incref/Decref removal is restricted to the basic block. + * + * General idea is to be able to prune within a block as follows: + * + * ┌─────────────┐ + * │ Block entry │ + * | Instruction │ + * | Incref(A) │ ──> No match, cannot remove. + * | Incref(B) │ ──┐ + * | Instruction │ │ Matching pair, can be removed. + * | Instruction │ │ + * | Decref(B) │ <─┘ + * | Instruction │ + * | Decref(NULL)│ ──> Decref on NULL, can be removed. + * | Terminator │ + * └─────────────┘ + * Parameters: + * - F a Function + * + * Returns: + * - true if pruning took place, false otherwise + * + */ + bool runPerBasicBlockPrune(Function &F) { + bool mutated = false; - SmallBBSet decref_blocks; - // Check for the chosen "fan out" condition - if (findFanout(incref, bad_blocks, &decref_blocks, prune_raise_exit)) { - if (DEBUG_PRINT) { - F.viewCFG(); - errs() << "------------\n"; - errs() << "incref " << incref->getParent()->getName() << "\n"; - errs() << " decref_blocks.size()" << decref_blocks.size() << "\n"; - incref->dump(); - } - // Remove first related decref in each block - // for each block - for (BasicBlock *each : decref_blocks) { - // for each instruction - for (Instruction &ii : *each) { - CallInst *decref; - // walrus: - // is the current instruction the decref associated with - // the incref under consideration, if so assign to - // decref and continue. - if ((decref = isRelatedDecref(incref, &ii))) { - if (DEBUG_PRINT) { - errs() << decref->getParent()->getName() << "\n"; - decref->dump(); - } - // Remove this decref from its block - decref->eraseFromParent(); + // walk the basic blocks in Function F. + for (BasicBlock &bb : F) { + // allocate some buffers + SmallVector incref_list, decref_list, null_list; - // update counters based on decref removal - if (prune_raise_exit) - stats_fanout_raise += 1; - else - stats_fanout += 1; - break; + // This is a scanning phase looking to classify instructions into + // inrefs, decrefs and operations on already NULL pointers. + // walk the instructions in the current basic block + for (Instruction &ii : bb) { + // If the instruction is a refop + CallInst *ci; + if ((ci = GetRefOpCall(&ii))) { + if (!isNonNullFirstArg(ci)) { + // Drop refops on NULL pointers + null_list.push_back(ci); + } else if (IsIncRef(ci)) { + incref_list.push_back(ci); + } else if (IsDecRef(ci)) { + decref_list.push_back(ci); + } + } } - } - } - // remove the incref from its block - incref->eraseFromParent(); - // update counters based on incref removal + // First: Remove refops on NULL + for (CallInst *ci : null_list) { + ci->eraseFromParent(); + mutated = true; + + // Do we care about differentiating between prunes of NULL + // and prunes of pairs? + stats_per_bb += 1; + } + + // Second: Find matching pairs of incref decref + while (incref_list.size() > 0) { + // get an incref + CallInst *incref = incref_list.pop_back_val(); + // walk decrefs + for (size_t i = 0; i < decref_list.size(); ++i) { + CallInst *decref = decref_list[i]; + // is this instruction a decref thats non-NULL and + // the decref related to the incref? + if (decref && isRelatedDecref(incref, decref)) { + if (DEBUG_PRINT) { + errs() << "Prune: matching pair in BB:\n"; + incref->dump(); + decref->dump(); + incref->getParent()->dump(); + } + // strip incref and decref from blck + incref->eraseFromParent(); + decref->eraseFromParent(); + + // set stripped decref to null + decref_list[i] = NULL; + // set mutated bit and update prune stats + mutated = true; + stats_per_bb += 2; + break; + } + } + } + } + return mutated; + } + + /** + * "Diamond" pruning pass. + * + * Looks to prune across basic blocks in cases where incref/decref pairs + * appear in a "diamond" shape CFG structure. For example: + * + * ┌────────────┐ + * │ incref (A) │ + * └────────────┘ + * / \ + * / \ + * / \ + * . . + * . . + * ┌────────────┐ ┌────────────┐ + * │ MORE CFG │ │ MORE CFG │ + * └────────────┘ └────────────┘ + * . . + * . . + * \ / + * \ / + * \ / + * \ / + * ┌────────────┐ + * │ decref (A) │ + * └────────────┘ + * + * Condition for prune is that, in an incref/decref pair: + * - the incref dominates the decref. + * - the decref postdominates the incref. + * - in the blocks in the CFG between the basic blocks containing the + * incref/decref pair there's no other decref present (this is + * conservative and is to handle aliasing of references). + * - that the decref is not in a cycle dominated by the incref (i.e. decref + * in a loop). + * + * Parameters: + * - F a Function + * + * Returns: + * - true if pruning took place, false otherwise + * + */ + bool runDiamondPrune(Function &F) { + bool mutated = false; + // gets the dominator tree + auto &domtree = getAnalysis().getDomTree(); + // gets the post-dominator tree + auto &postdomtree = + getAnalysis().getPostDomTree(); + + // Find all increfs and decrefs in the Function and store them in + // incref_list and decref_list respectively. + std::vector incref_list, decref_list; + listRefOps(F, IsIncRef, incref_list); + listRefOps(F, IsDecRef, decref_list); + + // Walk the incref list + for (CallInst *&incref : incref_list) { + // NULL is the token for already erased, skip on it + if (incref == NULL) + continue; + + // Walk the decref_list + for (CallInst *&decref : decref_list) { + // NULL is the token for already erased, skip on it + if (decref == NULL) + continue; + + // Diamond prune is for refops not in the same BB + if (incref->getParent() == decref->getParent()) + continue; + + // If the refops are unrelated, skip + if (!isRelatedDecref(incref, decref)) + continue; + + // incref DOM decref && decref POSTDOM incref + if (domtree.dominates(incref, decref) && + postdomtree.dominates(decref, incref)) { + // check that the decref cannot be executed multiple times + SmallBBSet tail_nodes; + tail_nodes.insert(decref->getParent()); + if (!verifyFanoutBackward(incref, incref->getParent(), + &tail_nodes)) + continue; + + // scan the CFG between the incref and decref BBs, if + // there's a decref present then skip, this is conservative. + if (hasDecrefBetweenGraph(incref->getParent(), + decref->getParent())) { + continue; + } else { + + if (DEBUG_PRINT) { + errs() << F.getName() << "-------------\n"; + errs() << incref->getParent()->getName() << "\n"; + incref->dump(); + errs() << decref->getParent()->getName() << "\n"; + decref->dump(); + } + + // erase instruction from block and set NULL marker for + // bookkeeping purposes + incref->eraseFromParent(); + decref->eraseFromParent(); + incref = NULL; + decref = NULL; + + stats_diamond += 2; + } + // mark mutated + mutated = true; + break; + } + } + } + return mutated; + } + + /** + * "Fan-out" pruning passes. + * + * Prunes "fan-out"s, this is where control flow from a block containing an + * incref "fans out" into blocks that contain corresponding decrefs. + * + * There are two supported fan-out shape CFG structures. + * + * Supported case 1, simple "fan-out" with no raise, prune occurs when the + * incref dominates the predecessor blocks containing associated decrefs. + * + * ┌────────────┐ + * │ incref (A) │ + * └────────────┘ + * / \ + * / \ + * / \ + * . . + * . . + * ┌────────────┐ ┌────────────┐ + * │ MORE CFG │ │ MORE CFG │ + * └────────────┘ └────────────┘ + * . . + * . . + * ┌────────────┐ ┌────────────┐ + * │ decref (A) │ │ decref (A) │ + * └────────────┘ └────────────┘ + * . . + * . . + * . . + * + * + * Supported case 2, simple "fan-out" with raise, prune occurs when the + * incref dominates the predecessor blocks containing associated decrefs + * with the exception of the raise block (this is to "forgive" the + * occasional missing decref in a raise block). + * + * ┌────────────┐ + * │ incref (A) │ + * └────────────┘ + * / \ + * / \ + * / \ + * . . + * . . + * ┌────────────┐ ┌────────────┐ + * │ MORE CFG │ │ MORE CFG │ + * └────────────┘ └────────────┘ + * . . + * . . + * ┌────────────┐ ┌────────────┐ + * │ decref (A) │ │ raise │ + * └────────────┘ └────────────┘ + * . + * . + * ┌────────────┐ + * │ MORE CFG │ + * └────────────┘ + * + * Parameters: + * - F a Function + * - prune_raise_exit, if false case 1 is considered, if true case 2 is + * considered. + * + * Returns: + * - true if pruning took place, false otherwise + */ + bool runFanoutPrune(Function &F, bool prune_raise_exit) { + bool mutated = false; + + // Find all Increfs and store them in incref_list + std::vector incref_list; + listRefOps(F, IsIncRef, incref_list); + + // Remember incref-blocks that will always fail. + SmallBBSet bad_blocks; + // walk the incref_list + for (CallInst *incref : incref_list) { + // Skip blocks that will always fail. + if (bad_blocks.count(incref->getParent())) { + continue; // skip + } + + // Is there *any* decref in the parent node of the incref? + // If so skip this incref (considering that aliases may exist). + if (hasAnyDecrefInNode(incref->getParent())) { + // be careful of potential alias + continue; // skip + } + + SmallBBSet decref_blocks; + // Check for the chosen "fan out" condition + if (findFanout(incref, bad_blocks, &decref_blocks, + prune_raise_exit)) { + if (DEBUG_PRINT) { + F.viewCFG(); + errs() << "------------\n"; + errs() << "incref " << incref->getParent()->getName() + << "\n"; + errs() << " decref_blocks.size()" << decref_blocks.size() + << "\n"; + incref->dump(); + } + // Remove first related decref in each block + // for each block + for (BasicBlock *each : decref_blocks) { + // for each instruction + for (Instruction &ii : *each) { + CallInst *decref; + // walrus: + // is the current instruction the decref associated with + // the incref under consideration, if so assign to + // decref and continue. + if ((decref = isRelatedDecref(incref, &ii))) { + if (DEBUG_PRINT) { + errs() + << decref->getParent()->getName() << "\n"; + decref->dump(); + } + // Remove this decref from its block + decref->eraseFromParent(); + + // update counters based on decref removal + if (prune_raise_exit) + stats_fanout_raise += 1; + else + stats_fanout += 1; + break; + } + } + } + // remove the incref from its block + incref->eraseFromParent(); + + // update counters based on incref removal + if (prune_raise_exit) + stats_fanout_raise += 1; + else + stats_fanout += 1; + mutated = true; + } + } + return mutated; + } + + /** + * This searches for the "fan-out" condition and returns true if it is + * found. + * + * Parameters: + * - incref: the incref from which fan-out should be checked. + * - bad_blocks: a set of blocks that are known to not satisfy the + * the fanout condition. Mutated by this function. + * - decref_blocks: pointer to a set of basic blocks, this is mutated by + * this function, on return it contains the basic blocks containing + * decrefs related to the incref + * - prune_raise_exit: this is a bool to signal whether to just look for + * the fan-out case or also look for the fan-out with raise condition, + * if true the fan-out with raise condition is considered else it is + * not. + * + * Returns: + * - true if the fan-out condition specified by `prune_raise_exit` was + * found, false otherwise. + */ + bool findFanout(CallInst *incref, SmallBBSet &bad_blocks, + SmallBBSet *decref_blocks, bool prune_raise_exit) { + + // get the basic block of the incref instruction + BasicBlock *head_node = incref->getParent(); + + // work space, a set of basic blocks to hold the block which contain + // raises, only used in the case of prune_raise_exit + SmallBBSet raising_blocks, *p_raising_blocks = NULL; + // Set up pointer to raising_blocks if (prune_raise_exit) - stats_fanout_raise += 1; - else - stats_fanout += 1; - mutated = true; - } - } - return mutated; - } + p_raising_blocks = &raising_blocks; - /** - * This searches for the "fan-out" condition and returns true if it is - * found. - * - * Parameters: - * - incref: the incref from which fan-out should be checked. - * - bad_blocks: a set of blocks that are known to not satisfy the - * the fanout condition. Mutated by this function. - * - decref_blocks: pointer to a set of basic blocks, this is mutated by - * this function, on return it contains the basic blocks containing - * decrefs related to the incref - * - prune_raise_exit: this is a bool to signal whether to just look for - * the fan-out case or also look for the fan-out with raise condition, - * if true the fan-out with raise condition is considered else it is - * not. - * - * Returns: - * - true if the fan-out condition specified by `prune_raise_exit` was - * found, false otherwise. - */ - bool findFanout(CallInst *incref, SmallBBSet &bad_blocks, - SmallBBSet *decref_blocks, bool prune_raise_exit) { - - // get the basic block of the incref instruction - BasicBlock *head_node = incref->getParent(); - - // work space, a set of basic blocks to hold the block which contain - // raises, only used in the case of prune_raise_exit - SmallBBSet raising_blocks, *p_raising_blocks = NULL; - // Set up pointer to raising_blocks - if (prune_raise_exit) - p_raising_blocks = &raising_blocks; - - if (findFanoutDecrefCandidates(incref, head_node, bad_blocks, decref_blocks, - p_raising_blocks)) { - if (DEBUG_PRINT) { - errs() << "forward pass candids.size() = " << decref_blocks->size() - << "\n"; - errs() << " " << head_node->getName() << "\n"; - incref->dump(); - } - if (decref_blocks->size() == 0) { - // no decref blocks - if (DEBUG_PRINT) { - errs() << "missing decref blocks = " << raising_blocks.size() << "\n"; - } - return false; - } - if (prune_raise_exit) { - if (raising_blocks.size() == 0) { - // no raising blocks - if (DEBUG_PRINT) { - errs() << "missing raising blocks = " << raising_blocks.size() - << "\n"; - for (auto bb : *decref_blocks) { - errs() << " " << bb->getName() << "\n"; + if (findFanoutDecrefCandidates(incref, head_node, bad_blocks, + decref_blocks, p_raising_blocks)) { + if (DEBUG_PRINT) { + errs() << "forward pass candids.size() = " + << decref_blocks->size() << "\n"; + errs() << " " << head_node->getName() << "\n"; + incref->dump(); + } + if (decref_blocks->size() == 0) { + // no decref blocks + if (DEBUG_PRINT) { + errs() << "missing decref blocks = " + << raising_blocks.size() << "\n"; + } + return false; + } + if (prune_raise_exit) { + if (raising_blocks.size() == 0) { + // no raising blocks + if (DEBUG_PRINT) { + errs() << "missing raising blocks = " + << raising_blocks.size() << "\n"; + for (auto bb : *decref_blocks) { + errs() << " " << bb->getName() << "\n"; + } + } + return false; + } + + // combine decref_blocks into raising blocks for checking the + // exit node condition + for (BasicBlock *bb : *decref_blocks) { + raising_blocks.insert(bb); + } + if (verifyFanoutBackward(incref, head_node, p_raising_blocks)) + return true; + + } else if (verifyFanoutBackward(incref, head_node, decref_blocks)) { + return true; } - } - return false; } - - // combine decref_blocks into raising blocks for checking the exit node - // condition - for (BasicBlock *bb : *decref_blocks) { - raising_blocks.insert(bb); - } - if (verifyFanoutBackward(incref, head_node, p_raising_blocks)) - return true; - - } else if (verifyFanoutBackward(incref, head_node, decref_blocks)) { - return true; - } - } - return false; - } - - /** - * Forward pass. - * - * Walk the successors of the incref node recursively until a decref - * or an exit node is found. - * - * In the case of a decref node, the node is added to decref_blocks only if - * it contains a decref associated with the incref and there is no interior - * back-edge to a predecessor in the current sub-graph. - * - * In the case of an exit, it must be a raise for it to be added to - * raising_blocks. - * - * Parameters: - * - incref: The incref under consideration. - * - cur_node: The basic block in which incref is found. - * - bad_blocks: a set of blocks that are known to not satisfy the - * the fanout condition. Mutated by this function. - * - decref_blocks: pointer to a set of basic blocks, it is mutated by this - * function and on successful return contains the basic blocks which have - * a decref related to the supplied incref in them. - * - raising_blocks: point to a set of basic blocks OR NULL. If not-NULL - * it is mutated by this function and on successful return contains the - * basic blocks which have a raise in them that is reachable from the - * incref. - * - * Return condition: - * depends on the value of raising_blocks: - * == NULL -> return true iff all paths from the incref have led to a - * decref. - * != NULL -> return true iff all paths from the incref have led to - * either a decref or a raising exit. - */ - bool findFanoutDecrefCandidates(CallInst *incref, BasicBlock *cur_node, - SmallBBSet &bad_blocks, - SmallBBSet *decref_blocks, - SmallBBSet *raising_blocks) { - // stack of basic blocks for the walked path(s) - SmallVector path_stack; - bool found = false; - // Get the terminator of the basic block containing the incref, the - // search starts from here. - auto term = cur_node->getTerminator(); - - // RAII push cur_node onto the work stack - raiiStack> raii_path_stack(path_stack, - cur_node); - - // This is a pass-by-ref accumulator. - unsigned subgraph_size = 0; - - // Walk the successors of the terminator. - for (unsigned i = 0; i < term->getNumSuccessors(); ++i) { - // Get the successor - BasicBlock *child = term->getSuccessor(i); - // Walk the successor looking for decrefs - found = walkChildForDecref(incref, child, path_stack, subgraph_size, - bad_blocks, decref_blocks, raising_blocks); - // if not found, return false - if (!found) - return found; // found must be false - } - return found; - } - - /** - * "Walk" a child node looking for blocks containing decrefs or raises that - * meet the conditions described in findFanoutDecrefCandidates. - * - * Parameters: - * - incref: The incref under consideration - * - cur_node: The current basic block being assessed - * - path_stack: A stack of basic blocks representing unsearched paths - * - bad_blocks: a set of blocks that are known to not satisfy the - * the fanout condition. Mutated by this function. - * - subgraph_size: accumulator to count the subgraph size (node count). - * - decref_blocks: a set that stores references to accepted blocks that - * contain decrefs associated with the incref. - * - raising_blocks: a set that stores references to accepted blocks that - * contain raises. - * - * Returns: - * - true if the conditions above hold, false otherwise. - */ - bool walkChildForDecref(CallInst *incref, BasicBlock *cur_node, - SmallVectorImpl &path_stack, - unsigned &subgraph_size, SmallBBSet &bad_blocks, - SmallBBSet *decref_blocks, - SmallBBSet *raising_blocks) { - // If the current path stack exceeds the recursion depth, stop, return - // false. - if (path_stack.size() >= FANOUT_RECURSE_DEPTH) - return false; - - // Reject subgraph that is bigger than the subgraph_limit - if (++subgraph_size > subgraph_limit) { - // mark head-node as always fail because that subgraph is too big - // to analyze. - bad_blocks.insert(incref->getParent()); - return false; - } - - // Check for the back-edge condition... - // If the current block is in the path stack - if (basicBlockInList(cur_node, path_stack)) { - // If the current node is TOS - if (cur_node == path_stack[0]) { - // Reject interior node back-edge to start of sub-graph. - // This means that the incref can be executed multiple times - // before reaching the decref. - - // mark head-node as always fail. - bad_blocks.insert(incref->getParent()); - return false; - } - // it is a legal backedge; skip - return true; - } - - // Does the current block have a related decref? - if (hasDecrefInNode(incref, cur_node)) { - // Add to the list of decref_blocks - decref_blocks->insert(cur_node); - return true; // done for this path - } - - // Are there any decrefs in the current node? - if (hasAnyDecrefInNode(cur_node)) { - // Because we don't know about aliasing - - // mark head-node as always fail. - bad_blocks.insert(incref->getParent()); - return false; - } - - // If raising_blocks is non-NULL, see if the current node is a block - // which raises, if so add to the raising_blocks list, this path is now - // finished. - if (raising_blocks && isRaising(cur_node)) { - raising_blocks->insert(cur_node); - return true; // done for this path - } - - // Continue searching by recursing into successors of the current - // block. - - // First RAII push cur_node as TOS - raiiStack> raii_push_pop(path_stack, - cur_node); - bool found = false; - // get cur_node terminator - auto term = cur_node->getTerminator(); - // walk successors of the current node - for (unsigned i = 0; i < term->getNumSuccessors(); ++i) { - // get a successor - BasicBlock *child = term->getSuccessor(i); - // recurse - found = walkChildForDecref(incref, child, path_stack, subgraph_size, - bad_blocks, decref_blocks, raising_blocks); - if (!found) return false; } - // If this is a leaf node, returns false. - return found; - } - /** - * Backward pass. - * Check the tail-node condition for the fanout subgraph: - * The reverse walks from all exit-nodes must end with the head-node - * and the tail-nodes cannot be executed multiple times. - * - * Parameters: - * - incref: the incref instruction - * - head_node: the basic block containing the arg incref - * - tail_nodes: a set containing the basic block(s) in which decrefs - * corresponding to the arg incref instruction exist. - * - * Returns: - * - true if it could be verified that there's no loop structure - * surrounding the use of the decrefs, false else. - * - */ - bool verifyFanoutBackward(CallInst *incref, BasicBlock *head_node, - const SmallBBSet *tail_nodes) { - // push the tail nodes into a work list - SmallVector todo; - for (BasicBlock *bb : *tail_nodes) { - todo.push_back(bb); + /** + * Forward pass. + * + * Walk the successors of the incref node recursively until a decref + * or an exit node is found. + * + * In the case of a decref node, the node is added to decref_blocks only if + * it contains a decref associated with the incref and there is no interior + * back-edge to a predecessor in the current sub-graph. + * + * In the case of an exit, it must be a raise for it to be added to + * raising_blocks. + * + * Parameters: + * - incref: The incref under consideration. + * - cur_node: The basic block in which incref is found. + * - bad_blocks: a set of blocks that are known to not satisfy the + * the fanout condition. Mutated by this function. + * - decref_blocks: pointer to a set of basic blocks, it is mutated by this + * function and on successful return contains the basic blocks which have + * a decref related to the supplied incref in them. + * - raising_blocks: point to a set of basic blocks OR NULL. If not-NULL + * it is mutated by this function and on successful return contains the + * basic blocks which have a raise in them that is reachable from the + * incref. + * + * Return condition: + * depends on the value of raising_blocks: + * == NULL -> return true iff all paths from the incref have led to a + * decref. + * != NULL -> return true iff all paths from the incref have led to + * either a decref or a raising exit. + */ + bool findFanoutDecrefCandidates(CallInst *incref, BasicBlock *cur_node, + SmallBBSet &bad_blocks, + SmallBBSet *decref_blocks, + SmallBBSet *raising_blocks) { + // stack of basic blocks for the walked path(s) + SmallVector path_stack; + bool found = false; + // Get the terminator of the basic block containing the incref, the + // search starts from here. + auto term = cur_node->getTerminator(); + + // RAII push cur_node onto the work stack + raiiStack> raii_path_stack(path_stack, + cur_node); + + // This is a pass-by-ref accumulator. + unsigned subgraph_size = 0; + + // Walk the successors of the terminator. + for (unsigned i = 0; i < term->getNumSuccessors(); ++i) { + // Get the successor + BasicBlock *child = term->getSuccessor(i); + // Walk the successor looking for decrefs + found = + walkChildForDecref(incref, child, path_stack, subgraph_size, + bad_blocks, decref_blocks, raising_blocks); + // if not found, return false + if (!found) + return found; // found must be false + } + return found; } - // visited is for bookkeeping to hold reference to those nodes which - // have already been visited. - SmallBBSet visited; - // while there is work... - while (todo.size() > 0) { - SmallVector workstack; - // pop an element from the work list into the work stack - workstack.push_back(todo.pop_back_val()); - - // while there's work on the local workstack - while (workstack.size() > 0) { - // Get a basic block - BasicBlock *cur_node = workstack.pop_back_val(); - // if the block has been seen before then skip - if (visited.count(cur_node)) { - // Already visited - continue; // skip - } - - if (cur_node == &head_node->getParent()->getEntryBlock()) { - // Arrived at the entry node of the function. - // This means the reverse walk from a tail-node can - // bypass the head-node (incref node) of this fanout - // subgraph. - return false; - } - - // remember that we have visited this node already - visited.insert(cur_node); - - // Walk into all predecessors - // pred_begin and pred_end are defined under Functions in: - // http://llvm.org/doxygen/IR_2CFG_8h.html - auto it = pred_begin(cur_node), end = pred_end(cur_node); - for (; it != end; ++it) { - auto pred = *it; - if (tail_nodes->count(pred)) { - // reject because a predecessor is a block containing - // a decref matching the incref + /** + * "Walk" a child node looking for blocks containing decrefs or raises that + * meet the conditions described in findFanoutDecrefCandidates. + * + * Parameters: + * - incref: The incref under consideration + * - cur_node: The current basic block being assessed + * - path_stack: A stack of basic blocks representing unsearched paths + * - bad_blocks: a set of blocks that are known to not satisfy the + * the fanout condition. Mutated by this function. + * - subgraph_size: accumulator to count the subgraph size (node count). + * - decref_blocks: a set that stores references to accepted blocks that + * contain decrefs associated with the incref. + * - raising_blocks: a set that stores references to accepted blocks that + * contain raises. + * + * Returns: + * - true if the conditions above hold, false otherwise. + */ + bool walkChildForDecref(CallInst *incref, BasicBlock *cur_node, + SmallVectorImpl &path_stack, + unsigned &subgraph_size, SmallBBSet &bad_blocks, + SmallBBSet *decref_blocks, + SmallBBSet *raising_blocks) { + // If the current path stack exceeds the recursion depth, stop, return + // false. + if (path_stack.size() >= FANOUT_RECURSE_DEPTH) + return false; + + // Reject subgraph that is bigger than the subgraph_limit + if (++subgraph_size > subgraph_limit) { + // mark head-node as always fail because that subgraph is too big + // to analyze. + bad_blocks.insert(incref->getParent()); return false; - } - if (pred != head_node) { - // If the predecessor is the head-node, - // this path is ok; otherwise, continue to walk up. - workstack.push_back(pred); - } } - } - } - // analysis didn't exit, all conditions must be ok, return true - return true; - } - /** - * Check if a basic block is a block which raises, this relies on a - * metadata "ret_is_raise" being present the terminator and the - * terminator opcode being Instruction::Ret. - * - * Parameters: - * - bb a basic block - * - * Returns: - * - true if basic block bb contains a raise with the appropriate metadata, - * false otherwise - */ - bool isRaising(const BasicBlock *bb) { + // Check for the back-edge condition... + // If the current block is in the path stack + if (basicBlockInList(cur_node, path_stack)) { + // If the current node is TOS + if (cur_node == path_stack[0]) { + // Reject interior node back-edge to start of sub-graph. + // This means that the incref can be executed multiple times + // before reaching the decref. - // Get the terminator - auto term = bb->getTerminator(); - // Get the opcode of the terminator, if it's not a Ret then return false - if (term->getOpcode() != Instruction::Ret) - return false; - // Get the metadata on the terminator node - auto md = term->getMetadata("ret_is_raise"); - // If there's no metadata return false (normal or unmarked Ret) - if (!md) - return false; - // If the number of operands on the metadata is not 1 then return false - if (md->getNumOperands() != 1) - return false; - // Fetch the ref to the metadata operand at location 0 - auto &operand = md->getOperand(0); - // and then cast the const as Metadata (Numba sets this as literal 1) - auto data = dyn_cast(operand.get()); - // If dyn_cast failed type check then return false - if (!data) - return false; - // get the value of the casted metadata and then return bool on whether - // it is the number one. - return data->getValue()->isOneValue(); - } - - /** - * Does "Is a basic block in a given list" - * - * Template parameter : - * - the type of list - * - * Parameters: - * - bb a basic block - * - list a list-like container in which to search - * - * Returns: - * - true if bb is in list, false else. - */ - template - bool basicBlockInList(const BasicBlock *bb, const T &list) { - for (BasicBlock *each : list) { - if (bb == each) - return true; - } - return false; - } - - /** - * Check to see if a basic block contains a decref related to a given incref - * - * Parameters: - * - incref an incref - * - bb a basic block - * - * Returns: - * - true if basic block bb contains a decref related to incref, false - * otherwise. - */ - bool hasDecrefInNode(CallInst *incref, BasicBlock *bb) { - for (Instruction &ii : *bb) { - if (isRelatedDecref(incref, &ii) != NULL) { - return true; - } - } - return false; - } - - /** - * Checks if an instruction is a decref that is related to the given incref. - * - * Parameters: - * - incref an incref - * - bb a basic block - * - * Returns: - * - returns input ii as a CallInst* if it is a decref related to incref, - * NULL otherwise. - */ - CallInst *isRelatedDecref(CallInst *incref, Instruction *ii) { - CallInst *suspect; - if ((suspect = GetRefOpCall(ii))) { - if (!IsDecRef(suspect)) { - return NULL; - } - if (incref->getArgOperand(0) != suspect->getArgOperand(0)) { - return NULL; - } - return suspect; - } - return NULL; - } - - /** - * getAnalysisUsage() LLVM plumbing for the pass - */ - void getAnalysisUsage(AnalysisUsage &Info) const override { - Info.addRequired(); - Info.addRequired(); - } - - /** - * Checks if the first argument to the supplied call_inst is NULL and - * returns true if so, false otherwise. - * - * Parameters: - * - call_inst, a call instruction to check. - * - * Returns: - * - true is the first argument to call_inst is not NULL, false otherwise - */ - bool isNonNullFirstArg(CallInst *call_inst) { - auto val = call_inst->getArgOperand(0); - auto ptr = dyn_cast(val); - return ptr == NULL; - } - - /** - * Scans a basic block for decrefs and returns true if one is found, - * false otherwise - * - * Parameters: - * - bb, a basic block - * - * Returns: - * - true if there is a decref in the basic block, false otherwise. - */ - bool hasAnyDecrefInNode(BasicBlock *bb) { - for (Instruction &ii : *bb) { - CallInst *refop = GetRefOpCall(&ii); - if (refop != NULL && IsDecRef(refop)) { - return true; - } - } - return false; - } - - /** - * Determines if there is a decref between two nodes in a graph. - * - * NOTE: Required condition: head_node dominates tail_node - * - * Parameters: - * - head_node, a basic block which is the head of the graph - * - tail_node, a basic block which is the tail of the graph - * - * Returns: - * - true if there is a decref, false else - * - */ - bool hasDecrefBetweenGraph(BasicBlock *head_node, BasicBlock *tail_node) { - // This function implements a depth-first search. - - // visited keeps track of the visited blocks - SmallBBSet visited; - // stack keeps track of blocks to be checked. - SmallVector stack; - // start with the head_node; - stack.push_back(head_node); - do { - BasicBlock *cur_node = stack.pop_back_val(); - // First, is the current BB already visited, if so return false, - // its already been checked. - if (visited.count(cur_node)) { - continue; // skip - } - // remember that it is visited - visited.insert(cur_node); - if (DEBUG_PRINT) { - errs() << "Check..." << cur_node->getName() << "\n"; - } - - // scan the current BB for decrefs, if any are present return true - if (hasAnyDecrefInNode(cur_node)) - return true; - - // get the terminator of the current node - Instruction *term = cur_node->getTerminator(); - // walk the successor blocks - for (unsigned i = 0; i < term->getNumSuccessors(); ++i) { - BasicBlock *child = term->getSuccessor(i); - // if the successor is the tail node, skip - if (child == tail_node) - continue; - // else check the subgraph between the current successor and the - // tail - stack.push_back(child); - } - } while (stack.size() > 0); - return false; - } - - typedef bool (*test_refops_function)(CallInst *); - - /** - * Walks the basic blocks of a function F, scans each instruction, if the - * instruction is a refop and calling `test_refops_function` on it evaluates - * to true then add it to list. - * - * Templates Parameter - * - the type of list - * - * Parameters: - * - F a LLVM function - * - test_refops_function a function that takes an Instruction instance and - * returns true if the instance is a refop, false otherwise - * - list, a list-like container to hold reference to instruction instances - * which are identified by test_refops_function. - */ - template - void listRefOps(Function &F, test_refops_function fn, T &list) { - // For each basic block in the function - for (BasicBlock &bb : F) { - // For each instruction the basic block - for (Instruction &ii : bb) { - CallInst *ci; - // if the instruction is a refop - if ((ci = GetRefOpCall(&ii))) { - // and the test_refops_function returns true when called - // on the instruction - if (fn(ci)) { - // add to the list - list.push_back(ci); - } + // mark head-node as always fail. + bad_blocks.insert(incref->getParent()); + return false; + } + // it is a legal backedge; skip + return true; + } + + // Does the current block have a related decref? + if (hasDecrefInNode(incref, cur_node)) { + // Add to the list of decref_blocks + decref_blocks->insert(cur_node); + return true; // done for this path + } + + // Are there any decrefs in the current node? + if (hasAnyDecrefInNode(cur_node)) { + // Because we don't know about aliasing + + // mark head-node as always fail. + bad_blocks.insert(incref->getParent()); + return false; + } + + // If raising_blocks is non-NULL, see if the current node is a block + // which raises, if so add to the raising_blocks list, this path is now + // finished. + if (raising_blocks && isRaising(cur_node)) { + raising_blocks->insert(cur_node); + return true; // done for this path + } + + // Continue searching by recursing into successors of the current + // block. + + // First RAII push cur_node as TOS + raiiStack> raii_push_pop(path_stack, + cur_node); + bool found = false; + // get cur_node terminator + auto term = cur_node->getTerminator(); + // walk successors of the current node + for (unsigned i = 0; i < term->getNumSuccessors(); ++i) { + // get a successor + BasicBlock *child = term->getSuccessor(i); + // recurse + found = + walkChildForDecref(incref, child, path_stack, subgraph_size, + bad_blocks, decref_blocks, raising_blocks); + if (!found) + return false; + } + // If this is a leaf node, returns false. + return found; + } + + /** + * Backward pass. + * Check the tail-node condition for the fanout subgraph: + * The reverse walks from all exit-nodes must end with the head-node + * and the tail-nodes cannot be executed multiple times. + * + * Parameters: + * - incref: the incref instruction + * - head_node: the basic block containing the arg incref + * - tail_nodes: a set containing the basic block(s) in which decrefs + * corresponding to the arg incref instruction exist. + * + * Returns: + * - true if it could be verified that there's no loop structure + * surrounding the use of the decrefs, false else. + * + */ + bool verifyFanoutBackward(CallInst *incref, BasicBlock *head_node, + const SmallBBSet *tail_nodes) { + // push the tail nodes into a work list + SmallVector todo; + for (BasicBlock *bb : *tail_nodes) { + todo.push_back(bb); + } + + // visited is for bookkeeping to hold reference to those nodes which + // have already been visited. + SmallBBSet visited; + // while there is work... + while (todo.size() > 0) { + SmallVector workstack; + // pop an element from the work list into the work stack + workstack.push_back(todo.pop_back_val()); + + // while there's work on the local workstack + while (workstack.size() > 0) { + // Get a basic block + BasicBlock *cur_node = workstack.pop_back_val(); + // if the block has been seen before then skip + if (visited.count(cur_node)) { + // Already visited + continue; // skip + } + + if (cur_node == &head_node->getParent()->getEntryBlock()) { + // Arrived at the entry node of the function. + // This means the reverse walk from a tail-node can + // bypass the head-node (incref node) of this fanout + // subgraph. + return false; + } + + // remember that we have visited this node already + visited.insert(cur_node); + + // Walk into all predecessors + // pred_begin and pred_end are defined under Functions in: + // http://llvm.org/doxygen/IR_2CFG_8h.html + auto it = pred_begin(cur_node), end = pred_end(cur_node); + for (; it != end; ++it) { + auto pred = *it; + if (tail_nodes->count(pred)) { + // reject because a predecessor is a block containing + // a decref matching the incref + return false; + } + if (pred != head_node) { + // If the predecessor is the head-node, + // this path is ok; otherwise, continue to walk up. + workstack.push_back(pred); + } + } + } + } + // analysis didn't exit, all conditions must be ok, return true + return true; + } + + /** + * Check if a basic block is a block which raises, this relies on a + * metadata "ret_is_raise" being present the terminator and the + * terminator opcode being Instruction::Ret. + * + * Parameters: + * - bb a basic block + * + * Returns: + * - true if basic block bb contains a raise with the appropriate metadata, + * false otherwise + */ + bool isRaising(const BasicBlock *bb) { + + // Get the terminator + auto term = bb->getTerminator(); + // Get the opcode of the terminator, if it's not a Ret then return false + if (term->getOpcode() != Instruction::Ret) + return false; + // Get the metadata on the terminator node + auto md = term->getMetadata("ret_is_raise"); + // If there's no metadata return false (normal or unmarked Ret) + if (!md) + return false; + // If the number of operands on the metadata is not 1 then return false + if (md->getNumOperands() != 1) + return false; + // Fetch the ref to the metadata operand at location 0 + auto &operand = md->getOperand(0); + // and then cast the const as Metadata (Numba sets this as literal 1) + auto data = dyn_cast(operand.get()); + // If dyn_cast failed type check then return false + if (!data) + return false; + // get the value of the casted metadata and then return bool on whether + // it is the number one. + return data->getValue()->isOneValue(); + } + + /** + * Does "Is a basic block in a given list" + * + * Template parameter : + * - the type of list + * + * Parameters: + * - bb a basic block + * - list a list-like container in which to search + * + * Returns: + * - true if bb is in list, false else. + */ + template + bool basicBlockInList(const BasicBlock *bb, const T &list) { + for (BasicBlock *each : list) { + if (bb == each) + return true; + } + return false; + } + + /** + * Check to see if a basic block contains a decref related to a given incref + * + * Parameters: + * - incref an incref + * - bb a basic block + * + * Returns: + * - true if basic block bb contains a decref related to incref, false + * otherwise. + */ + bool hasDecrefInNode(CallInst *incref, BasicBlock *bb) { + for (Instruction &ii : *bb) { + if (isRelatedDecref(incref, &ii) != NULL) { + return true; + } + } + return false; + } + + /** + * Checks if an instruction is a decref that is related to the given incref. + * + * Parameters: + * - incref an incref + * - bb a basic block + * + * Returns: + * - returns input ii as a CallInst* if it is a decref related to incref, + * NULL otherwise. + */ + CallInst *isRelatedDecref(CallInst *incref, Instruction *ii) { + CallInst *suspect; + if ((suspect = GetRefOpCall(ii))) { + if (!IsDecRef(suspect)) { + return NULL; + } + if (incref->getArgOperand(0) != suspect->getArgOperand(0)) { + return NULL; + } + return suspect; + } + return NULL; + } + + /** + * getAnalysisUsage() LLVM plumbing for the pass + */ + void getAnalysisUsage(AnalysisUsage &Info) const override { + Info.addRequired(); + Info.addRequired(); + } + + /** + * Checks if the first argument to the supplied call_inst is NULL and + * returns true if so, false otherwise. + * + * Parameters: + * - call_inst, a call instruction to check. + * + * Returns: + * - true is the first argument to call_inst is not NULL, false otherwise + */ + bool isNonNullFirstArg(CallInst *call_inst) { + auto val = call_inst->getArgOperand(0); + auto ptr = dyn_cast(val); + return ptr == NULL; + } + + /** + * Scans a basic block for decrefs and returns true if one is found, + * false otherwise + * + * Parameters: + * - bb, a basic block + * + * Returns: + * - true if there is a decref in the basic block, false otherwise. + */ + bool hasAnyDecrefInNode(BasicBlock *bb) { + for (Instruction &ii : *bb) { + CallInst *refop = GetRefOpCall(&ii); + if (refop != NULL && IsDecRef(refop)) { + return true; + } + } + return false; + } + + /** + * Determines if there is a decref between two nodes in a graph. + * + * NOTE: Required condition: head_node dominates tail_node + * + * Parameters: + * - head_node, a basic block which is the head of the graph + * - tail_node, a basic block which is the tail of the graph + * + * Returns: + * - true if there is a decref, false else + * + */ + bool hasDecrefBetweenGraph(BasicBlock *head_node, BasicBlock *tail_node) { + // This function implements a depth-first search. + + // visited keeps track of the visited blocks + SmallBBSet visited; + // stack keeps track of blocks to be checked. + SmallVector stack; + // start with the head_node; + stack.push_back(head_node); + do { + BasicBlock *cur_node = stack.pop_back_val(); + // First, is the current BB already visited, if so return false, + // its already been checked. + if (visited.count(cur_node)) { + continue; // skip + } + // remember that it is visited + visited.insert(cur_node); + if (DEBUG_PRINT) { + errs() << "Check..." << cur_node->getName() << "\n"; + } + + // scan the current BB for decrefs, if any are present return true + if (hasAnyDecrefInNode(cur_node)) + return true; + + // get the terminator of the current node + Instruction *term = cur_node->getTerminator(); + // walk the successor blocks + for (unsigned i = 0; i < term->getNumSuccessors(); ++i) { + BasicBlock *child = term->getSuccessor(i); + // if the successor is the tail node, skip + if (child == tail_node) + continue; + // else check the subgraph between the current successor and the + // tail + stack.push_back(child); + } + } while (stack.size() > 0); + return false; + } + + typedef bool (*test_refops_function)(CallInst *); + + /** + * Walks the basic blocks of a function F, scans each instruction, if the + * instruction is a refop and calling `test_refops_function` on it evaluates + * to true then add it to list. + * + * Templates Parameter + * - the type of list + * + * Parameters: + * - F a LLVM function + * - test_refops_function a function that takes an Instruction instance and + * returns true if the instance is a refop, false otherwise + * - list, a list-like container to hold reference to instruction instances + * which are identified by test_refops_function. + */ + template + void listRefOps(Function &F, test_refops_function fn, T &list) { + // For each basic block in the function + for (BasicBlock &bb : F) { + // For each instruction the basic block + for (Instruction &ii : bb) { + CallInst *ci; + // if the instruction is a refop + if ((ci = GetRefOpCall(&ii))) { + // and the test_refops_function returns true when called + // on the instruction + if (fn(ci)) { + // add to the list + list.push_back(ci); + } + } + } } - } } - } }; // end of struct RefPrunePass char RefNormalizePass::ID = 0; @@ -1161,9 +1170,9 @@ extern "C" { API_EXPORT(void) LLVMPY_AddRefPrunePass(LLVMPassManagerRef PM, int subpasses, size_t subgraph_limit) { - unwrap(PM)->add(new RefNormalizePass()); - unwrap(PM)->add( - new RefPrunePass((RefPrunePass::Subpasses)subpasses, subgraph_limit)); + unwrap(PM)->add(new RefNormalizePass()); + unwrap(PM)->add( + new RefPrunePass((RefPrunePass::Subpasses)subpasses, subgraph_limit)); } /** @@ -1171,33 +1180,33 @@ LLVMPY_AddRefPrunePass(LLVMPassManagerRef PM, int subpasses, * each type of pruning algorithm. */ typedef struct PruneStats { - size_t basicblock; - size_t diamond; - size_t fanout; - size_t fanout_raise; + size_t basicblock; + size_t diamond; + size_t fanout; + size_t fanout_raise; } PRUNESTATS; API_EXPORT(void) LLVMPY_DumpRefPruneStats(PRUNESTATS *buf, bool do_print) { - /* PRUNESTATS is updated with the statistics about what has been pruned from - * the RefPrunePass static state vars. This isn't threadsafe but neither is - * the LLVM pass infrastructure so it's all done under a python thread lock. - * - * do_print if set will print the stats to stderr. - */ - if (do_print) { - errs() << "refprune stats " - << "per-BB " << RefPrunePass::stats_per_bb << " " - << "diamond " << RefPrunePass::stats_diamond << " " - << "fanout " << RefPrunePass::stats_fanout << " " - << "fanout+raise " << RefPrunePass::stats_fanout_raise << " " - << "\n"; - }; + /* PRUNESTATS is updated with the statistics about what has been pruned from + * the RefPrunePass static state vars. This isn't threadsafe but neither is + * the LLVM pass infrastructure so it's all done under a python thread lock. + * + * do_print if set will print the stats to stderr. + */ + if (do_print) { + errs() << "refprune stats " + << "per-BB " << RefPrunePass::stats_per_bb << " " + << "diamond " << RefPrunePass::stats_diamond << " " + << "fanout " << RefPrunePass::stats_fanout << " " + << "fanout+raise " << RefPrunePass::stats_fanout_raise << " " + << "\n"; + }; - buf->basicblock = RefPrunePass::stats_per_bb; - buf->diamond = RefPrunePass::stats_diamond; - buf->fanout = RefPrunePass::stats_fanout; - buf->fanout_raise = RefPrunePass::stats_fanout_raise; + buf->basicblock = RefPrunePass::stats_per_bb; + buf->diamond = RefPrunePass::stats_diamond; + buf->fanout = RefPrunePass::stats_fanout; + buf->fanout_raise = RefPrunePass::stats_fanout_raise; } } // extern "C" diff --git a/ffi/dylib.cpp b/ffi/dylib.cpp index 9253f805..efe46ad0 100644 --- a/ffi/dylib.cpp +++ b/ffi/dylib.cpp @@ -6,23 +6,23 @@ extern "C" { API_EXPORT(void *) LLVMPY_SearchAddressOfSymbol(const char *name) { - return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(name); + return llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(name); } API_EXPORT(void) LLVMPY_AddSymbol(const char *name, void *addr) { - llvm::sys::DynamicLibrary::AddSymbol(name, addr); + llvm::sys::DynamicLibrary::AddSymbol(name, addr); } API_EXPORT(bool) LLVMPY_LoadLibraryPermanently(const char *filename, const char **OutError) { - std::string error; - bool failed = - llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename, &error); - if (failed) { - *OutError = LLVMPY_CreateString(error.c_str()); - } - return failed; + std::string error; + bool failed = + llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename, &error); + if (failed) { + *OutError = LLVMPY_CreateString(error.c_str()); + } + return failed; } } // end extern "C" diff --git a/ffi/executionengine.cpp b/ffi/executionengine.cpp index d762f7dc..79f1ec9a 100644 --- a/ffi/executionengine.cpp +++ b/ffi/executionengine.cpp @@ -20,10 +20,11 @@ namespace llvm { // Ripped from lib/Target/TargetMachineC.cpp. inline TargetMachine *unwrap(LLVMTargetMachineRef P) { - return reinterpret_cast(P); + return reinterpret_cast(P); } inline LLVMTargetMachineRef wrap(const TargetMachine *P) { - return reinterpret_cast(const_cast(P)); + return reinterpret_cast( + const_cast(P)); } // unwrap for LLVMObjectFileRef @@ -31,7 +32,7 @@ inline LLVMTargetMachineRef wrap(const TargetMachine *P) { namespace object { inline OwningBinary *unwrap(LLVMObjectFileRef OF) { - return reinterpret_cast *>(OF); + return reinterpret_cast *>(OF); } } // namespace object } // namespace llvm @@ -43,127 +44,127 @@ LLVMPY_LinkInMCJIT() { LLVMLinkInMCJIT(); } API_EXPORT(void) LLVMPY_DisposeExecutionEngine(LLVMExecutionEngineRef EE) { - LLVMDisposeExecutionEngine(EE); + LLVMDisposeExecutionEngine(EE); } API_EXPORT(void) LLVMPY_AddModule(LLVMExecutionEngineRef EE, LLVMModuleRef M) { - LLVMAddModule(EE, M); + LLVMAddModule(EE, M); } API_EXPORT(int) LLVMPY_RemoveModule(LLVMExecutionEngineRef EE, LLVMModuleRef M, char **OutError) { - return LLVMRemoveModule(EE, M, &M, OutError); + return LLVMRemoveModule(EE, M, &M, OutError); } API_EXPORT(void) LLVMPY_FinalizeObject(LLVMExecutionEngineRef EE) { - llvm::unwrap(EE)->finalizeObject(); + llvm::unwrap(EE)->finalizeObject(); } static LLVMExecutionEngineRef create_execution_engine(LLVMModuleRef M, LLVMTargetMachineRef TM, const char **OutError) { - LLVMExecutionEngineRef ee = nullptr; + LLVMExecutionEngineRef ee = nullptr; - llvm::EngineBuilder eb(std::unique_ptr(llvm::unwrap(M))); - std::string err; - eb.setErrorStr(&err); - eb.setEngineKind(llvm::EngineKind::JIT); + llvm::EngineBuilder eb(std::unique_ptr(llvm::unwrap(M))); + std::string err; + eb.setErrorStr(&err); + eb.setEngineKind(llvm::EngineKind::JIT); - /* EngineBuilder::create loads the current process symbols */ - llvm::ExecutionEngine *engine = eb.create(llvm::unwrap(TM)); + /* EngineBuilder::create loads the current process symbols */ + llvm::ExecutionEngine *engine = eb.create(llvm::unwrap(TM)); - if (!engine) - *OutError = LLVMPY_CreateString(err.c_str()); - else - ee = llvm::wrap(engine); - return ee; + if (!engine) + *OutError = LLVMPY_CreateString(err.c_str()); + else + ee = llvm::wrap(engine); + return ee; } API_EXPORT(LLVMExecutionEngineRef) LLVMPY_CreateMCJITCompiler(LLVMModuleRef M, LLVMTargetMachineRef TM, const char **OutError) { - return create_execution_engine(M, TM, OutError); + return create_execution_engine(M, TM, OutError); } API_EXPORT(uint64_t) LLVMPY_GetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name) { - return LLVMGetGlobalValueAddress(EE, Name); + return LLVMGetGlobalValueAddress(EE, Name); } API_EXPORT(uint64_t) LLVMPY_GetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name) { - return LLVMGetFunctionAddress(EE, Name); + return LLVMGetFunctionAddress(EE, Name); } API_EXPORT(void) LLVMPY_RunStaticConstructors(LLVMExecutionEngineRef EE) { - return LLVMRunStaticConstructors(EE); + return LLVMRunStaticConstructors(EE); } API_EXPORT(void) LLVMPY_RunStaticDestructors(LLVMExecutionEngineRef EE) { - return LLVMRunStaticDestructors(EE); + return LLVMRunStaticDestructors(EE); } API_EXPORT(void) LLVMPY_AddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *Addr) { - LLVMAddGlobalMapping(EE, Global, Addr); + LLVMAddGlobalMapping(EE, Global, Addr); } API_EXPORT(LLVMTargetDataRef) LLVMPY_GetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { - return LLVMGetExecutionEngineTargetData(EE); + return LLVMGetExecutionEngineTargetData(EE); } API_EXPORT(int) LLVMPY_TryAllocateExecutableMemory(void) { - using namespace llvm::sys; - std::error_code ec; - MemoryBlock mb = Memory::allocateMappedMemory( - 4096, nullptr, Memory::MF_READ | Memory::MF_WRITE, ec); - if (!ec) { - ec = Memory::protectMappedMemory(mb, Memory::MF_READ | Memory::MF_EXEC); - (void)Memory::releaseMappedMemory(mb); /* Should always succeed */ - } - return ec.value(); + using namespace llvm::sys; + std::error_code ec; + MemoryBlock mb = Memory::allocateMappedMemory( + 4096, nullptr, Memory::MF_READ | Memory::MF_WRITE, ec); + if (!ec) { + ec = Memory::protectMappedMemory(mb, Memory::MF_READ | Memory::MF_EXEC); + (void)Memory::releaseMappedMemory(mb); /* Should always succeed */ + } + return ec.value(); } API_EXPORT(bool) LLVMPY_EnableJITEvents(LLVMExecutionEngineRef EE) { - llvm::JITEventListener *listener; - bool result = false; + llvm::JITEventListener *listener; + bool result = false; #ifdef __linux__ - listener = llvm::JITEventListener::createOProfileJITEventListener(); - // if listener is null, then LLVM was not compiled for OProfile JIT events. - if (listener) { - llvm::unwrap(EE)->RegisterJITEventListener(listener); - result = true; - } + listener = llvm::JITEventListener::createOProfileJITEventListener(); + // if listener is null, then LLVM was not compiled for OProfile JIT events. + if (listener) { + llvm::unwrap(EE)->RegisterJITEventListener(listener); + result = true; + } #endif - listener = llvm::JITEventListener::createIntelJITEventListener(); - // if listener is null, then LLVM was not compiled for Intel JIT events. - if (listener) { - llvm::unwrap(EE)->RegisterJITEventListener(listener); - result = true; - } - return result; + listener = llvm::JITEventListener::createIntelJITEventListener(); + // if listener is null, then LLVM was not compiled for Intel JIT events. + if (listener) { + llvm::unwrap(EE)->RegisterJITEventListener(listener); + result = true; + } + return result; } API_EXPORT(void) LLVMPY_MCJITAddObjectFile(LLVMExecutionEngineRef EE, LLVMObjectFileRef ObjF) { - using namespace llvm; - using namespace llvm::object; - auto engine = unwrap(EE); - auto object_file = unwrap(ObjF); - auto binary_tuple = object_file->takeBinary(); + using namespace llvm; + using namespace llvm::object; + auto engine = unwrap(EE); + auto object_file = unwrap(ObjF); + auto binary_tuple = object_file->takeBinary(); - engine->addObjectFile( - {std::move(binary_tuple.first), std::move(binary_tuple.second)}); + engine->addObjectFile( + {std::move(binary_tuple.first), std::move(binary_tuple.second)}); } // @@ -171,55 +172,56 @@ LLVMPY_MCJITAddObjectFile(LLVMExecutionEngineRef EE, LLVMObjectFileRef ObjF) { // typedef struct { - LLVMModuleRef modref; - const char *buf_ptr; - size_t buf_len; + LLVMModuleRef modref; + const char *buf_ptr; + size_t buf_len; } ObjectCacheData; typedef void (*ObjectCacheNotifyFunc)(void *, const ObjectCacheData *); typedef void (*ObjectCacheGetObjectFunc)(void *, ObjectCacheData *); class LLVMPYObjectCache : public llvm::ObjectCache { -public: - LLVMPYObjectCache(ObjectCacheNotifyFunc notify_func, - ObjectCacheGetObjectFunc getobject_func, void *user_data) - : notify_func(notify_func), getobject_func(getobject_func), - user_data(user_data) {} + public: + LLVMPYObjectCache(ObjectCacheNotifyFunc notify_func, + ObjectCacheGetObjectFunc getobject_func, void *user_data) + : notify_func(notify_func), getobject_func(getobject_func), + user_data(user_data) {} - virtual void notifyObjectCompiled(const llvm::Module *M, - llvm::MemoryBufferRef MBR) { - if (notify_func) { - ObjectCacheData data = {llvm::wrap(M), MBR.getBufferStart(), - MBR.getBufferSize()}; - notify_func(user_data, &data); + virtual void notifyObjectCompiled(const llvm::Module *M, + llvm::MemoryBufferRef MBR) { + if (notify_func) { + ObjectCacheData data = {llvm::wrap(M), MBR.getBufferStart(), + MBR.getBufferSize()}; + notify_func(user_data, &data); + } } - } - // MCJIT will call this function before compiling any module - // MCJIT takes ownership of both the MemoryBuffer object and the memory - // to which it refers. - virtual std::unique_ptr getObject(const llvm::Module *M) { - std::unique_ptr res = nullptr; + // MCJIT will call this function before compiling any module + // MCJIT takes ownership of both the MemoryBuffer object and the memory + // to which it refers. + virtual std::unique_ptr + getObject(const llvm::Module *M) { + std::unique_ptr res = nullptr; - if (getobject_func) { - ObjectCacheData data = {llvm::wrap(M), nullptr, 0}; + if (getobject_func) { + ObjectCacheData data = {llvm::wrap(M), nullptr, 0}; - getobject_func(user_data, &data); - if (data.buf_ptr && data.buf_len > 0) { - // Assume the returned string was allocated - // with LLVMPY_CreateByteString - res = llvm::MemoryBuffer::getMemBufferCopy( - llvm::StringRef(data.buf_ptr, data.buf_len)); - LLVMPY_DisposeString(data.buf_ptr); - } + getobject_func(user_data, &data); + if (data.buf_ptr && data.buf_len > 0) { + // Assume the returned string was allocated + // with LLVMPY_CreateByteString + res = llvm::MemoryBuffer::getMemBufferCopy( + llvm::StringRef(data.buf_ptr, data.buf_len)); + LLVMPY_DisposeString(data.buf_ptr); + } + } + return res; } - return res; - } -private: - ObjectCacheNotifyFunc notify_func; - ObjectCacheGetObjectFunc getobject_func; - void *user_data; + private: + ObjectCacheNotifyFunc notify_func; + ObjectCacheGetObjectFunc getobject_func; + void *user_data; }; typedef LLVMPYObjectCache *LLVMPYObjectCacheRef; @@ -228,7 +230,7 @@ API_EXPORT(LLVMPYObjectCacheRef) LLVMPY_CreateObjectCache(ObjectCacheNotifyFunc notify_func, ObjectCacheGetObjectFunc getobject_func, void *user_data) { - return new LLVMPYObjectCache(notify_func, getobject_func, user_data); + return new LLVMPYObjectCache(notify_func, getobject_func, user_data); } API_EXPORT(void) @@ -236,7 +238,7 @@ LLVMPY_DisposeObjectCache(LLVMPYObjectCacheRef C) { delete C; } API_EXPORT(void) LLVMPY_SetObjectCache(LLVMExecutionEngineRef EE, LLVMPYObjectCacheRef C) { - llvm::unwrap(EE)->setObjectCache(C); + llvm::unwrap(EE)->setObjectCache(C); } } // end extern "C" diff --git a/ffi/initfini.cpp b/ffi/initfini.cpp index 3b601c9a..ae13d292 100644 --- a/ffi/initfini.cpp +++ b/ffi/initfini.cpp @@ -8,9 +8,9 @@ extern "C" { #define INIT(F) \ - API_EXPORT(void) LLVMPY_Initialize##F() { \ - LLVMInitialize##F(LLVMGetGlobalPassRegistry()); \ - } + API_EXPORT(void) LLVMPY_Initialize##F() { \ + LLVMInitialize##F(LLVMGetGlobalPassRegistry()); \ + } INIT(Core) INIT(TransformUtils) @@ -32,7 +32,7 @@ LLVMPY_Shutdown() { LLVMShutdown(); } // Target Initialization #define INIT(F) \ - API_EXPORT(void) LLVMPY_Initialize##F() { LLVMInitialize##F(); } + API_EXPORT(void) LLVMPY_Initialize##F() { LLVMInitialize##F(); } // NOTE: it is important that we don't export functions which we don't use, // especially those which may pull in large amounts of additional code or data. @@ -50,14 +50,14 @@ INIT(NativeAsmPrinter) API_EXPORT(unsigned int) LLVMPY_GetVersionInfo() { - unsigned int verinfo = 0; - verinfo += LLVM_VERSION_MAJOR << 16; - verinfo += LLVM_VERSION_MINOR << 8; + unsigned int verinfo = 0; + verinfo += LLVM_VERSION_MAJOR << 16; + verinfo += LLVM_VERSION_MINOR << 8; #ifdef LLVM_VERSION_PATCH - /* Not available under Windows... */ - verinfo += LLVM_VERSION_PATCH << 0; + /* Not available under Windows... */ + verinfo += LLVM_VERSION_PATCH << 0; #endif - return verinfo; + return verinfo; } } // end extern "C" diff --git a/ffi/linker.cpp b/ffi/linker.cpp index aaf8c9fe..753ea7bd 100644 --- a/ffi/linker.cpp +++ b/ffi/linker.cpp @@ -11,50 +11,50 @@ extern "C" { API_EXPORT(int) LLVMPY_LinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, const char **Err) { - using namespace llvm; - std::string errorstring; - llvm::raw_string_ostream errstream(errorstring); - Module *D = unwrap(Dest); - LLVMContext &Ctx = D->getContext(); + using namespace llvm; + std::string errorstring; + llvm::raw_string_ostream errstream(errorstring); + Module *D = unwrap(Dest); + LLVMContext &Ctx = D->getContext(); - // This exists at the change to LLVM 6.x - // Link error diagnostics end up with a call to abort() - // install this handler to instead extract the reason for failure - // and report it. - class ReportNotAbortDiagnosticHandler : public DiagnosticHandler { - public: - ReportNotAbortDiagnosticHandler(llvm::raw_string_ostream &s) - : raw_stream(s) {} + // This exists at the change to LLVM 6.x + // Link error diagnostics end up with a call to abort() + // install this handler to instead extract the reason for failure + // and report it. + class ReportNotAbortDiagnosticHandler : public DiagnosticHandler { + public: + ReportNotAbortDiagnosticHandler(llvm::raw_string_ostream &s) + : raw_stream(s) {} - bool handleDiagnostics(const DiagnosticInfo &DI) override { - llvm::DiagnosticPrinterRawOStream DP(raw_stream); - DI.print(DP); - return true; + bool handleDiagnostics(const DiagnosticInfo &DI) override { + llvm::DiagnosticPrinterRawOStream DP(raw_stream); + DI.print(DP); + return true; + } + + private: + llvm::raw_string_ostream &raw_stream; + }; + + // save current handler as "old" + auto OldDiagnosticHandler = Ctx.getDiagnosticHandler(); + + Ctx.setDiagnosticHandler( + std::make_unique(errstream)); + + // link + bool failed = LLVMLinkModules2(Dest, Src); + + // put old handler back + Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); + + // if linking failed extract the reason for the failure + if (failed) { + errstream.flush(); + *Err = LLVMPY_CreateString(errorstring.c_str()); } - private: - llvm::raw_string_ostream &raw_stream; - }; - - // save current handler as "old" - auto OldDiagnosticHandler = Ctx.getDiagnosticHandler(); - - Ctx.setDiagnosticHandler( - std::make_unique(errstream)); - - // link - bool failed = LLVMLinkModules2(Dest, Src); - - // put old handler back - Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); - - // if linking failed extract the reason for the failure - if (failed) { - errstream.flush(); - *Err = LLVMPY_CreateString(errorstring.c_str()); - } - - return failed; + return failed; } } // end extern "C" diff --git a/ffi/module.cpp b/ffi/module.cpp index 898691c8..55eed7dd 100644 --- a/ffi/module.cpp +++ b/ffi/module.cpp @@ -8,11 +8,11 @@ /* An iterator around a module's globals, including the stop condition */ struct GlobalsIterator { - typedef llvm::Module::global_iterator iterator; - iterator cur; - iterator end; + typedef llvm::Module::global_iterator iterator; + iterator cur; + iterator end; - GlobalsIterator(iterator cur, iterator end) : cur(cur), end(end) {} + GlobalsIterator(iterator cur, iterator end) : cur(cur), end(end) {} }; struct OpaqueGlobalsIterator; @@ -20,12 +20,12 @@ typedef OpaqueGlobalsIterator *LLVMGlobalsIteratorRef; /* An iterator around a module's functions, including the stop condition */ struct FunctionsIterator { - typedef llvm::Module::const_iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::Module::const_iterator const_iterator; + const_iterator cur; + const_iterator end; - FunctionsIterator(const_iterator cur, const_iterator end) - : cur(cur), end(end) {} + FunctionsIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueFunctionsIterator; @@ -33,22 +33,23 @@ typedef OpaqueFunctionsIterator *LLVMFunctionsIteratorRef; /* module types iterator */ class TypesIterator { -private: - llvm::TypeFinder finder; - using const_iterator = llvm::TypeFinder::const_iterator; - const_iterator cur; + private: + llvm::TypeFinder finder; + using const_iterator = llvm::TypeFinder::const_iterator; + const_iterator cur; -public: - TypesIterator(llvm::Module &m, bool namedOnly) : finder(llvm::TypeFinder()) { - finder.run(m, namedOnly); - cur = finder.begin(); - } - const llvm::Type *next() { - if (cur != finder.end()) { - return *cur++; + public: + TypesIterator(llvm::Module &m, bool namedOnly) + : finder(llvm::TypeFinder()) { + finder.run(m, namedOnly); + cur = finder.begin(); + } + const llvm::Type *next() { + if (cur != finder.end()) { + return *cur++; + } + return nullptr; } - return nullptr; - } }; typedef TypesIterator *LLVMTypesIteratorRef; @@ -60,27 +61,27 @@ typedef TypesIterator *LLVMTypesIteratorRef; namespace llvm { static LLVMGlobalsIteratorRef wrap(GlobalsIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static GlobalsIterator *unwrap(LLVMGlobalsIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMFunctionsIteratorRef wrap(FunctionsIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static FunctionsIterator *unwrap(LLVMFunctionsIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMTypesIteratorRef wrap(TypesIterator *TyI) { - return reinterpret_cast(TyI); + return reinterpret_cast(TyI); } static TypesIterator *unwrap(LLVMTypesIteratorRef TyI) { - return reinterpret_cast(TyI); + return reinterpret_cast(TyI); } } // end namespace llvm @@ -96,95 +97,95 @@ LLVMPY_DisposeModule(LLVMModuleRef m) { return LLVMDisposeModule(m); } API_EXPORT(void) LLVMPY_PrintModuleToString(LLVMModuleRef M, const char **outstr) { - // Change the locale to en_US before calling LLVM to print the module - // due to a LLVM bug https://llvm.org/bugs/show_bug.cgi?id=12906 - char *old_locale = strdup(setlocale(LC_ALL, NULL)); - setlocale(LC_ALL, "C"); + // Change the locale to en_US before calling LLVM to print the module + // due to a LLVM bug https://llvm.org/bugs/show_bug.cgi?id=12906 + char *old_locale = strdup(setlocale(LC_ALL, NULL)); + setlocale(LC_ALL, "C"); - *outstr = LLVMPrintModuleToString(M); + *outstr = LLVMPrintModuleToString(M); - // Revert locale - setlocale(LC_ALL, old_locale); - free(old_locale); + // Revert locale + setlocale(LC_ALL, old_locale); + free(old_locale); } API_EXPORT(const char *) LLVMPY_GetModuleSourceFileName(LLVMModuleRef M) { - return llvm::unwrap(M)->getSourceFileName().c_str(); + return llvm::unwrap(M)->getSourceFileName().c_str(); } API_EXPORT(const char *) LLVMPY_GetModuleName(LLVMModuleRef M) { - return llvm::unwrap(M)->getModuleIdentifier().c_str(); + return llvm::unwrap(M)->getModuleIdentifier().c_str(); } API_EXPORT(void) LLVMPY_SetModuleName(LLVMModuleRef M, const char *Name) { - llvm::unwrap(M)->setModuleIdentifier(Name); + llvm::unwrap(M)->setModuleIdentifier(Name); } API_EXPORT(LLVMValueRef) LLVMPY_GetNamedFunction(LLVMModuleRef M, const char *Name) { - return LLVMGetNamedFunction(M, Name); + return LLVMGetNamedFunction(M, Name); } API_EXPORT(LLVMValueRef) LLVMPY_GetNamedGlobalVariable(LLVMModuleRef M, const char *Name) { - using namespace llvm; - return wrap(unwrap(M)->getGlobalVariable(Name)); + using namespace llvm; + return wrap(unwrap(M)->getGlobalVariable(Name)); } API_EXPORT(LLVMTypeRef) LLVMPY_GetNamedStructType(LLVMModuleRef M, const char *Name) { - return LLVMGetTypeByName(M, Name); + return LLVMGetTypeByName(M, Name); } API_EXPORT(int) LLVMPY_VerifyModule(LLVMModuleRef M, char **OutMsg) { - return LLVMVerifyModule(M, LLVMReturnStatusAction, OutMsg); + return LLVMVerifyModule(M, LLVMReturnStatusAction, OutMsg); } API_EXPORT(void) LLVMPY_GetDataLayout(LLVMModuleRef M, const char **DL) { - *DL = LLVMGetDataLayoutStr(M); + *DL = LLVMGetDataLayoutStr(M); } API_EXPORT(void) LLVMPY_SetDataLayout(LLVMModuleRef M, const char *DL) { - LLVMSetDataLayout(M, DL); + LLVMSetDataLayout(M, DL); } API_EXPORT(void) LLVMPY_GetTarget(LLVMModuleRef M, const char **Triple) { - *Triple = LLVMGetTarget(M); + *Triple = LLVMGetTarget(M); } API_EXPORT(void) LLVMPY_SetTarget(LLVMModuleRef M, const char *Triple) { - LLVMSetTarget(M, Triple); + LLVMSetTarget(M, Triple); } // Iteration APIs API_EXPORT(LLVMGlobalsIteratorRef) LLVMPY_ModuleGlobalsIter(LLVMModuleRef M) { - using namespace llvm; - Module *mod = unwrap(M); - return wrap(new GlobalsIterator(mod->global_begin(), mod->global_end())); + using namespace llvm; + Module *mod = unwrap(M); + return wrap(new GlobalsIterator(mod->global_begin(), mod->global_end())); } API_EXPORT(LLVMFunctionsIteratorRef) LLVMPY_ModuleFunctionsIter(LLVMModuleRef M) { - using namespace llvm; - Module *mod = unwrap(M); - return wrap(new FunctionsIterator(mod->begin(), mod->end())); + using namespace llvm; + Module *mod = unwrap(M); + return wrap(new FunctionsIterator(mod->begin(), mod->end())); } API_EXPORT(LLVMTypesIteratorRef) LLVMPY_ModuleTypesIter(LLVMModuleRef M) { - llvm::Module *mod = llvm::unwrap(M); - auto *iter = new TypesIterator(*mod, false); - return llvm::wrap(iter); + llvm::Module *mod = llvm::unwrap(M); + auto *iter = new TypesIterator(*mod, false); + return llvm::wrap(iter); } /* @@ -192,39 +193,39 @@ LLVMPY_ModuleTypesIter(LLVMModuleRef M) { */ API_EXPORT(LLVMValueRef) LLVMPY_GlobalsIterNext(LLVMGlobalsIteratorRef GI) { - using namespace llvm; - GlobalsIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return wrap(&*iter->cur++); - } else { - return NULL; - } + using namespace llvm; + GlobalsIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return wrap(&*iter->cur++); + } else { + return NULL; + } } API_EXPORT(LLVMValueRef) LLVMPY_FunctionsIterNext(LLVMFunctionsIteratorRef GI) { - using namespace llvm; - FunctionsIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return wrap(&*iter->cur++); - } else { - return NULL; - } + using namespace llvm; + FunctionsIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return wrap(&*iter->cur++); + } else { + return NULL; + } } API_EXPORT(LLVMTypeRef) LLVMPY_TypesIterNext(LLVMTypesIteratorRef TyI) { - return llvm::wrap(llvm::unwrap(TyI)->next()); + return llvm::wrap(llvm::unwrap(TyI)->next()); } API_EXPORT(void) LLVMPY_DisposeGlobalsIter(LLVMGlobalsIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) LLVMPY_DisposeFunctionsIter(LLVMFunctionsIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) diff --git a/ffi/object_file.cpp b/ffi/object_file.cpp index f1ec288f..054a14d1 100644 --- a/ffi/object_file.cpp +++ b/ffi/object_file.cpp @@ -10,12 +10,12 @@ // From lib/Object/Object.cpp namespace llvm { inline object::section_iterator *unwrap(LLVMSectionIteratorRef SI) { - return reinterpret_cast(SI); + return reinterpret_cast(SI); } inline LLVMSectionIteratorRef wrap(const object::section_iterator *SI) { - return reinterpret_cast( - const_cast(SI)); + return reinterpret_cast( + const_cast(SI)); } } // namespace llvm @@ -23,13 +23,13 @@ extern "C" { API_EXPORT(LLVMObjectFileRef) LLVMPY_CreateObjectFile(const char *buf, const size_t n) { - return LLVMCreateObjectFile( - LLVMCreateMemoryBufferWithMemoryRangeCopy(buf, n, "")); + return LLVMCreateObjectFile( + LLVMCreateMemoryBufferWithMemoryRangeCopy(buf, n, "")); } API_EXPORT(void) LLVMPY_DisposeObjectFile(LLVMObjectFileRef O) { - return LLVMDisposeObjectFile(O); + return LLVMDisposeObjectFile(O); } API_EXPORT(LLVMSectionIteratorRef) @@ -37,42 +37,42 @@ LLVMPY_GetSections(LLVMObjectFileRef O) { return LLVMGetSections(O); } API_EXPORT(void) LLVMPY_DisposeSectionIterator(LLVMSectionIteratorRef SI) { - LLVMDisposeSectionIterator(SI); + LLVMDisposeSectionIterator(SI); } API_EXPORT(void) LLVMPY_MoveToNextSection(LLVMSectionIteratorRef SI) { - LLVMMoveToNextSection(SI); + LLVMMoveToNextSection(SI); } API_EXPORT(bool) LLVMPY_IsSectionIteratorAtEnd(LLVMObjectFileRef O, LLVMSectionIteratorRef SI) { - return LLVMIsSectionIteratorAtEnd(O, SI); + return LLVMIsSectionIteratorAtEnd(O, SI); } API_EXPORT(const char *) LLVMPY_GetSectionName(LLVMSectionIteratorRef SI) { - return LLVMGetSectionName(SI); + return LLVMGetSectionName(SI); } API_EXPORT(uint64_t) LLVMPY_GetSectionAddress(LLVMSectionIteratorRef SI) { - return LLVMGetSectionAddress(SI); + return LLVMGetSectionAddress(SI); } API_EXPORT(const char *) LLVMPY_GetSectionContents(LLVMSectionIteratorRef SI) { - return LLVMGetSectionContents(SI); + return LLVMGetSectionContents(SI); } API_EXPORT(uint64_t) LLVMPY_GetSectionSize(LLVMSectionIteratorRef SI) { - return LLVMGetSectionSize(SI); + return LLVMGetSectionSize(SI); } API_EXPORT(bool) LLVMPY_IsSectionText(LLVMSectionIteratorRef SI) { - return (*llvm::unwrap(SI))->isText(); + return (*llvm::unwrap(SI))->isText(); } } // end extern C diff --git a/ffi/passmanagers.cpp b/ffi/passmanagers.cpp index ab39ab5d..325a4576 100644 --- a/ffi/passmanagers.cpp +++ b/ffi/passmanagers.cpp @@ -28,11 +28,11 @@ LLVMPY_SetTimePasses(bool enable) { TimePassesIsEnabled = enable; } API_EXPORT(void) LLVMPY_ReportAndResetTimings(const char **outmsg) { - std::string osbuf; - raw_string_ostream os(osbuf); - reportAndResetTimings(&os); - os.flush(); - *outmsg = LLVMPY_CreateString(os.str().c_str()); + std::string osbuf; + raw_string_ostream os(osbuf); + reportAndResetTimings(&os); + os.flush(); + *outmsg = LLVMPY_CreateString(os.str().c_str()); } API_EXPORT(LLVMPassManagerRef) @@ -40,57 +40,57 @@ LLVMPY_CreatePassManager() { return LLVMCreatePassManager(); } API_EXPORT(void) LLVMPY_DisposePassManager(LLVMPassManagerRef PM) { - return LLVMDisposePassManager(PM); + return LLVMDisposePassManager(PM); } API_EXPORT(LLVMPassManagerRef) LLVMPY_CreateFunctionPassManager(LLVMModuleRef M) { - return LLVMCreateFunctionPassManagerForModule(M); + return LLVMCreateFunctionPassManagerForModule(M); } API_EXPORT(int) LLVMPY_RunPassManager(LLVMPassManagerRef PM, LLVMModuleRef M) { - return LLVMRunPassManager(PM, M); + return LLVMRunPassManager(PM, M); } API_EXPORT(int) LLVMPY_RunFunctionPassManager(LLVMPassManagerRef PM, LLVMValueRef F) { - return LLVMRunFunctionPassManager(PM, F); + return LLVMRunFunctionPassManager(PM, F); } API_EXPORT(int) LLVMPY_InitializeFunctionPassManager(LLVMPassManagerRef FPM) { - return LLVMInitializeFunctionPassManager(FPM); + return LLVMInitializeFunctionPassManager(FPM); } API_EXPORT(int) LLVMPY_FinalizeFunctionPassManager(LLVMPassManagerRef FPM) { - return LLVMFinalizeFunctionPassManager(FPM); + return LLVMFinalizeFunctionPassManager(FPM); } API_EXPORT(void) LLVMPY_AddConstantMergePass(LLVMPassManagerRef PM) { - LLVMAddConstantMergePass(PM); + LLVMAddConstantMergePass(PM); } API_EXPORT(void) LLVMPY_AddDeadArgEliminationPass(LLVMPassManagerRef PM) { - LLVMAddDeadArgEliminationPass(PM); + LLVMAddDeadArgEliminationPass(PM); } API_EXPORT(void) LLVMPY_AddFunctionAttrsPass(LLVMPassManagerRef PM) { - LLVMAddFunctionAttrsPass(PM); + LLVMAddFunctionAttrsPass(PM); } API_EXPORT(void) LLVMPY_AddFunctionInliningPass(LLVMPassManagerRef PM, int Threshold) { - unwrap(PM)->add(createFunctionInliningPass(Threshold)); + unwrap(PM)->add(createFunctionInliningPass(Threshold)); } API_EXPORT(void) LLVMPY_AddGlobalOptimizerPass(LLVMPassManagerRef PM) { - LLVMAddGlobalOptimizerPass(PM); + LLVMAddGlobalOptimizerPass(PM); } API_EXPORT(void) @@ -101,12 +101,12 @@ LLVMPY_AddIPSCCPPass(LLVMPassManagerRef PM) { LLVMAddIPSCCPPass(PM); } API_EXPORT(void) LLVMPY_AddDeadCodeEliminationPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createDeadCodeEliminationPass()); + unwrap(PM)->add(createDeadCodeEliminationPass()); } API_EXPORT(void) LLVMPY_AddCFGSimplificationPass(LLVMPassManagerRef PM) { - LLVMAddCFGSimplificationPass(PM); + LLVMAddCFGSimplificationPass(PM); } API_EXPORT(void) @@ -114,7 +114,7 @@ LLVMPY_AddGVNPass(LLVMPassManagerRef PM) { LLVMAddGVNPass(PM); } API_EXPORT(void) LLVMPY_AddInstructionCombiningPass(LLVMPassManagerRef PM) { - LLVMAddInstructionCombiningPass(PM); + LLVMAddInstructionCombiningPass(PM); } API_EXPORT(void) @@ -128,17 +128,17 @@ LLVMPY_AddSROAPass(LLVMPassManagerRef PM) { unwrap(PM)->add(createSROAPass()); } API_EXPORT(void) LLVMPY_AddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM) { - LLVMAddTypeBasedAliasAnalysisPass(PM); + LLVMAddTypeBasedAliasAnalysisPass(PM); } API_EXPORT(void) LLVMPY_AddBasicAliasAnalysisPass(LLVMPassManagerRef PM) { - LLVMAddBasicAliasAnalysisPass(PM); + LLVMAddBasicAliasAnalysisPass(PM); } API_EXPORT(void) LLVMPY_LLVMAddLoopRotatePass(LLVMPassManagerRef PM) { - LLVMAddLoopRotatePass(PM); + LLVMAddLoopRotatePass(PM); } } // end extern "C" diff --git a/ffi/targets.cpp b/ffi/targets.cpp index 2ee89202..3b5abf51 100644 --- a/ffi/targets.cpp +++ b/ffi/targets.cpp @@ -16,21 +16,21 @@ namespace llvm { inline LLVMTargetLibraryInfoRef wrap(TargetLibraryInfo *TLI) { - return reinterpret_cast(TLI); + return reinterpret_cast(TLI); } inline TargetLibraryInfo *unwrap(LLVMTargetLibraryInfoRef TLI) { - return reinterpret_cast(TLI); + return reinterpret_cast(TLI); } inline Target *unwrap(LLVMTargetRef T) { return reinterpret_cast(T); } inline TargetMachine *unwrap(LLVMTargetMachineRef TM) { - return reinterpret_cast(TM); + return reinterpret_cast(TM); } inline LLVMTargetMachineRef wrap(TargetMachine *TM) { - return reinterpret_cast(TM); + return reinterpret_cast(TM); } } // namespace llvm @@ -39,7 +39,7 @@ extern "C" { API_EXPORT(void) LLVMPY_GetProcessTriple(const char **Out) { - *Out = LLVMPY_CreateString(llvm::sys::getProcessTriple().c_str()); + *Out = LLVMPY_CreateString(llvm::sys::getProcessTriple().c_str()); } /** @@ -49,39 +49,39 @@ LLVMPY_GetProcessTriple(const char **Out) { */ API_EXPORT(int) LLVMPY_GetHostCPUFeatures(const char **Out) { - llvm::StringMap features; - std::ostringstream buf; - if (llvm::sys::getHostCPUFeatures(features)) { - for (auto &F : features) { - if (buf.tellp()) { - buf << ','; - } - buf << ((F.second ? "+" : "-") + F.first()).str(); + llvm::StringMap features; + std::ostringstream buf; + if (llvm::sys::getHostCPUFeatures(features)) { + for (auto &F : features) { + if (buf.tellp()) { + buf << ','; + } + buf << ((F.second ? "+" : "-") + F.first()).str(); + } + *Out = LLVMPY_CreateString(buf.str().c_str()); + return 1; } - *Out = LLVMPY_CreateString(buf.str().c_str()); - return 1; - } - return 0; + return 0; } API_EXPORT(void) LLVMPY_GetDefaultTargetTriple(const char **Out) { - *Out = LLVMPY_CreateString(llvm::sys::getDefaultTargetTriple().c_str()); + *Out = LLVMPY_CreateString(llvm::sys::getDefaultTargetTriple().c_str()); } API_EXPORT(void) LLVMPY_GetHostCPUName(const char **Out) { - *Out = LLVMPY_CreateString(llvm::sys::getHostCPUName().data()); + *Out = LLVMPY_CreateString(llvm::sys::getHostCPUName().data()); } API_EXPORT(int) LLVMPY_GetTripleObjectFormat(const char *tripleStr) { - return llvm::Triple(tripleStr).getObjectFormat(); + return llvm::Triple(tripleStr).getObjectFormat(); } API_EXPORT(LLVMTargetDataRef) LLVMPY_CreateTargetData(const char *StringRep) { - return LLVMCreateTargetData(StringRep); + return LLVMCreateTargetData(StringRep); } //// Nothing is creating a TargetLibraryInfo @@ -94,7 +94,7 @@ LLVMPY_CreateTargetData(const char *StringRep) { API_EXPORT(void) LLVMPY_CopyStringRepOfTargetData(LLVMTargetDataRef TD, char **Out) { - *Out = LLVMCopyStringRepOfTargetData(TD); + *Out = LLVMCopyStringRepOfTargetData(TD); } API_EXPORT(void) @@ -102,45 +102,45 @@ LLVMPY_DisposeTargetData(LLVMTargetDataRef TD) { LLVMDisposeTargetData(TD); } API_EXPORT(long long) LLVMPY_ABISizeOfType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - return (long long)LLVMABISizeOfType(TD, Ty); + return (long long)LLVMABISizeOfType(TD, Ty); } API_EXPORT(long long) LLVMPY_OffsetOfElement(LLVMTargetDataRef TD, LLVMTypeRef Ty, int Element) { - llvm::Type *tp = llvm::unwrap(Ty); - if (!tp->isStructTy()) - return -1; - return (long long)LLVMOffsetOfElement(TD, Ty, Element); + llvm::Type *tp = llvm::unwrap(Ty); + if (!tp->isStructTy()) + return -1; + return (long long)LLVMOffsetOfElement(TD, Ty, Element); } API_EXPORT(long long) LLVMPY_ABISizeOfElementType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - llvm::Type *tp = llvm::unwrap(Ty); - if (!tp->isPointerTy()) - return -1; - tp = tp->getPointerElementType(); - return (long long)LLVMABISizeOfType(TD, llvm::wrap(tp)); + llvm::Type *tp = llvm::unwrap(Ty); + if (!tp->isPointerTy()) + return -1; + tp = tp->getPointerElementType(); + return (long long)LLVMABISizeOfType(TD, llvm::wrap(tp)); } API_EXPORT(long long) LLVMPY_ABIAlignmentOfElementType(LLVMTargetDataRef TD, LLVMTypeRef Ty) { - llvm::Type *tp = llvm::unwrap(Ty); - if (!tp->isPointerTy()) - return -1; - tp = tp->getPointerElementType(); - return (long long)LLVMABIAlignmentOfType(TD, llvm::wrap(tp)); + llvm::Type *tp = llvm::unwrap(Ty); + if (!tp->isPointerTy()) + return -1; + tp = tp->getPointerElementType(); + return (long long)LLVMABIAlignmentOfType(TD, llvm::wrap(tp)); } API_EXPORT(LLVMTargetRef) LLVMPY_GetTargetFromTriple(const char *Triple, const char **ErrOut) { - char *ErrorMessage; - LLVMTargetRef T; - if (LLVMGetTargetFromTriple(Triple, &T, &ErrorMessage)) { - *ErrOut = LLVMPY_CreateString(ErrorMessage); - LLVMDisposeMessage(ErrorMessage); - return NULL; - } - return T; + char *ErrorMessage; + LLVMTargetRef T; + if (LLVMGetTargetFromTriple(Triple, &T, &ErrorMessage)) { + *ErrOut = LLVMPY_CreateString(ErrorMessage); + LLVMDisposeMessage(ErrorMessage); + return NULL; + } + return T; } API_EXPORT(const char *) @@ -148,7 +148,7 @@ LLVMPY_GetTargetName(LLVMTargetRef T) { return LLVMGetTargetName(T); } API_EXPORT(const char *) LLVMPY_GetTargetDescription(LLVMTargetRef T) { - return LLVMGetTargetDescription(T); + return LLVMGetTargetDescription(T); } API_EXPORT(LLVMTargetMachineRef) @@ -156,107 +156,108 @@ LLVMPY_CreateTargetMachine(LLVMTargetRef T, const char *Triple, const char *CPU, const char *Features, int OptLevel, const char *RelocModel, const char *CodeModel, int PrintMC, int JIT, const char *ABIName) { - using namespace llvm; - CodeGenOpt::Level cgol; - switch (OptLevel) { - case 0: - cgol = CodeGenOpt::None; - break; - case 1: - cgol = CodeGenOpt::Less; - break; - case 3: - cgol = CodeGenOpt::Aggressive; - break; - case 2: - default: - cgol = CodeGenOpt::Default; - } + using namespace llvm; + CodeGenOpt::Level cgol; + switch (OptLevel) { + case 0: + cgol = CodeGenOpt::None; + break; + case 1: + cgol = CodeGenOpt::Less; + break; + case 3: + cgol = CodeGenOpt::Aggressive; + break; + case 2: + default: + cgol = CodeGenOpt::Default; + } - CodeModel::Model cm; - std::string cms(CodeModel); - if (cms == "small") - cm = CodeModel::Small; - else if (cms == "kernel") - cm = CodeModel::Kernel; - else if (cms == "medium") - cm = CodeModel::Medium; - else if (cms == "large") - cm = CodeModel::Large; - else if (cms == "default") // As per LLVM 5, needed for AOT - cm = CodeModel::Small; - else { // catches "jitdefault" and not set, as per LLVM 5, needed for MCJIT - // fall through, use model based on bitness - int bits = sizeof(void *); - if (bits == 4) - cm = CodeModel::Small; - else - cm = CodeModel::Large; - } + CodeModel::Model cm; + std::string cms(CodeModel); + if (cms == "small") + cm = CodeModel::Small; + else if (cms == "kernel") + cm = CodeModel::Kernel; + else if (cms == "medium") + cm = CodeModel::Medium; + else if (cms == "large") + cm = CodeModel::Large; + else if (cms == "default") // As per LLVM 5, needed for AOT + cm = CodeModel::Small; + else { // catches "jitdefault" and not set, as per LLVM 5, needed for MCJIT + // fall through, use model based on bitness + int bits = sizeof(void *); + if (bits == 4) + cm = CodeModel::Small; + else + cm = CodeModel::Large; + } - Optional rm; - std::string rms(RelocModel); - if (rms == "static") - rm = Reloc::Static; - else if (rms == "pic") - rm = Reloc::PIC_; - else if (rms == "dynamicnopic") - rm = Reloc::DynamicNoPIC; + Optional rm; + std::string rms(RelocModel); + if (rms == "static") + rm = Reloc::Static; + else if (rms == "pic") + rm = Reloc::PIC_; + else if (rms == "dynamicnopic") + rm = Reloc::DynamicNoPIC; - TargetOptions opt; - opt.PrintMachineCode = PrintMC; - opt.MCOptions.ABIName = ABIName; + TargetOptions opt; + opt.PrintMachineCode = PrintMC; + opt.MCOptions.ABIName = ABIName; - bool jit = JIT; + bool jit = JIT; - return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, rm, cm, - cgol, jit)); + return wrap(unwrap(T)->createTargetMachine(Triple, CPU, Features, opt, rm, + cm, cgol, jit)); } API_EXPORT(void) LLVMPY_DisposeTargetMachine(LLVMTargetMachineRef TM) { - return LLVMDisposeTargetMachine(TM); + return LLVMDisposeTargetMachine(TM); } API_EXPORT(void) LLVMPY_GetTargetMachineTriple(LLVMTargetMachineRef TM, const char **Out) { - // result is already strdup()ed by LLVMGetTargetMachineTriple - *Out = LLVMGetTargetMachineTriple(TM); + // result is already strdup()ed by LLVMGetTargetMachineTriple + *Out = LLVMGetTargetMachineTriple(TM); } API_EXPORT(void) LLVMPY_SetTargetMachineAsmVerbosity(LLVMTargetMachineRef TM, int verbose) { - LLVMSetTargetMachineAsmVerbosity(TM, verbose); + LLVMSetTargetMachineAsmVerbosity(TM, verbose); } API_EXPORT(LLVMMemoryBufferRef) LLVMPY_TargetMachineEmitToMemory(LLVMTargetMachineRef TM, LLVMModuleRef M, int use_object, const char **ErrOut) { - LLVMCodeGenFileType filetype = LLVMAssemblyFile; - if (use_object) - filetype = LLVMObjectFile; + LLVMCodeGenFileType filetype = LLVMAssemblyFile; + if (use_object) + filetype = LLVMObjectFile; - char *ErrorMessage; - LLVMMemoryBufferRef BufOut; - int err = LLVMTargetMachineEmitToMemoryBuffer(TM, M, filetype, &ErrorMessage, - &BufOut); - if (err) { - *ErrOut = LLVMPY_CreateString(ErrorMessage); - LLVMDisposeMessage(ErrorMessage); - return NULL; - } + char *ErrorMessage; + LLVMMemoryBufferRef BufOut; + int err = LLVMTargetMachineEmitToMemoryBuffer(TM, M, filetype, + &ErrorMessage, &BufOut); + if (err) { + *ErrOut = LLVMPY_CreateString(ErrorMessage); + LLVMDisposeMessage(ErrorMessage); + return NULL; + } - return BufOut; + return BufOut; } API_EXPORT(LLVMTargetDataRef) LLVMPY_CreateTargetMachineData(LLVMTargetMachineRef TM) { - return llvm::wrap(new llvm::DataLayout(llvm::unwrap(TM)->createDataLayout())); + return llvm::wrap( + new llvm::DataLayout(llvm::unwrap(TM)->createDataLayout())); } API_EXPORT(void) LLVMPY_AddAnalysisPasses(LLVMTargetMachineRef TM, LLVMPassManagerRef PM) { - LLVMAddAnalysisPasses(TM, PM); + LLVMAddAnalysisPasses(TM, PM); } API_EXPORT(const void *) @@ -267,15 +268,15 @@ LLVMPY_GetBufferSize(LLVMMemoryBufferRef MB) { return LLVMGetBufferSize(MB); } API_EXPORT(void) LLVMPY_DisposeMemoryBuffer(LLVMMemoryBufferRef MB) { - return LLVMDisposeMemoryBuffer(MB); + return LLVMDisposeMemoryBuffer(MB); } API_EXPORT(int) LLVMPY_HasSVMLSupport(void) { #ifdef HAVE_SVML - return 1; + return 1; #else - return 0; + return 0; #endif } diff --git a/ffi/transforms.cpp b/ffi/transforms.cpp index 03b6cb05..8d6d7f39 100644 --- a/ffi/transforms.cpp +++ b/ffi/transforms.cpp @@ -10,87 +10,87 @@ LLVMPY_PassManagerBuilderCreate() { return LLVMPassManagerBuilderCreate(); } API_EXPORT(void) LLVMPY_PassManagerBuilderDispose(LLVMPassManagerBuilderRef PMB) { - LLVMPassManagerBuilderDispose(PMB); + LLVMPassManagerBuilderDispose(PMB); } API_EXPORT(void) LLVMPY_PassManagerBuilderPopulateModulePassManager( LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { - LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); + LLVMPassManagerBuilderPopulateModulePassManager(PMB, PM); } API_EXPORT(unsigned) LLVMPY_PassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->OptLevel; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->OptLevel; } API_EXPORT(void) LLVMPY_PassManagerBuilderSetOptLevel(LLVMPassManagerBuilderRef PMB, unsigned OptLevel) { - LLVMPassManagerBuilderSetOptLevel(PMB, OptLevel); + LLVMPassManagerBuilderSetOptLevel(PMB, OptLevel); } API_EXPORT(unsigned) LLVMPY_PassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->SizeLevel; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->SizeLevel; } API_EXPORT(void) LLVMPY_PassManagerBuilderSetSizeLevel(LLVMPassManagerBuilderRef PMB, unsigned SizeLevel) { - LLVMPassManagerBuilderSetSizeLevel(PMB, SizeLevel); + LLVMPassManagerBuilderSetSizeLevel(PMB, SizeLevel); } API_EXPORT(int) LLVMPY_PassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->DisableUnrollLoops; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->DisableUnrollLoops; } API_EXPORT(void) LLVMPY_PassManagerBuilderSetDisableUnrollLoops(LLVMPassManagerBuilderRef PMB, LLVMBool Value) { - LLVMPassManagerBuilderSetDisableUnrollLoops(PMB, Value); + LLVMPassManagerBuilderSetDisableUnrollLoops(PMB, Value); } API_EXPORT(void) LLVMPY_PassManagerBuilderUseInlinerWithThreshold(LLVMPassManagerBuilderRef PMB, unsigned Threshold) { - LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); + LLVMPassManagerBuilderUseInlinerWithThreshold(PMB, Threshold); } API_EXPORT(void) LLVMPY_PassManagerBuilderPopulateFunctionPassManager( LLVMPassManagerBuilderRef PMB, LLVMPassManagerRef PM) { - LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); + LLVMPassManagerBuilderPopulateFunctionPassManager(PMB, PM); } API_EXPORT(void) LLVMPY_PassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef PMB, int Value) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - pmb->LoopVectorize = Value; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + pmb->LoopVectorize = Value; } API_EXPORT(int) LLVMPY_PassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->LoopVectorize; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->LoopVectorize; } API_EXPORT(void) LLVMPY_PassManagerBuilderSetSLPVectorize(LLVMPassManagerBuilderRef PMB, int Value) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - pmb->SLPVectorize = Value; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + pmb->SLPVectorize = Value; } API_EXPORT(int) LLVMPY_PassManagerBuilderGetSLPVectorize(LLVMPassManagerBuilderRef PMB) { - llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); - return pmb->SLPVectorize; + llvm::PassManagerBuilder *pmb = llvm::unwrap(PMB); + return pmb->SLPVectorize; } } // end extern "C" diff --git a/ffi/value.cpp b/ffi/value.cpp index e8222ca5..771acd42 100644 --- a/ffi/value.cpp +++ b/ffi/value.cpp @@ -9,12 +9,12 @@ /* An iterator around a attribute list, including the stop condition */ struct AttributeListIterator { - typedef llvm::AttributeList::iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::AttributeList::iterator const_iterator; + const_iterator cur; + const_iterator end; - AttributeListIterator(const_iterator cur, const_iterator end) - : cur(cur), end(end) {} + AttributeListIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueAttributeListIterator; @@ -22,12 +22,12 @@ typedef OpaqueAttributeListIterator *LLVMAttributeListIteratorRef; /* An iterator around a attribute set, including the stop condition */ struct AttributeSetIterator { - typedef llvm::AttributeSet::iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::AttributeSet::iterator const_iterator; + const_iterator cur; + const_iterator end; - AttributeSetIterator(const_iterator cur, const_iterator end) - : cur(cur), end(end) {} + AttributeSetIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueAttributeSetIterator; @@ -35,11 +35,12 @@ typedef OpaqueAttributeSetIterator *LLVMAttributeSetIteratorRef; /* An iterator around a function's blocks, including the stop condition */ struct BlocksIterator { - typedef llvm::Function::const_iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::Function::const_iterator const_iterator; + const_iterator cur; + const_iterator end; - BlocksIterator(const_iterator cur, const_iterator end) : cur(cur), end(end) {} + BlocksIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueBlocksIterator; @@ -47,12 +48,12 @@ typedef OpaqueBlocksIterator *LLVMBlocksIteratorRef; /* An iterator around a function's arguments, including the stop condition */ struct ArgumentsIterator { - typedef llvm::Function::const_arg_iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::Function::const_arg_iterator const_iterator; + const_iterator cur; + const_iterator end; - ArgumentsIterator(const_iterator cur, const_iterator end) - : cur(cur), end(end) {} + ArgumentsIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueArgumentsIterator; @@ -61,12 +62,12 @@ typedef OpaqueArgumentsIterator *LLVMArgumentsIteratorRef; /* An iterator around a basic block's instructions, including the stop condition */ struct InstructionsIterator { - typedef llvm::BasicBlock::const_iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::BasicBlock::const_iterator const_iterator; + const_iterator cur; + const_iterator end; - InstructionsIterator(const_iterator cur, const_iterator end) - : cur(cur), end(end) {} + InstructionsIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueInstructionsIterator; @@ -74,12 +75,12 @@ typedef OpaqueInstructionsIterator *LLVMInstructionsIteratorRef; /* An iterator around a instruction's operands, including the stop condition */ struct OperandsIterator { - typedef llvm::Instruction::const_op_iterator const_iterator; - const_iterator cur; - const_iterator end; + typedef llvm::Instruction::const_op_iterator const_iterator; + const_iterator cur; + const_iterator end; - OperandsIterator(const_iterator cur, const_iterator end) - : cur(cur), end(end) {} + OperandsIterator(const_iterator cur, const_iterator end) + : cur(cur), end(end) {} }; struct OpaqueOperandsIterator; @@ -88,51 +89,51 @@ typedef OpaqueOperandsIterator *LLVMOperandsIteratorRef; namespace llvm { static LLVMAttributeListIteratorRef wrap(AttributeListIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static AttributeListIterator *unwrap(LLVMAttributeListIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMAttributeSetIteratorRef wrap(AttributeSetIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static AttributeSetIterator *unwrap(LLVMAttributeSetIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMBlocksIteratorRef wrap(BlocksIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static BlocksIterator *unwrap(LLVMBlocksIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMArgumentsIteratorRef wrap(ArgumentsIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static ArgumentsIterator *unwrap(LLVMArgumentsIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMInstructionsIteratorRef wrap(InstructionsIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static InstructionsIterator *unwrap(LLVMInstructionsIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static LLVMOperandsIteratorRef wrap(OperandsIterator *GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } static OperandsIterator *unwrap(LLVMOperandsIteratorRef GI) { - return reinterpret_cast(GI); + return reinterpret_cast(GI); } } // namespace llvm @@ -141,148 +142,148 @@ extern "C" { API_EXPORT(LLVMAttributeListIteratorRef) LLVMPY_FunctionAttributesIter(LLVMValueRef F) { - using namespace llvm; - Function *func = unwrap(F); - AttributeList attrs = func->getAttributes(); - return wrap(new AttributeListIterator(attrs.begin(), attrs.end())); + using namespace llvm; + Function *func = unwrap(F); + AttributeList attrs = func->getAttributes(); + return wrap(new AttributeListIterator(attrs.begin(), attrs.end())); } API_EXPORT(LLVMAttributeSetIteratorRef) LLVMPY_ArgumentAttributesIter(LLVMValueRef A) { - using namespace llvm; - Argument *arg = unwrap(A); - unsigned argno = arg->getArgNo(); - AttributeSet attrs = - arg->getParent()->getAttributes().getParamAttributes(argno); - return wrap(new AttributeSetIterator(attrs.begin(), attrs.end())); + using namespace llvm; + Argument *arg = unwrap(A); + unsigned argno = arg->getArgNo(); + AttributeSet attrs = + arg->getParent()->getAttributes().getParamAttributes(argno); + return wrap(new AttributeSetIterator(attrs.begin(), attrs.end())); } API_EXPORT(LLVMAttributeListIteratorRef) LLVMPY_CallInstAttributesIter(LLVMValueRef C) { - using namespace llvm; - CallInst *inst = unwrap(C); - AttributeList attrs = inst->getAttributes(); - return wrap(new AttributeListIterator(attrs.begin(), attrs.end())); + using namespace llvm; + CallInst *inst = unwrap(C); + AttributeList attrs = inst->getAttributes(); + return wrap(new AttributeListIterator(attrs.begin(), attrs.end())); } API_EXPORT(LLVMAttributeListIteratorRef) LLVMPY_InvokeInstAttributesIter(LLVMValueRef C) { - using namespace llvm; - InvokeInst *inst = unwrap(C); - AttributeList attrs = inst->getAttributes(); - return wrap(new AttributeListIterator(attrs.begin(), attrs.end())); + using namespace llvm; + InvokeInst *inst = unwrap(C); + AttributeList attrs = inst->getAttributes(); + return wrap(new AttributeListIterator(attrs.begin(), attrs.end())); } API_EXPORT(LLVMAttributeSetIteratorRef) LLVMPY_GlobalAttributesIter(LLVMValueRef G) { - using namespace llvm; - GlobalVariable *g = unwrap(G); - AttributeSet attrs = g->getAttributes(); - return wrap(new AttributeSetIterator(attrs.begin(), attrs.end())); + using namespace llvm; + GlobalVariable *g = unwrap(G); + AttributeSet attrs = g->getAttributes(); + return wrap(new AttributeSetIterator(attrs.begin(), attrs.end())); } API_EXPORT(LLVMBlocksIteratorRef) LLVMPY_FunctionBlocksIter(LLVMValueRef F) { - using namespace llvm; - Function *func = unwrap(F); - return wrap(new BlocksIterator(func->begin(), func->end())); + using namespace llvm; + Function *func = unwrap(F); + return wrap(new BlocksIterator(func->begin(), func->end())); } API_EXPORT(LLVMArgumentsIteratorRef) LLVMPY_FunctionArgumentsIter(LLVMValueRef F) { - using namespace llvm; - Function *func = unwrap(F); - return wrap(new ArgumentsIterator(func->arg_begin(), func->arg_end())); + using namespace llvm; + Function *func = unwrap(F); + return wrap(new ArgumentsIterator(func->arg_begin(), func->arg_end())); } API_EXPORT(LLVMInstructionsIteratorRef) LLVMPY_BlockInstructionsIter(LLVMValueRef B) { - using namespace llvm; - BasicBlock *block = unwrap(B); - return wrap(new InstructionsIterator(block->begin(), block->end())); + using namespace llvm; + BasicBlock *block = unwrap(B); + return wrap(new InstructionsIterator(block->begin(), block->end())); } API_EXPORT(LLVMOperandsIteratorRef) LLVMPY_InstructionOperandsIter(LLVMValueRef I) { - using namespace llvm; - Instruction *inst = unwrap(I); - return wrap(new OperandsIterator(inst->op_begin(), inst->op_end())); + using namespace llvm; + Instruction *inst = unwrap(I); + return wrap(new OperandsIterator(inst->op_begin(), inst->op_end())); } API_EXPORT(const char *) LLVMPY_AttributeListIterNext(LLVMAttributeListIteratorRef GI) { - using namespace llvm; - AttributeListIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return LLVMPY_CreateString((&*iter->cur++)->getAsString().c_str()); - } else { - return NULL; - } + using namespace llvm; + AttributeListIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return LLVMPY_CreateString((&*iter->cur++)->getAsString().c_str()); + } else { + return NULL; + } } API_EXPORT(const char *) LLVMPY_AttributeSetIterNext(LLVMAttributeSetIteratorRef GI) { - using namespace llvm; - AttributeSetIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return LLVMPY_CreateString((&*iter->cur++)->getAsString().c_str()); - } else { - return NULL; - } + using namespace llvm; + AttributeSetIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return LLVMPY_CreateString((&*iter->cur++)->getAsString().c_str()); + } else { + return NULL; + } } API_EXPORT(LLVMValueRef) LLVMPY_BlocksIterNext(LLVMBlocksIteratorRef GI) { - using namespace llvm; - BlocksIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return wrap(static_cast(&*iter->cur++)); - } else { - return NULL; - } + using namespace llvm; + BlocksIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return wrap(static_cast(&*iter->cur++)); + } else { + return NULL; + } } API_EXPORT(LLVMValueRef) LLVMPY_ArgumentsIterNext(LLVMArgumentsIteratorRef GI) { - using namespace llvm; - ArgumentsIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return wrap(&*iter->cur++); - } else { - return NULL; - } + using namespace llvm; + ArgumentsIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return wrap(&*iter->cur++); + } else { + return NULL; + } } API_EXPORT(LLVMValueRef) LLVMPY_InstructionsIterNext(LLVMInstructionsIteratorRef GI) { - using namespace llvm; - InstructionsIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return wrap(&*iter->cur++); - } else { - return NULL; - } + using namespace llvm; + InstructionsIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return wrap(&*iter->cur++); + } else { + return NULL; + } } API_EXPORT(LLVMValueRef) LLVMPY_OperandsIterNext(LLVMOperandsIteratorRef GI) { - using namespace llvm; - OperandsIterator *iter = unwrap(GI); - if (iter->cur != iter->end) { - return wrap((&*iter->cur++)->get()); - } else { - return NULL; - } + using namespace llvm; + OperandsIterator *iter = unwrap(GI); + if (iter->cur != iter->end) { + return wrap((&*iter->cur++)->get()); + } else { + return NULL; + } } API_EXPORT(void) LLVMPY_DisposeAttributeListIter(LLVMAttributeListIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) LLVMPY_DisposeAttributeSetIter(LLVMAttributeSetIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) @@ -290,22 +291,22 @@ LLVMPY_DisposeBlocksIter(LLVMBlocksIteratorRef GI) { delete llvm::unwrap(GI); } API_EXPORT(void) LLVMPY_DisposeArgumentsIter(LLVMArgumentsIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) LLVMPY_DisposeInstructionsIter(LLVMInstructionsIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) LLVMPY_DisposeOperandsIter(LLVMOperandsIteratorRef GI) { - delete llvm::unwrap(GI); + delete llvm::unwrap(GI); } API_EXPORT(void) LLVMPY_PrintValueToString(LLVMValueRef Val, const char **outstr) { - *outstr = LLVMPrintValueToString(Val); + *outstr = LLVMPrintValueToString(Val); } API_EXPORT(const char *) @@ -313,7 +314,7 @@ LLVMPY_GetValueName(LLVMValueRef Val) { return LLVMGetValueName(Val); } API_EXPORT(void) LLVMPY_SetValueName(LLVMValueRef Val, const char *Name) { - LLVMSetValueName(Val, Name); + LLVMSetValueName(Val, Name); } API_EXPORT(LLVMModuleRef) @@ -324,42 +325,42 @@ LLVMPY_TypeOf(LLVMValueRef Val) { return LLVMTypeOf(Val); } API_EXPORT(const char *) LLVMPY_PrintType(LLVMTypeRef type) { - char *str = LLVMPrintTypeToString(type); - const char *out = LLVMPY_CreateString(str); - LLVMDisposeMessage(str); - return out; + char *str = LLVMPrintTypeToString(type); + const char *out = LLVMPY_CreateString(str); + LLVMDisposeMessage(str); + return out; } API_EXPORT(const char *) LLVMPY_GetTypeName(LLVMTypeRef type) { - // try to convert to a struct type, works for other derived - // types too - llvm::Type *unwrapped = llvm::unwrap(type); - llvm::StructType *ty = llvm::dyn_cast(unwrapped); - if (ty && !ty->isLiteral()) { - return LLVMPY_CreateString(ty->getStructName().str().c_str()); - } - return LLVMPY_CreateString(""); + // try to convert to a struct type, works for other derived + // types too + llvm::Type *unwrapped = llvm::unwrap(type); + llvm::StructType *ty = llvm::dyn_cast(unwrapped); + if (ty && !ty->isLiteral()) { + return LLVMPY_CreateString(ty->getStructName().str().c_str()); + } + return LLVMPY_CreateString(""); } API_EXPORT(bool) LLVMPY_TypeIsPointer(LLVMTypeRef type) { - return llvm::unwrap(type)->isPointerTy(); + return llvm::unwrap(type)->isPointerTy(); } API_EXPORT(LLVMTypeRef) LLVMPY_GetElementType(LLVMTypeRef type) { - llvm::Type *unwrapped = llvm::unwrap(type); - llvm::PointerType *ty = llvm::dyn_cast(unwrapped); - if (ty != nullptr) { - return llvm::wrap(ty->getElementType()); - } - return nullptr; + llvm::Type *unwrapped = llvm::unwrap(type); + llvm::PointerType *ty = llvm::dyn_cast(unwrapped); + if (ty != nullptr) { + return llvm::wrap(ty->getElementType()); + } + return nullptr; } API_EXPORT(void) LLVMPY_SetLinkage(LLVMValueRef Val, int Linkage) { - LLVMSetLinkage(Val, (LLVMLinkage)Linkage); + LLVMSetLinkage(Val, (LLVMLinkage)Linkage); } API_EXPORT(int) @@ -367,7 +368,7 @@ LLVMPY_GetLinkage(LLVMValueRef Val) { return (int)LLVMGetLinkage(Val); } API_EXPORT(void) LLVMPY_SetVisibility(LLVMValueRef Val, int Visibility) { - LLVMSetVisibility(Val, (LLVMVisibility)Visibility); + LLVMSetVisibility(Val, (LLVMVisibility)Visibility); } API_EXPORT(int) @@ -375,25 +376,25 @@ LLVMPY_GetVisibility(LLVMValueRef Val) { return (int)LLVMGetVisibility(Val); } API_EXPORT(void) LLVMPY_SetDLLStorageClass(LLVMValueRef Val, int DLLStorageClass) { - LLVMSetDLLStorageClass(Val, (LLVMDLLStorageClass)DLLStorageClass); + LLVMSetDLLStorageClass(Val, (LLVMDLLStorageClass)DLLStorageClass); } API_EXPORT(int) LLVMPY_GetDLLStorageClass(LLVMValueRef Val) { - return (int)LLVMGetDLLStorageClass(Val); + return (int)LLVMGetDLLStorageClass(Val); } API_EXPORT(unsigned) LLVMPY_GetEnumAttributeKindForName(const char *name, size_t len) { - /* zero is returned if no match */ - return LLVMGetEnumAttributeKindForName(name, len); + /* zero is returned if no match */ + return LLVMGetEnumAttributeKindForName(name, len); } API_EXPORT(void) LLVMPY_AddFunctionAttr(LLVMValueRef Fn, unsigned AttrKind) { - LLVMContextRef ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Fn)); - LLVMAttributeRef attr_ref = LLVMCreateEnumAttribute(ctx, AttrKind, 0); - LLVMAddAttributeAtIndex(Fn, LLVMAttributeReturnIndex, attr_ref); + LLVMContextRef ctx = LLVMGetModuleContext(LLVMGetGlobalParent(Fn)); + LLVMAttributeRef attr_ref = LLVMCreateEnumAttribute(ctx, AttrKind, 0); + LLVMAddAttributeAtIndex(Fn, LLVMAttributeReturnIndex, attr_ref); } API_EXPORT(int) @@ -401,25 +402,25 @@ LLVMPY_IsDeclaration(LLVMValueRef GV) { return LLVMIsDeclaration(GV); } API_EXPORT(void) LLVMPY_WriteCFG(LLVMValueRef Fval, const char **OutStr, int ShowInst) { - using namespace llvm; - Function *F = unwrap(Fval); - std::string buffer; - raw_string_ostream stream(buffer); - DOTFuncInfo CFGInfo(F, nullptr, nullptr, 0); - WriteGraph(stream, &CFGInfo, !ShowInst); - *OutStr = LLVMPY_CreateString(stream.str().c_str()); + using namespace llvm; + Function *F = unwrap(Fval); + std::string buffer; + raw_string_ostream stream(buffer); + DOTFuncInfo CFGInfo(F, nullptr, nullptr, 0); + WriteGraph(stream, &CFGInfo, !ShowInst); + *OutStr = LLVMPY_CreateString(stream.str().c_str()); } API_EXPORT(const char *) LLVMPY_GetOpcodeName(LLVMValueRef Val) { - // try to convert to an instruction value, works for other derived - // types too - llvm::Value *unwrapped = llvm::unwrap(Val); - llvm::Instruction *inst = llvm::dyn_cast(unwrapped); - if (inst) { - return LLVMPY_CreateString(inst->getOpcodeName()); - } - return LLVMPY_CreateString(""); + // try to convert to an instruction value, works for other derived + // types too + llvm::Value *unwrapped = llvm::unwrap(Val); + llvm::Instruction *inst = llvm::dyn_cast(unwrapped); + if (inst) { + return LLVMPY_CreateString(inst->getOpcodeName()); + } + return LLVMPY_CreateString(""); } } // end extern "C"