示例#1
0
bool
destruct_(Context *ctx, ParseResult *pr, ParseResult *ret_pr,
          llvm::IRBuilder<> *builder, bool value_is_ptr)
{
    pr->copyTo(ret_pr);

    if (pr->do_not_destruct) {
        return true;
    }

    if (pr->type->is_array && pr->type->array_size) {
        return destructArray(ctx, pr, ret_pr, builder, value_is_ptr);
    }

    Function *fn = getDestructor(ctx, pr->type);
    if (!fn) {
        if (pr->type->struct_name.size()) {
            destructStruct(ctx, pr, ret_pr, builder, value_is_ptr);
        }
        return true;
    }

    std::vector<llvm::Value *> call_args;
    llvm::Value *value_ptr;
    if (value_is_ptr) {
        value_ptr = pr->value;
    } else {
        value_ptr = llvm::cast<llvm::Value>(
            builder->CreateAlloca(ctx->toLLVMType(pr->type, NULL, false))
        );
        builder->CreateStore(pr->value, value_ptr);
    }

    call_args.push_back(value_ptr);
    builder->CreateCall(
        fn->llvm_function,
        llvm::ArrayRef<llvm::Value*>(call_args)
    );

    return true;
}
示例#2
0
	/// TODO: add trivial marker for tagtypes
	bool isTrivial(const TypePtr& type) {
		auto ttype = type.isa<TagTypePtr>();
		if(!ttype) {
			if (core::lang::isArray(type)) {
				// in case of an array, check the enclosed type for triviality
				return isTrivial(core::lang::ArrayType(type).getElementType());
			}
			// non-tag-type & non-array types are always trivial
			return true;
		}

		auto record = ttype->getRecord();

		IRBuilder builder(type->getNodeManager());

		auto containsCtor = [&](const LambdaExprPtr& ctor)->bool {
			return any(record->getConstructors(), [&](const ExpressionPtr& cur) {
				return *builder.normalize(cur) == *builder.normalize(ctor);
			});
		};

		auto containsMemberFunction = [&](const MemberFunctionPtr& member)->bool {
			return any(record->getMemberFunctions(), [&](const MemberFunctionPtr& cur) {
				return *builder.normalize(cur) == *builder.normalize(member);
			});
		};

		auto thisType = builder.refType(builder.tagTypeReference(record->getName()));

		ParentsPtr parents =
				(record.isa<StructPtr>()) ?
				record.as<StructPtr>()->getParents() :
				builder.parents();

		// check for trivial constructors
		bool trivialDefaultConstructor = containsCtor(builder.getDefaultConstructor(thisType, parents, record->getFields()));
		if (!trivialDefaultConstructor) return false;

		bool trivialCopyConstructor = containsCtor(builder.getDefaultCopyConstructor(thisType, parents, record->getFields()));
		if (!trivialCopyConstructor) return false;

		bool trivialMoveConstructor = containsCtor(builder.getDefaultMoveConstructor(thisType, parents, record->getFields()));
		if (!trivialMoveConstructor) return false;


		// check for trivial copy and move assignments
		bool trivialCopyAssignment = containsMemberFunction(builder.getDefaultCopyAssignOperator(thisType, parents, record->getFields()));
		if (!trivialCopyAssignment) return false;

		bool trivialMoveAssignment = containsMemberFunction(builder.getDefaultMoveAssignOperator(thisType, parents, record->getFields()));
		if (!trivialMoveAssignment) return false;

		// check for trivial, non-virtual destructor
		if(record->getDestructor().as<LambdaExprPtr>()->getBody().size() != 0 || record->getDestructorVirtual().getValue()) return false;

		// check for virtual member functions
		for(auto memFun : record->getMemberFunctions()) {
			if(memFun->getVirtualFlag().getValue()) return false;
		}

		if(!record->getPureVirtualMemberFunctions().empty()) return false;

		// check for virtual & non-trivial base classes
		if(ttype->isStruct()) {
			auto stype = ttype->getStruct();
			for(auto par : stype->getParents()) {
				if(par->getVirtual().getValue()) return false;
				// if our direct base class is non-trivial, we cannot be trivial per-se
				if(!isTrivial(par->getType())) return false;
			}
		}

		// check that all non-static members are trivial
		for(auto field : record->getFields()) {
			auto fieldType = field->getType();
			if(!isTrivial(fieldType)) return false;
			//check cpp_ref field types
			if(analysis::isRefType(fieldType) && lang::isCppReference(fieldType)) {
				//TODO this is an over approximation which has to be refined
				return false;
			}
		}

		return true;
	}
示例#3
0
bool
destructArray(Context *ctx, ParseResult *pr, ParseResult *ret_pr,
              llvm::IRBuilder<> *builder, bool value_is_ptr)
{
    Type *array_type = pr->type->array_type;
    llvm::BasicBlock *block = pr->block;
    llvm::Value *array_value = pr->value;

    if (!array_value) {
        return true;
    }
    if (!array_value->getType()) {
        return true;
    }

    if (!array_type->is_array) {
        Function *fn = getDestructor(ctx, array_type);
        if (!fn) {
            return true;
        }
    }

    llvm::Type *llvm_array_type = ctx->toLLVMType(pr->type, NULL, false);

    /* Array literals are stored in the variable table as actual
     * arrays, rather than pointers to arrays.  This should be fixed at
     * some point, but for now, if this value is not a pointer, then
     * store it in a temporary location. */

    if (!pr->value->getType()->isPointerTy()) {
        array_value = llvm::cast<llvm::Value>(
            builder->CreateAlloca(llvm_array_type)
        );
        builder->CreateStore(pr->value, array_value);
    }

    for (int i = (pr->type->array_size - 1); i >= 0; i--) {
        ParseResult element;
        element.type  = array_type;
        element.block = block;
        std::vector<llvm::Value *> indices;
        STL::push_back2(
            &indices,
            ctx->nt->getLLVMZero(),
            llvm::cast<llvm::Value>(ctx->nt->getNativeInt(i))
        );

        llvm::Value *res =
            builder->Insert(
                llvm::GetElementPtrInst::Create(
                    array_value, llvm::ArrayRef<llvm::Value*>(indices)
                ),
                "ap"
            );
        if (!array_type->is_array) {
            element.value = builder->CreateLoad(res);
        } else {
            element.value = res;
        }
        element.do_not_destruct = false;
        Destruct(ctx, &element, &element, builder);
        block = element.block;
    }

    ret_pr->block = block;
    return true;
}