Intel® Implicit SPMD Program Compiler (Intel® ISPC)  1.13.0
func.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2011-2020, Intel Corporation
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15 
16  * Neither the name of Intel Corporation nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /** @file func.cpp
35  @brief
36 */
37 
38 #include "func.h"
39 #include "ctx.h"
40 #include "expr.h"
41 #include "llvmutil.h"
42 #include "module.h"
43 #include "stmt.h"
44 #include "sym.h"
45 #include "type.h"
46 #include "util.h"
47 #include <stdio.h>
48 
49 #include <llvm/IR/DerivedTypes.h>
50 #include <llvm/IR/Instructions.h>
51 #include <llvm/IR/Intrinsics.h>
52 #include <llvm/IR/LLVMContext.h>
53 #include <llvm/IR/Module.h>
54 #include <llvm/IR/Type.h>
55 
56 #include "llvm/IR/LegacyPassManager.h"
57 #include <llvm/IR/CFG.h>
58 #include <llvm/IR/IRPrintingPasses.h>
59 #include <llvm/IR/Verifier.h>
60 #include <llvm/PassRegistry.h>
61 #include <llvm/Support/FileUtilities.h>
62 #include <llvm/Support/FormattedStream.h>
63 #include <llvm/Target/TargetMachine.h>
64 #include <llvm/Target/TargetOptions.h>
65 #include <llvm/Transforms/IPO.h>
66 
67 #include <llvm/Support/ToolOutputFile.h>
68 
70  sym = s;
71  code = c;
72 
73  maskSymbol = m->symbolTable->LookupVariable("__mask");
74  Assert(maskSymbol != NULL);
75 
76  if (code != NULL) {
77  code = TypeCheck(code);
78 
79  if (code != NULL && g->debugPrint) {
80  printf("After typechecking function \"%s\":\n", sym->name.c_str());
81  code->Print(0);
82  printf("---------------------\n");
83  }
84 
85  if (code != NULL) {
86  code = Optimize(code);
87  if (g->debugPrint) {
88  printf("After optimizing function \"%s\":\n", sym->name.c_str());
89  code->Print(0);
90  printf("---------------------\n");
91  }
92  }
93  }
94 
95  if (g->debugPrint) {
96  printf("Add Function %s\n", sym->name.c_str());
97  if (code != NULL) {
98  code->Print(0);
99  }
100  printf("\n\n\n");
101  }
102 
103  const FunctionType *type = CastType<FunctionType>(sym->type);
104  Assert(type != NULL);
105 
106  for (int i = 0; i < type->GetNumParameters(); ++i) {
107  const char *paramName = type->GetParameterName(i).c_str();
108  Symbol *paramSym = m->symbolTable->LookupVariable(paramName);
109  if (paramSym == NULL)
110  Assert(strncmp(paramName, "__anon_parameter_", 17) == 0);
111  args.push_back(paramSym);
112 
113  const Type *t = type->GetParameterType(i);
114  if (paramSym != NULL && CastType<ReferenceType>(t) == NULL)
115  paramSym->parentFunction = this;
116  }
117 
118  if (type->isTask) {
119  threadIndexSym = m->symbolTable->LookupVariable("threadIndex");
121  threadCountSym = m->symbolTable->LookupVariable("threadCount");
123  taskIndexSym = m->symbolTable->LookupVariable("taskIndex");
125  taskCountSym = m->symbolTable->LookupVariable("taskCount");
127 
128  taskIndexSym0 = m->symbolTable->LookupVariable("taskIndex0");
130  taskIndexSym1 = m->symbolTable->LookupVariable("taskIndex1");
132  taskIndexSym2 = m->symbolTable->LookupVariable("taskIndex2");
134 
135  taskCountSym0 = m->symbolTable->LookupVariable("taskCount0");
137  taskCountSym1 = m->symbolTable->LookupVariable("taskCount1");
139  taskCountSym2 = m->symbolTable->LookupVariable("taskCount2");
141  } else {
145  }
146 }
147 
149  const FunctionType *type = CastType<FunctionType>(sym->type);
150  Assert(type != NULL);
151  return type->GetReturnType();
152 }
153 
155  const FunctionType *type = CastType<FunctionType>(sym->type);
156  Assert(type != NULL);
157  return type;
158 }
159 
160 /** Parameters for tasks are stored in a big structure; this utility
161  function emits code to copy those values out of the task structure into
162  local stack-allocated variables. (Which we expect that LLVM's
163  'mem2reg' pass will in turn promote to SSA registers..
164  */
165 static void lCopyInTaskParameter(int i, llvm::Value *structArgPtr, const std::vector<Symbol *> &args,
166  FunctionEmitContext *ctx) {
167  // We expect the argument structure to come in as a poitner to a
168  // structure. Confirm and figure out its type here.
169  const llvm::Type *structArgType = structArgPtr->getType();
170  Assert(llvm::isa<llvm::PointerType>(structArgType));
171  const llvm::PointerType *pt = llvm::dyn_cast<const llvm::PointerType>(structArgType);
172  Assert(pt);
173  Assert(llvm::isa<llvm::StructType>(pt->getElementType()));
174 
175  // Get the type of the argument we're copying in and its Symbol pointer
176  Symbol *sym = args[i];
177 
178  if (sym == NULL)
179  // anonymous parameter, so don't worry about it
180  return;
181 
182  // allocate space to copy the parameter in to
183  sym->storagePtr = ctx->AllocaInst(sym->type, sym->name.c_str());
184 
185  // get a pointer to the value in the struct
186  llvm::Value *ptr = ctx->AddElementOffset(structArgPtr, i, NULL, sym->name.c_str());
187 
188  // and copy the value from the struct and into the local alloca'ed
189  // memory
190  llvm::Value *ptrval = ctx->LoadInst(ptr, sym->type, sym->name.c_str());
191  ctx->StoreInst(ptrval, sym->storagePtr, sym->type);
192  ctx->EmitFunctionParameterDebugInfo(sym, i);
193 }
194 
195 /** Given the statements implementing a function, emit the code that
196  implements the function. Most of the work do be done here just
197  involves wiring up the function parameter values to be available in the
198  function body code.
199  */
200 void Function::emitCode(FunctionEmitContext *ctx, llvm::Function *function, SourcePos firstStmtPos) {
201  // Connect the __mask builtin to the location in memory that stores its
202  // value
204 
205  // add debugging info for __mask
206  maskSymbol->pos = firstStmtPos;
208 
209  if (g->NoOmitFramePointer)
210  function->addFnAttr("no-frame-pointer-elim", "true");
211  if (g->target->getArch() == Arch::wasm32)
212  function->addFnAttr("target-features", "+simd128");
213 
214  g->target->markFuncWithTargetAttr(function);
215 #if 0
216  llvm::BasicBlock *entryBBlock = ctx->GetCurrentBasicBlock();
217 #endif
218  const FunctionType *type = CastType<FunctionType>(sym->type);
219  Assert(type != NULL);
220  if (type->isTask == true) {
221  // For tasks, there should always be three parameters: the
222  // pointer to the structure that holds all of the arguments, the
223  // thread index, and the thread count variables.
224  llvm::Function::arg_iterator argIter = function->arg_begin();
225 
226  llvm::Value *structParamPtr = &*(argIter++);
227  llvm::Value *threadIndex = &*(argIter++);
228  llvm::Value *threadCount = &*(argIter++);
229  llvm::Value *taskIndex = &*(argIter++);
230  llvm::Value *taskCount = &*(argIter++);
231  llvm::Value *taskIndex0 = &*(argIter++);
232  llvm::Value *taskIndex1 = &*(argIter++);
233  llvm::Value *taskIndex2 = &*(argIter++);
234  llvm::Value *taskCount0 = &*(argIter++);
235  llvm::Value *taskCount1 = &*(argIter++);
236  llvm::Value *taskCount2 = &*(argIter++);
237  // Copy the function parameter values from the structure into local
238  // storage
239  for (unsigned int i = 0; i < args.size(); ++i)
240  lCopyInTaskParameter(i, structParamPtr, args, ctx);
241 
242  if (type->isUnmasked == false) {
243  // Copy in the mask as well.
244  int nArgs = (int)args.size();
245  // The mask is the last parameter in the argument structure
246  llvm::Value *ptr = ctx->AddElementOffset(structParamPtr, nArgs, NULL, "task_struct_mask");
247  llvm::Value *ptrval = ctx->LoadInst(ptr, NULL, "mask");
248  ctx->SetFunctionMask(ptrval);
249  }
250 
251  // Copy threadIndex and threadCount into stack-allocated storage so
252  // that their symbols point to something reasonable.
254  ctx->StoreInst(threadIndex, threadIndexSym->storagePtr);
255 
257  ctx->StoreInst(threadCount, threadCountSym->storagePtr);
258 
259  // Copy taskIndex and taskCount into stack-allocated storage so
260  // that their symbols point to something reasonable.
262  ctx->StoreInst(taskIndex, taskIndexSym->storagePtr);
263 
265  ctx->StoreInst(taskCount, taskCountSym->storagePtr);
266 
268  ctx->StoreInst(taskIndex0, taskIndexSym0->storagePtr);
270  ctx->StoreInst(taskIndex1, taskIndexSym1->storagePtr);
272  ctx->StoreInst(taskIndex2, taskIndexSym2->storagePtr);
273 
275  ctx->StoreInst(taskCount0, taskCountSym0->storagePtr);
277  ctx->StoreInst(taskCount1, taskCountSym1->storagePtr);
279  ctx->StoreInst(taskCount2, taskCountSym2->storagePtr);
280  } else {
281  // Regular, non-task function
282  llvm::Function::arg_iterator argIter = function->arg_begin();
283  for (unsigned int i = 0; i < args.size(); ++i, ++argIter) {
284  Symbol *argSym = args[i];
285  if (argSym == NULL)
286  // anonymous function parameter
287  continue;
288 
289  argIter->setName(argSym->name.c_str());
290 
291  // Allocate stack storage for the parameter and emit code
292  // to store the its value there.
293  argSym->storagePtr = ctx->AllocaInst(argSym->type, argSym->name.c_str());
294 
295  ctx->StoreInst(&*argIter, argSym->storagePtr, argSym->type);
296  ctx->EmitFunctionParameterDebugInfo(argSym, i);
297  }
298 
299  // If the number of actual function arguments is equal to the
300  // number of declared arguments in decl->functionParams, then we
301  // don't have a mask parameter, so set it to be all on. This
302  // happens for exmaple with 'export'ed functions that the app
303  // calls.
304  if (argIter == function->arg_end()) {
305  Assert(type->isUnmasked || type->isExported);
307  } else {
308  Assert(type->isUnmasked == false);
309 
310  // Otherwise use the mask to set the entry mask value
311  argIter->setName("__mask");
312  Assert(argIter->getType() == LLVMTypes::MaskType);
313 
314  ctx->SetFunctionMask(&*argIter);
315  Assert(++argIter == function->arg_end());
316  }
317  }
318 
319  // Finally, we can generate code for the function
320  if (code != NULL) {
321  ctx->SetDebugPos(code->pos);
322  ctx->AddInstrumentationPoint("function entry");
323 
324  int costEstimate = EstimateCost(code);
325  Debug(code->pos, "Estimated cost for function \"%s\" = %d\n", sym->name.c_str(), costEstimate);
326 
327  // If the body of the function is non-trivial, then we wrap the
328  // entire thing inside code that tests to see if the mask is all
329  // on, all off, or mixed. If this is a simple function, then this
330  // isn't worth the code bloat / overhead.
331  bool checkMask =
332  (type->isTask == true) ||
333  ((function->getAttributes().getFnAttributes().hasAttribute(llvm::Attribute::AlwaysInline) == false) &&
334  costEstimate > CHECK_MASK_AT_FUNCTION_START_COST);
335  checkMask &= (type->isUnmasked == false);
336  checkMask &= (g->target->getMaskingIsFree() == false);
337  checkMask &= (g->opt.disableCoherentControlFlow == false);
338 
339  if (checkMask) {
340  llvm::Value *mask = ctx->GetFunctionMask();
341  llvm::Value *allOn = ctx->All(mask);
342  llvm::BasicBlock *bbAllOn = ctx->CreateBasicBlock("all_on");
343  llvm::BasicBlock *bbSomeOn = ctx->CreateBasicBlock("some_on");
344 
345  // Set up basic blocks for goto targets
346  ctx->InitializeLabelMap(code);
347 
348  ctx->BranchInst(bbAllOn, bbSomeOn, allOn);
349  // all on: we've determined dynamically that the mask is all
350  // on. Set the current mask to "all on" explicitly so that
351  // codegen for this path can be improved with this knowledge in
352  // hand...
353  ctx->SetCurrentBasicBlock(bbAllOn);
356  code->EmitCode(ctx);
357  if (ctx->GetCurrentBasicBlock())
358  ctx->ReturnInst();
359 
360  // not all on: however, at least one lane must be running,
361  // since we should never run with all off... some on: reset
362  // the mask to the value it had at function entry and emit the
363  // code. Resetting the mask here is important, due to the "all
364  // on" setting of it for the path above.
365  ctx->SetCurrentBasicBlock(bbSomeOn);
366  ctx->SetFunctionMask(mask);
367 
368  // Set up basic blocks for goto targets again; we want to have
369  // one set of them for gotos in the 'all on' case, and a
370  // distinct set for the 'mixed mask' case.
371  ctx->InitializeLabelMap(code);
372 
373  code->EmitCode(ctx);
374  if (ctx->GetCurrentBasicBlock())
375  ctx->ReturnInst();
376  } else {
377  // Set up basic blocks for goto targets
378  ctx->InitializeLabelMap(code);
379  // No check, just emit the code
380  code->EmitCode(ctx);
381  }
382  }
383 
384  if (ctx->GetCurrentBasicBlock()) {
385  // FIXME: We'd like to issue a warning if we've reached the end of
386  // the function without a return statement (for non-void
387  // functions). But the test below isn't right, since we can have
388  // (with 'x' a varying test) "if (x) return a; else return b;", in
389  // which case we have a valid basic block but its unreachable so ok
390  // to not have return statement.
391 #if 0
392  // If the bblock has no predecessors, then it doesn't matter if it
393  // doesn't have a return; it'll never be reached. If it does,
394  // issue a warning. Also need to warn if it's the entry block for
395  // the function (in which case it will not have predeccesors but is
396  // still reachable.)
397  if (type->GetReturnType()->IsVoidType() == false &&
398  (pred_begin(ec.bblock) != pred_end(ec.bblock) || (ec.bblock == entryBBlock)))
399  Warning(sym->pos, "Missing return statement in function returning \"%s\".",
400  type->rType->GetString().c_str());
401 #endif
402 
403  // FIXME: would like to set the context's current position to
404  // e.g. the end of the function code
405 
406  // if bblock is non-NULL, it hasn't been terminated by e.g. a
407  // return instruction. Need to add a return instruction.
408  ctx->ReturnInst();
409  }
410 }
411 
413  if (sym == NULL)
414  // May be NULL due to error earlier in compilation
415  return;
416 
417  llvm::Function *function = sym->function;
418  Assert(function != NULL);
419 
420  // But if that function has a definition, we don't want to redefine it.
421  if (function->empty() == false) {
422  Error(sym->pos, "Ignoring redefinition of function \"%s\".", sym->name.c_str());
423  return;
424  }
425 
426  // If function is an 'extern C', it cannot be defined in ISPC.
427  const FunctionType *type = CastType<FunctionType>(sym->type);
428  Assert(type != NULL);
429  if (type->isExternC) {
430  Error(sym->pos, "\n\'extern \"C\"\' function \"%s\" cannot be defined in ISPC.", sym->name.c_str());
431  return;
432  }
433 
434  // Figure out a reasonable source file position for the start of the
435  // function body. If possible, get the position of the first actual
436  // non-StmtList statment...
437  SourcePos firstStmtPos = sym->pos;
438  if (code) {
439  StmtList *sl = llvm::dyn_cast<StmtList>(code);
440  if (sl && sl->stmts.size() > 0 && sl->stmts[0] != NULL)
441  firstStmtPos = sl->stmts[0]->pos;
442  else
443  firstStmtPos = code->pos;
444  }
445 
446  // And we can now go ahead and emit the code
447  {
448  FunctionEmitContext ec(this, sym, function, firstStmtPos);
449  emitCode(&ec, function, firstStmtPos);
450  }
451 
452  if (m->errorCount == 0) {
453  // If the function is 'export'-qualified, emit a second version of
454  // it without a mask parameter and without name mangling so that
455  // the application can call it
456  if (type->isExported) {
457  if (!type->isTask) {
458  llvm::FunctionType *ftype = type->LLVMFunctionType(g->ctx, true);
459  llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage;
460  std::string functionName = sym->name;
462  functionName += std::string("_") + g->target->GetISAString();
463  }
464 
465  llvm::Function *appFunction = llvm::Function::Create(ftype, linkage, functionName.c_str(), m->module);
466  appFunction->setDoesNotThrow();
467 
468  for (int i = 0; i < function->getFunctionType()->getNumParams() - 1; i++) {
469  if (function->hasParamAttribute(i, llvm::Attribute::NoAlias)) {
470  appFunction->addParamAttr(i, llvm::Attribute::NoAlias);
471  }
472  }
473  g->target->markFuncWithTargetAttr(appFunction);
474 
475  if (appFunction->getName() != functionName) {
476  // this was a redefinition for which we already emitted an
477  // error, so don't worry about this one...
478  appFunction->eraseFromParent();
479  } else {
480  // And emit the code again
481  FunctionEmitContext ec(this, sym, appFunction, firstStmtPos);
482  emitCode(&ec, appFunction, firstStmtPos);
483  if (m->errorCount == 0) {
484  sym->exportedFunction = appFunction;
485  }
486  }
487  }
488  }
489  }
490 }
llvm::Value * storagePtr
Definition: sym.h:70
llvm::Function * function
Definition: sym.h:74
void InitializeLabelMap(Stmt *code)
Definition: ctx.cpp:1031
llvm::Value * AddElementOffset(llvm::Value *basePtr, int elementNum, const Type *ptrType, const char *name=NULL, const PointerType **resultPtrType=NULL)
Definition: ctx.cpp:1951
Opt opt
Definition: ispc.h:509
const Type * GetReturnType() const
Definition: type.h:864
Declaration of the FunctionEmitContext class
void EmitVariableDebugInfo(Symbol *sym)
Definition: ctx.cpp:1333
Symbol * taskIndexSym
Definition: func.h:61
Symbol * threadIndexSym
Definition: func.h:60
void BranchInst(llvm::BasicBlock *block)
Definition: ctx.cpp:2819
Interface class for statements in the ispc language.
Definition: stmt.h:48
Target * target
Definition: ispc.h:512
llvm::Value * LoadInst(llvm::Value *ptr, llvm::Value *mask, const Type *ptrType, const char *name=NULL, bool one_elem=false)
Definition: ctx.cpp:2172
ASTNode * TypeCheck(ASTNode *root)
Definition: ast.cpp:242
const std::string & GetParameterName(int i) const
Definition: type.cpp:2556
void emitCode(FunctionEmitContext *ctx, llvm::Function *function, SourcePos firstStmtPos)
Definition: func.cpp:200
llvm::Constant * LLVMMaskAllOn
Definition: llvmutil.cpp:94
Symbol * maskSymbol
Definition: func.h:59
llvm::Value * AllocaInst(llvm::Type *llvmType, const char *name=NULL, int align=0, bool atEntryBlock=true)
Definition: ctx.cpp:2401
bool getMaskingIsFree() const
Definition: ispc.h:249
bool NoOmitFramePointer
Definition: ispc.h:542
std::vector< Symbol * > args
Definition: func.h:57
Symbol * taskIndexSym2
Definition: func.h:64
void AddInstrumentationPoint(const char *note)
Definition: ctx.cpp:1269
int GetNumParameters() const
Definition: type.h:874
Module * m
Definition: ispc.cpp:73
std::string name
Definition: sym.h:69
Symbol * LookupVariable(const char *name)
Definition: sym.cpp:112
llvm::BasicBlock * GetCurrentBasicBlock()
Definition: ctx.cpp:359
virtual void EmitCode(FunctionEmitContext *ctx) const =0
llvm::BasicBlock * CreateBasicBlock(const char *name)
Definition: ctx.cpp:1228
header file with declarations for symbol and symbol table classes.
bool disableMaskAllOnOptimizations
Definition: ispc.h:431
llvm::Module * module
Definition: module.h:151
File with declarations for classes related to statements in the language.
Symbol * taskCountSym0
Definition: func.h:62
void StoreInst(llvm::Value *value, llvm::Value *ptr, const Type *ptrType=NULL)
Definition: ctx.cpp:2674
bool debugPrint
Definition: ispc.h:536
llvm::Value * GetFunctionMask()
Definition: ctx.cpp:363
bool disableCoherentControlFlow
Definition: ispc.h:453
Symbol * taskIndexSym1
Definition: func.h:63
const bool isExternC
Definition: type.h:890
Symbol * taskCountSym2
Definition: func.h:64
const FunctionType * GetType() const
Definition: func.cpp:154
bool mangleFunctionsWithTarget
Definition: ispc.h:600
Header file with declarations for various LLVM utility stuff.
Stmt * code
Definition: func.h:58
SourcePos pos
Definition: sym.h:68
Symbol * taskCountSym
Definition: func.h:61
Function(Symbol *sym, Stmt *code)
Definition: func.cpp:69
Representation of a range of positions in a source file.
Definition: ispc.h:123
Symbol * taskCountSym1
Definition: func.h:63
void markFuncWithTargetAttr(llvm::Function *func)
Definition: ispc.cpp:1410
SourcePos pos
Definition: ast.h:76
Symbol * taskIndexSym0
Definition: func.h:62
bool IsVoidType() const
Definition: type.cpp:167
void Error(SourcePos p, const char *fmt,...)
Definition: util.cpp:351
static llvm::Type * Int32Type
Definition: llvmutil.h:67
void SetDebugPos(SourcePos pos)
Definition: ctx.cpp:1288
Representation of a function in a source file.
Symbol * sym
Definition: func.h:56
Arch getArch() const
Definition: ispc.h:233
#define Assert(expr)
Definition: util.h:128
const bool isTask
Definition: type.h:882
void GenerateIR()
Definition: func.cpp:412
llvm::Value * GetFullMaskPointer()
Definition: ctx.cpp:371
const Type * GetParameterType(int i) const
Definition: type.cpp:2541
const char * GetISAString() const
Definition: ispc.cpp:1287
Type representing a function (return type + argument types)
Definition: type.h:829
Representation of a program symbol.
Definition: sym.h:62
Interface class that defines the type abstraction.
Definition: type.h:90
Globals * g
Definition: ispc.cpp:72
std::vector< Stmt * > stmts
Definition: stmt.h:458
Expr abstract base class and expression implementations.
void SetCurrentBasicBlock(llvm::BasicBlock *bblock)
Definition: ctx.cpp:361
static llvm::VectorType * MaskType
Definition: llvmutil.h:79
const bool isUnmasked
Definition: type.h:895
int EstimateCost(ASTNode *root)
Definition: ast.cpp:271
void Debug(SourcePos p, const char *fmt,...)
Definition: util.cpp:366
static void lCopyInTaskParameter(int i, llvm::Value *structArgPtr, const std::vector< Symbol *> &args, FunctionEmitContext *ctx)
Definition: func.cpp:165
void EmitFunctionParameterDebugInfo(Symbol *sym, int parameterNum)
Definition: ctx.cpp:1348
const Function * parentFunction
Definition: sym.h:102
Representation of a list of statements in the program.
Definition: stmt.h:440
llvm::Value * All(llvm::Value *mask)
Definition: ctx.cpp:1138
virtual void Print(int indent) const =0
ASTNode * Optimize(ASTNode *root)
Definition: ast.cpp:234
const Type * GetReturnType() const
Definition: func.cpp:148
const bool isExported
Definition: type.h:886
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
int errorCount
Definition: module.h:144
llvm::LLVMContext * ctx
Definition: ispc.h:611
const Type * type
Definition: sym.h:82
std::string GetString() const
Definition: type.cpp:2334
void Warning(SourcePos p, const char *fmt,...)
Definition: util.cpp:378
Symbol * threadCountSym
Definition: func.h:60
llvm::Instruction * ReturnInst()
Definition: ctx.cpp:3139
void SetFunctionMask(llvm::Value *val)
Definition: ctx.cpp:373
SymbolTable * symbolTable
Definition: module.h:148
llvm::Function * exportedFunction
Definition: sym.h:77
File with declarations for classes related to type representation.
llvm::FunctionType * LLVMFunctionType(llvm::LLVMContext *ctx, bool disableMask=false) const
Definition: type.cpp:2476