Exemple #1
0
bool TypeSetConstraint::isReferenceType() const {
  QualifiedTypeSet expansion;
  expandImpl(expansion, 0);
  for (QualifiedTypeSet::iterator it = expansion.begin(); it != expansion.end(); ++it) {
    QualifiedType ty = *it;
    if (!ty->isReferenceType()) {
      return false;
    }
  }

  return true;
}
Exemple #2
0
bool CodeGenerator::genFunction(FunctionDefn * fdef) {
  // Don't generate undefined functions.
  if (fdef->isUndefined() || fdef->isAbstract() || fdef->isInterfaceMethod()) {
    return true;
  }

  DASSERT_OBJ(fdef->isSingular(), fdef);
  DASSERT_OBJ(fdef->type(), fdef);
  DASSERT_OBJ(fdef->type()->isSingular(), fdef);

  // Don't generate intrinsic functions.
  if (fdef->isIntrinsic()) {
    return true;
  }

  // Don't generate a function if it has been merged to another function
  if (fdef->mergeTo() != NULL || fdef->isUndefined()) {
    return true;
  }

  // Create the function
  Function * f = genFunctionValue(fdef);

  if (fdef->hasBody() && f->getBasicBlockList().empty()) {
    FunctionType * ftype = fdef->functionType();

    if (fdef->isSynthetic()) {
      f->setLinkage(GlobalValue::LinkOnceODRLinkage);
    }

    if (gcEnabled_) {
      if (SsGC) {
        f->setGC("shadow-stack");
      } else {
        f->setGC("tart-gc");
      }
    }

    if (debug_) {
      dbgContext_ = genDISubprogram(fdef);
      //dbgContext_ = genLexicalBlock(fdef->location());
      dbgInlineContext_ = DIScope();
      setDebugLocation(fdef->location());
    }

    BasicBlock * prologue = BasicBlock::Create(context_, "prologue", f);

    // Create the LLVM Basic Blocks corresponding to each high level BB.
//    BlockList & blocks = fdef->blocks();
//    for (BlockList::iterator b = blocks.begin(); b != blocks.end(); ++b) {
//      Block * blk = *b;
//      blk->setIRBlock(BasicBlock::Create(context_, blk->label(), f));
//    }

    builder_.SetInsertPoint(prologue);

    // Handle the explicit parameters
    unsigned param_index = 0;
    Function::arg_iterator it = f->arg_begin();

    Value * saveStructRet = structRet_;
    if (ftype->isStructReturn()) {
      it->addAttr(llvm::Attribute::StructRet);
      structRet_ = it;
      ++it;
    }

    // Handle the 'self' parameter
    if (ftype->selfParam() != NULL) {
      ParameterDefn * selfParam = ftype->selfParam();
      const Type * selfParamType = selfParam->type().unqualified();
      DASSERT_OBJ(fdef->storageClass() == Storage_Instance ||
          fdef->storageClass() == Storage_Local, fdef);
      DASSERT_OBJ(it != f->arg_end(), ftype);

      // Check if the self param is a root.
      if (selfParamType->isReferenceType()) {
        selfParam->setFlag(ParameterDefn::LValueParam, true);
        Value * selfAlloca = builder_.CreateAlloca(
            selfParam->type()->irEmbeddedType(), 0, "self.alloca");
        builder_.CreateStore(it, selfAlloca);
        selfParam->setIRValue(selfAlloca);
        markGCRoot(selfAlloca, NULL, "self.alloca");
      } else {
        // Since selfParam is always a pointer, we don't need to mark the object pointed
        // to as a root, since the next call frame up is responsible for tracing it.
        ftype->selfParam()->setIRValue(it);
      }

      it->setName("self");
      ++it;
    }

    // If this function needs to make allocations, cache a copy of the
    // allocation context pointer for this thread, since it can on some
    // platforms be expensive to look up.
    if (fdef->flags() & FunctionDefn::MakesAllocs) {
      Function * gcGetAllocContext = genFunctionValue(gc_allocContext);
      gcAllocContext_ = builder_.CreateCall(gcGetAllocContext, "allocCtx");
    }

    for (; it != f->arg_end(); ++it, ++param_index) {

      // Set the name of the Nth parameter
      ParameterDefn * param = ftype->params()[param_index];
      DASSERT_OBJ(param != NULL, fdef);
      DASSERT_OBJ(param->storageClass() == Storage_Local, param);
      QualifiedType paramType = param->internalType();
      it->setName(param->name());
      Value * paramValue = it;

      // If the parameter is a shared reference, then create the shared ref.
      if (param->isSharedRef()) {
        genLocalVar(param, paramValue);
        genGCRoot(param->irValue(), param->sharedRefType(), param->name());
        continue;
      }

      // If the parameter type contains any reference types, then the parameter needs
      // to be a root.
      bool paramIsRoot = false;
      if (paramType->isReferenceType()) {
        param->setFlag(ParameterDefn::LValueParam, true);
        paramIsRoot = true;
      } else if (paramType->containsReferenceType()) {
        // TODO: Handle roots of various shapes
        //param->setFlag(ParameterDefn::LValueParam, true);
      }

      // See if we need to make a local copy of the param.
      if (param->isLValue()) {
        Value * paramAlloca = builder_.CreateAlloca(paramType->irEmbeddedType(), 0, param->name());
        param->setIRValue(paramAlloca);

        if (paramType->typeShape() == Shape_Large_Value) {
          paramValue = builder_.CreateLoad(paramValue);
        }

        builder_.CreateStore(paramValue, paramAlloca);
        if (paramIsRoot) {
          genGCRoot(paramAlloca, paramType.unqualified(), param->name());
        }
      } else {
        param->setIRValue(paramValue);
      }
    }

    // Generate the body
    Function * saveFn = currentFn_;
    currentFn_ = f;
#if 0
    if (fdef->isGenerator()) {
      assert(false);
    } else {
#endif
      genLocalStorage(fdef->localScopes());
      genDISubprogramStart(fdef);
      genLocalRoots(fdef->localScopes());

      BasicBlock * blkEntry = createBlock("entry");
      builder_.SetInsertPoint(blkEntry);
      genExpr(fdef->body());

      if (!atTerminator()) {
        if (fdef->returnType()->isVoidType()) {
          builder_.CreateRetVoid();
        } else {
          // TODO: Use the location from the last statement of the function.
          diag.error(fdef) << "Missing return statement at end of non-void function.";
        }
      }

      gcAllocContext_ = NULL;
#if 0
    }
#endif

    builder_.SetInsertPoint(prologue);
    builder_.CreateBr(blkEntry);

    currentFn_ = saveFn;
    structRet_ = saveStructRet;

    if (!diag.inRecovery()) {
      if (verifyFunction(*f, PrintMessageAction)) {
        f->dump();
        DFAIL("Function failed to verify");
      }
    }

    //if (debug_ && !dbgContext_.isNull() && !dbgContext_.Verify()) {
    //  dbgContext_.Verify();
    //  DFAIL("BAD DBG");
    //}

    dbgContext_ = DIScope();
    dbgInlineContext_ = DIScope();
    builder_.ClearInsertionPoint();
    builder_.SetCurrentDebugLocation(llvm::DebugLoc());
  }

  return true;
}