示例#1
0
文件: symbol.cpp 项目: rlugojr/chapel
void TypeSymbol::codegenMetadata() {
#ifdef HAVE_LLVM
  // Don't do anything if we've already visited this type.
  if( llvmTbaaNode ) return;

  GenInfo* info = gGenInfo;
  llvm::LLVMContext& ctx = info->module->getContext();
  // Create the TBAA root node if necessary.
  if( ! info->tbaaRootNode ) {
    LLVM_METADATA_OPERAND_TYPE* Ops[1];
    Ops[0] = llvm::MDString::get(ctx, "Chapel types");
    info->tbaaRootNode = llvm::MDNode::get(ctx, Ops);
  }

  // Set the llvmTbaaNode to non-NULL so that we can
  // avoid recursing.
  llvmTbaaNode = info->tbaaRootNode;

  AggregateType* ct = toAggregateType(type);

  Type* superType = NULL;
  // Recursively generate the TBAA nodes for this type.
  if( ct ) {
    for_fields(field, ct) {
      AggregateType* fct = toAggregateType(field->type);
      if(fct && field->hasFlag(FLAG_SUPER_CLASS)) {
        superType = field->type;
      }
      field->type->symbol->codegenMetadata();
    }
  }
示例#2
0
  //
  // clear back pointers to dead ast instances
  //
  forv_Vec(TypeSymbol, ts, gTypeSymbols) {
    for (int i = 0; i < ts->type->methods.n; i++) {
      FnSymbol* method = ts->type->methods.v[i];

      if (method && !isAliveQuick(method)) {
        ts->type->methods.v[i] = NULL;
      }

      if (AggregateType* ct = toAggregateType(ts->type)) {
        if (ct->defaultInitializer               != NULL &&
            isAliveQuick(ct->defaultInitializer) == false) {
          ct->defaultInitializer = NULL;
        }

        if (ct->hasDestructor()                  == true &&
            isAliveQuick(ct->getDestructor())    == false) {
          ct->setDestructor(NULL);
        }
      }
    }

    if (AggregateType* at = toAggregateType(ts->type)) {
      for (int i = 0; i < at->dispatchChildren.n; i++) {
        if (AggregateType* type = at->dispatchChildren.v[i]) {
          if (isAlive(type) == false) {
            at->dispatchChildren.v[i] = NULL;
          }
        }
      }
    }
  }
示例#3
0
static Type*
returnInfoVal(CallExpr* call) {
  AggregateType* ct = toAggregateType(call->get(1)->typeInfo());
  if (!ct || !ct->symbol->hasFlag(FLAG_REF))
    INT_FATAL(call, "attempt to get value type of non-reference type");
  return ct->getField(1)->type;
}
示例#4
0
bool ReturnByRef::isTransformableFunction(FnSymbol* fn)
{
  bool retval = false;

  if (AggregateType* type = toAggregateType(fn->retType))
  {
    if      (fn->hasFlag(FLAG_INIT_COPY_FN) == true)
      retval = false;

    else if (fn->hasFlag(FLAG_AUTO_COPY_FN) == true)
      retval = false;

    // Function is an iterator "helper"
    else if (fn->hasFlag(FLAG_AUTO_II)      == true)
      retval = false;

    // Can't transform extern functions
    else if (fn->hasFlag(FLAG_EXTERN)       == true)
      retval = false;

    // Noakes: 2016/02/24.  Only "user defined records" for now
    else if (isUserDefinedRecord(type)      == true)
      retval = true;

    else
      retval = false;
  }

  return retval;
}
示例#5
0
static Expr* postFoldPrimop(CallExpr* call) {
  Expr* retval = call;

  if (call->isPrimitive(PRIM_MOVE) == true) {
    retval = postFoldMove(call);

  } else if (call->isPrimitive(PRIM_QUERY_TYPE_FIELD)  == true ||
             call->isPrimitive(PRIM_QUERY_PARAM_FIELD) == true) {
    SymExpr* classWrap = toSymExpr(call->get(1));

    if (AggregateType* at = toAggregateType(classWrap->symbol()->type)) {
      const char*  memberName = get_string(call->get(2));
      Vec<Symbol*> keys;

      at->substitutions.get_keys(keys);

      forv_Vec(Symbol, key, keys) {
        if (strcmp(memberName, key->name) == 0) {
          // If there is a substitution for it, replace this call with that
          // substitution
          if (Symbol* value = at->substitutions.get(key)) {
            retval = new SymExpr(value);

            call->replace(retval);
          }
        }
      }

    } else {
示例#6
0
static QualifiedType
returnInfoVal(CallExpr* call) {
  AggregateType* ct = toAggregateType(call->get(1)->typeInfo());
  if (ct) {
    if (call->get(1)->isRef()) {
      if(ct->symbol->hasFlag(FLAG_REF)) {
        return QualifiedType(ct->getField(1)->type, QUAL_VAL);
      } else {
        return QualifiedType(ct, QUAL_VAL);
      }
    } else if (call->get(1)->isWideRef()) {
      if(ct->symbol->hasFlag(FLAG_WIDE_REF)) {
        return QualifiedType(ct->getField(2)->type, QUAL_VAL);
      } else {
        return QualifiedType(ct, QUAL_VAL);
      }
    } else if (ct->symbol->hasFlag(FLAG_WIDE_CLASS)) {
      // insertWideReferences will sometimes insert a PRIM_DEREF to a
      // wide class. There should probably be a better way of expressing the
      // desired pattern...
      return QualifiedType(ct, QUAL_VAL);
    }
  }
  INT_FATAL(call, "attempt to get value type of non-reference type");
  return QualifiedType(NULL);
}
/*
To implement task reduce intents, we follow the steps in
propagateExtraLeaderArgs() and setupOneReduceIntent()

I.e. add the following to the AST:

* before 'call'
    def globalOp = new reduceType(origSym.type);

* pass globalOp to call();
  corresponding formal in 'fn': parentOp

* inside 'fn'
    def currOp = parentOp.clone()
    def symReplace = currOp.identify;
    ...
    currOp.accumulate(symReplace);
    parentOp.combine(currOp);
    delete currOp;

* after 'call' and its _waitEndCount()
    origSym = parentOp.generate();
    delete parentOp;

Put in a different way, a coforall like this:

    var x: int;
    coforall ITER with (OP reduce x) {
      BODY(x);      // will typically include:  x OP= something;
    }

with its corresponding task-function representation:

    var x: int;
    proc coforall_fn() {
      BODY(x);
    }
    call coforall_fn();

is transformed into

    var x: int;
    var globalOp = new OP_SCAN_REDUCE_CLASS(x.type);

    proc coforall_fn(parentOp) {
      var currOp = parentOp.clone()
      var symReplace = currOp.identify;

      BODY(symReplace);

      currOp.accumulate(symReplace);
      parentOp.combine(currOp);
      delete currOp;
    }

    call coforall_fn(globalOp);
    // wait for endCount - not shown
    x = globalOp.generate();
    delete globalOp;

Todo: to support cobegin constructs, need to share 'globalOp'
across all fn+call pairs for the same construct.
*/
static void addReduceIntentSupport(FnSymbol* fn, CallExpr* call,
                                   TypeSymbol* reduceType, Symbol* origSym,
                                   ArgSymbol*& newFormal, Symbol*& newActual,
                                   Symbol*& symReplace, bool isCoforall,
                                   Expr*& redRef1, Expr*& redRef2)
{
  setupRedRefs(fn, true, redRef1, redRef2);
  VarSymbol* globalOp = new VarSymbol("reduceGlobal");
  globalOp->addFlag(FLAG_NO_CAPTURE_FOR_TASKING);
  newActual = globalOp;

  VarSymbol* eltType = newTemp("redEltType");
  eltType->addFlag(FLAG_MAYBE_TYPE);

  Expr* headAnchor = call;
  if (isCoforall) headAnchor = headAnchor->parentExpr;
  headAnchor->insertBefore(new DefExpr(eltType));
  headAnchor->insertBefore("'move'(%S, 'typeof'(%S))", eltType, origSym);
  headAnchor->insertBefore(new DefExpr(globalOp));

  AggregateType* reduceAt = toAggregateType(reduceType->type);
  INT_ASSERT(reduceAt);

  CallExpr* newOp = new CallExpr(reduceAt->defaultInitializer->name,
                                 new NamedExpr("eltType", new SymExpr(eltType)));
  headAnchor->insertBefore(new CallExpr(PRIM_MOVE, globalOp, newOp));

  Expr* tailAnchor = findTailInsertionPoint(call, isCoforall);
  // Doing insertAfter() calls in reverse order.
  // Can't insertBefore() on tailAnchor->next - that can be NULL.
  tailAnchor->insertAfter("'delete'(%S)",
                         globalOp);
  tailAnchor->insertAfter("'='(%S, generate(%S,%S))",
                         origSym, gMethodToken, globalOp);

  ArgSymbol* parentOp = new ArgSymbol(INTENT_BLANK, "reduceParent", dtUnknown);
  newFormal = parentOp;

  VarSymbol* currOp = new VarSymbol("reduceCurr");
  VarSymbol* svar  = new VarSymbol(origSym->name, origSym->type);
  symReplace = svar;

  redRef1->insertBefore(new DefExpr(currOp));
  redRef1->insertBefore("'move'(%S, clone(%S,%S))", // init
                        currOp, gMethodToken, parentOp);
  redRef1->insertBefore(new DefExpr(svar));
  redRef1->insertBefore("'move'(%S, identity(%S,%S))", // init
                        svar, gMethodToken, currOp);

  redRef2->insertBefore(new CallExpr("accumulate",
                                     gMethodToken, currOp, svar));
  redRef2->insertBefore(new CallExpr("chpl__reduceCombine",
                                     parentOp, currOp));
  redRef2->insertBefore(new CallExpr("chpl__cleanupLocalOp",
                                     parentOp, currOp));
}
示例#8
0
void flattenClasses(void) {
  //
  // collect nested classes
  //
  Vec<AggregateType*> nestedClasses;
  forv_Vec(TypeSymbol, ts, gTypeSymbols) {
    if (AggregateType* ct = toAggregateType(ts->type))
      if (toAggregateType(ct->symbol->defPoint->parentSymbol->type))
        nestedClasses.add(ct);
  }

  //
  // move nested classes to module level
  //
  forv_Vec(AggregateType, ct, nestedClasses) {
    ModuleSymbol* mod = ct->getModule();
    DefExpr *def = ct->symbol->defPoint;
    def->remove();
    mod->block->insertAtTail(def);
  }
示例#9
0
static QualifiedType
returnInfoGetMember(CallExpr* call) {
  AggregateType* ct = toAggregateType(call->get(1)->typeInfo());
  if (ct->symbol->hasFlag(FLAG_REF))
    ct = toAggregateType(ct->getValType());
  if (!ct)
    INT_FATAL(call, "bad member primitive");
  SymExpr* sym = toSymExpr(call->get(2));
  if (!sym)
    INT_FATAL(call, "bad member primitive");
  VarSymbol* var = toVarSymbol(sym->symbol());
  if (!var)
    INT_FATAL(call, "bad member primitive");
  if (var->immediate) {
    const char* name = var->immediate->v_string;
    for_fields(field, ct) {
      if (!strcmp(field->name, name))
        return field->qualType();
    }
  } else
    return sym->qualType();
示例#10
0
static void
genClassIDs(Vec<TypeSymbol*> & typeSymbols) {
  genComment("Class Type Identification Numbers");

  int count=0;
  forv_Vec(TypeSymbol, ts, typeSymbols) {
    if (AggregateType* ct = toAggregateType(ts->type)) {
      if (!isReferenceType(ct) && isClass(ct)) {
        genGlobalDefClassId(ts->cname, count);
        count++;
      }
    }
  }
}
示例#11
0
static QualifiedType
returnInfoVal(CallExpr* call) {
  AggregateType* ct = toAggregateType(call->get(1)->typeInfo());
  if (ct) {
    if(ct->symbol->hasFlag(FLAG_REF)) {
      return QualifiedType(ct->getField(1)->type, QUAL_VAL);
    }
    else if(ct->symbol->hasFlag(FLAG_WIDE_REF)) {
      return QualifiedType(ct->getField(2)->type, QUAL_VAL);
    }
  }
  INT_FATAL(call, "attempt to get value type of non-reference type");
  return QualifiedType(NULL);
}
示例#12
0
//
// compute topological order for types; this functions assumes that
// there are no cycles and that the typeOrder map is initialized to -1
// for all class types
//
static int
computeOrder(AggregateType* ct) {
  if (typeOrder.get(ct) != -1)
    return typeOrder.get(ct);

  typeOrder.put(ct, -2);
  int order = 0;
  for_fields(field, ct) {
    if (AggregateType* fct = toAggregateType(field->type)) {
      int fieldOrder = computeOrder(fct);
      if (fieldOrder >= order)
        order = fieldOrder+1;
    }
  }
  typeOrder.put(ct, order);
  return order;
}
示例#13
0
 //
 // clear back pointers to dead ast instances
 //
 forv_Vec(TypeSymbol, ts, gTypeSymbols) {
   for(int i = 0; i < ts->type->methods.n; i++) {
     FnSymbol* method = ts->type->methods.v[i];
     if (method && !isAliveQuick(method))
       ts->type->methods.v[i] = NULL;
     if (AggregateType* ct = toAggregateType(ts->type)) {
       if (ct->defaultInitializer && !isAliveQuick(ct->defaultInitializer))
         ct->defaultInitializer = NULL;
       if (ct->destructor && !isAliveQuick(ct->destructor))
         ct->destructor = NULL;
     }
   }
   for(int i = 0; i < ts->type->dispatchChildren.n; i++) {
     Type* type = ts->type->dispatchChildren.v[i];
     if (type && !isAlive(type))
       ts->type->dispatchChildren.v[i] = NULL;
   }
 }
示例#14
0
void cleanAst() {
  cleanModuleList();
  //
  // clear back pointers to dead ast instances
  //
  forv_Vec(TypeSymbol, ts, gTypeSymbols) {
    for(int i = 0; i < ts->type->methods.n; i++) {
      FnSymbol* method = ts->type->methods.v[i];
      if (method && !isAliveQuick(method))
        ts->type->methods.v[i] = NULL;
      if (AggregateType* ct = toAggregateType(ts->type)) {
        if (ct->defaultInitializer && !isAliveQuick(ct->defaultInitializer))
          ct->defaultInitializer = NULL;
        if (ct->destructor && !isAliveQuick(ct->destructor))
          ct->destructor = NULL;
      }
    }
    for(int i = 0; i < ts->type->dispatchChildren.n; i++) {
      Type* type = ts->type->dispatchChildren.v[i];
      if (type && !isAlive(type))
        ts->type->dispatchChildren.v[i] = NULL;
    }
  }

  // check iterator-resume-label/goto data before nodes are free'd
  verifyNcleanRemovedIterResumeGotos();
  verifyNcleanCopiedIterResumeGotos();

  // clean the other module vectors, without deleting the ast instances (they
  // will be deleted with the clean_gvec call for ModuleSymbols.) 
  clean_modvec(allModules);
  clean_modvec(userModules);
  clean_modvec(mainModules);
 
  //
  // clean global vectors and delete dead ast instances
  //
  foreach_ast(clean_gvec);
}
示例#15
0
//
// DefExpr
//
bool AstDumpToHtml::enterDefExpr(DefExpr* node) {
  bool retval = true;

  if (isBlockStmt(node->parentExpr)) {
    fprintf(mFP, "<DL>\n");
  }

  fprintf(mFP, " ");

  if (FnSymbol* fn = toFnSymbol(node->sym)) {
    fprintf(mFP, "<UL CLASS =\"mktree\">\n<LI>");

    adjacent_passes(fn);

    fprintf(mFP, "<CHPLTAG=\"FN%d\">\n", fn->id);
    fprintf(mFP, "<B>function ");

    writeFnSymbol(fn);

    fprintf(mFP, "</B><UL>\n");

  } else if (isTypeSymbol(node->sym)) {
    if (toAggregateType(node->sym->type)) {
      fprintf(mFP, "<UL CLASS =\"mktree\">\n");
      fprintf(mFP, "<LI>");

      if (node->sym->hasFlag(FLAG_SYNC))
        fprintf(mFP, "<B>sync</B> ");

      if (node->sym->hasFlag(FLAG_SINGLE))
        fprintf(mFP, "<B>single</B> ");

      fprintf(mFP, "<B>type ");
      writeSymbol(node->sym, true);
      fprintf(mFP, "</B><UL>\n");

    } else {
      fprintf(mFP, "<B>type </B> ");
      writeSymbol(node->sym, true);
    }

  } else if (VarSymbol* vs = toVarSymbol(node->sym)) {
    if (vs->type->symbol->hasFlag(FLAG_SYNC))
      fprintf(mFP, "<B>sync </B>");

    if (vs->type->symbol->hasFlag(FLAG_SINGLE))
      fprintf(mFP, "<B>single </B>");

    fprintf(mFP, "<B>var </B> ");
    writeSymbol(node->sym, true);

  } else if (ArgSymbol* s = toArgSymbol(node->sym)) {
    switch (s->intent) {
      case INTENT_IN:        fprintf(mFP, "<B>in</B> ");        break;
      case INTENT_INOUT:     fprintf(mFP, "<B>inout</B> ");     break;
      case INTENT_OUT:       fprintf(mFP, "<B>out</B> ");       break;
      case INTENT_CONST:     fprintf(mFP, "<B>const</B> ");     break;
      case INTENT_CONST_IN:  fprintf(mFP, "<B>const in</B> ");  break;
      case INTENT_CONST_REF: fprintf(mFP, "<B>const ref</B> "); break;
      case INTENT_REF:       fprintf(mFP, "<B>ref</B> ");       break;
      case INTENT_PARAM:     fprintf(mFP, "<B>param</B> ");     break;
      case INTENT_TYPE:      fprintf(mFP, "<B>type</B> ");      break;
      case INTENT_BLANK:                                        break;
    }

    fprintf(mFP, "<B>arg</B> ");

    writeSymbol(node->sym, true);

  } else if (isLabelSymbol(node->sym)) {
    fprintf(mFP, "<B>label</B> ");
    writeSymbol(node->sym, true);

  } else if (isModuleSymbol(node->sym)) {
    fprintf(mFP, "</DL>\n");
    // Don't process nested modules -- they'll be handled at the top-level
    retval = false;

  } else {
    fprintf(mFP, "<B>def</B> ");
    writeSymbol(node->sym, true);
  }

  return retval;
}
示例#16
0
const char* CallInfo::toString() {
  bool        method = false;
  bool        _this  = false;
  int         start  = 0;
  const char* retval = "";

  if (actuals.n            >  1 &&
      actuals.head()->type == dtMethodToken) {
    method = true;
    start  =    2;
  }

  if (name == astrThis) {
    _this  =  true;
    method = false;
    start  =     2;
  }

  if (method == true) {
    if (actuals.v[1] &&
        actuals.v[1]->hasFlag(FLAG_TYPE_VARIABLE)) {
      retval = astr(retval, "type ", ::toString(actuals.v[1]->type), ".");

    } else {
      retval = astr(retval,          ::toString(actuals.v[1]->type), ".");
    }
  }

  if (developer                                   == false &&
      strncmp("_type_construct_", name, 16) == 0) {
    retval = astr(retval, name+16);

  } else if (developer == false &&
             strncmp("_construct_", name, 11) == 0) {
    retval = astr(retval, name + 11);
    retval = astr(retval, ".init");

  } else if (_this == false) {
    retval = astr(retval, name);
  }

  if (call->methodTag == false) {
    if (call->square == true) {
      retval = astr(retval, "[");
    } else {
      retval = astr(retval, "(");
    }
  }

  for (int i = start; i < actuals.n; i++) {
    Symbol*        sym  = actuals.v[i];
    VarSymbol*     var  = toVarSymbol(sym);
    Type*          type = sym->type;
    AggregateType* at   = toAggregateType(type);
    IteratorInfo*  ii   = (at != NULL) ? at->iteratorInfo : NULL;

    if (i > start) {
      retval = astr(retval, ", ");
    }

    if (actualNames.v[i] != NULL) {
      retval = astr(retval, actualNames.v[i], "=");
    }

    if (type->symbol->hasFlag(FLAG_ITERATOR_RECORD)   == true &&
        ii->iterator->hasFlag(FLAG_PROMOTION_WRAPPER) == true) {
      retval = astr(retval, "promoted expression");

    } else if (sym->hasFlag(FLAG_TYPE_VARIABLE) == true) {
      retval = astr(retval, "type ", ::toString(type));

    } else if (var != NULL && var->immediate != NULL) {
      if (var->immediate->const_kind == CONST_KIND_STRING) {
        retval = astr(retval, "\"", var->immediate->v_string, "\"");

      } else {
        const size_t bufSize = 512;
        char         buff[bufSize];

        snprint_imm(buff, bufSize, *var->immediate);

        retval = astr(retval, buff);
      }

    } else {
      retval = astr(retval, ::toString(type));
    }
  }

  if (call->methodTag == false) {
    if (call->square == true) {
      retval = astr(retval, "]");
    } else {
      retval = astr(retval, ")");
    }
  }

  return retval;
}
示例#17
0
文件: symbol.cpp 项目: rlugojr/chapel
void VarSymbol::codegenDef() {
  GenInfo* info = gGenInfo;

  if (id == breakOnCodegenID)
    gdbShouldBreakHere();

  // Local variable symbols should never be
  // generated for extern or void types
  if (this->hasFlag(FLAG_EXTERN))
    return;
  if (type == dtVoid)
    return;

  if( info->cfile ) {
    codegenDefC();
  } else {
#ifdef HAVE_LLVM
    if(isImmediate()) {
      llvm::GlobalVariable *globalValue = llvm::cast<llvm::GlobalVariable>(
          info->module->getOrInsertGlobal(cname, type->codegen().type));
      globalValue->setConstant(true);

      if(immediate->const_kind == CONST_KIND_STRING) {
        if(llvm::Value *constString = codegenImmediateLLVM(immediate)) {
          llvm::GlobalVariable *globalString =
            llvm::cast<llvm::GlobalVariable>(constString);
          globalValue->setInitializer(llvm::cast<llvm::Constant>(
                info->builder->CreateConstInBoundsGEP2_32(
#if HAVE_LLVM_VER >= 37
                  NULL,
#endif
                  globalString, 0, 0)));
        } else {
          llvm::GlobalVariable *globalString =
            new llvm::GlobalVariable(
                *info->module,
                llvm::IntegerType::getInt8Ty(info->module->getContext()),
                true,
                llvm::GlobalVariable::PrivateLinkage,
                NULL,
                "string");
          globalString->setInitializer(llvm::Constant::getNullValue(
                llvm::IntegerType::getInt8Ty(info->module->getContext())));
          globalValue->setInitializer(llvm::cast<llvm::Constant>(
                info->builder->CreateConstInBoundsGEP1_32(
#if HAVE_LLVM_VER >= 37
                  NULL,
#endif
                  globalString, 0)));
        }
      } else {
        globalValue->setInitializer(llvm::cast<llvm::Constant>(
              codegenImmediateLLVM(immediate)));
      }
      info->lvt->addGlobalValue(cname, globalValue, GEN_VAL, ! is_signed(type));
    }
    llvm::Type *varType = type->codegen().type;
    llvm::Value *varAlloca = createTempVarLLVM(varType, cname);
    info->lvt->addValue(cname, varAlloca, GEN_PTR, ! is_signed(type));

    if(AggregateType *ctype = toAggregateType(type)) {
      if(ctype->isClass() ||
         ctype->symbol->hasFlag(FLAG_WIDE_REF) ||
         ctype->symbol->hasFlag(FLAG_WIDE_CLASS)) {
        if(isFnSymbol(defPoint->parentSymbol)) {
          info->builder->CreateStore(
              llvm::Constant::getNullValue(varType), varAlloca);
        }
      }
    }
    if(debug_info){
      debug_info->get_variable(this);
    }
#endif
  }
}
示例#18
0
文件: symbol.cpp 项目: rlugojr/chapel
void VarSymbol::codegenDefC(bool global, bool isHeader) {
  GenInfo* info = gGenInfo;
  if (this->hasFlag(FLAG_EXTERN))
    return;

  if (type == dtVoid)
    return;

  AggregateType* ct = toAggregateType(type);
  QualifiedType qt = qualType();

  if (qt.isRef() && !qt.isRefType()) {
    Type* refType = getOrMakeRefTypeDuringCodegen(type);
    ct = toAggregateType(refType);
  }
  if (qt.isWideRef() && !qt.isWideRefType()) {
    Type* refType = getOrMakeRefTypeDuringCodegen(type);
    Type* wideType = getOrMakeWideTypeDuringCodegen(refType);
    ct = toAggregateType(wideType);
  }

  Type* useType = type;
  if (ct) useType = ct;

  std::string typestr =  (this->hasFlag(FLAG_SUPER_CLASS) ?
                          std::string(toAggregateType(useType)->classStructName(true)) :
                          useType->codegen().c);

  //
  // a variable can be codegen'd as static if it is global and neither
  // exported nor external.
  //
  std::string str;

  if(fIncrementalCompilation) {
    bool addExtern =  global && isHeader;
    str = (addExtern ? "extern " : "") + typestr + " " + cname;
  } else {
    bool isStatic =  global && !hasFlag(FLAG_EXPORT) && !hasFlag(FLAG_EXTERN);
    str = (isStatic ? "static " : "") + typestr + " " + cname;
  }

  if (ct) {
    if (ct->isClass()) {
      if (isFnSymbol(defPoint->parentSymbol)) {
        str += " = NULL";
      }
    } else if (ct->symbol->hasFlag(FLAG_WIDE_REF) ||
               ct->symbol->hasFlag(FLAG_WIDE_CLASS)) {
      if (isFnSymbol(defPoint->parentSymbol)) {
        if (widePointersStruct) {
          //
          // CHPL_LOCALEID_T_INIT is #defined in the chpl-locale-model.h
          // file in the runtime, for the selected locale model.
          //
          str += " = {CHPL_LOCALEID_T_INIT, NULL}";
        } else {
          str += " = ((wide_ptr_t) NULL)";
        }
      }
    }
  }

  if (fGenIDS)
    str = idCommentTemp(this) + str;
  if (printCppLineno && !isHeader && !isTypeSymbol(defPoint->parentSymbol))
    str = zlineToString(this) + str;

  info->cLocalDecls.push_back(str);
}
示例#19
0
void buildDefaultFunctions() {
  build_chpl_entry_points();

  SET_LINENO(rootModule); // todo - remove reset_ast_loc() calls below?

  std::vector<BaseAST*> asts;
  collect_asts(rootModule, asts);
  for_vector(BaseAST, ast, asts) {
    if (TypeSymbol* type = toTypeSymbol(ast)) {
      // Here we build default functions that are always generated (even when
      // the type symbol has FLAG_NO_DEFAULT_FUNCTIONS attached).
      if (AggregateType* ct = toAggregateType(type->type)) {
        buildFieldAccessorFunctions(ct);

        if (!ct->symbol->hasFlag(FLAG_REF))
          buildDefaultDestructor(ct);
        // Classes should use the nil:<type> _defaultOf method unless they
        // do not inherit from object.  For those types and records, call
        // we need a more complicated _defaultOf method generated by the
        // compiler
        if (!ct->isClass() || ct->symbol->hasFlag(FLAG_NO_OBJECT))
          build_record_init_function(ct);
      }

      if (type->hasFlag(FLAG_NO_DEFAULT_FUNCTIONS))
        continue;

      // Here we build default functions that respect the "no default
      // functions" pragma.
      if (AggregateType* ct = toAggregateType(type->type))
      {
        buildDefaultReadWriteFunctions(ct);

        if (isRecord(ct)) {
          if (!isRecordWrappedType(ct)) {
            build_record_equality_function(ct);
            build_record_inequality_function(ct);
          }
          build_record_assignment_function(ct);
          build_record_cast_function(ct);
          build_record_copy_function(ct);
          build_record_hash_function(ct);
        }
        if (isUnion(ct))
          build_union_assignment_function(ct);
      }
      else if (EnumType* et = toEnumType(type->type)) {
        //buildDefaultReadFunction(et);
        buildStringCastFunction(et);

        build_enum_cast_function(et);
        build_enum_assignment_function(et);
        build_enum_first_function(et);
        build_enum_enumerate_function(et);
      }
      else
      {
        // The type is a simple type.

        // Other simple types are handled explicitly in the module code.
        // But to avoid putting a catch-all case there to implement assignment
        // for extern types that are simple (as far as we can tell), we build
        // definitions for those assignments here.
        if (type->hasFlag(FLAG_EXTERN)) {
          build_extern_init_function(type->type);
          build_extern_assignment_function(type->type);
        }
      }
    }
  }
}