mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
This requires us to potentially copy the value witness tables for generic struct types as part of computing layout, but that's not the end of the world (although it will rely on a future patch to split value witnesses out from protocol witness tables). Oh, and add a value witness for stride, changing Builtin.strideof to use that. Swift SVN r2829
221 lines
7.8 KiB
C++
221 lines
7.8 KiB
C++
//===--- IRGenModule.cpp - Swift Global LLVM IR Generation ----------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See http://swift.org/LICENSE.txt for license information
|
|
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements IR generation for global declarations in Swift.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/ASTContext.h"
|
|
#include "swift/AST/Module.h"
|
|
#include "swift/AST/Stmt.h"
|
|
#include "swift/AST/Diagnostics.h"
|
|
#include "llvm/Constants.h"
|
|
#include "llvm/DerivedTypes.h"
|
|
#include "llvm/Intrinsics.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/Type.h"
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
#include "llvm/Support/SourceMgr.h"
|
|
#include "llvm/Target/TargetData.h"
|
|
|
|
#include "GenType.h"
|
|
#include "IRGenModule.h"
|
|
#include "Linking.h"
|
|
|
|
using namespace swift;
|
|
using namespace irgen;
|
|
|
|
IRGenModule::IRGenModule(ASTContext &Context,
|
|
Options &Opts, llvm::Module &Module,
|
|
const llvm::TargetData &TargetData)
|
|
: Context(Context), Opts(Opts),
|
|
Module(Module), LLVMContext(Module.getContext()),
|
|
TargetData(TargetData), Types(*new TypeConverter(*this)) {
|
|
VoidTy = llvm::Type::getVoidTy(getLLVMContext());
|
|
Int1Ty = llvm::Type::getInt1Ty(getLLVMContext());
|
|
Int8Ty = llvm::Type::getInt8Ty(getLLVMContext());
|
|
Int16Ty = llvm::Type::getInt16Ty(getLLVMContext());
|
|
Int32Ty = llvm::Type::getInt32Ty(getLLVMContext());
|
|
Int64Ty = llvm::Type::getInt64Ty(getLLVMContext());
|
|
Int8PtrTy = llvm::Type::getInt8PtrTy(getLLVMContext());
|
|
Int8PtrPtrTy = Int8PtrTy->getPointerTo(0);
|
|
SizeTy = TargetData.getIntPtrType(getLLVMContext());
|
|
MemCpyFn = nullptr;
|
|
AllocObjectFn = nullptr;
|
|
RetainNoResultFn = nullptr;
|
|
ReleaseFn = nullptr;
|
|
DeallocObjectFn = nullptr;
|
|
ObjCRetainFn = nullptr;
|
|
ObjCReleaseFn = nullptr;
|
|
RawAllocFn = nullptr;
|
|
RawDeallocFn = nullptr;
|
|
SlowAllocFn = nullptr;
|
|
SlowRawDeallocFn = nullptr;
|
|
|
|
RefCountedStructTy =
|
|
llvm::StructType::create(getLLVMContext(), "swift.refcounted");
|
|
RefCountedPtrTy = RefCountedStructTy->getPointerTo(/*addrspace*/ 0);
|
|
RefCountedNull = llvm::ConstantPointerNull::get(RefCountedPtrTy);
|
|
|
|
DtorTy = llvm::FunctionType::get(SizeTy, RefCountedPtrTy, false);
|
|
llvm::Type *dtorPtrTy = DtorTy->getPointerTo();
|
|
llvm::Type *heapMetadataElts[] = { dtorPtrTy, dtorPtrTy };
|
|
HeapMetadataStructTy =
|
|
llvm::StructType::create(getLLVMContext(), heapMetadataElts,
|
|
"swift.heapmetadata");
|
|
HeapMetadataPtrTy = HeapMetadataStructTy->getPointerTo(/*addrspace*/ 0);
|
|
|
|
llvm::Type *refCountedElts[] = { HeapMetadataPtrTy, SizeTy };
|
|
RefCountedStructTy->setBody(refCountedElts);
|
|
|
|
PtrSize = Size(TargetData.getPointerSize());
|
|
|
|
llvm::Type *funcElts[] = { Int8PtrTy, RefCountedPtrTy };
|
|
FunctionPairTy = llvm::StructType::get(LLVMContext, funcElts,
|
|
/*packed*/ false);
|
|
|
|
OpaquePtrTy = llvm::StructType::create(LLVMContext, "swift.opaque")
|
|
->getPointerTo(0);
|
|
|
|
FixedBufferTy = nullptr;
|
|
for (unsigned i = 0; i != NumValueWitnessFunctions; ++i)
|
|
ValueWitnessTys[i] = nullptr;
|
|
|
|
ObjCPtrTy = llvm::StructType::create(getLLVMContext(), "objc_object")
|
|
->getPointerTo(0);
|
|
|
|
// TODO: use "tinycc" on platforms that support it
|
|
RuntimeCC = llvm::CallingConv::C;
|
|
}
|
|
|
|
IRGenModule::~IRGenModule() {
|
|
delete &Types;
|
|
}
|
|
|
|
static llvm::Constant *createRuntimeFunction(IRGenModule &IGM, StringRef name,
|
|
llvm::FunctionType *fnType) {
|
|
llvm::Constant *addr = IGM.Module.getOrInsertFunction(name, fnType);
|
|
if (auto fn = dyn_cast<llvm::Function>(addr))
|
|
fn->setCallingConv(IGM.RuntimeCC);
|
|
return addr;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getAllocObjectFn() {
|
|
if (AllocObjectFn) return AllocObjectFn;
|
|
|
|
llvm::Type *types[] = { HeapMetadataPtrTy, SizeTy, SizeTy };
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(RefCountedPtrTy, types, false);
|
|
AllocObjectFn = createRuntimeFunction(*this, "swift_allocObject", fnType);
|
|
return AllocObjectFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getRawAllocFn() {
|
|
if (RawAllocFn) return RawAllocFn;
|
|
|
|
/// void *swift_rawAlloc(SwiftAllocIndex index);
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(Int8PtrTy, SizeTy, false);
|
|
RawAllocFn = createRuntimeFunction(*this, "swift_rawAlloc", fnType);
|
|
return RawAllocFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getRawDeallocFn() {
|
|
if (RawDeallocFn) return RawDeallocFn;
|
|
|
|
/// void swift_rawDealloc(void *ptr, SwiftAllocIndex index);
|
|
llvm::Type *types[] = { Int8PtrTy, SizeTy };
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(VoidTy, types, false);
|
|
RawDeallocFn = createRuntimeFunction(*this, "swift_rawDealloc", fnType);
|
|
return RawDeallocFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getSlowAllocFn() {
|
|
if (SlowAllocFn) return SlowAllocFn;
|
|
|
|
/// void *swift_slowAlloc(size_t size, size_t flags);
|
|
llvm::Type *argTypes[] = { SizeTy, SizeTy };
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(Int8PtrTy, argTypes, false);
|
|
SlowAllocFn = createRuntimeFunction(*this, "swift_slowAlloc", fnType);
|
|
return SlowAllocFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getSlowRawDeallocFn() {
|
|
if (SlowRawDeallocFn) return SlowRawDeallocFn;
|
|
|
|
/// void swift_slowRawDealloc(void *ptr, size_t size);
|
|
llvm::Type *types[] = { Int8PtrTy, SizeTy };
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(VoidTy, types, false);
|
|
SlowRawDeallocFn = createRuntimeFunction(*this, "swift_slowRawDealloc", fnType);
|
|
return SlowRawDeallocFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getRetainNoResultFn() {
|
|
if (RetainNoResultFn) return RetainNoResultFn;
|
|
|
|
// void swift_retainNoResult(void *ptr);
|
|
auto fnType = llvm::FunctionType::get(VoidTy, RefCountedPtrTy, false);
|
|
RetainNoResultFn = createRuntimeFunction(*this, "swift_retain_noresult", fnType);
|
|
if (auto fn = dyn_cast<llvm::Function>(RetainNoResultFn))
|
|
fn->setDoesNotCapture(1);
|
|
return RetainNoResultFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getReleaseFn() {
|
|
if (ReleaseFn) return ReleaseFn;
|
|
|
|
// void swift_release(void *ptr);
|
|
auto fnType = llvm::FunctionType::get(VoidTy, RefCountedPtrTy, false);
|
|
ReleaseFn = createRuntimeFunction(*this, "swift_release", fnType);
|
|
if (auto fn = dyn_cast<llvm::Function>(ReleaseFn))
|
|
fn->setDoesNotCapture(1);
|
|
return ReleaseFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getDeallocObjectFn() {
|
|
if (DeallocObjectFn) return DeallocObjectFn;
|
|
|
|
// void swift_deallocObject(void *ptr, size_t size);
|
|
llvm::Type *argTypes[] = { RefCountedPtrTy, SizeTy };
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(VoidTy, argTypes, false);
|
|
DeallocObjectFn = createRuntimeFunction(*this, "swift_deallocObject", fnType);
|
|
return DeallocObjectFn;
|
|
}
|
|
|
|
llvm::Constant *IRGenModule::getGetGenericMetadataFn() {
|
|
if (GetGenericMetadataFn) return GetGenericMetadataFn;
|
|
|
|
// heap_metadata_t *swift_getGenericMetadata(heap_metadata_t *pattern,
|
|
// const void *arguments);
|
|
llvm::Type *argTypes[] = { HeapMetadataPtrTy, Int8PtrTy };
|
|
llvm::FunctionType *fnType =
|
|
llvm::FunctionType::get(HeapMetadataPtrTy, argTypes, false);
|
|
GetGenericMetadataFn =
|
|
createRuntimeFunction(*this, "swift_getGenericMetadata", fnType);
|
|
return GetGenericMetadataFn;
|
|
}
|
|
|
|
void IRGenModule::unimplemented(SourceLoc loc, StringRef message) {
|
|
Context.Diags.diagnose(loc, diag::irgen_unimplemented, message);
|
|
}
|
|
|
|
void IRGenModule::error(SourceLoc loc, const Twine &message) {
|
|
SmallVector<char, 128> buffer;
|
|
Context.Diags.diagnose(loc, diag::irgen_failure,
|
|
message.toStringRef(buffer));
|
|
}
|