diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -158,6 +158,8 @@ "%select{'expected-no-diagnostics' directive|other expected directives}0">; def err_verify_no_directives : Error< "no expected directives found: consider use of 'expected-no-diagnostics'">; +def err_verify_nonconst_addrspace : Error< + "qualifier 'const' is needed for variables in address space '%0'">; def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; def note_fixit_in_macro : Note< diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp --- a/clang/lib/Basic/Targets/AVR.cpp +++ b/clang/lib/Basic/Targets/AVR.cpp @@ -308,6 +308,7 @@ Builder.defineMacro("__AVR"); Builder.defineMacro("__AVR__"); Builder.defineMacro("__ELF__"); + Builder.defineMacro("__flash", "__attribute__((address_space(1)))"); if (!this->CPU.empty()) { auto It = llvm::find_if( diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -8108,6 +8108,19 @@ AVRTargetCodeGenInfo(CodeGenTypes &CGT) : TargetCodeGenInfo(std::make_unique(CGT)) {} + LangAS getGlobalVarAddressSpace(CodeGenModule &CGM, + const VarDecl *D) const override { + // Check if a global/static variable is defined within address space 1 + // but not constant. + LangAS AS = D->getType().getAddressSpace(); + if (isTargetAddressSpace(AS) && toTargetAddressSpace(AS) == 1 && + !D->getType().isConstQualified()) + CGM.getDiags().Report(D->getLocation(), + diag::err_verify_nonconst_addrspace) + << "__flash"; + return TargetCodeGenInfo::getGlobalVarAddressSpace(CGM, D); + } + void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { if (GV->isDeclaration()) diff --git a/clang/test/CodeGen/address-space-avr.c b/clang/test/CodeGen/address-space-avr.c --- a/clang/test/CodeGen/address-space-avr.c +++ b/clang/test/CodeGen/address-space-avr.c @@ -1,12 +1,21 @@ // RUN: %clang_cc1 -triple avr -emit-llvm < %s | FileCheck %s -// Test that function declarations in nonzero address spaces without prototype -// are called correctly. +// CHECK: @var0 {{.*}} addrspace(1) constant [3 x i16] +// CHECK: @bar.var2 {{.*}} addrspace(1) constant [3 x i16] +// CHECK: @var1 {{.*}} addrspace(1) constant [3 x i16] // CHECK: define{{.*}} void @bar() addrspace(1) -// CHECK: call addrspace(1) void bitcast (void (...) addrspace(1)* @foo to void (i16) addrspace(1)*)(i16 3) +// CHECK: call addrspace(1) void bitcast (void (...) addrspace(1)* @foo to void (i16) addrspace(1)*) // CHECK: declare void @foo(...) addrspace(1) + +__flash const int var0[] = {999, 888, 777}; +__flash static const int var1[] = {111, 222, 333}; + +int i; + void foo(); -void bar(void) { - foo(3); + +void bar() { + static __flash const int var2[] = {555, 666, 777}; + foo(var1[i]); } diff --git a/clang/test/CodeGen/avr-flash.c b/clang/test/CodeGen/avr-flash.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/avr-flash.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple avr -emit-llvm-only -verify %s + +int foo(void) { + static __flash int b[] = {4, 6}; // expected-error {{qualifier 'const' is needed for variables in address space '__flash'}} + return b[0]; +}