From a45e257772c8acb70c85413ece8a4d394c4a2535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?T=C3=B6r=C3=B6k=20Edvin?= Date: Wed, 11 Nov 2009 09:50:50 +0200 Subject: [PATCH] Fix bugs when loading bytecode. --- libclamav/bytecode.c | 10 +- libclamav/c++/Makefile.am | 4 +- libclamav/c++/Makefile.in | 26 ++++- libclamav/c++/bytecode2llvm.cpp | 199 ++++++++++++++++++++++++++++---- 4 files changed, 213 insertions(+), 26 deletions(-) diff --git a/libclamav/bytecode.c b/libclamav/bytecode.c index a866cc911..0aa5624bb 100644 --- a/libclamav/bytecode.c +++ b/libclamav/bytecode.c @@ -75,6 +75,7 @@ int cli_bytecode_context_clear(struct cli_bc_ctx *ctx) static unsigned typesize(const struct cli_bc *bc, uint16_t type) { + type &= 0x7fff; if (!type) return 0; if (type <= 8) @@ -90,6 +91,7 @@ static unsigned typesize(const struct cli_bc *bc, uint16_t type) static unsigned typealign(const struct cli_bc *bc, uint16_t type) { + type &= 0x7fff; if (type <= 64) { unsigned size = typesize(bc, type); return size ? size : 1; @@ -434,13 +436,13 @@ static int parseLSig(struct cli_bc *bc, unsigned char *buffer) char *vnames, *vend = strchr(buffer, ';'); if (vend) { bc->lsig = cli_strdup(buffer); + *vend++ = '\0'; + prefix = buffer; + vnames = strchr(vend, '{'); } else { /* Not a logical signature, but we still have a virusname */ bc->lsig = NULL; } - *vend++ = '\0'; - prefix = buffer; - vnames = strchr(vend, '{'); return CL_SUCCESS; } @@ -823,6 +825,8 @@ static int parseFunctionHeader(struct cli_bc *bc, unsigned fn, unsigned char *bu } for (i=0;itypes[i] = readNumber(buffer, &offset, len, &ok); + if (readFixedNumber(buffer, &offset, len, &ok, 1)) + func->types[i] |= 0x8000; } if (!ok) { cli_errmsg("Invalid local types\n"); diff --git a/libclamav/c++/Makefile.am b/libclamav/c++/Makefile.am index b0af110fe..b0789504e 100644 --- a/libclamav/c++/Makefile.am +++ b/libclamav/c++/Makefile.am @@ -582,7 +582,9 @@ libllvmscalar_la_SOURCES=\ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp\ llvm/lib/Transforms/Scalar/CodeGenLICM.cpp\ llvm/lib/Transforms/Scalar/DCE.cpp\ - llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp + llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp\ + llvm/lib/Transforms/Scalar/ConstantProp.cpp\ + llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp libllvmtransformutils_la_CPPFLAGS=$(LLVM_INCLUDES) $(LLVM_DEFS) libllvmtransformutils_la_CXXFLAGS=$(LLVM_CXXFLAGS) -fno-exceptions diff --git a/libclamav/c++/Makefile.in b/libclamav/c++/Makefile.in index 5e04d2057..6d1befa5d 100644 --- a/libclamav/c++/Makefile.in +++ b/libclamav/c++/Makefile.in @@ -355,7 +355,9 @@ libllvmmc_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ libllvmscalar_la_LIBADD = am_libllvmscalar_la_OBJECTS = libllvmscalar_la-CodeGenPrepare.lo \ libllvmscalar_la-CodeGenLICM.lo libllvmscalar_la-DCE.lo \ - libllvmscalar_la-LoopStrengthReduce.lo + libllvmscalar_la-LoopStrengthReduce.lo \ + libllvmscalar_la-ConstantProp.lo \ + libllvmscalar_la-SimplifyCFGPass.lo libllvmscalar_la_OBJECTS = $(am_libllvmscalar_la_OBJECTS) libllvmscalar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \ @@ -1399,7 +1401,9 @@ libllvmscalar_la_SOURCES = \ llvm/lib/Transforms/Scalar/CodeGenPrepare.cpp\ llvm/lib/Transforms/Scalar/CodeGenLICM.cpp\ llvm/lib/Transforms/Scalar/DCE.cpp\ - llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp + llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp\ + llvm/lib/Transforms/Scalar/ConstantProp.cpp\ + llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp libllvmtransformutils_la_CPPFLAGS = $(LLVM_INCLUDES) $(LLVM_DEFS) libllvmtransformutils_la_CXXFLAGS = $(LLVM_CXXFLAGS) -fno-exceptions @@ -1937,8 +1941,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmmc_la-TargetAsmParser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-CodeGenLICM.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-CodeGenPrepare.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-ConstantProp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-DCE.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-LoopStrengthReduce.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-AsmPrinter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-CallingConvLower.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libllvmsdag_la-DAGCombiner.Plo@am__quote@ @@ -3731,6 +3737,22 @@ libllvmscalar_la-LoopStrengthReduce.lo: llvm/lib/Transforms/Scalar/LoopStrengthR @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-LoopStrengthReduce.lo `test -f 'llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +libllvmscalar_la-ConstantProp.lo: llvm/lib/Transforms/Scalar/ConstantProp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-ConstantProp.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-ConstantProp.Tpo -c -o libllvmscalar_la-ConstantProp.lo `test -f 'llvm/lib/Transforms/Scalar/ConstantProp.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/ConstantProp.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-ConstantProp.Tpo $(DEPDIR)/libllvmscalar_la-ConstantProp.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/ConstantProp.cpp' object='libllvmscalar_la-ConstantProp.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-ConstantProp.lo `test -f 'llvm/lib/Transforms/Scalar/ConstantProp.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/ConstantProp.cpp + +libllvmscalar_la-SimplifyCFGPass.lo: llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmscalar_la-SimplifyCFGPass.lo -MD -MP -MF $(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Tpo -c -o libllvmscalar_la-SimplifyCFGPass.lo `test -f 'llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Tpo $(DEPDIR)/libllvmscalar_la-SimplifyCFGPass.Plo +@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp' object='libllvmscalar_la-SimplifyCFGPass.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmscalar_la_CPPFLAGS) $(CPPFLAGS) $(libllvmscalar_la_CXXFLAGS) $(CXXFLAGS) -c -o libllvmscalar_la-SimplifyCFGPass.lo `test -f 'llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp' || echo '$(srcdir)/'`llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp + libllvmsdag_la-CallingConvLower.lo: llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libllvmsdag_la_CPPFLAGS) $(CPPFLAGS) $(libllvmsdag_la_CXXFLAGS) $(CXXFLAGS) -MT libllvmsdag_la-CallingConvLower.lo -MD -MP -MF $(DEPDIR)/libllvmsdag_la-CallingConvLower.Tpo -c -o libllvmsdag_la-CallingConvLower.lo `test -f 'llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp' || echo '$(srcdir)/'`llvm/lib/CodeGen/SelectionDAG/CallingConvLower.cpp @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libllvmsdag_la-CallingConvLower.Tpo $(DEPDIR)/libllvmsdag_la-CallingConvLower.Plo diff --git a/libclamav/c++/bytecode2llvm.cpp b/libclamav/c++/bytecode2llvm.cpp index 5c8be9aa5..69f647d14 100644 --- a/libclamav/c++/bytecode2llvm.cpp +++ b/libclamav/c++/bytecode2llvm.cpp @@ -99,7 +99,7 @@ static void NORETURN jit_exception_handler(void) void llvm_error_handler(void *user_data, const std::string &reason) { // Output it to stderr, it might exceed the 1k/4k limit of cli_errmsg - errs() << reason; + errs() << MODULE << reason; jit_exception_handler(); } @@ -179,6 +179,7 @@ public: const Type *get(uint16_t ty) { + ty &= 0x7fff; if (ty < 69) return getStatic(ty); ty -= 69; @@ -225,9 +226,12 @@ private: return Values[operand]; if (operand < func->numValues) { Value *V = Values[operand]; - if (V->getType() == Ty) + if (func->types[operand]&0x8000 && V->getType() == Ty) { return V; - return Builder.CreateLoad(V); + } + V = Builder.CreateLoad(V); + assert(V->getType() == Ty); + return V; } unsigned w = (Ty->getPrimitiveSizeInBits()+7)/8; return convertOperand(func, map[w], operand); @@ -243,8 +247,11 @@ private: unsigned w, operand_t operand) { if (operand < func->numArgs) return Values[operand]; - if (operand < func->numValues) + if (operand < func->numValues) { + if (func->types[operand]&0x8000) + return Values[operand]; return Builder.CreateLoad(Values[operand]); + } if (operand & 0x80000000) { operand &= 0x7fffffff; @@ -309,7 +316,7 @@ private: const Type* mapType(uint16_t typeID) { - return TypeMap->get(typeID); + return TypeMap->get(typeID&0x7fffffff); } Constant *buildConstant(const Type *Ty, uint64_t *components, unsigned &c) @@ -364,6 +371,31 @@ public: } } + template + bool createGEP(unsigned dest, Value *Base, InputIterator Start, InputIterator End) { + assert(dest >= numArgs && dest < numLocals+numArgs && "Instruction destination out of range"); + const Type *Ty = GetElementPtrInst::getIndexedType(Base->getType(), Start, End); + const Type *ETy = cast(cast(Values[dest]->getType())->getElementType())->getElementType(); + if (!Ty || (Ty != ETy && (!isa(Ty) || !isa(ETy)))) { + errs() << MODULE << "Wrong indices for GEP opcode: " + << " expected type: " << *ETy; + if (Ty) + errs() << " actual type: " << *Ty; + errs() << " base: " << *Base << " indices: "; + for (InputIterator I=Start; I != End; I++) { + errs() << **I << ", "; + } + errs() << "\n"; + return false; + } + Value *V = Builder.CreateGEP(Base, Start, End); + if (Ty != ETy) { + V = Builder.CreateBitCast(V, PointerType::getUnqual(ETy)); + } + Store(dest, V); + return true; + } + bool generate() { TypeMap = new LLVMTypeMapper(Context, bc->types + 4, bc->num_types - 5); @@ -383,6 +415,55 @@ public: FHandler->addFnAttr(Attribute::NoInline); EE->addGlobalMapping(FHandler, (void*)jit_exception_handler); + std::vector args; + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(Type::getInt8Ty(Context)); + args.push_back(Type::getInt32Ty(Context)); + args.push_back(Type::getInt32Ty(Context)); + FunctionType* FuncTy_3 = FunctionType::get(Type::getVoidTy(Context), + args, false); + Function *FMemset = Function::Create(FuncTy_3, GlobalValue::ExternalLinkage, + "llvm.memset.i32", M); + FMemset->setDoesNotThrow(); + FMemset->setDoesNotCapture(1, true); + + args.clear(); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(Type::getInt32Ty(Context)); + args.push_back(Type::getInt32Ty(Context)); + FunctionType* FuncTy_4 = FunctionType::get(Type::getVoidTy(Context), + args, false); + Function *FMemmove = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage, + "llvm.memmove.i32", M); + FMemmove->setDoesNotThrow(); + FMemmove->setDoesNotCapture(1, true); + + Function *FMemcpy = Function::Create(FuncTy_4, GlobalValue::ExternalLinkage, + "llvm.memcpy.i32", M); + FMemcpy->setDoesNotThrow(); + FMemcpy->setDoesNotCapture(1, true); + + FunctionType* DummyTy = FunctionType::get(Type::getVoidTy(Context), false); + Function *FRealMemset = Function::Create(DummyTy, GlobalValue::ExternalLinkage, + "memset", M); + EE->addGlobalMapping(FRealMemset, (void*)memset); + Function *FRealMemmove = Function::Create(DummyTy, GlobalValue::ExternalLinkage, + "memmove", M); + EE->addGlobalMapping(FRealMemmove, (void*)memmove); + Function *FRealMemcpy = Function::Create(DummyTy, GlobalValue::ExternalLinkage, + "memcpy", M); + EE->addGlobalMapping(FRealMemcpy, (void*)memcpy); + + args.clear(); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); + args.push_back(EE->getTargetData()->getIntPtrType(Context)); + FunctionType* FuncTy_5 = FunctionType::get(Type::getInt32Ty(Context), + args, false); + Function* FRealMemcmp = Function::Create(FuncTy_5, GlobalValue::ExternalLinkage, "memcmp", M); + EE->addGlobalMapping(FRealMemcmp, (void*)memcmp); + // The hidden ctx param to all functions const Type *HiddenCtx = PointerType::getUnqual(Type::getInt8Ty(Context)); @@ -399,8 +480,6 @@ public: if (isa(Ty)) { unsigned g = bc->globals[i][1]; if (GVoffsetMap.count(g)) { - const Type *MTy = GVtypeMap[g]; - assert(Ty == MTy); FakeGVs.set(i); globals.push_back(0); continue; @@ -477,16 +556,21 @@ public: offset); Value *GEP = Builder.CreateInBoundsGEP(Ctx, Idx); const Type *Ty = GVtypeMap[g]; - Value *Cast = Builder.CreateBitCast(GEP, - PointerType::getUnqual(Ty)); + Ty = PointerType::getUnqual(PointerType::getUnqual(Ty)); + Value *Cast = Builder.CreateBitCast(GEP, Ty); Value *SpecialGV = Builder.CreateLoad(Cast); - Constant *C = ConstantInt::get(Type::getInt32Ty(Context), bc->globals[i][0]); - globals[i] = Builder.CreateInBoundsGEP(SpecialGV, C); + Value *C[] = { + ConstantInt::get(Type::getInt32Ty(Context), 0), + ConstantInt::get(Type::getInt32Ty(Context), bc->globals[i][0]) + }; + globals[i] = Builder.CreateInBoundsGEP(SpecialGV, C, + C+2); } } // Generate LLVM IR for each BB for (unsigned i=0;inumBB;i++) { + bool unreachable = false; const struct cli_bc_bb *bb = &func->BB[i]; Builder.SetInsertPoint(BB[i]); for (unsigned j=0;jnumInsts;j++) { @@ -507,6 +591,7 @@ public: case OP_BC_GEPN: case OP_BC_STORE: case OP_BC_COPY: + case OP_BC_RET: // these instructions represents operands differently break; default: @@ -624,8 +709,11 @@ public: break; } case OP_BC_RET: + { + Op0 = convertOperand(func, F->getReturnType(), inst->u.unaryop); Builder.CreateRet(Op0); break; + } case OP_BC_RET_VOID: Builder.CreateRetVoid(); break; @@ -698,44 +786,110 @@ public: } case OP_BC_GEP1: { - Value *V = Values[inst->u.binop[0]]; + Value *V = convertOperand(func, inst, inst->u.binop[0]); Value *Op = convertOperand(func, I32Ty, inst->u.binop[1]); - Store(inst->dest, Builder.CreateGEP(V, Op)); + if (!createGEP(inst->dest, V, &Op, &Op+1)) + return false; break; } case OP_BC_GEP2: { std::vector Idxs; - Value *V = Values[inst->u.three[0]]; + Value *V = convertOperand(func, inst, inst->u.three[0]); Idxs.push_back(convertOperand(func, I32Ty, inst->u.three[1])); Idxs.push_back(convertOperand(func, I32Ty, inst->u.three[2])); - Store(inst->dest, Builder.CreateGEP(V, Idxs.begin(), Idxs.end())); + if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end())) + return false; break; } case OP_BC_GEPN: { std::vector Idxs; assert(inst->u.ops.numOps > 1); - Value *V = Values[inst->u.ops.ops[0]]; + Value *V = convertOperand(func, inst, inst->u.binop[0]); for (unsigned a=1;au.ops.numOps;a++) Idxs.push_back(convertOperand(func, I32Ty, inst->u.ops.ops[a])); - Store(inst->dest, Builder.CreateGEP(V, Idxs.begin(), Idxs.end())); + if (!createGEP(inst->dest, V, Idxs.begin(), Idxs.end())) + return false; break; } case OP_BC_STORE: { Value *Dest = convertOperand(func, inst, inst->u.binop[1]); const Type *ETy = cast(Dest->getType())->getElementType(); - Builder.CreateStore(getOperand(func, ETy, inst->u.binop[0]), + Builder.CreateStore(convertOperand(func, ETy, inst->u.binop[0]), Dest); break; } case OP_BC_LOAD: + { + Op0 = Builder.CreateBitCast(Op0, + Values[inst->dest]->getType()); Op0 = Builder.CreateLoad(Op0); Store(inst->dest, Op0); break; + } + case OP_BC_MEMSET: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Val = convertOperand(func, Type::getInt8Ty(Context), inst->u.three[1]); + Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FMemset, Dst, Val, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + break; + } + case OP_BC_MEMCPY: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Src = convertOperand(func, inst, inst->u.three[1]); + Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FMemcpy, Dst, Src, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + break; + } + case OP_BC_MEMMOVE: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Src = convertOperand(func, inst, inst->u.three[1]); + Value *Len = convertOperand(func, Type::getInt32Ty(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FMemmove, Dst, Src, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + break; + } + case OP_BC_MEMCMP: + { + Value *Dst = convertOperand(func, inst, inst->u.three[0]); + Value *Src = convertOperand(func, inst, inst->u.three[1]); + Value *Len = convertOperand(func, EE->getTargetData()->getIntPtrType(Context), inst->u.three[2]); + CallInst *c = Builder.CreateCall4(FRealMemcmp, Dst, Src, Len, + ConstantInt::get(Type::getInt32Ty(Context), 1)); + c->setTailCall(true); + c->setDoesNotThrow(); + Store(inst->dest, c); + break; + } + case OP_BC_ISBIGENDIAN: + Store(inst->dest, WORDS_BIGENDIAN ? + ConstantInt::getTrue(Context) : + ConstantInt::getFalse(Context)); + break; + case OP_BC_ABORT: + if (!unreachable) { + CallInst *CI = Builder.CreateCall(FHandler); + CI->setDoesNotReturn(); + CI->setDoesNotThrow(); + Builder.CreateUnreachable(); + unreachable = true; + } + break; default: - errs() << "JIT doesn't implement opcode " << + errs() << MODULE << "JIT doesn't implement opcode " << inst->opcode << " yet!\n"; return false; } @@ -744,6 +898,7 @@ public: if (verifyFunction(*F, PrintMessageAction)) { errs() << MODULE << "Verification failed\n"; + F->dump(); // verification failed return false; } @@ -754,7 +909,7 @@ public: DEBUG(M->dump()); delete TypeMap; - std::vector args; + args.clear(); args.push_back(PointerType::getUnqual(Type::getInt8Ty(Context))); FunctionType *Callable = FunctionType::get(Type::getInt32Ty(Context), args, false); @@ -866,6 +1021,10 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs) OurFPM.add(createPromoteMemoryToRegisterPass()); // Delete dead instructions OurFPM.add(createDeadCodeEliminationPass()); + // Fold constants + OurFPM.add(createConstantPropagationPass()); + // SimplifyCFG + OurFPM.add(createCFGSimplificationPass()); OurFPM.doInitialization(); //TODO: create a wrapper that calls pthread_getspecific