Newer
Older
Chris Lattner
committed
// FIXME: param attributes for sext/zext etc.
return GetOrCreateLLVMFunction(Name, Ty, 0);
Chris Lattner
committed
}
llvm::Function *CodeGenModule::getIntrinsic(unsigned IID,const llvm::Type **Tys,
unsigned NumTys) {
return llvm::Intrinsic::getDeclaration(&getModule(),
(llvm::Intrinsic::ID)IID, Tys, NumTys);
}
Chris Lattner
committed
llvm::Function *CodeGenModule::getMemCpyFn() {
if (MemCpyFn) return MemCpyFn;
Chris Lattner
committed
const llvm::Type *IntPtr = TheTargetData.getIntPtrType();
return MemCpyFn = getIntrinsic(llvm::Intrinsic::memcpy, &IntPtr, 1);
llvm::Function *CodeGenModule::getMemMoveFn() {
if (MemMoveFn) return MemMoveFn;
Chris Lattner
committed
const llvm::Type *IntPtr = TheTargetData.getIntPtrType();
return MemMoveFn = getIntrinsic(llvm::Intrinsic::memmove, &IntPtr, 1);
}
llvm::Function *CodeGenModule::getMemSetFn() {
if (MemSetFn) return MemSetFn;
Chris Lattner
committed
const llvm::Type *IntPtr = TheTargetData.getIntPtrType();
return MemSetFn = getIntrinsic(llvm::Intrinsic::memset, &IntPtr, 1);
static void appendFieldAndPadding(CodeGenModule &CGM,
std::vector<llvm::Constant*>& Fields,
FieldDecl *FieldD, FieldDecl *NextFieldD,
llvm::Constant* Field,
// Append the field.
Fields.push_back(Field);
int StructFieldNo = CGM.getTypes().getLLVMFieldNo(FieldD);
int NextStructFieldNo;
if (!NextFieldD) {
NextStructFieldNo = STy->getNumElements();
} else {
NextStructFieldNo = CGM.getTypes().getLLVMFieldNo(NextFieldD);
}
// Append padding
for (int i = StructFieldNo + 1; i < NextStructFieldNo; i++) {
llvm::Constant *C =
llvm::Constant::getNullValue(STy->getElementType(StructFieldNo + 1));
Fields.push_back(C);
}
}
Chris Lattner
committed
llvm::Constant *CodeGenModule::
GetAddrOfConstantCFString(const StringLiteral *Literal) {
unsigned StringLength = 0;
bool isUTF16 = false;
if (Literal->containsNonAsciiOrNull()) {
// Convert from UTF-8 to UTF-16.
llvm::SmallVector<UTF16, 128> ToBuf(Literal->getByteLength());
const UTF8 *FromPtr = (UTF8 *)Literal->getStrData();
UTF16 *ToPtr = &ToBuf[0];
ConversionResult Result;
Result = ConvertUTF8toUTF16(&FromPtr, FromPtr+Literal->getByteLength(),
&ToPtr, ToPtr+Literal->getByteLength(),
strictConversion);
Steve Naroff
committed
if (Result == conversionOK) {
// FIXME: Storing UTF-16 in a C string is a hack to test Unicode strings
// without doing more surgery to this routine. Since we aren't explicitly
// checking for endianness here, it's also a bug (when generating code for
// a target that doesn't match the host endianness). Modeling this as an
// i16 array is likely the cleanest solution.
StringLength = ToPtr-&ToBuf[0];
str.assign((char *)&ToBuf[0], StringLength*2);// Twice as many UTF8 chars.
isUTF16 = true;
} else if (Result == sourceIllegal) {
// FIXME: Have Sema::CheckObjCString() validate the UTF-8 string.
Steve Naroff
committed
str.assign(Literal->getStrData(), Literal->getByteLength());
StringLength = str.length();
} else
assert(Result == conversionOK && "UTF-8 to UTF-16 conversion failed");
} else {
str.assign(Literal->getStrData(), Literal->getByteLength());
StringLength = str.length();
}
llvm::StringMapEntry<llvm::Constant *> &Entry =
CFConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
if (llvm::Constant *C = Entry.getValue())
return C;
llvm::Constant *Zero = llvm::Constant::getNullValue(llvm::Type::Int32Ty);
llvm::Constant *Zeros[] = { Zero, Zero };
if (!CFConstantStringClassRef) {
const llvm::Type *Ty = getTypes().ConvertType(getContext().IntTy);
Ty = llvm::ArrayType::get(Ty, 0);
// FIXME: This is fairly broken if
// __CFConstantStringClassReference is already defined, in that it
// will get renamed and the user will most likely see an opaque
// error message. This is a general issue with relying on
// particular names.
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(Ty, false,
llvm::GlobalVariable::ExternalLinkage, 0,
"__CFConstantStringClassReference",
&getModule());
// Decay array -> ptr
CFConstantStringClassRef =
llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2);
QualType CFTy = getContext().getCFConstantStringType();
RecordDecl *CFRD = CFTy->getAsRecordType()->getDecl();
const llvm::StructType *STy =
cast<llvm::StructType>(getTypes().ConvertType(CFTy));
std::vector<llvm::Constant*> Fields;
RecordDecl::field_iterator Field = CFRD->field_begin(getContext());
FieldDecl *CurField = *Field++;
FieldDecl *NextField = *Field++;
appendFieldAndPadding(*this, Fields, CurField, NextField,
CFConstantStringClassRef, CFRD, STy);
CurField = NextField;
NextField = *Field++;
const llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
appendFieldAndPadding(*this, Fields, CurField, NextField,
isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0)
: llvm::ConstantInt::get(Ty, 0x07C8),
CFRD, STy);
// String pointer.
CurField = NextField;
NextField = *Field++;
llvm::Constant *C = llvm::ConstantArray::get(str);
const char *Sect, *Prefix;
bool isConstant;
if (isUTF16) {
Prefix = getContext().Target.getUnicodeStringSymbolPrefix();
Sect = getContext().Target.getUnicodeStringSection();
// FIXME: Why does GCC not set constant here?
isConstant = false;
} else {
Prefix = getContext().Target.getStringSymbolPrefix(true);
Sect = getContext().Target.getCFStringDataSection();
// FIXME: -fwritable-strings should probably affect this, but we
// are following gcc here.
isConstant = true;
}
llvm::GlobalVariable *GV =
new llvm::GlobalVariable(C->getType(), isConstant,
llvm::GlobalValue::InternalLinkage,
C, Prefix, &getModule());
if (Sect)
GV->setSection(Sect);
if (isUTF16) {
unsigned Align = getContext().getTypeAlign(getContext().ShortTy)/8;
GV->setAlignment(Align);
}
appendFieldAndPadding(*this, Fields, CurField, NextField,
llvm::ConstantExpr::getGetElementPtr(GV, Zeros, 2),
CFRD, STy);
// String length.
CurField = NextField;
NextField = 0;
Ty = getTypes().ConvertType(getContext().LongTy);
appendFieldAndPadding(*this, Fields, CurField, NextField,
llvm::ConstantInt::get(Ty, StringLength), CFRD, STy);
// The struct.
C = llvm::ConstantStruct::get(STy, Fields);
GV = new llvm::GlobalVariable(C->getType(), true,
llvm::GlobalVariable::InternalLinkage, C,
getContext().Target.getCFStringSymbolPrefix(),
&getModule());
if (const char *Sect = getContext().Target.getCFStringSection())
GV->setSection(Sect);
Entry.setValue(GV);
/// GetStringForStringLiteral - Return the appropriate bytes for a
/// string literal, properly padded to match the literal type.
std::string CodeGenModule::GetStringForStringLiteral(const StringLiteral *E) {
const char *StrData = E->getStrData();
unsigned Len = E->getByteLength();
const ConstantArrayType *CAT =
getContext().getAsConstantArrayType(E->getType());
assert(CAT && "String isn't pointer or array!");
Chris Lattner
committed
// Resize the string to the right size.
std::string Str(StrData, StrData+Len);
uint64_t RealLen = CAT->getSize().getZExtValue();
Chris Lattner
committed
if (E->isWide())
RealLen *= getContext().Target.getWCharWidth()/8;
Str.resize(RealLen, '\0');
return Str;
}
/// GetAddrOfConstantStringFromLiteral - Return a pointer to a
/// constant array for the given string literal.
llvm::Constant *
CodeGenModule::GetAddrOfConstantStringFromLiteral(const StringLiteral *S) {
// FIXME: This can be more efficient.
return GetAddrOfConstantString(GetStringForStringLiteral(S));
}
/// GetAddrOfConstantStringFromObjCEncode - Return a pointer to a constant
/// array for the given ObjCEncodeExpr node.
llvm::Constant *
CodeGenModule::GetAddrOfConstantStringFromObjCEncode(const ObjCEncodeExpr *E) {
std::string Str;
getContext().getObjCEncodingForType(E->getEncodedType(), Str);
return GetAddrOfConstantCString(Str);
}
/// GenerateWritableString -- Creates storage for a string literal.
static llvm::Constant *GenerateStringLiteral(const std::string &str,
bool constant,
CodeGenModule &CGM,
const char *GlobalName) {
// Create Constant for this string literal. Don't add a '\0'.
llvm::Constant *C = llvm::ConstantArray::get(str, false);
// Create a global variable for this string
return new llvm::GlobalVariable(C->getType(), constant,
llvm::GlobalValue::InternalLinkage,
C, GlobalName, &CGM.getModule());
}
/// GetAddrOfConstantString - Returns a pointer to a character array
/// containing the literal. This contents are exactly that of the
/// given string, i.e. it will not be null terminated automatically;
/// see GetAddrOfConstantCString. Note that whether the result is
/// actually a pointer to an LLVM constant depends on
/// Feature.WriteableStrings.
///
/// The result has pointer to array type.
llvm::Constant *CodeGenModule::GetAddrOfConstantString(const std::string &str,
const char *GlobalName) {
bool IsConstant = !Features.WritableStrings;
// Get the default prefix if a name wasn't specified.
if (!GlobalName)
GlobalName = getContext().Target.getStringSymbolPrefix(IsConstant);
// Don't share any string literals if strings aren't constant.
if (!IsConstant)
return GenerateStringLiteral(str, false, *this, GlobalName);
llvm::StringMapEntry<llvm::Constant *> &Entry =
ConstantStringMap.GetOrCreateValue(&str[0], &str[str.length()]);
if (Entry.getValue())
return Entry.getValue();
// Create a global variable for this.
llvm::Constant *C = GenerateStringLiteral(str, true, *this, GlobalName);
Entry.setValue(C);
return C;
}
/// GetAddrOfConstantCString - Returns a pointer to a character
/// array containing the literal and a terminating '\-'
/// character. The result has pointer to array type.
llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str,
const char *GlobalName){
return GetAddrOfConstantString(str + '\0', GlobalName);
/// EmitObjCPropertyImplementations - Emit information for synthesized
/// properties for an implementation.
void CodeGenModule::EmitObjCPropertyImplementations(const
ObjCImplementationDecl *D) {
for (ObjCImplementationDecl::propimpl_iterator i = D->propimpl_begin(),
e = D->propimpl_end(); i != e; ++i) {
ObjCPropertyImplDecl *PID = *i;
// Dynamic is just for type-checking.
if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
ObjCPropertyDecl *PD = PID->getPropertyDecl();
// Determine which methods need to be implemented, some may have
// been overridden. Note that ::isSynthesized is not the method
// we want, that just indicates if the decl came from a
// property. What we want to know is if the method is defined in
// this implementation.
if (!D->getInstanceMethod(PD->getGetterName()))
CodeGenFunction(*this).GenerateObjCGetter(
const_cast<ObjCImplementationDecl *>(D), PID);
if (!PD->isReadOnly() &&
!D->getInstanceMethod(PD->getSetterName()))
CodeGenFunction(*this).GenerateObjCSetter(
const_cast<ObjCImplementationDecl *>(D), PID);
/// EmitNamespace - Emit all declarations in a namespace.
void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) {
for (RecordDecl::decl_iterator I = ND->decls_begin(getContext()),
E = ND->decls_end(getContext());
I != E; ++I)
EmitTopLevelDecl(*I);
}
// EmitLinkageSpec - Emit all declarations in a linkage spec.
void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) {
if (LSD->getLanguage() != LinkageSpecDecl::lang_c) {
ErrorUnsupported(LSD, "linkage spec");
return;
}
for (RecordDecl::decl_iterator I = LSD->decls_begin(getContext()),
E = LSD->decls_end(getContext());
I != E; ++I)
EmitTopLevelDecl(*I);
}
/// EmitTopLevelDecl - Emit code for a single top level declaration.
void CodeGenModule::EmitTopLevelDecl(Decl *D) {
// If an error has occurred, stop code generation, but continue
// parsing and semantic analysis (to ensure all warnings and errors
// are emitted).
if (Diags.hasErrorOccurred())
return;
switch (D->getKind()) {
case Decl::CXXMethod:
case Decl::Function:
case Decl::Var:
EmitGlobal(cast<ValueDecl>(D));
break;
EmitNamespace(cast<NamespaceDecl>(D));
case Decl::CXXConstructor:
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
break;
Anders Carlsson
committed
case Decl::CXXDestructor:
EmitCXXDestructors(cast<CXXDestructorDecl>(D));
break;
// Objective-C Decls
// Forward declarations, no (immediate) code generation.
case Decl::ObjCClass:
case Decl::ObjCForwardProtocol:
case Decl::ObjCCategory:
break;
case Decl::ObjCInterface:
// If we already laid out this interface due to an @class, and if we
// codegen'd a reference it, update the 'opaque' type to be a real type now.
Types.UpdateCompletedType(cast<ObjCInterfaceDecl>(D));
Runtime->GenerateProtocol(cast<ObjCProtocolDecl>(D));
break;
case Decl::ObjCCategoryImpl:
// Categories have properties but don't support synthesize so we
// can ignore them here.
Runtime->GenerateCategory(cast<ObjCCategoryImplDecl>(D));
break;
case Decl::ObjCImplementation: {
ObjCImplementationDecl *OMD = cast<ObjCImplementationDecl>(D);
EmitObjCPropertyImplementations(OMD);
Runtime->GenerateClass(OMD);
case Decl::ObjCMethod: {
ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D);
// If this is not a prototype, emit the body.
if (OMD->getBody(getContext()))
CodeGenFunction(*this).GenerateObjCMethod(OMD);
break;
}
case Decl::ObjCCompatibleAlias:
// compatibility-alias is a directive and has no code gen.
case Decl::LinkageSpec:
EmitLinkageSpec(cast<LinkageSpecDecl>(D));
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
break;
case Decl::FileScopeAsm: {
FileScopeAsmDecl *AD = cast<FileScopeAsmDecl>(D);
std::string AsmString(AD->getAsmString()->getStrData(),
AD->getAsmString()->getByteLength());
const std::string &S = getModule().getModuleInlineAsm();
if (S.empty())
getModule().setModuleInlineAsm(AsmString);
else
getModule().setModuleInlineAsm(S + '\n' + AsmString);
break;
}
default:
// Make sure we handled everything we should, every other kind is
// a non-top-level decl. FIXME: Would be nice to have an
// isTopLevelDeclKind function. Need to recode Decl::Kind to do
// that easily.
assert(isa<TypeDecl>(D) && "Unsupported decl kind");
}
}