forked from OSchip/llvm-project
OpenCL: introduce support for function scope __local variables
llvm-svn: 140068
This commit is contained in:
parent
c945f54ea5
commit
2dbb708b8a
|
@ -815,7 +815,7 @@ public:
|
|||
return !isFileVarDecl();
|
||||
|
||||
// Return true for: Auto, Register.
|
||||
// Return false for: Extern, Static, PrivateExtern.
|
||||
// Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal.
|
||||
|
||||
return getStorageClass() >= SC_Auto;
|
||||
}
|
||||
|
|
|
@ -2589,6 +2589,8 @@ def err_at_least_one_initializer_needed_to_size_array : Error<
|
|||
def err_array_size_non_int : Error<"size of array has non-integer type %0">;
|
||||
def err_init_element_not_constant : Error<
|
||||
"initializer element is not a compile-time constant">;
|
||||
def err_local_cant_init : Error<
|
||||
"'__local' variable cannot have an initializer">;
|
||||
def err_block_extern_cant_init : Error<
|
||||
"'extern' variable cannot have an initializer">;
|
||||
def warn_extern_init : Warning<"'extern' variable has an initializer">;
|
||||
|
|
|
@ -146,6 +146,7 @@ namespace clang {
|
|||
SC_PrivateExtern,
|
||||
|
||||
// These are only legal on variables.
|
||||
SC_OpenCLWorkGroupLocal,
|
||||
SC_Auto,
|
||||
SC_Register
|
||||
};
|
||||
|
|
|
@ -1119,12 +1119,13 @@ QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context,
|
|||
|
||||
const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) {
|
||||
switch (SC) {
|
||||
case SC_None: break;
|
||||
case SC_Auto: return "auto"; break;
|
||||
case SC_Extern: return "extern"; break;
|
||||
case SC_PrivateExtern: return "__private_extern__"; break;
|
||||
case SC_Register: return "register"; break;
|
||||
case SC_Static: return "static"; break;
|
||||
case SC_None: break;
|
||||
case SC_Auto: return "auto"; break;
|
||||
case SC_Extern: return "extern"; break;
|
||||
case SC_OpenCLWorkGroupLocal: return "<<work-group-local>>"; break;
|
||||
case SC_PrivateExtern: return "__private_extern__"; break;
|
||||
case SC_Register: return "register"; break;
|
||||
case SC_Static: return "static"; break;
|
||||
}
|
||||
|
||||
assert(0 && "Invalid storage class");
|
||||
|
|
|
@ -381,7 +381,8 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
|
|||
case SC_Extern: Out << "extern "; break;
|
||||
case SC_Static: Out << "static "; break;
|
||||
case SC_PrivateExtern: Out << "__private_extern__ "; break;
|
||||
case SC_Auto: case SC_Register: llvm_unreachable("invalid for functions");
|
||||
case SC_Auto: case SC_Register: case SC_OpenCLWorkGroupLocal:
|
||||
llvm_unreachable("invalid for functions");
|
||||
}
|
||||
|
||||
if (D->isInlineSpecified()) Out << "inline ";
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "CGDebugInfo.h"
|
||||
#include "CodeGenFunction.h"
|
||||
#include "CodeGenModule.h"
|
||||
#include "CGOpenCLRuntime.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
@ -131,6 +132,8 @@ void CodeGenFunction::EmitVarDecl(const VarDecl &D) {
|
|||
case SC_PrivateExtern:
|
||||
// Don't emit it now, allow it to be emitted lazily on its first use.
|
||||
return;
|
||||
case SC_OpenCLWorkGroupLocal:
|
||||
return CGM.getOpenCLRuntime().EmitWorkGroupLocalVarDecl(*this, D);
|
||||
}
|
||||
|
||||
assert(0 && "Unknown storage class");
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//===----- CGOpenCLRuntime.cpp - Interface to OpenCL Runtimes -------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This provides an abstract class for OpenCL code generation. Concrete
|
||||
// subclasses of this implement code generation for specific OpenCL
|
||||
// runtime libraries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CGOpenCLRuntime.h"
|
||||
#include "CodeGenFunction.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
|
||||
using namespace clang;
|
||||
using namespace CodeGen;
|
||||
|
||||
CGOpenCLRuntime::~CGOpenCLRuntime() {}
|
||||
|
||||
void CGOpenCLRuntime::EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
|
||||
const VarDecl &D) {
|
||||
return CGF.EmitStaticVarDecl(D, llvm::GlobalValue::InternalLinkage);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
//===----- CGOpenCLRuntime.h - Interface to OpenCL Runtimes -----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This provides an abstract class for OpenCL code generation. Concrete
|
||||
// subclasses of this implement code generation for specific OpenCL
|
||||
// runtime libraries.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CLANG_CODEGEN_OPENCLRUNTIME_H
|
||||
#define CLANG_CODEGEN_OPENCLRUNTIME_H
|
||||
|
||||
namespace clang {
|
||||
|
||||
class VarDecl;
|
||||
|
||||
namespace CodeGen {
|
||||
|
||||
class CodeGenFunction;
|
||||
class CodeGenModule;
|
||||
|
||||
class CGOpenCLRuntime {
|
||||
protected:
|
||||
CodeGenModule &CGM;
|
||||
|
||||
public:
|
||||
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
|
||||
virtual ~CGOpenCLRuntime();
|
||||
|
||||
/// Emit the IR required for a work-group-local variable declaration, and add
|
||||
/// an entry to CGF's LocalDeclMap for D. The base class does this using
|
||||
/// CodeGenFunction::EmitStaticVarDecl to emit an internal global for D.
|
||||
virtual void EmitWorkGroupLocalVarDecl(CodeGenFunction &CGF,
|
||||
const VarDecl &D);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -31,6 +31,7 @@ add_clang_library(clangCodeGen
|
|||
CGObjCGNU.cpp
|
||||
CGObjCMac.cpp
|
||||
CGObjCRuntime.cpp
|
||||
CGOpenCLRuntime.cpp
|
||||
CGRecordLayoutBuilder.cpp
|
||||
CGRTTI.cpp
|
||||
CGStmt.cpp
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "CGCall.h"
|
||||
#include "CGCXXABI.h"
|
||||
#include "CGObjCRuntime.h"
|
||||
#include "CGOpenCLRuntime.h"
|
||||
#include "TargetInfo.h"
|
||||
#include "clang/Frontend/CodeGenOptions.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
|
@ -65,15 +66,17 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
|
|||
ABI(createCXXABI(*this)),
|
||||
Types(C, M, TD, getTargetCodeGenInfo().getABIInfo(), ABI, CGO),
|
||||
TBAA(0),
|
||||
VTables(*this), ObjCRuntime(0), DebugInfo(0), ARCData(0), RRData(0),
|
||||
CFConstantStringClassRef(0), ConstantStringClassRef(0),
|
||||
VTables(*this), ObjCRuntime(0), OpenCLRuntime(0), DebugInfo(0), ARCData(0),
|
||||
RRData(0), CFConstantStringClassRef(0), ConstantStringClassRef(0),
|
||||
NSConstantStringType(0),
|
||||
VMContext(M.getContext()),
|
||||
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0),
|
||||
BlockObjectAssign(0), BlockObjectDispose(0),
|
||||
BlockDescriptorType(0), GenericBlockLiteralType(0) {
|
||||
if (Features.ObjC1)
|
||||
createObjCRuntime();
|
||||
createObjCRuntime();
|
||||
if (Features.OpenCL)
|
||||
createOpenCLRuntime();
|
||||
|
||||
// Enable TBAA unless it's suppressed.
|
||||
if (!CodeGenOpts.RelaxedAliasing && CodeGenOpts.OptimizationLevel > 0)
|
||||
|
@ -109,6 +112,7 @@ CodeGenModule::CodeGenModule(ASTContext &C, const CodeGenOptions &CGO,
|
|||
|
||||
CodeGenModule::~CodeGenModule() {
|
||||
delete ObjCRuntime;
|
||||
delete OpenCLRuntime;
|
||||
delete &ABI;
|
||||
delete TBAA;
|
||||
delete DebugInfo;
|
||||
|
@ -123,6 +127,10 @@ void CodeGenModule::createObjCRuntime() {
|
|||
ObjCRuntime = CreateMacObjCRuntime(*this);
|
||||
}
|
||||
|
||||
void CodeGenModule::createOpenCLRuntime() {
|
||||
OpenCLRuntime = new CGOpenCLRuntime(*this);
|
||||
}
|
||||
|
||||
void CodeGenModule::Release() {
|
||||
EmitDeferred();
|
||||
EmitCXXGlobalInitFunc();
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace CodeGen {
|
|||
class CGCXXABI;
|
||||
class CGDebugInfo;
|
||||
class CGObjCRuntime;
|
||||
class CGOpenCLRuntime;
|
||||
class BlockFieldFlags;
|
||||
class FunctionArgList;
|
||||
|
||||
|
@ -226,6 +227,7 @@ class CodeGenModule : public CodeGenTypeCache {
|
|||
friend class CodeGenVTables;
|
||||
|
||||
CGObjCRuntime* ObjCRuntime;
|
||||
CGOpenCLRuntime* OpenCLRuntime;
|
||||
CGDebugInfo* DebugInfo;
|
||||
ARCEntrypoints *ARCData;
|
||||
RREntrypoints *RRData;
|
||||
|
@ -317,6 +319,8 @@ class CodeGenModule : public CodeGenTypeCache {
|
|||
/// Lazily create the Objective-C runtime
|
||||
void createObjCRuntime();
|
||||
|
||||
void createOpenCLRuntime();
|
||||
|
||||
llvm::LLVMContext &VMContext;
|
||||
|
||||
/// @name Cache for Blocks Runtime Globals
|
||||
|
@ -356,6 +360,12 @@ public:
|
|||
/// been configured.
|
||||
bool hasObjCRuntime() { return !!ObjCRuntime; }
|
||||
|
||||
/// getObjCRuntime() - Return a reference to the configured OpenCL runtime.
|
||||
CGOpenCLRuntime &getOpenCLRuntime() {
|
||||
assert(OpenCLRuntime != 0);
|
||||
return *OpenCLRuntime;
|
||||
}
|
||||
|
||||
/// getCXXABI() - Return a reference to the configured C++ ABI.
|
||||
CGCXXABI &getCXXABI() { return ABI; }
|
||||
|
||||
|
|
|
@ -3734,6 +3734,13 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
}
|
||||
}
|
||||
|
||||
if (getLangOptions().OpenCL) {
|
||||
// Set up the special work-group-local storage class for variables in the
|
||||
// OpenCL __local address space.
|
||||
if (R.getAddressSpace() == LangAS::opencl_local)
|
||||
SC = SC_OpenCLWorkGroupLocal;
|
||||
}
|
||||
|
||||
bool isExplicitSpecialization = false;
|
||||
VarDecl *NewVD;
|
||||
if (!getLangOptions().CPlusPlus) {
|
||||
|
@ -3883,6 +3890,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
case SC_Static:
|
||||
case SC_Extern:
|
||||
case SC_PrivateExtern:
|
||||
case SC_OpenCLWorkGroupLocal:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5715,6 +5723,14 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init,
|
|||
}
|
||||
}
|
||||
|
||||
// OpenCL 1.1 6.5.2: "Variables allocated in the __local address space inside
|
||||
// a kernel function cannot be initialized."
|
||||
if (VDecl->getStorageClass() == SC_OpenCLWorkGroupLocal) {
|
||||
Diag(VDecl->getLocation(), diag::err_local_cant_init);
|
||||
VDecl->setInvalidDecl();
|
||||
return;
|
||||
}
|
||||
|
||||
// Capture the variable that is being initialized and the style of
|
||||
// initialization.
|
||||
InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl);
|
||||
|
@ -6131,6 +6147,9 @@ void Sema::ActOnCXXForRangeDecl(Decl *D) {
|
|||
case SC_Register:
|
||||
Error = 4;
|
||||
break;
|
||||
case SC_OpenCLWorkGroupLocal:
|
||||
assert(0 && "Unexpected storage class");
|
||||
break;
|
||||
}
|
||||
// FIXME: constexpr isn't allowed here.
|
||||
//if (DS.isConstexprSpecified())
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
// RUN: %clang_cc1 %s -ffake-address-space-map -emit-llvm -o - | FileCheck %s
|
||||
|
||||
__kernel void foo(void) {
|
||||
// CHECK: @foo.i = internal addrspace(2)
|
||||
__local int i;
|
||||
++i;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
|
||||
|
||||
__kernel void foo(void) {
|
||||
__local int i;
|
||||
__local int j = 2; // expected-error {{'__local' variable cannot have an initializer}}
|
||||
}
|
Loading…
Reference in New Issue