irgen.h 8.07 KB
Newer Older
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1
// Copyright (c) 2014-2015 Dropbox, Inc.
Kevin Modzelewski's avatar
Kevin Modzelewski committed
2
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
3 4 5
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
Kevin Modzelewski's avatar
Kevin Modzelewski committed
6
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
7
//    http://www.apache.org/licenses/LICENSE-2.0
Kevin Modzelewski's avatar
Kevin Modzelewski committed
8
//
Kevin Modzelewski's avatar
Kevin Modzelewski committed
9 10 11 12 13 14 15 16 17
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef PYSTON_CODEGEN_IRGEN_H
#define PYSTON_CODEGEN_IRGEN_H

18 19
#include "llvm/ADT/SmallString.h"
#include "llvm/ExecutionEngine/ObjectCache.h"
20
#include "llvm/IR/CallSite.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
21
#include "llvm/IR/Function.h"
22 23
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IRBuilder.h"
24
#include "llvm/IR/ValueMap.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
25

26
#include "core/options.h"
27
#include "core/types.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
28 29 30 31

namespace pyston {

class AST_expr;
32
class AST_stmt;
33
class CFGBlock;
34
class GCBuilder;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
35
class IREmitter;
36

37
struct UnwindInfo {
38
public:
39
    AST_stmt* current_stmt;
40

41
    llvm::BasicBlock* exc_dest;
42

43
    bool hasHandler() const { return exc_dest != NULL; }
44

45 46 47
    UnwindInfo(AST_stmt* current_stmt, llvm::BasicBlock* exc_dest) : current_stmt(current_stmt), exc_dest(exc_dest) {}

    ExceptionStyle preferredExceptionStyle() const;
48

49 50 51
    // Risky!  This means that we can't unwind from this location, and should be used in the
    // rare case that there are language-specific reasons that the statement should not unwind
    // (ex: loading function arguments into the appropriate scopes).
52
    static UnwindInfo cantUnwind() { return UnwindInfo(NULL, NULL); }
53 54 55
};

// TODO get rid of this
Kevin Modzelewski's avatar
Kevin Modzelewski committed
56
class MyInserter : public llvm::IRBuilderDefaultInserter<true> {
57 58
private:
    IREmitter* emitter;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
59

60 61 62
protected:
    void InsertHelper(llvm::Instruction* I, const llvm::Twine& Name, llvm::BasicBlock* BB,
                      llvm::BasicBlock::iterator InsertPt) const;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
63

64 65
public:
    void setEmitter(IREmitter* emitter) { this->emitter = emitter; }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
66 67
};

68
class ICSetupInfo;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
69 70

class IREmitter {
71 72
public:
    typedef llvm::IRBuilder<true, llvm::ConstantFolder, MyInserter> IRBuilder;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
73

74
    virtual ~IREmitter() {}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
75

76 77 78
    virtual IRBuilder* getBuilder() = 0;
    virtual GCBuilder* getGC() = 0;
    virtual CompiledFunction* currentFunction() = 0;
79
    virtual llvm::BasicBlock* currentBasicBlock() = 0;
80
    virtual llvm::BasicBlock* createBasicBlock(const char* name = "") = 0;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
81

82 83
    virtual void setCurrentBasicBlock(llvm::BasicBlock*) = 0;

84 85 86
    virtual llvm::Value* getScratch(int num_bytes) = 0;
    virtual void releaseScratch(llvm::Value*) = 0;

87
    virtual llvm::Function* getIntrinsic(llvm::Intrinsic::ID) = 0;
88

89 90
    virtual llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
                                    const std::vector<llvm::Value*>& args, ExceptionStyle target_exception_style = CXX)
91
        = 0;
92 93 94 95 96 97 98 99
    virtual llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
                                    ExceptionStyle target_exception_style = CXX) = 0;
    virtual llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
                                    ExceptionStyle target_exception_style = CXX) = 0;
    virtual llvm::Value* createCall2(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
                                     llvm::Value* arg2, ExceptionStyle target_exception_style = CXX) = 0;
    virtual llvm::Value* createCall3(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
                                     llvm::Value* arg2, llvm::Value* arg3, ExceptionStyle target_exception_style = CXX)
100
        = 0;
101
    virtual llvm::Value* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args,
102 103 104 105
                                  const UnwindInfo& unw_info, ExceptionStyle target_exception_style = CXX) = 0;

    virtual void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val,
                                                llvm::Value* exc_val, bool double_check = false) = 0;
106

107 108 109 110 111
    virtual BORROWED(Box*) getIntConstant(int64_t n) = 0;
    virtual BORROWED(Box*) getFloatConstant(double d) = 0;

    virtual void setType(llvm::Value* v, RefType reftype) = 0;
    virtual ConcreteCompilerVariable* getNone() = 0;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
112 113
};

Kevin Modzelewski's avatar
Kevin Modzelewski committed
114 115 116 117
extern const std::string CREATED_CLOSURE_NAME;
extern const std::string PASSED_CLOSURE_NAME;
extern const std::string PASSED_GENERATOR_NAME;

118
InternedString getIsDefinedName(InternedString name, InternedStringPool& interned_strings);
119
bool isIsDefinedName(llvm::StringRef name);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
120

121
CompiledFunction* doCompile(FunctionMetadata* md, SourceInfo* source, ParamNames* param_names,
122
                            const OSREntryDescriptor* entry_descriptor, EffortLevel effort,
123
                            ExceptionStyle exception_style, FunctionSpecialization* spec, llvm::StringRef nameprefix);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
124

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
// A common pattern is to branch based off whether a variable is defined but only if it is
// potentially-undefined.  If it is potentially-undefined, we have to generate control-flow
// that branches on the is_defined variable and then generate different code on those two paths;
// if the variable is guaranteed to be defined, we just want to emit the when_defined version.
//
// I suppose we could always emit both and let the LLVM optimizer fix it up for us, but for now
// do it the hard (and hopefully faster) way.
//
// - is_defined_var is allowed to be NULL, signifying that the variable is always defined.
//   Otherwise it should be a BOOL variable that signifies if the variable is defined or not.
// - speculate_undefined means whether or not we should execute the when_undefined code generator
//   in the current block (the one that we're in when calling this function); if set to true we will
//   avoid generating a BB for the undefined case, which is useful if the "codegen" just returns
//   an existing value or a constant.
llvm::Value* handlePotentiallyUndefined(ConcreteCompilerVariable* is_defined_var, llvm::Type* rtn_type,
                                        llvm::BasicBlock*& cur_block, IREmitter& emitter, bool speculate_undefined,
                                        std::function<llvm::Value*(IREmitter&)> when_defined,
                                        std::function<llvm::Value*(IREmitter&)> when_undefined);

144 145
class TypeRecorder;
class OpInfo {
146
private:
147
    const EffortLevel effort;
148
    TypeRecorder* const type_recorder;
149
    ICInfo* bjit_ic_info;
150 151

public:
152
    const UnwindInfo unw_info;
153

154 155
    OpInfo(EffortLevel effort, TypeRecorder* type_recorder, const UnwindInfo& unw_info, ICInfo* bjit_ic_info)
        : effort(effort), type_recorder(type_recorder), bjit_ic_info(bjit_ic_info), unw_info(unw_info) {}
156

157
    TypeRecorder* getTypeRecorder() const { return type_recorder; }
158
    ICInfo* getBJitICInfo() const { return bjit_ic_info; }
159 160

    ExceptionStyle preferredExceptionStyle() const { return unw_info.preferredExceptionStyle(); }
161
};
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190


class PystonObjectCache : public llvm::ObjectCache {
private:
    llvm::SmallString<128> cache_dir;
    std::string module_identifier;
    std::string hash_before_codegen;

public:
    PystonObjectCache();


#if LLVMREV < 216002
    virtual void notifyObjectCompiled(const llvm::Module* M, const llvm::MemoryBuffer* Obj);
#else
    virtual void notifyObjectCompiled(const llvm::Module* M, llvm::MemoryBufferRef Obj);
#endif

#if LLVMREV < 215566
    virtual llvm::MemoryBuffer* getObject(const llvm::Module* M);
#else
    virtual std::unique_ptr<llvm::MemoryBuffer> getObject(const llvm::Module* M);
#endif

    void cleanupCacheDirectory();

    void calculateModuleHash(const llvm::Module* M, EffortLevel effort);
    bool haveCacheFileForHash();
};
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208

class IRGenState;

class RefcountTracker {
private:
    struct RefcountState {
        RefType reftype;

        llvm::SmallVector<llvm::Instruction*, 2> ref_consumers;
    };
    llvm::ValueMap<llvm::Value*, RefcountState> vars;
public:

    void setType(llvm::Value* v, RefType reftype);
    void refConsumed(llvm::Value* v, llvm::Instruction*);
    static void addRefcounts(IRGenState* state);
};

Kevin Modzelewski's avatar
Kevin Modzelewski committed
209 210 211
}

#endif