Add arch features

Allow architecture toolchains to register "features" supported by the
current variant, and then apply properties from the selected features.
Equivalent to the ARCH_*_HAS_* variables in the combo makefiles.

Change-Id: Ib6823be1c1a52da677d081db9f24336a072eaf39
diff --git a/common/arch.go b/common/arch.go
index 21f638a..3669e80 100644
--- a/common/arch.go
+++ b/common/arch.go
@@ -208,12 +208,34 @@
 	}
 }
 
+var archFeatureMap = map[ArchType]map[string][]string{}
+
+func RegisterArchFeatures(arch ArchType, variant string, features ...string) {
+	field := proptools.FieldNameForProperty(variant)
+	if variant != "" {
+		if !reflect.ValueOf(archProperties{}.Arch).FieldByName(field).IsValid() {
+			panic(fmt.Errorf("Invalid variant %q for arch %q", variant, arch))
+		}
+	}
+	for _, feature := range features {
+		field := proptools.FieldNameForProperty(feature)
+		if !reflect.ValueOf(archProperties{}.Arch).FieldByName(field).IsValid() {
+			panic(fmt.Errorf("Invalid feature %q for arch %q variant %q", feature, arch, variant))
+		}
+	}
+	if archFeatureMap[arch] == nil {
+		archFeatureMap[arch] = make(map[string][]string)
+	}
+	archFeatureMap[arch][variant] = features
+}
+
 // An Arch indicates a single CPU architecture.
 type Arch struct {
-	ArchType    ArchType
-	ArchVariant string
-	CpuVariant  string
-	Abi         []string
+	ArchType     ArchType
+	ArchVariant  string
+	CpuVariant   string
+	Abi          []string
+	ArchFeatures []string
 }
 
 func (a Arch) String() string {
@@ -516,6 +538,18 @@
 			a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
 		}
 
+		// Handle arch-feature-specific properties in the form:
+		// arch: {
+		//     feature: {
+		//         key: value,
+		//     },
+		// },
+		for _, feature := range arch.ArchFeatures {
+			field := proptools.FieldNameForProperty(feature)
+			prefix := "arch." + feature
+			a.appendProperties(ctx, genProps, archProps.Arch, field, prefix)
+		}
+
 		// Handle multilib-specific properties in the form:
 		// multilib: {
 		//     lib32: {
@@ -729,6 +763,10 @@
 		}
 	}
 
+	if featureMap, ok := archFeatureMap[archType]; ok {
+		a.ArchFeatures = featureMap[stringPtr(archVariant)]
+	}
+
 	return a, nil
 }