Skip to content

Commit 0046365

Browse files
committed
refactor our compiler substitutes into separate classes
1 parent 5301c08 commit 0046365

File tree

5 files changed

+439
-233
lines changed

5 files changed

+439
-233
lines changed
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.shell;
42+
43+
import java.io.IOException;
44+
import java.nio.file.Files;
45+
import java.nio.file.Path;
46+
import java.nio.file.Paths;
47+
import java.nio.file.StandardCopyOption;
48+
import java.util.ArrayList;
49+
import java.util.Arrays;
50+
import java.util.List;
51+
52+
public class GraalPythonCC extends GraalPythonCompiler {
53+
private String outputFilename;
54+
private boolean linkExecutable;
55+
private boolean link;
56+
private Boolean compile;
57+
private List<String> clangArgs;
58+
private List<String> fileInputs;
59+
60+
GraalPythonCC() {
61+
}
62+
63+
private static List<String> clangPrefix = Arrays.asList(new String[]{
64+
"clang",
65+
"-emit-llvm",
66+
"-fPIC",
67+
"-Wno-int-to-void-pointer-cast",
68+
"-Wno-int-conversion",
69+
"-Wno-incompatible-pointer-types-discards-qualifiers",
70+
"-ggdb",
71+
"-O1",
72+
});
73+
private static List<String> optPrefix = Arrays.asList(new String[]{
74+
"opt",
75+
"-mem2reg",
76+
"-globalopt",
77+
"-simplifycfg",
78+
"-constprop",
79+
"-always-inline",
80+
"-instcombine",
81+
"-dse",
82+
"-loop-simplify",
83+
"-reassociate",
84+
"-licm",
85+
"-gvn",
86+
"-o",
87+
});
88+
89+
static void main(String[] args) {
90+
new GraalPythonCC().run(args);
91+
}
92+
93+
private void run(String[] args) {
94+
parseOptions(args);
95+
launchCC();
96+
}
97+
98+
private void parseOptions(String[] args) {
99+
outputFilename = A_OUT;
100+
linkExecutable = true;
101+
link = true;
102+
verbose = false;
103+
compile = null;
104+
clangArgs = new ArrayList<>(clangPrefix);
105+
fileInputs = new ArrayList<>();
106+
for (int i = 0; i < args.length; i++) {
107+
String arg = args[i];
108+
switch (arg) {
109+
case "-o":
110+
clangArgs.add(arg);
111+
i++;
112+
if (i >= args.length) {
113+
throw new RuntimeException("-o needs an argument");
114+
}
115+
outputFilename = arg = args[i];
116+
break;
117+
case "-shared":
118+
linkExecutable = false;
119+
break;
120+
case "-c":
121+
link = false;
122+
linkExecutable = false;
123+
break;
124+
case "-v":
125+
if (!verbose) {
126+
verbose = true;
127+
continue; // the first verbose is not passed on to clang
128+
}
129+
break;
130+
default:
131+
if (arg.endsWith(".o") || arg.endsWith(".bc")) {
132+
if (compile == null) {
133+
compile = false;
134+
} else if (compile != false) {
135+
throw new RuntimeException("cannot mix source and compiled sources");
136+
}
137+
fileInputs.add(arg);
138+
} else if (arg.endsWith(".c") || arg.endsWith(".cpp") || arg.endsWith(".cxx")) {
139+
if (compile == null) {
140+
compile = true;
141+
} else if (compile != true) {
142+
throw new RuntimeException("cannot mix source and compiled sources");
143+
}
144+
fileInputs.add(arg);
145+
}
146+
}
147+
clangArgs.add(arg);
148+
}
149+
String targetFlags = System.getenv("LLVM_TARGET_FLAGS");
150+
if (targetFlags != null) {
151+
clangArgs.addAll(Arrays.asList(targetFlags.split(" ")));
152+
}
153+
}
154+
155+
private void launchCC() {
156+
// run the clang compiler to generate bc files
157+
try {
158+
Files.delete(Paths.get(outputFilename));
159+
} catch (IOException e) {
160+
// no matter;
161+
}
162+
163+
if (compile) {
164+
exec(clangArgs);
165+
logV("opt: ", fileInputs);
166+
if (!Files.exists(Paths.get(outputFilename))) {
167+
// if no explicit output filename was given or produced, we search the commandline
168+
// for files for which now have a bc file and optimize those. This happens when you
169+
// pass multiple .c files to clang and ask it to emit llvm bitcode
170+
for (String f : fileInputs) {
171+
String bcFile = bcFileFromFilename(f);
172+
assert Files.exists(Paths.get(bcFile));
173+
optFile(bcFile);
174+
}
175+
} else {
176+
optFile(outputFilename);
177+
}
178+
}
179+
180+
if (link) {
181+
linkShared(fileInputs);
182+
if (!linkExecutable) {
183+
try {
184+
Path linkedBCfile = Files.move(Paths.get(outputFilename), Paths.get(bcFileFromFilename(outputFilename)), StandardCopyOption.REPLACE_EXISTING);
185+
linkExecutable(outputFilename, linkedBCfile.toString());
186+
} catch (IOException e) {
187+
throw new RuntimeException(e);
188+
}
189+
}
190+
}
191+
}
192+
193+
private static void linkExecutable(String executableScript, String linkedBcFile) throws IOException {
194+
List<String> cmdline = GraalPythonMain.getCmdline(Arrays.asList(), Arrays.asList());
195+
cmdline.add("-LLI");
196+
cmdline.add(linkedBcFile);
197+
Files.write(Paths.get(executableScript), ("#!" + String.join(" ", cmdline)).getBytes());
198+
}
199+
200+
private void linkShared(List<String> bitcodeFiles) {
201+
if (fileInputs.size() > 1) {
202+
ArrayList<String> ldCmd = new ArrayList<>(bitcodeFiles);
203+
if (verbose) {
204+
ldCmd.add("-v");
205+
}
206+
ldCmd.add("-o");
207+
ldCmd.add(outputFilename);
208+
GraalPythonLD.main(ldCmd.toArray(new String[0]));
209+
}
210+
}
211+
212+
private void optFile(String bcFile) {
213+
List<String> opt = new ArrayList<>(optPrefix);
214+
opt.add(bcFile);
215+
opt.add(bcFile);
216+
exec(opt);
217+
}
218+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
package com.oracle.graal.python.shell;
42+
43+
import java.io.IOException;
44+
import java.util.List;
45+
46+
public class GraalPythonCompiler {
47+
protected static final String A_OUT = "a.out";
48+
49+
protected static String bcFileFromFilename(String f) {
50+
int dotIdx = f.lastIndexOf('.');
51+
if (dotIdx > 1) {
52+
return f.substring(0, dotIdx + 1) + "bc";
53+
} else {
54+
return f + ".bc";
55+
}
56+
}
57+
58+
protected boolean verbose;
59+
60+
public GraalPythonCompiler() {
61+
super();
62+
}
63+
64+
protected void exec(List<String> args) {
65+
try {
66+
ProcessBuilder processBuilder = new ProcessBuilder();
67+
processBuilder.inheritIO();
68+
processBuilder.command(args);
69+
logV(args);
70+
int status = processBuilder.start().waitFor();
71+
if (status != 0) {
72+
System.exit(status);
73+
}
74+
} catch (IOException | InterruptedException e) {
75+
throw new RuntimeException(e);
76+
}
77+
}
78+
79+
protected void logV(String prefix, List<String> args) {
80+
if (verbose) {
81+
System.err.print("[python] ");
82+
System.err.print("[" + getClass().getSimpleName() + "] ");
83+
if (prefix != null) {
84+
System.err.print(prefix);
85+
}
86+
System.err.println(String.join(" ", args));
87+
}
88+
}
89+
90+
protected void logV(List<String> args) {
91+
logV(null, args);
92+
}
93+
94+
}

0 commit comments

Comments
 (0)