1// Copyright (C) 2016 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package clang
16
17import (
18	"path/filepath"
19	"strings"
20
21	"android/soong/android"
22	"android/soong/genrule"
23
24	"github.com/google/blueprint"
25)
26
27func init() {
28	android.RegisterModuleType("clang_tblgen", clangTblgenFactory)
29}
30
31var (
32	pctx = android.NewPackageContext("android/soong/clang")
33
34	clangTblgen = pctx.HostBinToolVariable("clangTblgen", "clang-tblgen")
35
36	tblgenRule = pctx.StaticRule("tblgenRule", blueprint.RuleParams{
37		Depfile:     "${out}.d",
38		Deps:        blueprint.DepsGCC,
39		Command:     "${clangTblgen} ${includes} ${generator} -d ${depfile} -o ${out} ${in}",
40		CommandDeps: []string{"${clangTblgen}"},
41		Description: "Clang TableGen $in => $out",
42	}, "includes", "depfile", "generator")
43)
44
45type tblgenProperties struct {
46	In   string
47	Outs []string
48}
49
50type tblgen struct {
51	android.ModuleBase
52
53	properties tblgenProperties
54
55	exportedHeaderDirs android.Paths
56	generatedHeaders   android.Paths
57}
58
59var _ genrule.SourceFileGenerator = (*tblgen)(nil)
60
61func (t *tblgen) GenerateAndroidBuildActions(ctx android.ModuleContext) {
62	in := android.PathForModuleSrc(ctx, t.properties.In)
63
64	includes := []string{
65		"-I " + ctx.ModuleDir(),
66		"-I external/llvm/include",
67		"-I external/llvm/lib/Target",
68		"-I external/clang/include",
69		"-I " + filepath.Dir(in.String()),
70	}
71
72	for _, o := range t.properties.Outs {
73		out := android.PathForModuleGen(ctx, o)
74		generator := outToGenerator(ctx, o)
75
76		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
77			Rule:   tblgenRule,
78			Input:  in,
79			Output: out,
80			Args: map[string]string{
81				"includes":  strings.Join(includes, " "),
82				"generator": generator,
83			},
84		})
85		t.generatedHeaders = append(t.generatedHeaders, out)
86	}
87
88	t.exportedHeaderDirs = append(t.exportedHeaderDirs, android.PathForModuleGen(ctx, ""))
89}
90
91func outToGenerator(ctx android.ModuleContext, out string) string {
92	out = filepath.Base(out)
93	switch {
94	case out == "AttrDump.inc":
95		return "-gen-clang-attr-dump"
96	case out == "AttrImpl.inc":
97		return "-gen-clang-attr-impl"
98	case out == "AttrHasAttributeImpl.inc":
99		return "-gen-clang-attr-has-attribute-impl"
100	case out == "AttrList.inc":
101		return "-gen-clang-attr-list"
102	case out == "AttrSpellingListIndex.inc":
103		return "-gen-clang-attr-spelling-index"
104	case out == "AttrPCHRead.inc":
105		return "-gen-clang-attr-pch-read"
106	case out == "AttrPCHWrite.inc":
107		return "-gen-clang-attr-pch-write"
108	case out == "Attrs.inc":
109		return "-gen-clang-attr-classes"
110	case out == "AttrParserStringSwitches.inc":
111		return "-gen-clang-attr-parser-string-switches"
112	case out == "AttrVisitor.inc":
113		return "-gen-clang-attr-ast-visitor"
114	case out == "AttrParsedAttrKinds.inc":
115		return "-gen-clang-attr-parsed-attr-kinds"
116	case out == "AttrParsedAttrImpl.inc":
117		return "-gen-clang-attr-parsed-attr-impl"
118	case out == "AttrParsedAttrList.inc":
119		return "-gen-clang-attr-parsed-attr-list"
120	case out == "AttrTemplateInstantiate.inc":
121		return "-gen-clang-attr-template-instantiate"
122	case out == "Checkers.inc":
123		return "-gen-clang-sa-checkers"
124	case out == "CommentCommandInfo.inc":
125		return "-gen-clang-comment-command-info"
126	case out == "CommentCommandList.inc":
127		return "-gen-clang-comment-command-list"
128	case out == "CommentHTMLNamedCharacterReferences.inc":
129		return "-gen-clang-comment-html-named-character-references"
130	case out == "CommentHTMLTagsProperties.inc":
131		return "-gen-clang-comment-html-tags-properties"
132	case out == "CommentHTMLTags.inc":
133		return "-gen-clang-comment-html-tags"
134	case out == "CommentNodes.inc":
135		return "-gen-clang-comment-nodes"
136	case strings.HasPrefix(out, "Diagnostic") && strings.HasSuffix(out, "Kinds.inc"):
137		component := strings.TrimPrefix(strings.TrimSuffix(out, "Kinds.inc"), "Diagnostic")
138		return "-gen-clang-diags-defs -clang-component=" + component
139	case out == "DiagnosticGroups.inc":
140		return "-gen-clang-diag-groups"
141	case out == "DiagnosticIndexName.inc":
142		return "-gen-clang-diag-groups"
143	case out == "DeclNodes.inc":
144		return "-gen-clang-decl-nodes"
145	case out == "StmtNodes.inc":
146		return "-gen-clang-stmt-nodes"
147	case out == "arm_neon.inc":
148		return "-gen-arm-neon-sema"
149	case out == "arm_neon.h":
150		return "-gen-arm-neon"
151	}
152
153	ctx.ModuleErrorf("couldn't map output file %q to a generator", out)
154	return ""
155}
156
157func (t *tblgen) DepsMutator(ctx android.BottomUpMutatorContext) {
158}
159
160func (t *tblgen) GeneratedHeaderDirs() android.Paths {
161	return t.exportedHeaderDirs
162}
163
164func (t *tblgen) GeneratedSourceFiles() android.Paths {
165	return t.generatedHeaders
166}
167
168func clangTblgenFactory() (blueprint.Module, []interface{}) {
169	t := &tblgen{}
170
171	return android.InitAndroidModule(t, &t.properties)
172}
173