mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.ClassReader;
|
||||
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 {
|
||||
@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<>();
|
||||
for (String clsName : context.getClassSource().getClassNames()) {
|
||||
for (String clsName : classNames) {
|
||||
ClassReader cls = context.getClassSource().get(clsName);
|
||||
if (cls.getOwnerName() != null) {
|
||||
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.GCIntrinsic;
|
||||
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.PlatformClassIntrinsic;
|
||||
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.spi.TeaVMHostExtension;
|
||||
|
||||
public class CTarget implements TeaVMTarget {
|
||||
public class CTarget implements TeaVMTarget, TeaVMCHost {
|
||||
private TeaVMTargetController controller;
|
||||
private ClassInitializerInsertionTransformer clinitInsertionTransformer;
|
||||
private ClassInitializerEliminator classInitializerEliminator;
|
||||
|
@ -110,6 +111,7 @@ public class CTarget implements TeaVMTarget {
|
|||
private NullCheckTransformation nullCheckTransformation;
|
||||
private ExportDependencyListener exportDependencyListener = new ExportDependencyListener();
|
||||
private int minHeapSize = 32 * 1024 * 1024;
|
||||
private List<IntrinsicFactory> intrinsicFactories = new ArrayList<>();
|
||||
|
||||
public void setMinHeapSize(int minHeapSize) {
|
||||
this.minHeapSize = minHeapSize;
|
||||
|
@ -142,7 +144,12 @@ public class CTarget implements TeaVMTarget {
|
|||
|
||||
@Override
|
||||
public List<TeaVMHostExtension> getHostExtensions() {
|
||||
return Collections.emptyList();
|
||||
return Collections.singletonList(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIntrinsic(IntrinsicFactory intrinsicFactory) {
|
||||
intrinsicFactories.add(intrinsicFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -236,6 +243,13 @@ public class CTarget implements TeaVMTarget {
|
|||
|
||||
ClassGenerator classGenerator = new ClassGenerator(context, controller.getUnprocessedClassSource(),
|
||||
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);
|
||||
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;
|
||||
|
||||
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 staticGcRootsWriter;
|
||||
private CodeWriter callSiteWriter;
|
||||
private CodeWriter preCodeWriter;
|
||||
private CodeWriter codeWriter;
|
||||
private CodeWriter staticFieldInitWriter;
|
||||
|
||||
|
@ -95,6 +96,7 @@ public class ClassGenerator {
|
|||
isSupertypeWriter = writer.fragment();
|
||||
staticGcRootsWriter = writer.fragment();
|
||||
callSiteWriter = writer.fragment();
|
||||
preCodeWriter = writer.fragment();
|
||||
codeWriter = writer.fragment();
|
||||
|
||||
writer.println("static void initStaticFields() {").indent();
|
||||
|
@ -104,6 +106,14 @@ public class ClassGenerator {
|
|||
codeGenerator = new CodeGenerator(context, codeWriter, includes);
|
||||
}
|
||||
|
||||
public CodeWriter getPreCodeWriter() {
|
||||
return preCodeWriter;
|
||||
}
|
||||
|
||||
public CodeWriter getStructuresWriter() {
|
||||
return structuresWriter;
|
||||
}
|
||||
|
||||
public void generateClass(ClassHolder cls) {
|
||||
generateClassStructure(cls);
|
||||
generateClassMethods(cls);
|
||||
|
|
|
@ -693,5 +693,10 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
|
|||
public MethodReference getCallingMethod() {
|
||||
return callingMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringPool getStringPool() {
|
||||
return context.getStringPool();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,6 +51,10 @@ public class GenerationContext {
|
|||
this.generators = new ArrayList<>(generators);
|
||||
}
|
||||
|
||||
public void addIntrinsic(Intrinsic intrinsic) {
|
||||
intrinsics.add(intrinsic);
|
||||
}
|
||||
|
||||
public VirtualTableProvider getVirtualTableProvider() {
|
||||
return virtualTableProvider;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.backend.c.intrinsic;
|
|||
import org.teavm.ast.Expr;
|
||||
import org.teavm.backend.c.generate.CodeWriter;
|
||||
import org.teavm.backend.c.generate.NameProvider;
|
||||
import org.teavm.backend.c.generate.StringPool;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
|
@ -31,4 +32,6 @@ public interface IntrinsicContext {
|
|||
Diagnostics getDiagnotics();
|
||||
|
||||
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;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.MethodReference;
|
||||
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
|
||||
* {@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
|
||||
* {@link #generateMetadata(MetadataGeneratorContext, MethodReference)}.
|
||||
* {@link #generateMetadata(MetadataGeneratorContext, Collection, MethodReference)}.
|
||||
*
|
||||
* @see ClassScopedMetadataProvider
|
||||
* @see MetadataGenerator
|
||||
|
@ -31,5 +32,6 @@ import org.teavm.platform.PlatformClass;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
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 org.teavm.common.ServiceRepository;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.platform.Platform;
|
||||
import org.teavm.platform.plugin.ResourceTypeDescriptor;
|
||||
import org.teavm.vm.TeaVM;
|
||||
|
||||
/**
|
||||
|
@ -34,7 +35,7 @@ public interface MetadataGeneratorContext extends ServiceRepository {
|
|||
*
|
||||
* @return class source.
|
||||
*/
|
||||
ListableClassReaderSource getClassSource();
|
||||
ClassReaderSource getClassSource();
|
||||
|
||||
/**
|
||||
* Gets the class loader that is used by the compiler.
|
||||
|
@ -89,4 +90,6 @@ public interface MetadataGeneratorContext extends ServiceRepository {
|
|||
* @return a new resource.
|
||||
*/
|
||||
<T extends Resource> ResourceMap<T> createResourceMap();
|
||||
|
||||
ResourceTypeDescriptor getTypeDescriptor(Class<? extends Resource> type);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,11 @@ class BuildTimeResourceProxyBuilder {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -103,7 +107,7 @@ class BuildTimeResourceProxyBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
return new BuildTimeResourceProxyFactory(methods, initialData);
|
||||
return new BuildTimeResourceProxyFactory(methods, initialData, descriptor);
|
||||
}
|
||||
|
||||
private int getPropertyIndex(String propertyName) {
|
||||
|
|
|
@ -16,16 +16,18 @@
|
|||
package org.teavm.platform.plugin;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class BuildTimeResourceProxyFactory {
|
||||
private Map<Method, BuildTimeResourceMethod> methods = new HashMap<>();
|
||||
private Map<Method, BuildTimeResourceMethod> methods;
|
||||
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.initialData = initialData;
|
||||
this.typeDescriptor = typeDescriptor;
|
||||
}
|
||||
|
||||
BuildTimeResourceProxy create() {
|
||||
|
|
|
@ -81,7 +81,8 @@ public class ClassScopedMetadataProviderNativeGenerator implements Generator {
|
|||
DefaultMetadataGeneratorContext metadataContext = new DefaultMetadataGeneratorContext(context.getClassSource(),
|
||||
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.getNaming().getFullNameFor(methodRef)) + "\"").append(";").softNewLine();
|
||||
for (Map.Entry<String, Resource> entry : resourceMap.entrySet()) {
|
||||
|
|
|
@ -18,18 +18,23 @@ package org.teavm.platform.plugin;
|
|||
import java.lang.reflect.Proxy;
|
||||
import java.util.Properties;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.platform.metadata.*;
|
||||
import org.teavm.platform.metadata.ClassResource;
|
||||
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 {
|
||||
private ListableClassReaderSource classSource;
|
||||
private ClassReaderSource classSource;
|
||||
private ClassLoader classLoader;
|
||||
private Properties properties;
|
||||
private BuildTimeResourceProxyBuilder proxyBuilder = new BuildTimeResourceProxyBuilder();
|
||||
private ServiceRepository services;
|
||||
|
||||
DefaultMetadataGeneratorContext(ListableClassReaderSource classSource, ClassLoader classLoader,
|
||||
DefaultMetadataGeneratorContext(ClassReaderSource classSource, ClassLoader classLoader,
|
||||
Properties properties, ServiceRepository services) {
|
||||
this.classSource = classSource;
|
||||
this.classLoader = classLoader;
|
||||
|
@ -38,7 +43,7 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ListableClassReaderSource getClassSource() {
|
||||
public ClassReaderSource getClassSource() {
|
||||
return classSource;
|
||||
}
|
||||
|
||||
|
@ -59,6 +64,11 @@ class DefaultMetadataGeneratorContext implements MetadataGeneratorContext {
|
|||
proxyBuilder.buildProxy(resourceType)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceTypeDescriptor getTypeDescriptor(Class<? extends Resource> type) {
|
||||
return proxyBuilder.getProxyFactory(type).typeDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Resource> ResourceArray<T> createResourceArray() {
|
||||
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;
|
||||
|
||||
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.wasm.TeaVMWasmHost;
|
||||
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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
import org.teavm.dependency.PluggableDependency;
|
||||
import org.teavm.interop.Unmanaged;
|
||||
|
||||
final class StringAmplifier {
|
||||
private StringAmplifier() {
|
||||
}
|
||||
|
||||
@PluggableDependency(StringAmplifierDependencyPlugin.class)
|
||||
@Unmanaged
|
||||
static native String amplify(String string);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user