llvm_interpreter.cpp 30.4 KB
Newer Older
Kevin Modzelewski's avatar
Kevin Modzelewski committed
1
// Copyright (c) 2014 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
// 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.

15 16
#include "codegen/llvm_interpreter.h"

Kevin Modzelewski's avatar
Kevin Modzelewski committed
17 18 19
#include <sstream>
#include <unordered_map>

20
#include "llvm/IR/CallSite.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
21 22
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
23
#include "llvm/IR/DebugInfo.h"
24 25
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
26 27 28 29

#include "codegen/codegen.h"
#include "codegen/irgen/hooks.h"
#include "codegen/irgen/util.h"
30 31
#include "core/common.h"
#include "core/stats.h"
32
#include "core/thread_utils.h"
33
#include "core/util.h"
Kevin Modzelewski's avatar
Kevin Modzelewski committed
34

35 36 37 38
//#undef VERBOSITY
//#define VERBOSITY(x) 2
//#define TIME_INTERPRETS

39 40
extern "C" void* __cxa_allocate_exception(size_t);

Kevin Modzelewski's avatar
Kevin Modzelewski committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
namespace pyston {

union Val {
    bool b;
    int64_t n;
    double d;
    Box* o;

    Val(bool b) : b(b) {}
    Val(int64_t n) : n(n) {}
    Val(double d) : d(d) {}
    Val(Box* o) : o(o) {}
};

typedef std::unordered_map<llvm::Value*, Val> SymMap;

57
int width(llvm::Type* t, const llvm::DataLayout& dl) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
58
    return dl.getTypeSizeInBits(t) / 8;
59 60 61 62 63 64
    // if (t == g.i1) return 1;
    // if (t == g.i64) return 8;
    // if (t->isPointerTy()) return 8;
    //
    // t->dump();
    // RELEASE_ASSERT(0, "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
65 66
}

67
int width(llvm::Value* v, const llvm::DataLayout& dl) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
68 69 70
    return width(v->getType(), dl);
}

71
Val fetch(llvm::Value* v, const llvm::DataLayout& dl, const SymMap& symbols) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
72 73 74 75
    assert(v);

    int opcode = v->getValueID();

76 77 78 79
    // std::ostringstream os("");
    // os << "fetch_" << opcode;
    // int statid = Stats::getStatId(os.str());
    // Stats::log(statid);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
80 81 82 83 84 85

    if (opcode >= llvm::Value::InstructionVal) {
        assert(symbols.count(v));
        return symbols.find(v)->second;
    }

86
    switch (opcode) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
        case llvm::Value::ArgumentVal: {
            assert(symbols.count(v));
            return symbols.find(v)->second;
        }
        case llvm::Value::ConstantIntVal: {
            if (v->getType() == g.i1)
                return (int64_t)llvm::cast<llvm::ConstantInt>(v)->getZExtValue();
            if (v->getType() == g.i64 || v->getType() == g.i32)
                return llvm::cast<llvm::ConstantInt>(v)->getSExtValue();
            v->dump();
            RELEASE_ASSERT(0, "");
        }
        case llvm::Value::ConstantFPVal: {
            return llvm::cast<llvm::ConstantFP>(v)->getValueAPF().convertToDouble();
        }
        case llvm::Value::ConstantExprVal: {
103
            llvm::ConstantExpr* ce = llvm::cast<llvm::ConstantExpr>(v);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
104 105 106 107 108 109 110
            if (ce->isCast()) {
                assert(width(ce->getOperand(0), dl) == 8 && width(ce, dl) == 8);

                Val o = fetch(ce->getOperand(0), dl, symbols);
                return o;
            } else if (ce->getOpcode() == llvm::Instruction::GetElementPtr) {
                int64_t base = (int64_t)fetch(ce->getOperand(0), dl, symbols).o;
111
                llvm::Type* t = ce->getOperand(0)->getType();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152

                llvm::User::value_op_iterator begin = ce->value_op_begin();
                ++begin;
                std::vector<llvm::Value*> indices(begin, ce->value_op_end());

                int64_t offset = dl.getIndexedOffset(t, indices);

                /*if (VERBOSITY()) {
                    ce->dump();
                    ce->getOperand(0)->dump();
                    for (int i = 0; i < indices.size() ;i++) {
                        indices[i]->dump();
                    }
                    printf("resulting offset: %ld\n", offset);
                }*/

                return base + offset;
            } else {
                v->dump();
                RELEASE_ASSERT(0, "");
            }
        }
        /*case llvm::Value::FunctionVal: {
            llvm::Function* f = llvm::cast<llvm::Function>(v);
            if (f->getName() == "printf") {
                return (int64_t)printf;
            } else if (f->getName() == "reoptCompiledFunc") {
                return (int64_t)reoptCompiledFunc;
            } else if (f->getName() == "compilePartialFunc") {
                return (int64_t)compilePartialFunc;
            } else if (startswith(f->getName(), "runtimeCall")) {
                return (int64_t)g.func_registry.getFunctionAddress("runtimeCall");
            } else {
                return (int64_t)g.func_registry.getFunctionAddress(f->getName());
            }
        }*/
        case llvm::Value::GlobalVariableVal: {
            llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(v);
            if (!gv->isDeclaration() && gv->getLinkage() == llvm::GlobalVariable::InternalLinkage) {
                static std::unordered_map<llvm::GlobalVariable*, void*> made;

153
                void*& r = made[gv];
Kevin Modzelewski's avatar
Kevin Modzelewski committed
154
                if (r == NULL) {
155
                    llvm::Type* t = gv->getType()->getElementType();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
156 157 158 159 160
                    r = (void*)malloc(width(t, dl));
                    if (gv->hasInitializer()) {
                        llvm::Constant* init = gv->getInitializer();
                        assert(init->getType() == t);
                        if (t == g.i64) {
161
                            llvm::ConstantInt* ci = llvm::cast<llvm::ConstantInt>(init);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
162 163 164 165 166 167 168 169
                            *(int64_t*)r = ci->getSExtValue();
                        } else {
                            gv->dump();
                            RELEASE_ASSERT(0, "");
                        }
                    }
                }

170 171 172 173
                // gv->getType()->dump();
                // gv->dump();
                // printf("%p\n", r);
                // RELEASE_ASSERT(0, "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
174 175 176 177 178 179 180
                return (int64_t)r;
            }

            gv->dump();
            RELEASE_ASSERT(0, "");
        }
        case llvm::Value::UndefValueVal:
181 182 183 184 185
            // It's ok to evaluate an undef as long as we're being careful
            // to not use it later.
            // Typically this happens if we need to propagate the 'value' of an
            // maybe-defined Python variable; we won't actually read from it if
            // it's undef, since it should be guarded by an !is_defined variable.
186
            return (int64_t)-1337;
187 188
        case llvm::Value::ConstantPointerNullVal:
            return (int64_t)0;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
189 190 191 192 193 194
        default:
            v->dump();
            RELEASE_ASSERT(0, "%d", v->getValueID());
    }
}

195
static void set(SymMap& symbols, const llvm::BasicBlock::iterator& it, Val v) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
196 197 198 199 200 201 202 203 204 205 206
    if (VERBOSITY() >= 2) {
        printf("Setting to %lx / %f: ", v.n, v.d);
        fflush(stdout);
        it->dump();
    }

    SymMap::iterator f = symbols.find(it);
    if (f != symbols.end())
        f->second = v;
    else
        symbols.insert(std::make_pair(static_cast<llvm::Value*>(&(*it)), v));
207
    //#define SET(v) symbols.insert(std::make_pair(static_cast<llvm::Value*>(&(*it)), Val(v)))
Kevin Modzelewski's avatar
Kevin Modzelewski committed
208 209
}

210 211
static std::unordered_map<void*, llvm::Instruction*> cur_instruction_map;

212 213
typedef std::vector<const SymMap*> root_stack_t;
threading::PerThreadSet<root_stack_t> root_stack_set;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
214

215
void gatherInterpreterRoots(GCVisitor* visitor) {
216
    root_stack_set.forEachValue(std::function<void(root_stack_t*, GCVisitor*)>([](root_stack_t* v, GCVisitor* visitor) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
217 218 219 220 221 222 223
                                    for (const SymMap* sym_map : *v) {
                                        for (const auto& p2 : *sym_map) {
                                            visitor->visitPotential(p2.second.o);
                                        }
                                    }
                                }),
                                visitor);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
224 225 226
}

class UnregisterHelper {
227 228
private:
    void* frame_ptr;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
229

230 231
public:
    constexpr UnregisterHelper(void* frame_ptr) : frame_ptr(frame_ptr) {}
Kevin Modzelewski's avatar
Kevin Modzelewski committed
232

233
    ~UnregisterHelper() {
234
        root_stack_set.get()->pop_back();
235 236 237

        assert(cur_instruction_map.count(frame_ptr));
        cur_instruction_map.erase(frame_ptr);
238
    }
Kevin Modzelewski's avatar
Kevin Modzelewski committed
239 240
};

241 242 243 244 245 246 247 248 249 250 251
static std::unordered_map<llvm::Instruction*, LineInfo*> line_infos;
const LineInfo* getLineInfoForInterpretedFrame(void* frame_ptr) {
    llvm::Instruction* cur_instruction = cur_instruction_map[frame_ptr];
    assert(cur_instruction);

    auto it = line_infos.find(cur_instruction);
    if (it == line_infos.end()) {
        const llvm::DebugLoc& debug_loc = cur_instruction->getDebugLoc();
        llvm::DISubprogram subprog(debug_loc.getScope(g.context));

        // TODO better lifetime management
Kevin Modzelewski's avatar
Kevin Modzelewski committed
252
        LineInfo* rtn = new LineInfo(debug_loc.getLine(), debug_loc.getCol(), subprog.getFilename(), subprog.getName());
253 254 255 256 257 258 259
        line_infos.insert(it, std::make_pair(cur_instruction, rtn));
        return rtn;
    } else {
        return it->second;
    }
}

260 261
Box* interpretFunction(llvm::Function* f, int nargs, Box* closure, Box* generator, Box* arg1, Box* arg2, Box* arg3,
                       Box** args) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
262 263 264 265 266 267 268 269 270 271 272 273
    assert(f);

#ifdef TIME_INTERPRETS
    Timer _t("to interpret", 1000000);
    long this_us = 0;
#endif

    static StatCounter interpreted_runs("interpreted_runs");
    interpreted_runs.log();

    llvm::DataLayout dl(f->getParent());

274 275
    // f->dump();
    // assert(nargs == f->getArgumentList().size());
Kevin Modzelewski's avatar
Kevin Modzelewski committed
276 277 278 279

    SymMap symbols;

    void* frame_ptr = __builtin_frame_address(0);
280
    root_stack_set.get()->push_back(&symbols);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
281 282
    UnregisterHelper helper(frame_ptr);

Kevin Modzelewski's avatar
Kevin Modzelewski committed
283
    int arg_num = -1;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
284
    int closure_indicator = closure ? 1 : 0;
285 286
    int generator_indicator = generator ? 1 : 0;
    int argOffset = closure_indicator + generator_indicator;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
287 288 289
    for (llvm::Argument& arg : f->args()) {
        arg_num++;

Kevin Modzelewski's avatar
Kevin Modzelewski committed
290 291
        if (arg_num == 0 && closure)
            symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(closure)));
292 293 294
        else if ((arg_num == 0 || (arg_num == 1 && closure)) && generator)
            symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(generator)));
        else if (arg_num == 0 + argOffset)
295
            symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg1)));
296
        else if (arg_num == 1 + argOffset)
297
            symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg2)));
298
        else if (arg_num == 2 + argOffset)
299
            symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val(arg3)));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
300
        else {
301 302
            assert(arg_num == 3 + argOffset);
            assert(f->getArgumentList().size() == 4 + argOffset);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
303
            assert(f->getArgumentList().back().getType() == g.llvm_value_type_ptr->getPointerTo());
Kevin Modzelewski's avatar
Kevin Modzelewski committed
304
            symbols.insert(std::make_pair(static_cast<llvm::Value*>(&arg), Val((int64_t)args)));
305
            // printf("loading %%4 with %p\n", (void*)args);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
306 307 308 309
            break;
        }
    }

310 311
    llvm::BasicBlock* prevblock = NULL;
    llvm::BasicBlock* curblock = &f->getEntryBlock();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
312

313 314 315 316
    struct {
        Box* exc_obj;
        int64_t exc_selector;
    } landingpad_value;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
317 318

    while (true) {
319 320
        for (llvm::Instruction& _inst : *curblock) {
            llvm::Instruction* inst = &_inst;
321
            cur_instruction_map[frame_ptr] = inst;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
322

Kevin Modzelewski's avatar
Kevin Modzelewski committed
323 324 325
            if (VERBOSITY("interpreter") >= 2) {
                printf("executing in %s: ", f->getName().data());
                fflush(stdout);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
326
                inst->dump();
327
                // f->dump();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
328 329
            }

Kevin Modzelewski's avatar
Kevin Modzelewski committed
330
#define SET(v) set(symbols, inst, (v))
331 332

            if (llvm::LandingPadInst* lpad = llvm::dyn_cast<llvm::LandingPadInst>(inst)) {
333
                SET((intptr_t)&landingpad_value);
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
                continue;
            } else if (llvm::ExtractValueInst* ev = llvm::dyn_cast<llvm::ExtractValueInst>(inst)) {
                Val r = fetch(ev->getAggregateOperand(), dl, symbols);
                llvm::ArrayRef<unsigned> indexes = ev->getIndices();

#ifndef NDEBUG
                assert(indexes.size() == 1);
                llvm::Type* t = llvm::ExtractValueInst::getIndexedType(ev->getAggregateOperand()->getType(), indexes);
                assert(width(t, dl) == 8);
#endif

                int64_t* ptr = (int64_t*)r.n;
                int64_t val = ptr[indexes[0]];
                SET(val);
                continue;
            } else if (llvm::LoadInst* li = llvm::dyn_cast<llvm::LoadInst>(inst)) {
350
                llvm::Value* ptr = li->getOperand(0);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
351
                Val v = fetch(ptr, dl, symbols);
352
                // printf("loading from %p\n", v.o);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
353 354 355 356 357 358 359 360 361 362 363 364 365

                if (width(li, dl) == 1) {
                    Val r = Val(*(bool*)v.o);
                    SET(r);
                    continue;
                } else if (width(li, dl) == 8) {
                    Val r = Val(*(int64_t*)v.o);
                    SET(r);
                    continue;
                } else {
                    li->dump();
                    RELEASE_ASSERT(0, "");
                }
366 367 368
            } else if (llvm::StoreInst* si = llvm::dyn_cast<llvm::StoreInst>(inst)) {
                llvm::Value* val = si->getOperand(0);
                llvm::Value* ptr = si->getOperand(1);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
369 370 371
                Val v = fetch(val, dl, symbols);
                Val p = fetch(ptr, dl, symbols);

372
                // printf("storing %lx at %lx\n", v.n, p.n);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
373 374 375 376 377 378 379 380 381 382 383

                if (width(val, dl) == 1) {
                    *(bool*)p.o = v.b;
                    continue;
                } else if (width(val, dl) == 8) {
                    *(int64_t*)p.o = v.n;
                    continue;
                } else {
                    si->dump();
                    RELEASE_ASSERT(0, "");
                }
384
            } else if (llvm::CmpInst* ci = llvm::dyn_cast<llvm::CmpInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
                assert(ci->getType() == g.i1);

                Val a0 = fetch(ci->getOperand(0), dl, symbols);
                Val a1 = fetch(ci->getOperand(1), dl, symbols);
                llvm::CmpInst::Predicate pred = ci->getPredicate();
                switch (pred) {
                    case llvm::CmpInst::ICMP_EQ:
                        SET(a0.n == a1.n);
                        continue;
                    case llvm::CmpInst::ICMP_NE:
                        SET(a0.n != a1.n);
                        continue;
                    case llvm::CmpInst::ICMP_SLT:
                        SET(a0.n < a1.n);
                        continue;
                    case llvm::CmpInst::ICMP_SLE:
                        SET(a0.n <= a1.n);
                        continue;
                    case llvm::CmpInst::ICMP_SGT:
                        SET(a0.n > a1.n);
                        continue;
                    case llvm::CmpInst::ICMP_SGE:
                        SET(a0.n >= a1.n);
                        continue;
                    case llvm::CmpInst::FCMP_OEQ:
                        SET(a0.d == a1.d);
                        continue;
                    case llvm::CmpInst::FCMP_UNE:
                        SET(a0.d != a1.d);
                        continue;
                    case llvm::CmpInst::FCMP_OLT:
                        SET(a0.d < a1.d);
                        continue;
                    case llvm::CmpInst::FCMP_OLE:
                        SET(a0.d <= a1.d);
                        continue;
                    case llvm::CmpInst::FCMP_OGT:
                        SET(a0.d > a1.d);
                        continue;
                    case llvm::CmpInst::FCMP_OGE:
                        SET(a0.d >= a1.d);
                        continue;
                    default:
                        ci->dump();
                        RELEASE_ASSERT(0, "");
                }
                continue;
432
            } else if (llvm::BinaryOperator* bo = llvm::dyn_cast<llvm::BinaryOperator>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
433
                if (bo->getOperand(0)->getType() == g.i64 || bo->getOperand(0)->getType() == g.i1) {
434 435
                    // assert(bo->getOperand(0)->getType() == g.i64);
                    // assert(bo->getOperand(1)->getType() == g.i64);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470

                    Val a0 = fetch(bo->getOperand(0), dl, symbols);
                    Val a1 = fetch(bo->getOperand(1), dl, symbols);
                    llvm::Instruction::BinaryOps opcode = bo->getOpcode();
                    switch (opcode) {
                        case llvm::Instruction::Add:
                            SET(a0.n + a1.n);
                            continue;
                        case llvm::Instruction::And:
                            SET(a0.n & a1.n);
                            continue;
                        case llvm::Instruction::AShr:
                            SET(a0.n >> a1.n);
                            continue;
                        case llvm::Instruction::Mul:
                            SET(a0.n * a1.n);
                            continue;
                        case llvm::Instruction::Or:
                            SET(a0.n | a1.n);
                            continue;
                        case llvm::Instruction::Shl:
                            SET(a0.n << a1.n);
                            continue;
                        case llvm::Instruction::Sub:
                            SET(a0.n - a1.n);
                            continue;
                        case llvm::Instruction::Xor:
                            SET(a0.n ^ a1.n);
                            continue;
                        default:
                            bo->dump();
                            RELEASE_ASSERT(0, "");
                    }
                    continue;
                } else if (bo->getOperand(0)->getType() == g.double_) {
471 472
                    // assert(bo->getOperand(0)->getType() == g.i64);
                    // assert(bo->getOperand(1)->getType() == g.i64);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495

                    double lhs = fetch(bo->getOperand(0), dl, symbols).d;
                    double rhs = fetch(bo->getOperand(1), dl, symbols).d;
                    llvm::Instruction::BinaryOps opcode = bo->getOpcode();
                    switch (opcode) {
                        case llvm::Instruction::FAdd:
                            SET(lhs + rhs);
                            continue;
                        case llvm::Instruction::FMul:
                            SET(lhs * rhs);
                            continue;
                        case llvm::Instruction::FSub:
                            SET(lhs - rhs);
                            continue;
                        default:
                            bo->dump();
                            RELEASE_ASSERT(0, "");
                    }
                    continue;
                } else {
                    bo->dump();
                    RELEASE_ASSERT(0, "");
                }
496
            } else if (llvm::GetElementPtrInst* gep = llvm::dyn_cast<llvm::GetElementPtrInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
497 498 499 500 501 502 503
                int64_t base = fetch(gep->getPointerOperand(), dl, symbols).n;

                llvm::User::value_op_iterator begin = gep->value_op_begin();
                ++begin;
                std::vector<llvm::Value*> indices(begin, gep->value_op_end());

                int64_t offset = dl.getIndexedOffset(gep->getPointerOperandType(), indices);
504 505
                // gep->dump();
                // printf("offset for inst: %ld (base is %lx)\n", offset, base);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
506 507
                SET(base + offset);
                continue;
508
            } else if (llvm::AllocaInst* al = llvm::dyn_cast<llvm::AllocaInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
509 510
                int size = fetch(al->getArraySize(), dl, symbols).n * width(al->getAllocatedType(), dl);
                void* ptr = alloca(size);
511 512
                // void* ptr = malloc(size);
                // printf("alloca()'d at %p\n", ptr);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
513 514
                SET((int64_t)ptr);
                continue;
515
            } else if (llvm::SIToFPInst* si = llvm::dyn_cast<llvm::SIToFPInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
516 517 518
                assert(width(si->getOperand(0), dl) == 8);
                SET((double)fetch(si->getOperand(0), dl, symbols).n);
                continue;
519
            } else if (llvm::BitCastInst* bc = llvm::dyn_cast<llvm::BitCastInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
520 521 522
                assert(width(bc->getOperand(0), dl) == 8);
                SET(fetch(bc->getOperand(0), dl, symbols));
                continue;
523
            } else if (llvm::IntToPtrInst* bc = llvm::dyn_cast<llvm::IntToPtrInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
524 525 526
                assert(width(bc->getOperand(0), dl) == 8);
                SET(fetch(bc->getOperand(0), dl, symbols));
                continue;
527 528 529 530 531
                //} else if (llvm::CallInst* ci = llvm::dyn_cast<llvm::CallInst>(inst)) {
            } else if (llvm::isa<llvm::CallInst>(inst) || llvm::isa<llvm::InvokeInst>(inst)) {
                llvm::CallSite cs(inst);
                llvm::InvokeInst* invoke = llvm::dyn_cast<llvm::InvokeInst>(inst);

Kevin Modzelewski's avatar
Kevin Modzelewski committed
532 533
                void* f;
                int arg_start;
534 535 536 537
                if (cs.getCalledFunction()
                    && (cs.getCalledFunction()->getName() == "llvm.experimental.patchpoint.void"
                        || cs.getCalledFunction()->getName() == "llvm.experimental.patchpoint.i64")) {
                    // cs.dump();
538
                    assert(0 && "shouldn't be generating patchpoints for interpretation!");
539
                    f = (void*)fetch(cs.getArgument(2), dl, symbols).n;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
540 541
                    arg_start = 4;
                } else {
542
                    f = (void*)fetch(cs.getCalledValue(), dl, symbols).n;
Kevin Modzelewski's avatar
Kevin Modzelewski committed
543 544 545
                    arg_start = 0;
                }

546 547
                if (VERBOSITY("interpreter") >= 2)
                    printf("calling %s\n", g.func_addr_registry.getFuncNameAtAddress(f, true).c_str());
Kevin Modzelewski's avatar
Kevin Modzelewski committed
548 549

                std::vector<Val> args;
550
                int nargs = cs.arg_size();
Kevin Modzelewski's avatar
Kevin Modzelewski committed
551
                for (int i = arg_start; i < nargs; i++) {
552 553
                    // cs.getArgument(i)->dump();
                    args.push_back(fetch(cs.getArgument(i), dl, symbols));
Kevin Modzelewski's avatar
Kevin Modzelewski committed
554 555 556
                }

                int npassed_args = nargs - arg_start;
557
// printf("%d %d %d\n", nargs, arg_start, npassed_args);
Kevin Modzelewski's avatar
Kevin Modzelewski committed
558 559 560 561 562 563 564

#ifdef TIME_INTERPRETS
                this_us += _t.end();
#endif
                // This is dumb but I don't know how else to do it:

                int mask = 1;
565
                if (cs.getType() == g.double_)
Kevin Modzelewski's avatar
Kevin Modzelewski committed
566 567 568 569 570 571
                    mask = 3;
                else
                    mask = 2;

                for (int i = 0; i < npassed_args; i++) {
                    mask <<= 1;
572
                    if (cs.getArgument(i)->getType() == g.double_)
Kevin Modzelewski's avatar
Kevin Modzelewski committed
573 574 575 576
                        mask |= 1;
                }

                Val r((int64_t)0);
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
                try {
                    switch (mask) {
                        case 0b10:
                            r = reinterpret_cast<int64_t (*)()>(f)();
                            break;
                        case 0b11:
                            r = reinterpret_cast<double (*)()>(f)();
                            break;
                        case 0b100:
                            r = reinterpret_cast<int64_t (*)(int64_t)>(f)(args[0].n);
                            break;
                        case 0b101:
                            r = reinterpret_cast<int64_t (*)(double)>(f)(args[0].d);
                            break;
                        case 0b110:
                            r = reinterpret_cast<double (*)(int64_t)>(f)(args[0].n);
                            break;
                        case 0b1000:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t)>(f)(args[0].n, args[1].n);
                            break;
                        case 0b1001:
                            r = reinterpret_cast<int64_t (*)(int64_t, double)>(f)(args[0].n, args[1].d);
                            break;
                        case 0b1011:
                            r = reinterpret_cast<int64_t (*)(double, double)>(f)(args[0].d, args[1].d);
                            break;
                        case 0b1111:
                            r = reinterpret_cast<double (*)(double, double)>(f)(args[0].d, args[1].d);
                            break;
                        case 0b10000:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t)>(f)(args[0].n, args[1].n,
                                                                                            args[2].n);
                            break;
                        case 0b10001:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, double)>(f)(args[0].n, args[1].n,
                                                                                           args[2].d);
                            break;
                        case 0b10011:
                            r = reinterpret_cast<int64_t (*)(int64_t, double, double)>(f)(args[0].n, args[1].d,
                                                                                          args[2].d);
                            break;
                        case 0b100000:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t)>(f)(
                                args[0].n, args[1].n, args[2].n, args[3].n);
                            break;
                        case 0b100001:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, double)>(f)(
                                args[0].n, args[1].n, args[2].n, args[3].d);
                            break;
                        case 0b100110:
                            r = reinterpret_cast<int64_t (*)(int64_t, double, double, int64_t)>(f)(
                                args[0].n, args[1].d, args[2].d, args[3].n);
                            break;
                        case 0b101010:
                            r = reinterpret_cast<int64_t (*)(double, int, double, int64_t)>(f)(args[0].d, args[1].n,
632
                                                                                               args[2].d, args[3].n);
633 634 635 636 637 638 639 640 641 642 643 644 645 646
                            break;
                        case 0b1000000:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t)>(f)(
                                args[0].n, args[1].n, args[2].n, args[3].n, args[4].n);
                            break;
                        case 0b10000000:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t)>(f)(
                                args[0].n, args[1].n, args[2].n, args[3].n, args[4].n, args[5].n);
                            break;
                        case 0b100000000:
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
                                                             int64_t)>(f)(args[0].n, args[1].n, args[2].n, args[3].n,
                                                                          args[4].n, args[5].n, args[6].n);
                            break;
647
                        case 0b1000000000: // 512
648 649 650 651 652
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
                                                             int64_t, int64_t)>(f)(args[0].n, args[1].n, args[2].n,
                                                                                   args[3].n, args[4].n, args[5].n,
                                                                                   args[6].n, args[7].n);
                            break;
653 654 655 656 657 658
                        case 0b10000000000: // 1024
                            r = reinterpret_cast<int64_t (*)(int64_t, int64_t, int64_t, int64_t, int64_t, int64_t,
                                                             int64_t, int64_t, int64_t)>(
                                f)(args[0].n, args[1].n, args[2].n, args[3].n, args[4].n, args[5].n, args[6].n,
                                   args[7].n, args[8].n);
                            break;
659 660 661 662 663 664 665 666 667 668 669 670
                        default:
                            inst->dump();
                            RELEASE_ASSERT(0, "%d", mask);
                            break;
                    }
                    if (cs.getType() != g.void_)
                        SET(r);

                    if (invoke != nullptr) {
                        prevblock = curblock;
                        curblock = invoke->getNormalDest();
                    }
671
                } catch (Box* e) {
672 673 674 675
                    if (VERBOSITY("interpreter") >= 2) {
                        printf("Caught exception: %p\n", e);
                    }

676 677 678 679 680 681 682 683 684
                    if (invoke == nullptr)
                        throw;

                    prevblock = curblock;
                    curblock = invoke->getUnwindDest();

                    landingpad_value.exc_obj = e;
                    landingpad_value.exc_selector
                        = 1; // I don't think it's possible to determine what the value should be
Kevin Modzelewski's avatar
Kevin Modzelewski committed
685 686 687 688 689 690 691
                }


#ifdef TIME_INTERPRETS
                _t.restart("to interpret", 10000000);
#endif
                continue;
692
            } else if (llvm::SelectInst* si = llvm::dyn_cast<llvm::SelectInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
693 694 695 696 697 698 699 700
                Val test = fetch(si->getCondition(), dl, symbols);
                Val vt = fetch(si->getTrueValue(), dl, symbols);
                Val vf = fetch(si->getFalseValue(), dl, symbols);
                if (test.b)
                    SET(vt);
                else
                    SET(vf);
                continue;
701
            } else if (llvm::PHINode* phi = llvm::dyn_cast<llvm::PHINode>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
702 703 704
                assert(prevblock);
                SET(fetch(phi->getIncomingValueForBlock(prevblock), dl, symbols));
                continue;
705
            } else if (llvm::BranchInst* br = llvm::dyn_cast<llvm::BranchInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
706 707 708 709 710 711 712 713 714 715 716
                prevblock = curblock;
                if (br->isConditional()) {
                    Val t = fetch(br->getCondition(), dl, symbols);
                    if (t.b) {
                        curblock = br->getSuccessor(0);
                    } else {
                        curblock = br->getSuccessor(1);
                    }
                } else {
                    curblock = br->getSuccessor(0);
                }
717 718
                // if (VERBOSITY()) {
                // printf("jumped to %s\n", curblock->getName().data());
Kevin Modzelewski's avatar
Kevin Modzelewski committed
719 720
                //}
                break;
721
            } else if (llvm::ReturnInst* ret = llvm::dyn_cast<llvm::ReturnInst>(inst)) {
Kevin Modzelewski's avatar
Kevin Modzelewski committed
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
                llvm::Value* r = ret->getReturnValue();

#ifdef TIME_INTERPRETS
                this_us += _t.end();
                static StatCounter us_interpreting("us_interpreting");
                us_interpreting.log(this_us);
#endif

                if (!r)
                    return NULL;
                Val t = fetch(r, dl, symbols);
                return t.o;
            }


Kevin Modzelewski's avatar
Kevin Modzelewski committed
737
            inst->dump();
738
            RELEASE_ASSERT(0, "");
Kevin Modzelewski's avatar
Kevin Modzelewski committed
739 740 741 742 743 744
        }
    }

    RELEASE_ASSERT(0, "");
}
}