mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
C backend: implement support for simple cases of resources
This commit is contained in:
parent
ee2f389027
commit
4530167061
|
@ -15,17 +15,21 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.impl;
|
package org.teavm.classlib.impl;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.platform.metadata.*;
|
import org.teavm.platform.metadata.ClassScopedMetadataGenerator;
|
||||||
|
import org.teavm.platform.metadata.MetadataGeneratorContext;
|
||||||
|
import org.teavm.platform.metadata.Resource;
|
||||||
|
|
||||||
public class DeclaringClassMetadataGenerator implements ClassScopedMetadataGenerator {
|
public class DeclaringClassMetadataGenerator implements ClassScopedMetadataGenerator {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Resource> generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
public Map<String, Resource> generateMetadata(MetadataGeneratorContext context,
|
||||||
|
Collection<? extends String> classNames, MethodReference method) {
|
||||||
Map<String, Resource> result = new HashMap<>();
|
Map<String, Resource> result = new HashMap<>();
|
||||||
for (String clsName : context.getClassSource().getClassNames()) {
|
for (String clsName : classNames) {
|
||||||
ClassReader cls = context.getClassSource().get(clsName);
|
ClassReader cls = context.getClassSource().get(clsName);
|
||||||
if (cls.getOwnerName() != null) {
|
if (cls.getOwnerName() != null) {
|
||||||
result.put(clsName, context.createClassResource(cls.getOwnerName()));
|
result.put(clsName, context.createClassResource(cls.getOwnerName()));
|
||||||
|
|
|
@ -47,6 +47,7 @@ import org.teavm.backend.c.intrinsic.ExceptionHandlingIntrinsic;
|
||||||
import org.teavm.backend.c.intrinsic.FunctionIntrinsic;
|
import org.teavm.backend.c.intrinsic.FunctionIntrinsic;
|
||||||
import org.teavm.backend.c.intrinsic.GCIntrinsic;
|
import org.teavm.backend.c.intrinsic.GCIntrinsic;
|
||||||
import org.teavm.backend.c.intrinsic.Intrinsic;
|
import org.teavm.backend.c.intrinsic.Intrinsic;
|
||||||
|
import org.teavm.backend.c.intrinsic.IntrinsicFactory;
|
||||||
import org.teavm.backend.c.intrinsic.MutatorIntrinsic;
|
import org.teavm.backend.c.intrinsic.MutatorIntrinsic;
|
||||||
import org.teavm.backend.c.intrinsic.PlatformClassIntrinsic;
|
import org.teavm.backend.c.intrinsic.PlatformClassIntrinsic;
|
||||||
import org.teavm.backend.c.intrinsic.PlatformClassMetadataIntrinsic;
|
import org.teavm.backend.c.intrinsic.PlatformClassMetadataIntrinsic;
|
||||||
|
@ -100,7 +101,7 @@ import org.teavm.vm.TeaVMTarget;
|
||||||
import org.teavm.vm.TeaVMTargetController;
|
import org.teavm.vm.TeaVMTargetController;
|
||||||
import org.teavm.vm.spi.TeaVMHostExtension;
|
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||||
|
|
||||||
public class CTarget implements TeaVMTarget {
|
public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||||
private TeaVMTargetController controller;
|
private TeaVMTargetController controller;
|
||||||
private ClassInitializerInsertionTransformer clinitInsertionTransformer;
|
private ClassInitializerInsertionTransformer clinitInsertionTransformer;
|
||||||
private ClassInitializerEliminator classInitializerEliminator;
|
private ClassInitializerEliminator classInitializerEliminator;
|
||||||
|
@ -110,6 +111,7 @@ public class CTarget implements TeaVMTarget {
|
||||||
private NullCheckTransformation nullCheckTransformation;
|
private NullCheckTransformation nullCheckTransformation;
|
||||||
private ExportDependencyListener exportDependencyListener = new ExportDependencyListener();
|
private ExportDependencyListener exportDependencyListener = new ExportDependencyListener();
|
||||||
private int minHeapSize = 32 * 1024 * 1024;
|
private int minHeapSize = 32 * 1024 * 1024;
|
||||||
|
private List<IntrinsicFactory> intrinsicFactories = new ArrayList<>();
|
||||||
|
|
||||||
public void setMinHeapSize(int minHeapSize) {
|
public void setMinHeapSize(int minHeapSize) {
|
||||||
this.minHeapSize = minHeapSize;
|
this.minHeapSize = minHeapSize;
|
||||||
|
@ -142,7 +144,12 @@ public class CTarget implements TeaVMTarget {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<TeaVMHostExtension> getHostExtensions() {
|
public List<TeaVMHostExtension> getHostExtensions() {
|
||||||
return Collections.emptyList();
|
return Collections.singletonList(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addIntrinsic(IntrinsicFactory intrinsicFactory) {
|
||||||
|
intrinsicFactories.add(intrinsicFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -236,6 +243,13 @@ public class CTarget implements TeaVMTarget {
|
||||||
|
|
||||||
ClassGenerator classGenerator = new ClassGenerator(context, controller.getUnprocessedClassSource(),
|
ClassGenerator classGenerator = new ClassGenerator(context, controller.getUnprocessedClassSource(),
|
||||||
tagRegistry, decompiler, codeWriter);
|
tagRegistry, decompiler, codeWriter);
|
||||||
|
IntrinsicFactoryContextImpl intrinsicFactoryContext = new IntrinsicFactoryContextImpl(
|
||||||
|
classGenerator.getStructuresWriter(), classGenerator.getPreCodeWriter(),
|
||||||
|
controller.getUnprocessedClassSource(), controller.getClassLoader(), controller.getServices(),
|
||||||
|
controller.getProperties());
|
||||||
|
for (IntrinsicFactory intrinsicFactory : intrinsicFactories) {
|
||||||
|
context.addIntrinsic(intrinsicFactory.createIntrinsic(intrinsicFactoryContext));
|
||||||
|
}
|
||||||
|
|
||||||
generateClasses(classes, classGenerator);
|
generateClasses(classes, classGenerator);
|
||||||
generateSpecialFunctions(context, codeWriter);
|
generateSpecialFunctions(context, codeWriter);
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.c;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.teavm.backend.c.generate.CodeWriter;
|
||||||
|
import org.teavm.backend.c.intrinsic.IntrinsicFactoryContext;
|
||||||
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
|
||||||
|
class IntrinsicFactoryContextImpl implements IntrinsicFactoryContext {
|
||||||
|
private CodeWriter structureCodeWriter;
|
||||||
|
private CodeWriter staticFieldsInitWriter;
|
||||||
|
private ClassReaderSource classSource;
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
private ServiceRepository services;
|
||||||
|
private Properties properties;
|
||||||
|
|
||||||
|
IntrinsicFactoryContextImpl(CodeWriter structureCodeWriter, CodeWriter staticFieldsInitWriter,
|
||||||
|
ClassReaderSource classSource, ClassLoader classLoader, ServiceRepository services,
|
||||||
|
Properties properties) {
|
||||||
|
this.structureCodeWriter = structureCodeWriter;
|
||||||
|
this.staticFieldsInitWriter = staticFieldsInitWriter;
|
||||||
|
this.classSource = classSource;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
this.services = services;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeWriter getStructureCodeWriter() {
|
||||||
|
return structureCodeWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CodeWriter getStaticFieldsInitWriter() {
|
||||||
|
return staticFieldsInitWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassReaderSource getClassSource() {
|
||||||
|
return classSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClassLoader getClassLoader() {
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServiceRepository getServices() {
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Properties getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,5 +15,9 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.c;
|
package org.teavm.backend.c;
|
||||||
|
|
||||||
public class TeaVMCHost {
|
import org.teavm.backend.c.intrinsic.IntrinsicFactory;
|
||||||
|
import org.teavm.vm.spi.TeaVMHostExtension;
|
||||||
|
|
||||||
|
public interface TeaVMCHost extends TeaVMHostExtension {
|
||||||
|
void addIntrinsic(IntrinsicFactory intrinsicFactory);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ public class ClassGenerator {
|
||||||
private CodeWriter isSupertypeWriter;
|
private CodeWriter isSupertypeWriter;
|
||||||
private CodeWriter staticGcRootsWriter;
|
private CodeWriter staticGcRootsWriter;
|
||||||
private CodeWriter callSiteWriter;
|
private CodeWriter callSiteWriter;
|
||||||
|
private CodeWriter preCodeWriter;
|
||||||
private CodeWriter codeWriter;
|
private CodeWriter codeWriter;
|
||||||
private CodeWriter staticFieldInitWriter;
|
private CodeWriter staticFieldInitWriter;
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ public class ClassGenerator {
|
||||||
isSupertypeWriter = writer.fragment();
|
isSupertypeWriter = writer.fragment();
|
||||||
staticGcRootsWriter = writer.fragment();
|
staticGcRootsWriter = writer.fragment();
|
||||||
callSiteWriter = writer.fragment();
|
callSiteWriter = writer.fragment();
|
||||||
|
preCodeWriter = writer.fragment();
|
||||||
codeWriter = writer.fragment();
|
codeWriter = writer.fragment();
|
||||||
|
|
||||||
writer.println("static void initStaticFields() {").indent();
|
writer.println("static void initStaticFields() {").indent();
|
||||||
|
@ -104,6 +106,14 @@ public class ClassGenerator {
|
||||||
codeGenerator = new CodeGenerator(context, codeWriter, includes);
|
codeGenerator = new CodeGenerator(context, codeWriter, includes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CodeWriter getPreCodeWriter() {
|
||||||
|
return preCodeWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CodeWriter getStructuresWriter() {
|
||||||
|
return structuresWriter;
|
||||||
|
}
|
||||||
|
|
||||||
public void generateClass(ClassHolder cls) {
|
public void generateClass(ClassHolder cls) {
|
||||||
generateClassStructure(cls);
|
generateClassStructure(cls);
|
||||||
generateClassMethods(cls);
|
generateClassMethods(cls);
|
||||||
|
|
|
@ -693,5 +693,10 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
||||||
public MethodReference getCallingMethod() {
|
public MethodReference getCallingMethod() {
|
||||||
return callingMethod;
|
return callingMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StringPool getStringPool() {
|
||||||
|
return context.getStringPool();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,10 @@ public class GenerationContext {
|
||||||
this.generators = new ArrayList<>(generators);
|
this.generators = new ArrayList<>(generators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addIntrinsic(Intrinsic intrinsic) {
|
||||||
|
intrinsics.add(intrinsic);
|
||||||
|
}
|
||||||
|
|
||||||
public VirtualTableProvider getVirtualTableProvider() {
|
public VirtualTableProvider getVirtualTableProvider() {
|
||||||
return virtualTableProvider;
|
return virtualTableProvider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.backend.c.intrinsic;
|
||||||
import org.teavm.ast.Expr;
|
import org.teavm.ast.Expr;
|
||||||
import org.teavm.backend.c.generate.CodeWriter;
|
import org.teavm.backend.c.generate.CodeWriter;
|
||||||
import org.teavm.backend.c.generate.NameProvider;
|
import org.teavm.backend.c.generate.NameProvider;
|
||||||
|
import org.teavm.backend.c.generate.StringPool;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
@ -31,4 +32,6 @@ public interface IntrinsicContext {
|
||||||
Diagnostics getDiagnotics();
|
Diagnostics getDiagnotics();
|
||||||
|
|
||||||
MethodReference getCallingMethod();
|
MethodReference getCallingMethod();
|
||||||
|
|
||||||
|
StringPool getStringPool();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.c.intrinsic;
|
||||||
|
|
||||||
|
public interface IntrinsicFactory {
|
||||||
|
Intrinsic createIntrinsic(IntrinsicFactoryContext context);
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.backend.c.intrinsic;
|
||||||
|
|
||||||
|
import java.util.Properties;
|
||||||
|
import org.teavm.backend.c.generate.CodeWriter;
|
||||||
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
|
||||||
|
public interface IntrinsicFactoryContext {
|
||||||
|
CodeWriter getStructureCodeWriter();
|
||||||
|
|
||||||
|
CodeWriter getStaticFieldsInitWriter();
|
||||||
|
|
||||||
|
ClassReaderSource getClassSource();
|
||||||
|
|
||||||
|
ClassLoader getClassLoader();
|
||||||
|
|
||||||
|
ServiceRepository getServices();
|
||||||
|
|
||||||
|
Properties getProperties();
|
||||||
|
}
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.metadata;
|
package org.teavm.platform.metadata;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.platform.PlatformClass;
|
import org.teavm.platform.PlatformClass;
|
||||||
|
@ -23,7 +24,7 @@ import org.teavm.platform.PlatformClass;
|
||||||
* <p>Behaviour of this class is similar to {@link MetadataGenerator}. The difference is that method, marked with
|
* <p>Behaviour of this class is similar to {@link MetadataGenerator}. The difference is that method, marked with
|
||||||
* {@link ClassScopedMetadataProvider} must take one argument of type {@link PlatformClass}. It will
|
* {@link ClassScopedMetadataProvider} must take one argument of type {@link PlatformClass}. It will
|
||||||
* return different resource for each given class, corresponding to map entries, produced by
|
* return different resource for each given class, corresponding to map entries, produced by
|
||||||
* {@link #generateMetadata(MetadataGeneratorContext, MethodReference)}.
|
* {@link #generateMetadata(MetadataGeneratorContext, Collection, MethodReference)}.
|
||||||
*
|
*
|
||||||
* @see ClassScopedMetadataProvider
|
* @see ClassScopedMetadataProvider
|
||||||
* @see MetadataGenerator
|
* @see MetadataGenerator
|
||||||
|
@ -31,5 +32,6 @@ import org.teavm.platform.PlatformClass;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface ClassScopedMetadataGenerator {
|
public interface ClassScopedMetadataGenerator {
|
||||||
Map<String, Resource> generateMetadata(MetadataGeneratorContext context, MethodReference method);
|
Map<String, Resource> generateMetadata(MetadataGeneratorContext context, Collection<? extends String> classNames,
|
||||||
|
MethodReference method);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,10 @@ package org.teavm.platform.metadata;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
|
||||||
import org.teavm.platform.Platform;
|
import org.teavm.platform.Platform;
|
||||||
|
import org.teavm.platform.plugin.ResourceTypeDescriptor;
|
||||||
import org.teavm.vm.TeaVM;
|
import org.teavm.vm.TeaVM;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,7 +35,7 @@ public interface MetadataGeneratorContext extends ServiceRepository {
|
||||||
*
|
*
|
||||||
* @return class source.
|
* @return class source.
|
||||||
*/
|
*/
|
||||||
ListableClassReaderSource getClassSource();
|
ClassReaderSource getClassSource();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the class loader that is used by the compiler.
|
* Gets the class loader that is used by the compiler.
|
||||||
|
@ -89,4 +90,6 @@ public interface MetadataGeneratorContext extends ServiceRepository {
|
||||||
* @return a new resource.
|
* @return a new resource.
|
||||||
*/
|
*/
|
||||||
<T extends Resource> ResourceMap<T> createResourceMap();
|
<T extends Resource> ResourceMap<T> createResourceMap();
|
||||||
|
|
||||||
|
ResourceTypeDescriptor getTypeDescriptor(Class<? extends Resource> type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,11 @@ class BuildTimeResourceProxyBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public BuildTimeResourceProxy buildProxy(Class<?> iface) {
|
public BuildTimeResourceProxy buildProxy(Class<?> iface) {
|
||||||
return factories.computeIfAbsent(iface, k -> createFactory(iface)).create();
|
return getProxyFactory(iface).create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildTimeResourceProxyFactory getProxyFactory(Class<?> iface) {
|
||||||
|
return factories.computeIfAbsent(iface, k -> createFactory(iface));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BuildTimeResourceProxyFactory createFactory(Class<?> iface) {
|
private BuildTimeResourceProxyFactory createFactory(Class<?> iface) {
|
||||||
|
@ -103,7 +107,7 @@ class BuildTimeResourceProxyBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BuildTimeResourceProxyFactory(methods, initialData);
|
return new BuildTimeResourceProxyFactory(methods, initialData, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getPropertyIndex(String propertyName) {
|
private int getPropertyIndex(String propertyName) {
|
||||||
|
|
|
@ -16,16 +16,18 @@
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
class BuildTimeResourceProxyFactory {
|
class BuildTimeResourceProxyFactory {
|
||||||
private Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
private Map<Method, BuildTimeResourceMethod> methods;
|
||||||
private Object[] initialData;
|
private Object[] initialData;
|
||||||
|
ResourceTypeDescriptor typeDescriptor;
|
||||||
|
|
||||||
public BuildTimeResourceProxyFactory(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData) {
|
public BuildTimeResourceProxyFactory(Map<Method, BuildTimeResourceMethod> methods, Object[] initialData,
|
||||||
|
ResourceTypeDescriptor typeDescriptor) {
|
||||||
this.methods = methods;
|
this.methods = methods;
|
||||||
this.initialData = initialData;
|
this.initialData = initialData;
|
||||||
|
this.typeDescriptor = typeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
BuildTimeResourceProxy create() {
|
BuildTimeResourceProxy create() {
|
||||||
|
|
|
@ -81,7 +81,8 @@ public class ClassScopedMetadataProviderNativeGenerator implements Generator {
|
||||||
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
||||||
context.getClassLoader(), context.getProperties(), context);
|
context.getClassLoader(), context.getProperties(), context);
|
||||||
|
|
||||||
Map<String, Resource> resourceMap = generator.generateMetadata(metadataContext, methodRef);
|
Map<String, Resource> resourceMap = generator.generateMetadata(metadataContext,
|
||||||
|
context.getClassSource().getClassNames(), methodRef);
|
||||||
writer.append("var p").ws().append("=").ws().append("\"" + RenderingUtil.escapeString("$$res_"
|
writer.append("var p").ws().append("=").ws().append("\"" + RenderingUtil.escapeString("$$res_"
|
||||||
+ writer.getNaming().getFullNameFor(methodRef)) + "\"").append(";").softNewLine();
|
+ writer.getNaming().getFullNameFor(methodRef)) + "\"").append(";").softNewLine();
|
||||||
for (Map.Entry<String, Resource> entry : resourceMap.entrySet()) {
|
for (Map.Entry<String, Resource> entry : resourceMap.entrySet()) {
|
||||||
|
|
|
@ -18,18 +18,23 @@ package org.teavm.platform.plugin;
|
||||||
import java.lang.reflect.Proxy;
|
import java.lang.reflect.Proxy;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.ListableClassReaderSource;
|
import org.teavm.platform.metadata.ClassResource;
|
||||||
import org.teavm.platform.metadata.*;
|
import org.teavm.platform.metadata.MetadataGeneratorContext;
|
||||||
|
import org.teavm.platform.metadata.Resource;
|
||||||
|
import org.teavm.platform.metadata.ResourceArray;
|
||||||
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
import org.teavm.platform.metadata.StaticFieldResource;
|
||||||
|
|
||||||
class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
private ListableClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private ClassLoader classLoader;
|
private ClassLoader classLoader;
|
||||||
private Properties properties;
|
private Properties properties;
|
||||||
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
||||||
private ServiceRepository services;
|
private ServiceRepository services;
|
||||||
|
|
||||||
DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
DefaultMetadataGeneratorContext(ClassReaderSource classSource, ClassLoader classLoader,
|
||||||
Properties properties, ServiceRepository services) {
|
Properties properties, ServiceRepository services) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.classLoader = classLoader;
|
this.classLoader = classLoader;
|
||||||
|
@ -38,7 +43,7 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListableClassReaderSource getClassSource() {
|
public ClassReaderSource getClassSource() {
|
||||||
return classSource;
|
return classSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +64,11 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
||||||
proxyBuilder.buildProxy(resourceType)));
|
proxyBuilder.buildProxy(resourceType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResourceTypeDescriptor getTypeDescriptor(Class<? extends Resource> type) {
|
||||||
|
return proxyBuilder.getProxyFactory(type).typeDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends Resource> ResourceArray<T> createResourceArray() {
|
public <T extends Resource> ResourceArray<T> createResourceArray() {
|
||||||
return new BuildTimeResourceArray<>();
|
return new BuildTimeResourceArray<>();
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.teavm.ast.InvocationExpr;
|
||||||
|
import org.teavm.backend.c.generate.CodeWriter;
|
||||||
|
import org.teavm.backend.c.intrinsic.Intrinsic;
|
||||||
|
import org.teavm.backend.c.intrinsic.IntrinsicContext;
|
||||||
|
import org.teavm.common.ServiceRepository;
|
||||||
|
import org.teavm.model.CallLocation;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodReader;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.platform.metadata.MetadataGenerator;
|
||||||
|
import org.teavm.platform.metadata.MetadataProvider;
|
||||||
|
import org.teavm.platform.metadata.Resource;
|
||||||
|
|
||||||
|
public class MetadataCIntrinsic implements Intrinsic {
|
||||||
|
private ClassReaderSource classSource;
|
||||||
|
private ClassLoader classLoader;
|
||||||
|
private Set<String> writtenStructures = new HashSet<>();
|
||||||
|
private Set<MethodReference> writtenInitializers = new HashSet<>();
|
||||||
|
private CodeWriter structuresWriter;
|
||||||
|
private CodeWriter staticFieldInitWriter;
|
||||||
|
private DefaultMetadataGeneratorContext metadataContext;
|
||||||
|
|
||||||
|
public MetadataCIntrinsic(ClassReaderSource classSource, ClassLoader classLoader,
|
||||||
|
ServiceRepository services, Properties properties, CodeWriter structuresWriter,
|
||||||
|
CodeWriter staticFieldInitWriter) {
|
||||||
|
this.classSource = classSource;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
this.structuresWriter = structuresWriter;
|
||||||
|
this.staticFieldInitWriter = staticFieldInitWriter;
|
||||||
|
metadataContext = new DefaultMetadataGeneratorContext(classSource, classLoader, properties, services);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(MethodReference methodReference) {
|
||||||
|
MethodReader method = classSource.resolve(methodReference);
|
||||||
|
if (method == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return method.getAnnotations().get(MetadataProvider.class.getName()) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(IntrinsicContext context, InvocationExpr invocation) {
|
||||||
|
writeInitializer(context, invocation);
|
||||||
|
context.writer().print(context.names().forMethod(invocation.getMethod()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeInitializer(IntrinsicContext context, InvocationExpr invocation) {
|
||||||
|
MethodReference methodReference = invocation.getMethod();
|
||||||
|
if (!writtenInitializers.add(methodReference)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodReader method = classSource.resolve(methodReference);
|
||||||
|
MetadataGenerator generator = MetadataUtils.createMetadataGenerator(classLoader, method,
|
||||||
|
new CallLocation(invocation.getMethod()), context.getDiagnotics());
|
||||||
|
|
||||||
|
String variableName = context.names().forMethod(methodReference);
|
||||||
|
staticFieldInitWriter.print("static ").printType(method.getResultType()).print(" ")
|
||||||
|
.print(variableName).print(" = ");
|
||||||
|
if (generator == null) {
|
||||||
|
staticFieldInitWriter.print("NULL");
|
||||||
|
} else {
|
||||||
|
Resource resource = generator.generateMetadata(metadataContext, invocation.getMethod());
|
||||||
|
writeValue(context, resource);
|
||||||
|
}
|
||||||
|
staticFieldInitWriter.println(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeValue(IntrinsicContext context, Object value) {
|
||||||
|
if (value instanceof String) {
|
||||||
|
int stringIndex = context.getStringPool().getStringIndex((String) value);
|
||||||
|
staticFieldInitWriter.print("(stringPool + " + stringIndex + ")");
|
||||||
|
} else if (value instanceof ResourceTypeDescriptorProvider && value instanceof Resource) {
|
||||||
|
writeResource(context, (ResourceTypeDescriptorProvider) value);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Don't know how to write resource: " + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeResource(IntrinsicContext context, ResourceTypeDescriptorProvider resourceType) {
|
||||||
|
writeResourceStructure(context, resourceType.getDescriptor());
|
||||||
|
|
||||||
|
String structureName = context.names().forClass(resourceType.getDescriptor().getRootInterface().getName());
|
||||||
|
Object[] propertyValues = resourceType.getValues();
|
||||||
|
staticFieldInitWriter.print("&(" + structureName + ") {").indent();
|
||||||
|
boolean first = true;
|
||||||
|
for (String propertyName : resourceType.getDescriptor().getPropertyTypes().keySet()) {
|
||||||
|
if (!first) {
|
||||||
|
staticFieldInitWriter.print(",");
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
staticFieldInitWriter.println().print(".").print(propertyName).print(" = ");
|
||||||
|
int index = resourceType.getPropertyIndex(propertyName);
|
||||||
|
Object propertyValue = propertyValues[index];
|
||||||
|
writeValue(context, propertyValue);
|
||||||
|
}
|
||||||
|
staticFieldInitWriter.println().outdent().print("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeResourceStructure(IntrinsicContext context, ResourceTypeDescriptor structure) {
|
||||||
|
String className = structure.getRootInterface().getName();
|
||||||
|
if (!writtenStructures.add(className)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Class<?> propertyType : structure.getPropertyTypes().values()) {
|
||||||
|
if (Resource.class.isAssignableFrom(propertyType)) {
|
||||||
|
ResourceTypeDescriptor propertyStructure = metadataContext.getTypeDescriptor(
|
||||||
|
propertyType.asSubclass(Resource.class));
|
||||||
|
writeResourceStructure(context, propertyStructure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String structureName = context.names().forClass(className);
|
||||||
|
structuresWriter.println("typedef struct " + structureName + " {").indent();
|
||||||
|
|
||||||
|
for (String propertyName : structure.getPropertyTypes().keySet()) {
|
||||||
|
Class<?> propertyType = structure.getPropertyTypes().get(propertyName);
|
||||||
|
structuresWriter.println(typeToString(context, propertyType) + " " + propertyName + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
structuresWriter.outdent().println("} " + structureName + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String typeToString(IntrinsicContext context, Class<?> cls) {
|
||||||
|
if (cls == boolean.class || cls == byte.class) {
|
||||||
|
return "int8_t";
|
||||||
|
} else if (cls == short.class || cls == char.class) {
|
||||||
|
return "int16_t";
|
||||||
|
} else if (cls == int.class) {
|
||||||
|
return "int32_t";
|
||||||
|
} else if (cls == float.class) {
|
||||||
|
return "float";
|
||||||
|
} else if (cls == long.class) {
|
||||||
|
return "int64_t";
|
||||||
|
} else if (cls == double.class) {
|
||||||
|
return "double";
|
||||||
|
} else if (Resource.class.isAssignableFrom(cls)) {
|
||||||
|
return "&" + context.names().forClass(cls.getName());
|
||||||
|
} else if (cls == String.class) {
|
||||||
|
return "JavaObject*";
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Don't know how to write resource type " + cls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class MethodContext {
|
||||||
|
String baseName;
|
||||||
|
int suffix;
|
||||||
|
|
||||||
|
MethodContext(String baseName) {
|
||||||
|
this.baseName = baseName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,6 +16,9 @@
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
import org.teavm.ast.InvocationExpr;
|
import org.teavm.ast.InvocationExpr;
|
||||||
|
import org.teavm.backend.c.TeaVMCHost;
|
||||||
|
import org.teavm.backend.c.intrinsic.Intrinsic;
|
||||||
|
import org.teavm.backend.c.intrinsic.IntrinsicContext;
|
||||||
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
import org.teavm.backend.javascript.TeaVMJavaScriptHost;
|
||||||
import org.teavm.backend.wasm.TeaVMWasmHost;
|
import org.teavm.backend.wasm.TeaVMWasmHost;
|
||||||
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
|
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
|
||||||
|
@ -75,6 +78,25 @@ public class PlatformPlugin implements TeaVMPlugin {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TeaVMCHost cHost = host.getExtension(TeaVMCHost.class);
|
||||||
|
if (cHost != null) {
|
||||||
|
cHost.addIntrinsic(ctx -> new MetadataCIntrinsic(ctx.getClassSource(), ctx.getClassLoader(),
|
||||||
|
ctx.getServices(), ctx.getProperties(), ctx.getStructureCodeWriter(),
|
||||||
|
ctx.getStaticFieldsInitWriter()));
|
||||||
|
cHost.addIntrinsic(ctx -> new ResourceReadCIntrinsic(ctx.getClassSource()));
|
||||||
|
cHost.addIntrinsic(ctx -> new Intrinsic() {
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(MethodReference method) {
|
||||||
|
return method.getClassName().equals(StringAmplifier.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(IntrinsicContext context, InvocationExpr invocation) {
|
||||||
|
context.emit(invocation.getArguments().get(0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
host.add(new AsyncMethodProcessor());
|
host.add(new AsyncMethodProcessor());
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.ast.InvocationExpr;
|
||||||
|
import org.teavm.backend.c.intrinsic.Intrinsic;
|
||||||
|
import org.teavm.backend.c.intrinsic.IntrinsicContext;
|
||||||
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.platform.metadata.Resource;
|
||||||
|
|
||||||
|
public class ResourceReadCIntrinsic implements Intrinsic {
|
||||||
|
private ClassReaderSource classSource;
|
||||||
|
|
||||||
|
public ResourceReadCIntrinsic(ClassReaderSource classSource) {
|
||||||
|
this.classSource = classSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canHandle(MethodReference method) {
|
||||||
|
return classSource.isSuperType(Resource.class.getTypeName(), method.getClassName()).orElse(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(IntrinsicContext context, InvocationExpr invocation) {
|
||||||
|
String name = invocation.getMethod().getName();
|
||||||
|
if (name.startsWith("get")) {
|
||||||
|
name = name.substring(3);
|
||||||
|
} else if (name.startsWith("is")) {
|
||||||
|
name = name.substring(2);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
name = Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
||||||
|
|
||||||
|
context.writer().print("FIELD(");
|
||||||
|
context.emit(invocation.getArguments().get(0));
|
||||||
|
context.writer().print(", ").print(context.names().forClass(invocation.getMethod().getClassName()));
|
||||||
|
context.writer().print(", ").print(name).print(")");
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,11 +16,13 @@
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
|
import org.teavm.interop.Unmanaged;
|
||||||
|
|
||||||
final class StringAmplifier {
|
final class StringAmplifier {
|
||||||
private StringAmplifier() {
|
private StringAmplifier() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@PluggableDependency(StringAmplifierDependencyPlugin.class)
|
@PluggableDependency(StringAmplifierDependencyPlugin.class)
|
||||||
|
@Unmanaged
|
||||||
static native String amplify(String string);
|
static native String amplify(String string);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user