int LexicalTypeOrdering::compare(const QualifiedType & t0, const QualifiedType & t1) { int result = compare(t0.unqualified(), t1.unqualified()); if (result != 0) { return result; } if (t0.qualifiers() < t1.qualifiers()) { return -1; } else if (t0.qualifiers() > t1.qualifiers()) { return 1; } else { return 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; }
bool FunctionMergePass::areTypesCompatible(QualifiedType from, QualifiedType to) { return areTypesCompatible(from.unqualified(), to.unqualified()); }