Browse Source

Write specifiers before anonymous struct. (#423)

* Write specifiers before anonymous struct.
* Add rewrite option to mark all global variable not internal as extern.
Xiang Li 8 years ago
parent
commit
c9e9019780

+ 1 - 0
include/dxc/dxctools.h

@@ -18,6 +18,7 @@ enum RewriterOptionMask {
   Default = 0,
   Default = 0,
   SkipFunctionBody = 1,
   SkipFunctionBody = 1,
   SkipStatic = 2,
   SkipStatic = 2,
+  GlobalExternByDefault = 4,
 };
 };
 
 
 struct __declspec(uuid("c012115b-8893-4eb9-9c5a-111456ea1c45"))
 struct __declspec(uuid("c012115b-8893-4eb9-9c5a-111456ea1c45"))

+ 30 - 1
tools/clang/lib/AST/DeclPrinter.cpp

@@ -165,6 +165,35 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
   TagDecl* TD = dyn_cast<TagDecl>(*Begin);
   TagDecl* TD = dyn_cast<TagDecl>(*Begin);
   if (TD)
   if (TD)
     ++Begin;
     ++Begin;
+  // HLSL Change Begin - anonymous struct need to have static.
+  //static const struct {
+  //  float a;
+  //  SamplerState s;
+  //} A = {1.2, ss};
+  // will be rewrite to
+  // struct {
+  //  float a;
+  //  SamplerState s;
+  //} static const  A = {1.2, ss};
+  // without this change.
+  bool bAnonymous = false;
+  if (TD && TD->getName().empty()) {
+    bAnonymous = true;
+  }
+
+  if (bAnonymous && Begin) {
+    if (VarDecl *VD = dyn_cast<VarDecl>(*Begin)) {
+      if (!Policy.SuppressSpecifiers) {
+        StorageClass SC = VD->getStorageClass();
+        if (SC != SC_None)
+          Out << VarDecl::getStorageClassSpecifierString(SC) << " ";
+        if (VD->getType().hasQualifiers())
+          VD->getType().getQualifiers().print(Out, Policy,
+                                              /*appendSpaceIfNonEmpty*/ true);
+      }
+    }
+  }
+  // HLSL Change End
 
 
   PrintingPolicy SubPolicy(Policy);
   PrintingPolicy SubPolicy(Policy);
   if (TD && TD->isCompleteDefinition()) {
   if (TD && TD->isCompleteDefinition()) {
@@ -176,7 +205,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls,
   bool isFirst = true;
   bool isFirst = true;
   for ( ; Begin != End; ++Begin) {
   for ( ; Begin != End; ++Begin) {
     if (isFirst) {
     if (isFirst) {
-      SubPolicy.SuppressSpecifiers = false;
+      SubPolicy.SuppressSpecifiers = bAnonymous; // HLSL Change.
       isFirst = false;
       isFirst = false;
     } else {
     } else {
       if (!isFirst) Out << ", ";
       if (!isFirst) Out << ", ";

+ 11 - 0
tools/clang/test/HLSL/rewriter/anonymous_struct.hlsl

@@ -0,0 +1,11 @@
+
+SamplerState ss;
+
+static const struct {
+  float a;
+  SamplerState s;
+} A = {1.2, ss};
+
+float4 main() : SV_Target {
+    return A.a;
+}

+ 11 - 0
tools/clang/test/HLSL/rewriter/correct_rewrites/anonymous_struct_gold.hlsl

@@ -0,0 +1,11 @@
+// Rewrite unchanged result:
+SamplerState ss;
+static const struct {
+  float a;
+  SamplerState s;
+} A = { 1.2, ss };
+float4 main() : SV_Target {
+  return A.a;
+}
+
+

+ 2 - 2
tools/clang/test/HLSL/rewriter/correct_rewrites/cpp-errors_gold.hlsl

@@ -81,9 +81,9 @@ struct my_struct_type_init {
 };
 };
 const struct my_struct_type_init my_struct_type_init_one = { 1 };
 const struct my_struct_type_init my_struct_type_init_one = { 1 };
 const struct my_struct_type_init my_struct_type_init_two = { 2 };
 const struct my_struct_type_init my_struct_type_init_two = { 2 };
-struct {
+const struct {
   int my_anon_struct_field;
   int my_anon_struct_field;
-} const my_anon_struct_type;
+} my_anon_struct_type;
 void fn_my_struct_type_decl() {
 void fn_my_struct_type_decl() {
   my_struct_type_decl local_var;
   my_struct_type_decl local_var;
 }
 }

+ 15 - 0
tools/clang/test/HLSL/rewriter/force_extern.hlsl

@@ -0,0 +1,15 @@
+
+float a;
+
+namespace b {
+   float c;
+   namespace d {
+      float e;
+   }
+}
+
+static f = a;
+
+float4 main() : SV_Target {
+    return a + c + e + f;
+}

+ 3 - 2
tools/clang/tools/dotnetc/EditorForm.cs

@@ -2877,17 +2877,18 @@ namespace MainNs
         {
         {
             IDxcRewriter rewriter = HlslDxcLib.CreateDxcRewriter();
             IDxcRewriter rewriter = HlslDxcLib.CreateDxcRewriter();
             IDxcBlobEncoding code = CreateBlobForCodeText();
             IDxcBlobEncoding code = CreateBlobForCodeText();
-            IDxcRewriteResult rewriterResult = rewriter.RewriteUnchanged(code, null, 0);
+            IDxcRewriteResult rewriterResult = rewriter.RewriteUnchangedWithInclude(code, "input.hlsl", null, 0, library.CreateIncludeHandler(), 0);
             IDxcBlobEncoding rewriteBlob = rewriterResult.GetRewrite();
             IDxcBlobEncoding rewriteBlob = rewriterResult.GetRewrite();
             string rewriteText = GetStringFromBlob(rewriteBlob);
             string rewriteText = GetStringFromBlob(rewriteBlob);
             RewriterOutputTextBox.Text = rewriteText;
             RewriterOutputTextBox.Text = rewriteText;
+            AnalysisTabControl.SelectTab(RewriterOutputTabPage);
         }
         }
 
 
         private void rewriteNobodyToolStripMenuItem_Click(object sender, EventArgs e)
         private void rewriteNobodyToolStripMenuItem_Click(object sender, EventArgs e)
         {
         {
             IDxcRewriter rewriter = HlslDxcLib.CreateDxcRewriter();
             IDxcRewriter rewriter = HlslDxcLib.CreateDxcRewriter();
             IDxcBlobEncoding code = CreateBlobForCodeText();
             IDxcBlobEncoding code = CreateBlobForCodeText();
-            IDxcRewriteResult rewriterResult = rewriter.RewriteUnchangedWithInclude(code, "input.hlsl",null, 0, null, 1);
+            IDxcRewriteResult rewriterResult = rewriter.RewriteUnchangedWithInclude(code, "input.hlsl",null, 0, library.CreateIncludeHandler(), 1);
             IDxcBlobEncoding rewriteBlob = rewriterResult.GetRewrite();
             IDxcBlobEncoding rewriteBlob = rewriterResult.GetRewrite();
             string rewriteText = GetStringFromBlob(rewriteBlob);
             string rewriteText = GetStringFromBlob(rewriteBlob);
             RewriterOutputTextBox.Text = rewriteText;
             RewriterOutputTextBox.Text = rewriteText;

+ 22 - 0
tools/clang/tools/libclang/dxcrewriteunused.cpp

@@ -373,6 +373,23 @@ static void RemoveStaticDecls(DeclContext &Ctx) {
   }
   }
 }
 }
 
 
+static void GlobalVariableAsExternByDefault(DeclContext &Ctx) {
+  for (auto it = Ctx.decls_begin(); it != Ctx.decls_end(); ) {
+    auto cur = it++;
+    if (VarDecl *VD = dyn_cast<VarDecl>(*cur)) {
+      bool isInternal = VD->getStorageClass() == SC_Static || VD->isInAnonymousNamespace();
+      if (!isInternal) {
+        VD->setStorageClass(StorageClass::SC_Extern);
+      }
+    }
+    // Only iterate on namespaces.
+    if (NamespaceDecl *DC = dyn_cast<NamespaceDecl>(*cur)) {
+      GlobalVariableAsExternByDefault(*DC);
+    }
+  }
+}
+
+
 static
 static
 HRESULT DoSimpleReWrite(_In_ DxcLangExtensionsHelper *pHelper,
 HRESULT DoSimpleReWrite(_In_ DxcLangExtensionsHelper *pHelper,
                _In_ LPCSTR pFileName,
                _In_ LPCSTR pFileName,
@@ -386,6 +403,7 @@ HRESULT DoSimpleReWrite(_In_ DxcLangExtensionsHelper *pHelper,
 
 
   bool bSkipFunctionBody = rewriteOption & RewriterOptionMask::SkipFunctionBody;
   bool bSkipFunctionBody = rewriteOption & RewriterOptionMask::SkipFunctionBody;
   bool bSkipStatic = rewriteOption & RewriterOptionMask::SkipStatic;
   bool bSkipStatic = rewriteOption & RewriterOptionMask::SkipStatic;
+  bool bGlobalExternByDefault = rewriteOption & RewriterOptionMask::GlobalExternByDefault;
 
 
   std::string s, warnings;
   std::string s, warnings;
   raw_string_ostream o(s);
   raw_string_ostream o(s);
@@ -409,6 +427,10 @@ HRESULT DoSimpleReWrite(_In_ DxcLangExtensionsHelper *pHelper,
     RemoveStaticDecls(*tu);
     RemoveStaticDecls(*tu);
   }
   }
 
 
+  if (bGlobalExternByDefault) {
+    GlobalVariableAsExternByDefault(*tu);
+  }
+
   o << "// Rewrite unchanged result:\n";
   o << "// Rewrite unchanged result:\n";
   PrintingPolicy p = PrintingPolicy(C.getPrintingPolicy());
   PrintingPolicy p = PrintingPolicy(C.getPrintingPolicy());
   p.Indentation = 1;
   p.Indentation = 1;

+ 44 - 0
tools/clang/unittests/HLSL/RewriterTest.cpp

@@ -49,7 +49,9 @@ public:
   END_TEST_CLASS()
   END_TEST_CLASS()
 
 
   TEST_METHOD(RunAttributes);
   TEST_METHOD(RunAttributes);
+  TEST_METHOD(RunAnonymousStruct);
   TEST_METHOD(RunCppErrors);
   TEST_METHOD(RunCppErrors);
+  TEST_METHOD(RunForceExtern);
   TEST_METHOD(RunIndexingOperator);
   TEST_METHOD(RunIndexingOperator);
   TEST_METHOD(RunIntrinsicExamples);
   TEST_METHOD(RunIntrinsicExamples);
   TEST_METHOD(RunMatrixAssignments);
   TEST_METHOD(RunMatrixAssignments);
@@ -285,6 +287,10 @@ TEST_F(RewriterTest, RunAttributes) {
     CheckVerifiesHLSL(L"rewriter\\attributes_noerr.hlsl", L"rewriter\\correct_rewrites\\attributes_gold.hlsl");
     CheckVerifiesHLSL(L"rewriter\\attributes_noerr.hlsl", L"rewriter\\correct_rewrites\\attributes_gold.hlsl");
 }
 }
 
 
+TEST_F(RewriterTest, RunAnonymousStruct) {
+    CheckVerifiesHLSL(L"rewriter\\anonymous_struct.hlsl", L"rewriter\\correct_rewrites\\anonymous_struct_gold.hlsl");
+}
+
 TEST_F(RewriterTest, RunCppErrors) {
 TEST_F(RewriterTest, RunCppErrors) {
     CheckVerifiesHLSL(L"rewriter\\cpp-errors_noerr.hlsl", L"rewriter\\correct_rewrites\\cpp-errors_gold.hlsl");
     CheckVerifiesHLSL(L"rewriter\\cpp-errors_noerr.hlsl", L"rewriter\\correct_rewrites\\cpp-errors_gold.hlsl");
 }
 }
@@ -526,4 +532,42 @@ TEST_F(RewriterTest, RunNoStatic) {
   std::string strResult = BlobToUtf8(result);
   std::string strResult = BlobToUtf8(result);
   // No static.
   // No static.
   VERIFY_IS_TRUE(strResult.find("static") == std::string::npos);
   VERIFY_IS_TRUE(strResult.find("static") == std::string::npos);
+}
+
+TEST_F(RewriterTest, RunForceExtern) {  CComPtr<IDxcRewriter> pRewriter;
+  VERIFY_SUCCEEDED(CreateRewriter(&pRewriter));
+  CComPtr<IDxcOperationResult> pRewriteResult;
+
+  // Get the source text from a file
+  FileWithBlob source(
+      m_dllSupport,
+      GetPathToHlslDataFile(L"rewriter\\force_extern.hlsl")
+          .c_str());
+
+  const int myDefinesCount = 3;
+  DxcDefine myDefines[myDefinesCount] = {
+      {L"myDefine", L"2"}, {L"myDefine3", L"1994"}, {L"myDefine4", nullptr}};
+
+  // Run rewrite no function body on the source code
+  VERIFY_SUCCEEDED(pRewriter->RewriteUnchangedWithInclude(
+      source.BlobEncoding, L"vector-assignments_noerr.hlsl", myDefines,
+      myDefinesCount, /*pIncludeHandler*/ nullptr,
+      RewriterOptionMask::SkipFunctionBody |
+          RewriterOptionMask::GlobalExternByDefault,
+      &pRewriteResult));
+
+  CComPtr<IDxcBlob> result;
+  VERIFY_SUCCEEDED(pRewriteResult->GetResult(&result));
+  // Function decl only.
+  VERIFY_IS_TRUE(strcmp(BlobToUtf8(result).c_str(),
+      "// Rewrite unchanged result:\n\
+extern const float a;\n\
+namespace b {\n\
+  extern const float c;\n\
+  namespace d {\n\
+    extern const float e;\n\
+  }\n\
+}\n\
+static int f;\n\
+float4 main() : SV_Target;\n") == 0);
 }
 }