Ejemplo n.º 1
0
llvm::Type* LLVMCodeGenerator::_llvm_type(SLTypePtr type) {
	switch (type->type()) {
		case SLTypeTypeNullPointer:
			return llvm::Type::getInt8Ty(_context)->getPointerTo();
		case SLTypeTypePointer:
		case SLTypeTypeReference:
			// llvm doesn't do void pointers
			return type->pointed_to_type()->type() == SLTypeTypeVoid ? llvm::Type::getInt8Ty(_context)->getPointerTo() : _llvm_type(type->pointed_to_type())->getPointerTo();
		case SLTypeTypeAuto:
			assert(false);
		case SLTypeTypeVoid:
			return llvm::Type::getVoidTy(_context);
		case SLTypeTypeBool:
			return llvm::Type::getInt1Ty(_context);
		case SLTypeTypeInt8:
			return llvm::Type::getInt8Ty(_context);
		case SLTypeTypeInt32:
			return llvm::Type::getInt32Ty(_context);
		case SLTypeTypeInt64:
			return llvm::Type::getInt64Ty(_context);
		case SLTypeTypeDouble:
			return llvm::Type::getDoubleTy(_context);
		case SLTypeTypeFunction:
			assert(false); // TODO: ???
		case SLTypeTypeStruct: {
			llvm::StructType* ret = nullptr;
			
			if (!_named_types.count(type->global_name())) {
				_named_types[type->global_name()] = ret = llvm::StructType::create(_context, type->global_name());
			} else {
				auto t = _named_types[type->global_name()];
				assert(t->isStructTy());
				ret = (llvm::StructType*)t;
			}
			
			if (ret->isOpaque() && type->is_defined()) {
				std::vector<llvm::Type*> elements;
				auto& member_vars = type->struct_definition().member_vars();
				for (auto& var : member_vars) {
					elements.push_back(_llvm_type(var.type));
				}
				ret->setBody(elements, true);
			}
			
			return ret;
		}
	}
	
	assert(false);
	return llvm::Type::getVoidTy(_context);
}
/**
* @brief Converts indices of LLVM getelementptr instruction.
*
* @param[in] base Pointed operand of LLVM getelementptr instruction converted
*                 to an expression in BIR.
* @param[in] start First index of LLVM getelementptr instruction to be converted.
* @param[in] end End of iterator through LLVM getelementptr instruction indices.
*/
ShPtr<Expression> LLVMInstructionConverter::convertGEPIndices(ShPtr<Expression> base,
		llvm::gep_type_iterator start, llvm::gep_type_iterator end) {
	auto indexOp = base;
	for (auto i = start; i != end; ++i) {
		auto index = getConverter()->convertValueToExpression(i.getOperand());
		if (i->isStructTy()) {
			auto indexInt = ucast<ConstInt>(index);
			indexOp = StructIndexOpExpr::create(indexOp, indexInt);
		} else {
			indexOp = ArrayIndexOpExpr::create(indexOp, index);
		}
	}

	return AddressOpExpr::create(indexOp);
}
/**
* @brief Generates access to aggregate type as a part of conversion of LLVM
*        instruction insertvalue or extractvalue.
*
* @param[in] type Type of aggregate type.
* @param[in] base Base expression.
* @param[in] indices Array of indices.
*/
ShPtr<Expression> LLVMInstructionConverter::generateAccessToAggregateType(
		llvm::CompositeType *type, const ShPtr<Expression> &base,
		const llvm::ArrayRef<unsigned> &indices) {
	auto typeIt = type;
	auto access = base;
	for (const auto &index: indices) {
		auto indexBir = ConstInt::create(index, COMPOSITE_TYPE_INDEX_SIZE_BITS);

		if (typeIt->isStructTy()) {
			access = StructIndexOpExpr::create(access, indexBir);
		} else if (typeIt->isArrayTy()) {
			access = ArrayIndexOpExpr::create(access, indexBir);
		}

		typeIt = llvm::dyn_cast<llvm::CompositeType>(typeIt->getTypeAtIndex(index));
	}

	return access;
}
Ejemplo n.º 4
0
Continuation* CodeGen::emit_spawn(Continuation* continuation) {
    assert(continuation->num_args() >= SPAWN_NUM_ARGS && "required arguments are missing");
    auto kernel = continuation->arg(SPAWN_ARG_BODY)->as<Global>()->init()->as_continuation();
    const size_t num_kernel_args = continuation->num_args() - SPAWN_NUM_ARGS;

    // build parallel-function signature
    Array<llvm::Type*> par_args(num_kernel_args);
    for (size_t i = 0; i < num_kernel_args; ++i) {
        auto type = continuation->arg(i + SPAWN_NUM_ARGS)->type();
        par_args[i] = convert(type);
    }

    // fetch values and create a unified struct which contains all values (closure)
    auto closure_type = convert(world_.tuple_type(continuation->arg_fn_type()->ops().skip_front(SPAWN_NUM_ARGS)));
    llvm::Value* closure = nullptr;
    if (closure_type->isStructTy()) {
        closure = llvm::UndefValue::get(closure_type);
        for (size_t i = 0; i < num_kernel_args; ++i)
            closure = irbuilder_.CreateInsertValue(closure, lookup(continuation->arg(i + SPAWN_NUM_ARGS)), unsigned(i));
    } else {
        closure = lookup(continuation->arg(0 + SPAWN_NUM_ARGS));
    }

    // allocate closure object and write values into it
    auto ptr = irbuilder_.CreateAlloca(closure_type, nullptr);
    irbuilder_.CreateStore(closure, ptr, false);

    // create wrapper function and call the runtime
    // wrapper(void* closure)
    llvm::Type* wrapper_arg_types[] = { irbuilder_.getInt8PtrTy(0) };
    auto wrapper_ft = llvm::FunctionType::get(irbuilder_.getVoidTy(), wrapper_arg_types, false);
    auto wrapper_name = kernel->unique_name() + "_spawn_thread";
    auto wrapper = (llvm::Function*)module_->getOrInsertFunction(wrapper_name, wrapper_ft);
    auto call = runtime_->spawn_thread(ptr, wrapper);

    // set insert point to the wrapper function
    auto old_bb = irbuilder_.GetInsertBlock();
    auto bb = llvm::BasicBlock::Create(*context_, wrapper_name, wrapper);
    irbuilder_.SetInsertPoint(bb);

    // extract all arguments from the closure
    auto wrapper_args = wrapper->arg_begin();
    auto load_ptr = irbuilder_.CreateBitCast(&*wrapper_args, llvm::PointerType::get(closure_type, 0));
    auto val = irbuilder_.CreateLoad(load_ptr);
    std::vector<llvm::Value*> target_args(num_kernel_args);
    if (val->getType()->isStructTy()) {
        for (size_t i = 0; i < num_kernel_args; ++i)
            target_args[i] = irbuilder_.CreateExtractValue(val, { unsigned(i) });
    } else {
        target_args[0] = val;
    }

    // call kernel body
    auto par_type = llvm::FunctionType::get(irbuilder_.getVoidTy(), llvm_ref(par_args), false);
    auto kernel_par_func = (llvm::Function*)module_->getOrInsertFunction(kernel->unique_name(), par_type);
    irbuilder_.CreateCall(kernel_par_func, target_args);
    irbuilder_.CreateRetVoid();

    // restore old insert point
    irbuilder_.SetInsertPoint(old_bb);

    // bind parameter of continuation to received handle
    auto cont = continuation->arg(SPAWN_ARG_RETURN)->as_continuation();
    emit_result_phi(cont->param(1), call);
    return cont;
}