2525package com .oracle .svm .hosted .c .codegen ;
2626
2727import static com .oracle .svm .core .util .VMError .shouldNotReachHere ;
28- import static com .oracle .svm .core .util .VMError .shouldNotReachHereUnexpectedInput ;
2928import static com .oracle .svm .hosted .NativeImageOptions .CStandards .C11 ;
3029import static com .oracle .svm .hosted .NativeImageOptions .CStandards .C99 ;
3130
3231import java .io .BufferedWriter ;
3332import java .io .IOException ;
33+ import java .lang .reflect .AnnotatedType ;
3434import java .nio .channels .ClosedByInterruptException ;
3535import java .nio .charset .StandardCharsets ;
3636import java .nio .file .Files ;
4040import java .util .Arrays ;
4141import java .util .Collections ;
4242import java .util .List ;
43- import java .util .Optional ;
4443
4544import org .graalvm .nativeimage .c .function .CFunctionPointer ;
4645import org .graalvm .nativeimage .c .function .InvokeCFunctionPointer ;
47- import org .graalvm .word .SignedWord ;
48- import org .graalvm .word .UnsignedWord ;
46+ import org .graalvm .nativeimage .c .type .CTypedef ;
4947
5048import com .oracle .svm .core .util .InterruptImageBuilding ;
5149import com .oracle .svm .core .util .UserError ;
@@ -108,11 +106,11 @@ public void includeFiles(List<String> headerFiles) {
108106 if (headerFile .startsWith ("<" ) && headerFile .endsWith (">" )) {
109107 headerFileName = headerFile .substring (1 , headerFile .length () - 1 );
110108 Path headerFilePath = Paths .get (headerFileName );
111- appendln ("#include " + "<" + headerFilePath . toString () + ">" );
109+ appendln ("#include " + "<" + headerFilePath + ">" );
112110 } else if (headerFile .startsWith ("\" " ) && headerFile .endsWith ("\" " )) {
113111 headerFileName = headerFile .substring (1 , headerFile .length () - 1 );
114112 Path headerFilePath = Paths .get (headerFileName );
115- appendln ("#include " + "\" " + headerFilePath . toString () + "\" " );
113+ appendln ("#include " + "\" " + headerFilePath + "\" " );
116114 } else {
117115 throw UserError .abort ("Header file name must be surrounded by <...> or \" ...\" : %s" , headerFile );
118116 }
@@ -130,7 +128,7 @@ public CSourceCodeWriter printf(String firstArg, String secondArg, String thirdA
130128 }
131129
132130 public CSourceCodeWriter indents () {
133- assert currentLine .length () == 0 : "indenting in the middle of a line" ;
131+ assert currentLine .isEmpty () : "indenting in the middle of a line" ;
134132 for (int i = 0 ; i < indentLevel ; i ++) {
135133 append (INDENT4 );
136134 }
@@ -167,7 +165,7 @@ public CSourceCodeWriter append(String str) {
167165 }
168166
169167 public Path writeFile (String fileName ) {
170- assert currentLine .length () == 0 : "last line not finished" ;
168+ assert currentLine .isEmpty () : "last line not finished" ;
171169
172170 Path outputFile = tempDirectory .resolve (fileName );
173171 try (BufferedWriter writer = Files .newBufferedWriter (outputFile , StandardCharsets .UTF_8 )) {
@@ -184,83 +182,82 @@ public Path writeFile(String fileName) {
184182 return outputFile ;
185183 }
186184
187- public static String toCTypeName (ResolvedJavaMethod method , ResolvedJavaType type , Optional <String > useSiteTypedef , boolean isConst , boolean isUnsigned , MetaAccessProvider metaAccess ,
188- NativeLibraries nativeLibs ) {
189- boolean isNumericInteger = type .getJavaKind ().isNumericInteger ();
190- UserError .guarantee (isNumericInteger || !isUnsigned ,
191- "Only integer types can be unsigned. %s is not an integer type in %s" , type , method );
192-
193- boolean isUnsignedWord = metaAccess .lookupJavaType (UnsignedWord .class ).isAssignableFrom (type );
194- boolean isSignedWord = metaAccess .lookupJavaType (SignedWord .class ).isAssignableFrom (type );
195- boolean isWord = isUnsignedWord || isSignedWord ;
196- boolean isObject = type .getJavaKind () == JavaKind .Object && !isWord ;
197- UserError .guarantee (isObject || !isConst ,
198- "Only pointer types can be const. %s in method %s is not a pointer type." , type , method );
199-
200- if (useSiteTypedef .isPresent ()) {
201- return (isConst ? "const " : "" ) + useSiteTypedef .get ();
202- } else if (isNumericInteger ) {
203- return toCIntegerType (type , isUnsigned );
204- } else if (isUnsignedWord ) {
205- return "size_t" ;
206- } else if (isSignedWord ) {
207- return "ssize_t" ;
208- } else if (isObject ) {
185+ public static String toCTypeName (ResolvedJavaMethod method , ResolvedJavaType type , AnnotatedType annotatedType , boolean isConst , MetaAccessProvider metaAccess , NativeLibraries nativeLibs ) {
186+ CTypedef typeDef = annotatedType .getAnnotation (CTypedef .class );
187+ if (typeDef != null ) {
188+ return (isConst ? "const " : "" ) + typeDef .name ();
189+ }
190+
191+ JavaKind kind = type .getJavaKind ();
192+ if (kind .isObject () && !nativeLibs .isIntegerType (type )) {
209193 return (isConst ? "const " : "" ) + cTypeForObject (type , metaAccess , nativeLibs );
210- } else {
211- switch (type .getJavaKind ()) {
212- case Double :
213- return "double" ;
214- case Float :
215- return "float" ;
216- case Void :
217- return "void" ;
218- default :
219- throw shouldNotReachHereUnexpectedInput (type .getJavaKind ()); // ExcludeFromJacocoGeneratedReport
220- }
221194 }
195+
196+ UserError .guarantee (!isConst , "Only pointer types can be const. %s in method %s is not a pointer type." , type , method );
197+ return cTypeForPrimitive (method , type , annotatedType , nativeLibs );
222198 }
223199
224200 private static String cTypeForObject (ResolvedJavaType type , MetaAccessProvider metaAccess , NativeLibraries nativeLibs ) {
225201 ElementInfo elementInfo = nativeLibs .findElementInfo (type );
226- if (elementInfo instanceof PointerToInfo ) {
227- PointerToInfo pointerToInfo = (PointerToInfo ) elementInfo ;
202+ if (elementInfo instanceof PointerToInfo pointerToInfo ) {
228203 return (pointerToInfo .getTypedefName () != null ? pointerToInfo .getTypedefName () : pointerToInfo .getName () + "*" );
229- } else if (elementInfo instanceof StructInfo ) {
230- StructInfo structInfo = (StructInfo ) elementInfo ;
204+ } else if (elementInfo instanceof StructInfo structInfo ) {
231205 return structInfo .getTypedefName () != null ? structInfo .getTypedefName () : structInfo .getName () + "*" ;
232206 } else if (elementInfo instanceof EnumInfo ) {
233207 return elementInfo .getName ();
234- } else if (isFunctionPointer (metaAccess , type )) {
235- return InfoTreeBuilder .getTypedefName (type ) != null ? InfoTreeBuilder .getTypedefName (type ) : "void *" ;
208+ } else if (isFunctionPointer (metaAccess , type ) && InfoTreeBuilder .getTypedefName (type ) != null ) {
209+ return InfoTreeBuilder .getTypedefName (type );
210+ } else {
211+ return "void *" ;
236212 }
237- return "void *" ;
238213 }
239214
240- private static String toCIntegerType ( ResolvedJavaType type , boolean isUnsigned ) {
215+ private static String cTypeForPrimitive ( ResolvedJavaMethod method , ResolvedJavaType type , AnnotatedType annotatedType , NativeLibraries nativeLibs ) {
241216 boolean c11Compatible = NativeImageOptions .getCStandard ().compatibleWith (C11 );
242217 String prefix = "" ;
243- if (isUnsigned ) {
218+ if (isUnsigned ( annotatedType ) ) {
244219 prefix = c11Compatible ? "u" : "unsigned " ;
245220 }
246- switch (type .getJavaKind ()) {
247- case Boolean :
248- if (NativeImageOptions .getCStandard ().compatibleWith (CStandards .C99 )) {
249- return "bool" ;
250- } else {
251- return "int" ;
252- }
221+
222+ JavaKind javaKind = type .getJavaKind ();
223+ switch (javaKind ) {
253224 case Byte :
254225 return prefix + (c11Compatible ? "int8_t" : "char" );
255- case Char :
256226 case Short :
227+ case Char :
257228 return prefix + (c11Compatible ? "int16_t" : "short" );
258229 case Int :
259230 return prefix + (c11Compatible ? "int32_t" : "int" );
260231 case Long :
261232 return prefix + (c11Compatible ? "int64_t" : "long long int" );
262233 }
263- throw VMError .shouldNotReachHere ("All types integer types should be covered. Got " + type .getJavaKind ());
234+
235+ UserError .guarantee (prefix .isEmpty (), "Only integer types can be annotated with @%s. %s in method %s is not an integer type." ,
236+ org .graalvm .nativeimage .c .type .CUnsigned .class .getSimpleName (), type , method );
237+ switch (javaKind ) {
238+ case Boolean :
239+ if (NativeImageOptions .getCStandard ().compatibleWith (CStandards .C99 )) {
240+ return "bool" ;
241+ } else {
242+ return "int" ;
243+ }
244+ case Float :
245+ return "float" ;
246+ case Double :
247+ return "double" ;
248+ case Void :
249+ return "void" ;
250+ case Object :
251+ /* SignedWord or UnsignedWord. */
252+ assert nativeLibs .isIntegerType (type );
253+ return nativeLibs .isSigned (type ) ? "ssize_t" : "size_t" ;
254+ default :
255+ throw VMError .shouldNotReachHere ("Unexpected Java kind " + javaKind );
256+ }
257+ }
258+
259+ private static boolean isUnsigned (AnnotatedType type ) {
260+ return type .isAnnotationPresent (org .graalvm .nativeimage .c .type .CUnsigned .class ) || type .isAnnotationPresent (com .oracle .svm .core .c .CUnsigned .class );
264261 }
265262
266263 private static boolean isFunctionPointer (MetaAccessProvider metaAccess , ResolvedJavaType type ) {
0 commit comments