~louis/ubuntu/trusty/clamav/lp799623_fix_logrotate

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/unittests/ExecutionEngine/JIT/JITTest.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-03-12 11:30:04 UTC
  • mfrom: (0.41.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20100312113004-b0fop4bkycszdd0z
Tags: 0.96~rc1+dfsg-0ubuntu1
* New upstream RC - FFE (LP: #537636):
  - Add OfficialDatabaseOnly option to clamav-base.postinst.in
  - Add LocalSocketGroup option to clamav-base.postinst.in
  - Add LocalSocketMode option to clamav-base.postinst.in
  - Add CrossFilesystems option to clamav-base.postinst.in
  - Add ClamukoScannerCount option to clamav-base.postinst.in
  - Add BytecodeSecurity opiton to clamav-base.postinst.in
  - Add DetectionStatsHostID option to clamav-freshclam.postinst.in
  - Add Bytecode option to clamav-freshclam.postinst.in
  - Add MilterSocketGroup option to clamav-milter.postinst.in
  - Add MilterSocketMode option to clamav-milter.postinst.in
  - Add ReportHostname option to clamav-milter.postinst.in
  - Bump libclamav SO version to 6.1.0 in libclamav6.install
  - Drop clamdmon from clamav.examples (no longer shipped by upstream)
  - Drop libclamav.a from libclamav-dev.install (not built by upstream)
  - Update SO version for lintian override for libclamav6
  - Add new Bytecode Testing Tool, usr/bin/clambc, to clamav.install
  - Add build-depends on python and python-setuptools for new test suite
  - Update debian/copyright for the embedded copy of llvm (using the system
    llvm is not currently feasible)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//===- JITTest.cpp - Unit tests for the JIT -------------------------------===//
 
2
//
 
3
//                     The LLVM Compiler Infrastructure
 
4
//
 
5
// This file is distributed under the University of Illinois Open Source
 
6
// License. See LICENSE.TXT for details.
 
7
//
 
8
//===----------------------------------------------------------------------===//
 
9
 
 
10
#include "gtest/gtest.h"
 
11
#include "llvm/ADT/OwningPtr.h"
 
12
#include "llvm/ADT/SmallPtrSet.h"
 
13
#include "llvm/Assembly/Parser.h"
 
14
#include "llvm/BasicBlock.h"
 
15
#include "llvm/Bitcode/ReaderWriter.h"
 
16
#include "llvm/Constant.h"
 
17
#include "llvm/Constants.h"
 
18
#include "llvm/DerivedTypes.h"
 
19
#include "llvm/ExecutionEngine/JIT.h"
 
20
#include "llvm/ExecutionEngine/JITMemoryManager.h"
 
21
#include "llvm/Function.h"
 
22
#include "llvm/GlobalValue.h"
 
23
#include "llvm/GlobalVariable.h"
 
24
#include "llvm/LLVMContext.h"
 
25
#include "llvm/Module.h"
 
26
#include "llvm/Support/IRBuilder.h"
 
27
#include "llvm/Support/MemoryBuffer.h"
 
28
#include "llvm/Support/SourceMgr.h"
 
29
#include "llvm/Support/TypeBuilder.h"
 
30
#include "llvm/Target/TargetSelect.h"
 
31
#include "llvm/Type.h"
 
32
 
 
33
#include <vector>
 
34
 
 
35
using namespace llvm;
 
36
 
 
37
namespace {
 
38
 
 
39
Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
 
40
  std::vector<const Type*> params;
 
41
  const FunctionType *FTy = FunctionType::get(G->getType()->getElementType(),
 
42
                                              params, false);
 
43
  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M);
 
44
  BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F);
 
45
  IRBuilder<> builder(Entry);
 
46
  Value *Load = builder.CreateLoad(G);
 
47
  const Type *GTy = G->getType()->getElementType();
 
48
  Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL));
 
49
  builder.CreateStore(Add, G);
 
50
  builder.CreateRet(Add);
 
51
  return F;
 
52
}
 
53
 
 
54
std::string DumpFunction(const Function *F) {
 
55
  std::string Result;
 
56
  raw_string_ostream(Result) << "" << *F;
 
57
  return Result;
 
58
}
 
59
 
 
60
class RecordingJITMemoryManager : public JITMemoryManager {
 
61
  const OwningPtr<JITMemoryManager> Base;
 
62
public:
 
63
  RecordingJITMemoryManager()
 
64
    : Base(JITMemoryManager::CreateDefaultMemManager()) {
 
65
    stubsAllocated = 0;
 
66
  }
 
67
 
 
68
  void setSizeRequired(bool Required) { SizeRequired = Required; }
 
69
 
 
70
  virtual void setMemoryWritable() { Base->setMemoryWritable(); }
 
71
  virtual void setMemoryExecutable() { Base->setMemoryExecutable(); }
 
72
  virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); }
 
73
  virtual void AllocateGOT() { Base->AllocateGOT(); }
 
74
  virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); }
 
75
  struct StartFunctionBodyCall {
 
76
    StartFunctionBodyCall(uint8_t *Result, const Function *F,
 
77
                          uintptr_t ActualSize, uintptr_t ActualSizeResult)
 
78
      : Result(Result), F(F), F_dump(DumpFunction(F)),
 
79
        ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {}
 
80
    uint8_t *Result;
 
81
    const Function *F;
 
82
    std::string F_dump;
 
83
    uintptr_t ActualSize;
 
84
    uintptr_t ActualSizeResult;
 
85
  };
 
86
  std::vector<StartFunctionBodyCall> startFunctionBodyCalls;
 
87
  virtual uint8_t *startFunctionBody(const Function *F,
 
88
                                     uintptr_t &ActualSize) {
 
89
    uintptr_t InitialActualSize = ActualSize;
 
90
    uint8_t *Result = Base->startFunctionBody(F, ActualSize);
 
91
    startFunctionBodyCalls.push_back(
 
92
      StartFunctionBodyCall(Result, F, InitialActualSize, ActualSize));
 
93
    return Result;
 
94
  }
 
95
  int stubsAllocated;
 
96
  virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
 
97
                                unsigned Alignment) {
 
98
    stubsAllocated++;
 
99
    return Base->allocateStub(F, StubSize, Alignment);
 
100
  }
 
101
  struct EndFunctionBodyCall {
 
102
    EndFunctionBodyCall(const Function *F, uint8_t *FunctionStart,
 
103
                        uint8_t *FunctionEnd)
 
104
      : F(F), F_dump(DumpFunction(F)),
 
105
        FunctionStart(FunctionStart), FunctionEnd(FunctionEnd) {}
 
106
    const Function *F;
 
107
    std::string F_dump;
 
108
    uint8_t *FunctionStart;
 
109
    uint8_t *FunctionEnd;
 
110
  };
 
111
  std::vector<EndFunctionBodyCall> endFunctionBodyCalls;
 
112
  virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
 
113
                               uint8_t *FunctionEnd) {
 
114
    endFunctionBodyCalls.push_back(
 
115
      EndFunctionBodyCall(F, FunctionStart, FunctionEnd));
 
116
    Base->endFunctionBody(F, FunctionStart, FunctionEnd);
 
117
  }
 
118
  virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
 
119
    return Base->allocateSpace(Size, Alignment);
 
120
  }
 
121
  virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
 
122
    return Base->allocateGlobal(Size, Alignment);
 
123
  }
 
124
  struct DeallocateFunctionBodyCall {
 
125
    DeallocateFunctionBodyCall(const void *Body) : Body(Body) {}
 
126
    const void *Body;
 
127
  };
 
128
  std::vector<DeallocateFunctionBodyCall> deallocateFunctionBodyCalls;
 
129
  virtual void deallocateFunctionBody(void *Body) {
 
130
    deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body));
 
131
    Base->deallocateFunctionBody(Body);
 
132
  }
 
133
  struct DeallocateExceptionTableCall {
 
134
    DeallocateExceptionTableCall(const void *ET) : ET(ET) {}
 
135
    const void *ET;
 
136
  };
 
137
  std::vector<DeallocateExceptionTableCall> deallocateExceptionTableCalls;
 
138
  virtual void deallocateExceptionTable(void *ET) {
 
139
    deallocateExceptionTableCalls.push_back(DeallocateExceptionTableCall(ET));
 
140
    Base->deallocateExceptionTable(ET);
 
141
  }
 
142
  struct StartExceptionTableCall {
 
143
    StartExceptionTableCall(uint8_t *Result, const Function *F,
 
144
                            uintptr_t ActualSize, uintptr_t ActualSizeResult)
 
145
      : Result(Result), F(F), F_dump(DumpFunction(F)),
 
146
        ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {}
 
147
    uint8_t *Result;
 
148
    const Function *F;
 
149
    std::string F_dump;
 
150
    uintptr_t ActualSize;
 
151
    uintptr_t ActualSizeResult;
 
152
  };
 
153
  std::vector<StartExceptionTableCall> startExceptionTableCalls;
 
154
  virtual uint8_t* startExceptionTable(const Function* F,
 
155
                                       uintptr_t &ActualSize) {
 
156
    uintptr_t InitialActualSize = ActualSize;
 
157
    uint8_t *Result = Base->startExceptionTable(F, ActualSize);
 
158
    startExceptionTableCalls.push_back(
 
159
      StartExceptionTableCall(Result, F, InitialActualSize, ActualSize));
 
160
    return Result;
 
161
  }
 
162
  struct EndExceptionTableCall {
 
163
    EndExceptionTableCall(const Function *F, uint8_t *TableStart,
 
164
                          uint8_t *TableEnd, uint8_t* FrameRegister)
 
165
      : F(F), F_dump(DumpFunction(F)),
 
166
        TableStart(TableStart), TableEnd(TableEnd),
 
167
        FrameRegister(FrameRegister) {}
 
168
    const Function *F;
 
169
    std::string F_dump;
 
170
    uint8_t *TableStart;
 
171
    uint8_t *TableEnd;
 
172
    uint8_t *FrameRegister;
 
173
  };
 
174
  std::vector<EndExceptionTableCall> endExceptionTableCalls;
 
175
  virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
 
176
                                 uint8_t *TableEnd, uint8_t* FrameRegister) {
 
177
      endExceptionTableCalls.push_back(
 
178
          EndExceptionTableCall(F, TableStart, TableEnd, FrameRegister));
 
179
    return Base->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
 
180
  }
 
181
};
 
182
 
 
183
bool LoadAssemblyInto(Module *M, const char *assembly) {
 
184
  SMDiagnostic Error;
 
185
  bool success =
 
186
    NULL != ParseAssemblyString(assembly, M, Error, M->getContext());
 
187
  std::string errMsg;
 
188
  raw_string_ostream os(errMsg);
 
189
  Error.Print("", os);
 
190
  EXPECT_TRUE(success) << os.str();
 
191
  return success;
 
192
}
 
193
 
 
194
class JITTest : public testing::Test {
 
195
 protected:
 
196
  virtual void SetUp() {
 
197
    M = new Module("<main>", Context);
 
198
    RJMM = new RecordingJITMemoryManager;
 
199
    RJMM->setPoisonMemory(true);
 
200
    std::string Error;
 
201
    TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
 
202
                 .setJITMemoryManager(RJMM)
 
203
                 .setErrorStr(&Error).create());
 
204
    ASSERT_TRUE(TheJIT.get() != NULL) << Error;
 
205
  }
 
206
 
 
207
  void LoadAssembly(const char *assembly) {
 
208
    LoadAssemblyInto(M, assembly);
 
209
  }
 
210
 
 
211
  LLVMContext Context;
 
212
  Module *M;  // Owned by ExecutionEngine.
 
213
  RecordingJITMemoryManager *RJMM;
 
214
  OwningPtr<ExecutionEngine> TheJIT;
 
215
};
 
216
 
 
217
// Regression test for a bug.  The JIT used to allocate globals inside the same
 
218
// memory block used for the function, and when the function code was freed,
 
219
// the global was left in the same place.  This test allocates a function
 
220
// that uses and global, deallocates it, and then makes sure that the global
 
221
// stays alive after that.
 
222
TEST(JIT, GlobalInFunction) {
 
223
  LLVMContext context;
 
224
  Module *M = new Module("<main>", context);
 
225
 
 
226
  JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
 
227
  // Tell the memory manager to poison freed memory so that accessing freed
 
228
  // memory is more easily tested.
 
229
  MemMgr->setPoisonMemory(true);
 
230
  std::string Error;
 
231
  OwningPtr<ExecutionEngine> JIT(EngineBuilder(M)
 
232
                                 .setEngineKind(EngineKind::JIT)
 
233
                                 .setErrorStr(&Error)
 
234
                                 .setJITMemoryManager(MemMgr)
 
235
                                 // The next line enables the fix:
 
236
                                 .setAllocateGVsWithCode(false)
 
237
                                 .create());
 
238
  ASSERT_EQ(Error, "");
 
239
 
 
240
  // Create a global variable.
 
241
  const Type *GTy = Type::getInt32Ty(context);
 
242
  GlobalVariable *G = new GlobalVariable(
 
243
      *M,
 
244
      GTy,
 
245
      false,  // Not constant.
 
246
      GlobalValue::InternalLinkage,
 
247
      Constant::getNullValue(GTy),
 
248
      "myglobal");
 
249
 
 
250
  // Make a function that points to a global.
 
251
  Function *F1 = makeReturnGlobal("F1", G, M);
 
252
 
 
253
  // Get the pointer to the native code to force it to JIT the function and
 
254
  // allocate space for the global.
 
255
  void (*F1Ptr)() =
 
256
      reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F1));
 
257
 
 
258
  // Since F1 was codegen'd, a pointer to G should be available.
 
259
  int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G);
 
260
  ASSERT_NE((int32_t*)NULL, GPtr);
 
261
  EXPECT_EQ(0, *GPtr);
 
262
 
 
263
  // F1() should increment G.
 
264
  F1Ptr();
 
265
  EXPECT_EQ(1, *GPtr);
 
266
 
 
267
  // Make a second function identical to the first, referring to the same
 
268
  // global.
 
269
  Function *F2 = makeReturnGlobal("F2", G, M);
 
270
  void (*F2Ptr)() =
 
271
      reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F2));
 
272
 
 
273
  // F2() should increment G.
 
274
  F2Ptr();
 
275
  EXPECT_EQ(2, *GPtr);
 
276
 
 
277
  // Deallocate F1.
 
278
  JIT->freeMachineCodeForFunction(F1);
 
279
 
 
280
  // F2() should *still* increment G.
 
281
  F2Ptr();
 
282
  EXPECT_EQ(3, *GPtr);
 
283
}
 
284
 
 
285
int PlusOne(int arg) {
 
286
  return arg + 1;
 
287
}
 
288
 
 
289
TEST_F(JITTest, FarCallToKnownFunction) {
 
290
  // x86-64 can only make direct calls to functions within 32 bits of
 
291
  // the current PC.  To call anything farther away, we have to load
 
292
  // the address into a register and call through the register.  The
 
293
  // current JIT does this by allocating a stub for any far call.
 
294
  // There was a bug in which the JIT tried to emit a direct call when
 
295
  // the target was already in the JIT's global mappings and lazy
 
296
  // compilation was disabled.
 
297
 
 
298
  Function *KnownFunction = Function::Create(
 
299
      TypeBuilder<int(int), false>::get(Context),
 
300
      GlobalValue::ExternalLinkage, "known", M);
 
301
  TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne);
 
302
 
 
303
  // int test() { return known(7); }
 
304
  Function *TestFunction = Function::Create(
 
305
      TypeBuilder<int(), false>::get(Context),
 
306
      GlobalValue::ExternalLinkage, "test", M);
 
307
  BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction);
 
308
  IRBuilder<> Builder(Entry);
 
309
  Value *result = Builder.CreateCall(
 
310
      KnownFunction,
 
311
      ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
 
312
  Builder.CreateRet(result);
 
313
 
 
314
  TheJIT->DisableLazyCompilation(true);
 
315
  int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
 
316
      (intptr_t)TheJIT->getPointerToFunction(TestFunction));
 
317
  // This used to crash in trying to call PlusOne().
 
318
  EXPECT_EQ(8, TestFunctionPtr());
 
319
}
 
320
 
 
321
// Test a function C which calls A and B which call each other.
 
322
TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) {
 
323
  TheJIT->DisableLazyCompilation(true);
 
324
 
 
325
  const FunctionType *Func1Ty =
 
326
      cast<FunctionType>(TypeBuilder<void(void), false>::get(Context));
 
327
  std::vector<const Type*> arg_types;
 
328
  arg_types.push_back(Type::getInt1Ty(Context));
 
329
  const FunctionType *FuncTy = FunctionType::get(
 
330
      Type::getVoidTy(Context), arg_types, false);
 
331
  Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage,
 
332
                                     "func1", M);
 
333
  Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage,
 
334
                                     "func2", M);
 
335
  Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage,
 
336
                                     "func3", M);
 
337
  BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1);
 
338
  BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2);
 
339
  BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2);
 
340
  BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2);
 
341
  BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3);
 
342
  BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3);
 
343
  BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3);
 
344
 
 
345
  // Make Func1 call Func2(0) and Func3(0).
 
346
  IRBuilder<> Builder(Block1);
 
347
  Builder.CreateCall(Func2, ConstantInt::getTrue(Context));
 
348
  Builder.CreateCall(Func3, ConstantInt::getTrue(Context));
 
349
  Builder.CreateRetVoid();
 
350
 
 
351
  // void Func2(bool b) { if (b) { Func3(false); return; } return; }
 
352
  Builder.SetInsertPoint(Block2);
 
353
  Builder.CreateCondBr(Func2->arg_begin(), True2, False2);
 
354
  Builder.SetInsertPoint(True2);
 
355
  Builder.CreateCall(Func3, ConstantInt::getFalse(Context));
 
356
  Builder.CreateRetVoid();
 
357
  Builder.SetInsertPoint(False2);
 
358
  Builder.CreateRetVoid();
 
359
 
 
360
  // void Func3(bool b) { if (b) { Func2(false); return; } return; }
 
361
  Builder.SetInsertPoint(Block3);
 
362
  Builder.CreateCondBr(Func3->arg_begin(), True3, False3);
 
363
  Builder.SetInsertPoint(True3);
 
364
  Builder.CreateCall(Func2, ConstantInt::getFalse(Context));
 
365
  Builder.CreateRetVoid();
 
366
  Builder.SetInsertPoint(False3);
 
367
  Builder.CreateRetVoid();
 
368
 
 
369
  // Compile the function to native code
 
370
  void (*F1Ptr)() =
 
371
     reinterpret_cast<void(*)()>((intptr_t)TheJIT->getPointerToFunction(Func1));
 
372
 
 
373
  F1Ptr();
 
374
}
 
375
 
 
376
// Regression test for PR5162.  This used to trigger an AssertingVH inside the
 
377
// JIT's Function to stub mapping.
 
378
TEST_F(JITTest, NonLazyLeaksNoStubs) {
 
379
  TheJIT->DisableLazyCompilation(true);
 
380
 
 
381
  // Create two functions with a single basic block each.
 
382
  const FunctionType *FuncTy =
 
383
      cast<FunctionType>(TypeBuilder<int(), false>::get(Context));
 
384
  Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage,
 
385
                                     "func1", M);
 
386
  Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage,
 
387
                                     "func2", M);
 
388
  BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1);
 
389
  BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2);
 
390
 
 
391
  // The first function calls the second and returns the result
 
392
  IRBuilder<> Builder(Block1);
 
393
  Value *Result = Builder.CreateCall(Func2);
 
394
  Builder.CreateRet(Result);
 
395
 
 
396
  // The second function just returns a constant
 
397
  Builder.SetInsertPoint(Block2);
 
398
  Builder.CreateRet(ConstantInt::get(TypeBuilder<int, false>::get(Context),42));
 
399
 
 
400
  // Compile the function to native code
 
401
  (void)TheJIT->getPointerToFunction(Func1);
 
402
 
 
403
  // Free the JIT state for the functions
 
404
  TheJIT->freeMachineCodeForFunction(Func1);
 
405
  TheJIT->freeMachineCodeForFunction(Func2);
 
406
 
 
407
  // Delete the first function (and show that is has no users)
 
408
  EXPECT_EQ(Func1->getNumUses(), 0u);
 
409
  Func1->eraseFromParent();
 
410
 
 
411
  // Delete the second function (and show that it has no users - it had one,
 
412
  // func1 but that's gone now)
 
413
  EXPECT_EQ(Func2->getNumUses(), 0u);
 
414
  Func2->eraseFromParent();
 
415
}
 
416
 
 
417
TEST_F(JITTest, ModuleDeletion) {
 
418
  TheJIT->DisableLazyCompilation(false);
 
419
  LoadAssembly("define void @main() { "
 
420
               "  call i32 @computeVal() "
 
421
               "  ret void "
 
422
               "} "
 
423
               " "
 
424
               "define internal i32 @computeVal()  { "
 
425
               "  ret i32 0 "
 
426
               "} ");
 
427
  Function *func = M->getFunction("main");
 
428
  TheJIT->getPointerToFunction(func);
 
429
  TheJIT->removeModule(M);
 
430
  delete M;
 
431
 
 
432
  SmallPtrSet<const void*, 2> FunctionsDeallocated;
 
433
  for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size();
 
434
       i != e; ++i) {
 
435
    FunctionsDeallocated.insert(RJMM->deallocateFunctionBodyCalls[i].Body);
 
436
  }
 
437
  for (unsigned i = 0, e = RJMM->startFunctionBodyCalls.size(); i != e; ++i) {
 
438
    EXPECT_TRUE(FunctionsDeallocated.count(
 
439
                  RJMM->startFunctionBodyCalls[i].Result))
 
440
      << "Function leaked: \n" << RJMM->startFunctionBodyCalls[i].F_dump;
 
441
  }
 
442
  EXPECT_EQ(RJMM->startFunctionBodyCalls.size(),
 
443
            RJMM->deallocateFunctionBodyCalls.size());
 
444
 
 
445
  SmallPtrSet<const void*, 2> ExceptionTablesDeallocated;
 
446
  unsigned NumTablesDeallocated = 0;
 
447
  for (unsigned i = 0, e = RJMM->deallocateExceptionTableCalls.size();
 
448
       i != e; ++i) {
 
449
    ExceptionTablesDeallocated.insert(
 
450
        RJMM->deallocateExceptionTableCalls[i].ET);
 
451
    if (RJMM->deallocateExceptionTableCalls[i].ET != NULL) {
 
452
        // If JITEmitDebugInfo is off, we'll "deallocate" NULL, which doesn't
 
453
        // appear in startExceptionTableCalls.
 
454
        NumTablesDeallocated++;
 
455
    }
 
456
  }
 
457
  for (unsigned i = 0, e = RJMM->startExceptionTableCalls.size(); i != e; ++i) {
 
458
    EXPECT_TRUE(ExceptionTablesDeallocated.count(
 
459
                  RJMM->startExceptionTableCalls[i].Result))
 
460
      << "Function's exception table leaked: \n"
 
461
      << RJMM->startExceptionTableCalls[i].F_dump;
 
462
  }
 
463
  EXPECT_EQ(RJMM->startExceptionTableCalls.size(),
 
464
            NumTablesDeallocated);
 
465
}
 
466
 
 
467
// ARM and PPC still emit stubs for calls since the target may be too far away
 
468
// to call directly.  This #if can probably be removed when
 
469
// http://llvm.org/PR5201 is fixed.
 
470
#if !defined(__arm__) && !defined(__powerpc__) && !defined(__ppc__)
 
471
typedef int (*FooPtr) ();
 
472
 
 
473
TEST_F(JITTest, NoStubs) {
 
474
  LoadAssembly("define void @bar() {"
 
475
               "entry: "
 
476
               "ret void"
 
477
               "}"
 
478
               " "
 
479
               "define i32 @foo() {"
 
480
               "entry:"
 
481
               "call void @bar()"
 
482
               "ret i32 undef"
 
483
               "}"
 
484
               " "
 
485
               "define i32 @main() {"
 
486
               "entry:"
 
487
               "%0 = call i32 @foo()"
 
488
               "call void @bar()"
 
489
               "ret i32 undef"
 
490
               "}");
 
491
  Function *foo = M->getFunction("foo");
 
492
  uintptr_t tmp = (uintptr_t)(TheJIT->getPointerToFunction(foo));
 
493
  FooPtr ptr = (FooPtr)(tmp);
 
494
 
 
495
  (ptr)();
 
496
 
 
497
  // We should now allocate no more stubs, we have the code to foo
 
498
  // and the existing stub for bar.
 
499
  int stubsBefore = RJMM->stubsAllocated;
 
500
  Function *func = M->getFunction("main");
 
501
  TheJIT->getPointerToFunction(func);
 
502
 
 
503
  Function *bar = M->getFunction("bar");
 
504
  TheJIT->getPointerToFunction(bar);
 
505
 
 
506
  ASSERT_EQ(stubsBefore, RJMM->stubsAllocated);
 
507
}
 
508
#endif  // !ARM && !PPC
 
509
 
 
510
TEST_F(JITTest, FunctionPointersOutliveTheirCreator) {
 
511
  TheJIT->DisableLazyCompilation(true);
 
512
  LoadAssembly("define i8()* @get_foo_addr() { "
 
513
               "  ret i8()* @foo "
 
514
               "} "
 
515
               " "
 
516
               "define i8 @foo() { "
 
517
               "  ret i8 42 "
 
518
               "} ");
 
519
  Function *F_get_foo_addr = M->getFunction("get_foo_addr");
 
520
 
 
521
  typedef char(*fooT)();
 
522
  fooT (*get_foo_addr)() = reinterpret_cast<fooT(*)()>(
 
523
      (intptr_t)TheJIT->getPointerToFunction(F_get_foo_addr));
 
524
  fooT foo_addr = get_foo_addr();
 
525
 
 
526
  // Now free get_foo_addr.  This should not free the machine code for foo or
 
527
  // any call stub returned as foo's canonical address.
 
528
  TheJIT->freeMachineCodeForFunction(F_get_foo_addr);
 
529
 
 
530
  // Check by calling the reported address of foo.
 
531
  EXPECT_EQ(42, foo_addr());
 
532
 
 
533
  // The reported address should also be the same as the result of a subsequent
 
534
  // getPointerToFunction(foo).
 
535
#if 0
 
536
  // Fails until PR5126 is fixed:
 
537
  Function *F_foo = M->getFunction("foo");
 
538
  fooT foo = reinterpret_cast<fooT>(
 
539
      (intptr_t)TheJIT->getPointerToFunction(F_foo));
 
540
  EXPECT_EQ((intptr_t)foo, (intptr_t)foo_addr);
 
541
#endif
 
542
}
 
543
 
 
544
// ARM doesn't have an implementation of replaceMachineCodeForFunction(), so
 
545
// recompileAndRelinkFunction doesn't work.
 
546
#if !defined(__arm__)
 
547
TEST_F(JITTest, FunctionIsRecompiledAndRelinked) {
 
548
  Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context),
 
549
                                 GlobalValue::ExternalLinkage, "test", M);
 
550
  BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
 
551
  IRBuilder<> Builder(Entry);
 
552
  Value *Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 1);
 
553
  Builder.CreateRet(Val);
 
554
 
 
555
  TheJIT->DisableLazyCompilation(true);
 
556
  // Compile the function once, and make sure it works.
 
557
  int (*OrigFPtr)() = reinterpret_cast<int(*)()>(
 
558
    (intptr_t)TheJIT->recompileAndRelinkFunction(F));
 
559
  EXPECT_EQ(1, OrigFPtr());
 
560
 
 
561
  // Now change the function to return a different value.
 
562
  Entry->eraseFromParent();
 
563
  BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F);
 
564
  Builder.SetInsertPoint(NewEntry);
 
565
  Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 2);
 
566
  Builder.CreateRet(Val);
 
567
  // Recompile it, which should produce a new function pointer _and_ update the
 
568
  // old one.
 
569
  int (*NewFPtr)() = reinterpret_cast<int(*)()>(
 
570
    (intptr_t)TheJIT->recompileAndRelinkFunction(F));
 
571
 
 
572
  EXPECT_EQ(2, NewFPtr())
 
573
    << "The new pointer should call the new version of the function";
 
574
  EXPECT_EQ(2, OrigFPtr())
 
575
    << "The old pointer's target should now jump to the new version";
 
576
}
 
577
#endif  // !defined(__arm__)
 
578
 
 
579
}  // anonymous namespace
 
580
// This variable is intentionally defined differently in the statically-compiled
 
581
// program from the IR input to the JIT to assert that the JIT doesn't use its
 
582
// definition.
 
583
extern "C" int32_t JITTest_AvailableExternallyGlobal;
 
584
int32_t JITTest_AvailableExternallyGlobal = 42;
 
585
namespace {
 
586
 
 
587
#if 0
 
588
// CLAMAV LOCAL: disable because this needs rdynamic flag
 
589
TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) {
 
590
  TheJIT->DisableLazyCompilation(true);
 
591
  LoadAssembly("@JITTest_AvailableExternallyGlobal = "
 
592
               "  available_externally global i32 7 "
 
593
               " "
 
594
               "define i32 @loader() { "
 
595
               "  %result = load i32* @JITTest_AvailableExternallyGlobal "
 
596
               "  ret i32 %result "
 
597
               "} ");
 
598
  Function *loaderIR = M->getFunction("loader");
 
599
 
 
600
  int32_t (*loader)() = reinterpret_cast<int32_t(*)()>(
 
601
    (intptr_t)TheJIT->getPointerToFunction(loaderIR));
 
602
  EXPECT_EQ(42, loader()) << "func should return 42 from the external global,"
 
603
                          << " not 7 from the IR version.";
 
604
}
 
605
 
 
606
}  // anonymous namespace
 
607
// This function is intentionally defined differently in the statically-compiled
 
608
// program from the IR input to the JIT to assert that the JIT doesn't use its
 
609
// definition.
 
610
extern "C" int32_t JITTest_AvailableExternallyFunction() {
 
611
  return 42;
 
612
}
 
613
namespace {
 
614
 
 
615
TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) {
 
616
  TheJIT->DisableLazyCompilation(true);
 
617
  LoadAssembly("define available_externally i32 "
 
618
               "    @JITTest_AvailableExternallyFunction() { "
 
619
               "  ret i32 7 "
 
620
               "} "
 
621
               " "
 
622
               "define i32 @func() { "
 
623
               "  %result = tail call i32 "
 
624
               "    @JITTest_AvailableExternallyFunction() "
 
625
               "  ret i32 %result "
 
626
               "} ");
 
627
  Function *funcIR = M->getFunction("func");
 
628
 
 
629
  int32_t (*func)() = reinterpret_cast<int32_t(*)()>(
 
630
    (intptr_t)TheJIT->getPointerToFunction(funcIR));
 
631
  EXPECT_EQ(42, func()) << "func should return 42 from the static version,"
 
632
                        << " not 7 from the IR version.";
 
633
}
 
634
 
 
635
TEST_F(JITTest, NeedsExactSizeWithManyGlobals) {
 
636
  // PR5291: When the JMM needed the exact size of function bodies before
 
637
  // starting to emit them, the JITEmitter would modify a set while iterating
 
638
  // over it.
 
639
  TheJIT->DisableLazyCompilation(true);
 
640
  RJMM->setSizeRequired(true);
 
641
 
 
642
  LoadAssembly("@A = global i32 42 "
 
643
               "@B = global i32* @A "
 
644
               "@C = global i32** @B "
 
645
               "@D = global i32*** @C "
 
646
               "@E = global i32**** @D "
 
647
               "@F = global i32***** @E "
 
648
               "@G = global i32****** @F "
 
649
               "@H = global i32******* @G "
 
650
               "@I = global i32******** @H "
 
651
               "define i32********* @test() { "
 
652
               "  ret i32********* @I "
 
653
               "}");
 
654
  Function *testIR = M->getFunction("test");
 
655
  int32_t********* (*test)() = reinterpret_cast<int32_t*********(*)()>(
 
656
    (intptr_t)TheJIT->getPointerToFunction(testIR));
 
657
  EXPECT_EQ(42, *********test());
 
658
}
 
659
 
 
660
TEST_F(JITTest, EscapedLazyStubStillCallable) {
 
661
  TheJIT->DisableLazyCompilation(false);
 
662
  LoadAssembly("define internal i32 @stubbed() { "
 
663
               "  ret i32 42 "
 
664
               "} "
 
665
               " "
 
666
               "define i32()* @get_stub() { "
 
667
               "  ret i32()* @stubbed "
 
668
               "} ");
 
669
  typedef int32_t(*StubTy)();
 
670
 
 
671
  // Call get_stub() to get the address of @stubbed without actually JITting it.
 
672
  Function *get_stubIR = M->getFunction("get_stub");
 
673
  StubTy (*get_stub)() = reinterpret_cast<StubTy(*)()>(
 
674
    (intptr_t)TheJIT->getPointerToFunction(get_stubIR));
 
675
  StubTy stubbed = get_stub();
 
676
  // Now get_stubIR is the only reference to stubbed's stub.
 
677
  get_stubIR->eraseFromParent();
 
678
  // Now there are no references inside the JIT, but we've got a pointer outside
 
679
  // it.  The stub should be callable and return the right value.
 
680
  EXPECT_EQ(42, stubbed());
 
681
}
 
682
 
 
683
// Converts the LLVM assembly to bitcode and returns it in a std::string.  An
 
684
// empty string indicates an error.
 
685
std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) {
 
686
  Module TempModule("TempModule", Context);
 
687
  if (!LoadAssemblyInto(&TempModule, Assembly)) {
 
688
    return "";
 
689
  }
 
690
 
 
691
  std::string Result;
 
692
  raw_string_ostream OS(Result);
 
693
  WriteBitcodeToFile(&TempModule, OS);
 
694
  OS.flush();
 
695
  return Result;
 
696
}
 
697
 
 
698
// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode'
 
699
// lazily.  The associated Module (owned by the ExecutionEngine) is returned in
 
700
// M.  Both will be NULL on an error.  Bitcode must live at least as long as the
 
701
// ExecutionEngine.
 
702
ExecutionEngine *getJITFromBitcode(
 
703
  LLVMContext &Context, const std::string &Bitcode, Module *&M) {
 
704
  // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires.
 
705
  MemoryBuffer *BitcodeBuffer =
 
706
    MemoryBuffer::getMemBuffer(Bitcode.c_str(),
 
707
                               Bitcode.c_str() + Bitcode.size(),
 
708
                               "Bitcode for test");
 
709
  std::string errMsg;
 
710
  M = getLazyBitcodeModule(BitcodeBuffer, Context, &errMsg);
 
711
  if (M == NULL) {
 
712
    ADD_FAILURE() << errMsg;
 
713
    delete BitcodeBuffer;
 
714
    return NULL;
 
715
  }
 
716
  ExecutionEngine *TheJIT = EngineBuilder(M)
 
717
    .setEngineKind(EngineKind::JIT)
 
718
    .setErrorStr(&errMsg)
 
719
    .create();
 
720
  if (TheJIT == NULL) {
 
721
    ADD_FAILURE() << errMsg;
 
722
    delete M;
 
723
    M = NULL;
 
724
    return NULL;
 
725
  }
 
726
  return TheJIT;
 
727
}
 
728
 
 
729
TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) {
 
730
  LLVMContext Context;
 
731
  const std::string Bitcode =
 
732
    AssembleToBitcode(Context,
 
733
                      "define available_externally i32 "
 
734
                      "    @JITTest_AvailableExternallyFunction() { "
 
735
                      "  ret i32 7 "
 
736
                      "} "
 
737
                      " "
 
738
                      "define i32 @func() { "
 
739
                      "  %result = tail call i32 "
 
740
                      "    @JITTest_AvailableExternallyFunction() "
 
741
                      "  ret i32 %result "
 
742
                      "} ");
 
743
  ASSERT_FALSE(Bitcode.empty()) << "Assembling failed";
 
744
  Module *M;
 
745
  OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M));
 
746
  ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT.";
 
747
  TheJIT->DisableLazyCompilation(true);
 
748
 
 
749
  Function *funcIR = M->getFunction("func");
 
750
  Function *availableFunctionIR =
 
751
    M->getFunction("JITTest_AvailableExternallyFunction");
 
752
 
 
753
  // Double-check that the available_externally function is still unmaterialized
 
754
  // when getPointerToFunction needs to find out if it's available_externally.
 
755
  EXPECT_TRUE(availableFunctionIR->isMaterializable());
 
756
 
 
757
  int32_t (*func)() = reinterpret_cast<int32_t(*)()>(
 
758
    (intptr_t)TheJIT->getPointerToFunction(funcIR));
 
759
  EXPECT_EQ(42, func()) << "func should return 42 from the static version,"
 
760
                        << " not 7 from the IR version.";
 
761
}
 
762
 
 
763
TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) {
 
764
  LLVMContext Context;
 
765
  const std::string Bitcode =
 
766
    AssembleToBitcode(Context,
 
767
                      "define i32 @recur1(i32 %a) { "
 
768
                      "  %zero = icmp eq i32 %a, 0 "
 
769
                      "  br i1 %zero, label %done, label %notdone "
 
770
                      "done: "
 
771
                      "  ret i32 3 "
 
772
                      "notdone: "
 
773
                      "  %am1 = sub i32 %a, 1 "
 
774
                      "  %result = call i32 @recur2(i32 %am1) "
 
775
                      "  ret i32 %result "
 
776
                      "} "
 
777
                      " "
 
778
                      "define i32 @recur2(i32 %b) { "
 
779
                      "  %result = call i32 @recur1(i32 %b) "
 
780
                      "  ret i32 %result "
 
781
                      "} ");
 
782
  ASSERT_FALSE(Bitcode.empty()) << "Assembling failed";
 
783
  Module *M;
 
784
  OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M));
 
785
  ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT.";
 
786
  TheJIT->DisableLazyCompilation(true);
 
787
 
 
788
  Function *recur1IR = M->getFunction("recur1");
 
789
  Function *recur2IR = M->getFunction("recur2");
 
790
  EXPECT_TRUE(recur1IR->isMaterializable());
 
791
  EXPECT_TRUE(recur2IR->isMaterializable());
 
792
 
 
793
  int32_t (*recur1)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>(
 
794
    (intptr_t)TheJIT->getPointerToFunction(recur1IR));
 
795
  EXPECT_EQ(3, recur1(4));
 
796
}
 
797
#endif
 
798
// This code is copied from JITEventListenerTest, but it only runs once for all
 
799
// the tests in this directory.  Everything seems fine, but that's strange
 
800
// behavior.
 
801
class JITEnvironment : public testing::Environment {
 
802
  virtual void SetUp() {
 
803
    // Required to create a JIT.
 
804
    InitializeNativeTarget();
 
805
  }
 
806
};
 
807
testing::Environment* const jit_env =
 
808
  testing::AddGlobalTestEnvironment(new JITEnvironment);
 
809
 
 
810
}