Skip to content

Commit

Permalink
Compilation: Add driver/frontend support for pic/pie options
Browse files Browse the repository at this point in the history
  • Loading branch information
ehaas committed Sep 8, 2024
1 parent adfd13c commit 8a1c047
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/aro/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ const Allocator = mem.Allocator;
const assert = std.debug.assert;
const EpochSeconds = std.time.epoch.EpochSeconds;
const mem = std.mem;
const Interner = @import("backend").Interner;
const backend = @import("backend");
const Interner = backend.Interner;
const CodeGenOptions = backend.CodeGenOptions;
const Builtins = @import("Builtins.zig");
const Builtin = Builtins.Builtin;
const Diagnostics = @import("Diagnostics.zig");
Expand Down Expand Up @@ -92,6 +94,7 @@ const Compilation = @This();
gpa: Allocator,
diagnostics: Diagnostics,

code_gen_options: CodeGenOptions = .default,
environment: Environment = .{},
sources: std.StringArrayHashMapUnmanaged(Source) = .{},
include_dirs: std.ArrayListUnmanaged([]const u8) = .{},
Expand Down Expand Up @@ -527,6 +530,24 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void {
\\#define __DECIMAL_DIG__ __LDBL_DECIMAL_DIG__
\\
);

switch (comp.code_gen_options.pic_level) {
.none => {},
.one, .two => {
try w.print(
\\#define __pic__ {0d}
\\#define __PIC__ {0d}
\\
, .{@intFromEnum(comp.code_gen_options.pic_level)});
if (comp.code_gen_options.is_pie) {
try w.print(
\\#define __pie__ {0d}
\\#define __PIE__ {0d}
\\
, .{@intFromEnum(comp.code_gen_options.pic_level)});
}
},
}
}

/// Generate builtin macros that will be available to each source file.
Expand Down
31 changes: 31 additions & 0 deletions src/aro/Driver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ color: ?bool = null,
nobuiltininc: bool = false,
nostdinc: bool = false,
nostdlibinc: bool = false,
desired_pic_level: ?backend.CodeGenOptions.PicLevel = null,
desired_pie_level: ?backend.CodeGenOptions.PicLevel = null,
debug_dump_letters: packed struct(u3) {
d: bool = false,
m: bool = false,
Expand Down Expand Up @@ -115,6 +117,8 @@ pub const usage =
\\ -fno-char8_t Disable char8_t (disabled by default for pre-C23)
\\ -fcolor-diagnostics Enable colors in diagnostics
\\ -fno-color-diagnostics Disable colors in diagnostics
\\ -fcommon Place uninitialized global variables in a common block
\\ -fno-common Place uninitialized global variables in the BSS section of the object file
\\ -fdeclspec Enable support for __declspec attributes
\\ -fgnuc-version=<value> Controls value of __GNUC__ and related macros. Set to 0 or empty to disable them.
\\ -fno-declspec Disable support for __declspec attributes
Expand All @@ -135,6 +139,10 @@ pub const usage =
\\ -fnative-half-type Use the native half type for __fp16 instead of promoting to float
\\ -fnative-half-arguments-and-returns
\\ Allow half-precision function arguments and return values
\\ -fpic Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine
\\ -fPIC Similar to -fpic but avoid any limit on the size of the global offset table
\\ -fpie Similar to -fpic, but the generated position-independent code can only be linked into executables
\\ -fPIE Similar to -fPIC, but the generated position-independent code can only be linked into executables
\\ -fshort-enums Use the narrowest possible integer type for enums
\\ -fno-short-enums Use "int" as the tag type for enums
\\ -fsigned-char "char" is signed
Expand Down Expand Up @@ -273,6 +281,10 @@ pub fn parseArgs(
d.color = true;
} else if (mem.eql(u8, arg, "-fno-color-diagnostics")) {
d.color = false;
} else if (mem.eql(u8, arg, "-fcommon")) {
d.comp.code_gen_options.common = true;
} else if (mem.eql(u8, arg, "-fno-common")) {
d.comp.code_gen_options.common = false;
} else if (mem.eql(u8, arg, "-fdollars-in-identifiers")) {
d.comp.langopts.dollars_in_identifiers = true;
} else if (mem.eql(u8, arg, "-fno-dollars-in-identifiers")) {
Expand All @@ -297,6 +309,21 @@ pub fn parseArgs(
d.comp.langopts.use_native_half_type = true;
} else if (mem.eql(u8, arg, "-fnative-half-arguments-and-returns")) {
d.comp.langopts.allow_half_args_and_returns = true;
} else if (mem.eql(u8, arg, "-fno-pic") or mem.eql(u8, arg, "-fno-PIC") or mem.eql(u8, arg, "-fno-pie") or mem.eql(u8, arg, "-fno-PIE")) {
d.desired_pic_level = .none;
d.desired_pie_level = .none;
} else if (mem.eql(u8, arg, "-fpic")) {
d.desired_pic_level = .one;
d.desired_pie_level = .none;
} else if (mem.eql(u8, arg, "-fPIC")) {
d.desired_pic_level = .two;
d.desired_pie_level = .none;
} else if (mem.eql(u8, arg, "-fpie")) {
d.desired_pic_level = .one;
d.desired_pie_level = .one;
} else if (mem.eql(u8, arg, "-fPIE")) {
d.desired_pic_level = .two;
d.desired_pie_level = .two;
} else if (mem.eql(u8, arg, "-fshort-enums")) {
d.comp.langopts.short_enums = true;
} else if (mem.eql(u8, arg, "-fno-short-enums")) {
Expand Down Expand Up @@ -507,6 +534,10 @@ pub fn parseArgs(
return d.fatal("invalid value '{0s}' in '-fgnuc-version={0s}'", .{gnuc_version});
}
d.comp.langopts.gnuc_version = version.toUnsigned();
const wants_pie: ?bool = if (d.desired_pie_level) |level| level != .none else null;
const pic_level, const is_pie = target_util.getPICMode(d.comp.target, d.desired_pic_level, wants_pie);
d.comp.code_gen_options.pic_level = pic_level;
d.comp.code_gen_options.is_pie = is_pie;
return false;
}

Expand Down
7 changes: 7 additions & 0 deletions src/aro/target.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const std = @import("std");
const LangOpts = @import("LangOpts.zig");
const Type = @import("Type.zig");
const TargetSet = @import("Builtins/Properties.zig").TargetSet;
const backend = @import("backend");

/// intmax_t for this target
pub fn intMaxType(target: std.Target) Type {
Expand Down Expand Up @@ -722,6 +723,12 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 {
return stream.getWritten();
}

/// This currently just returns the desired settings without considering target defaults / requirements
pub fn getPICMode(target: std.Target, desired_pic_level: ?backend.CodeGenOptions.PicLevel, wants_pie: ?bool) struct { backend.CodeGenOptions.PicLevel, bool } {
_ = target;
return .{ desired_pic_level orelse .none, wants_pie orelse false };
}

test "alignment functions - smoke test" {
var target: std.Target = undefined;
const x86 = std.Target.Cpu.Arch.x86_64;
Expand Down
1 change: 1 addition & 0 deletions src/backend.zig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pub const Interner = @import("backend/Interner.zig");
pub const Ir = @import("backend/Ir.zig");
pub const Object = @import("backend/Object.zig");
pub const CodeGenOptions = @import("backend/CodeGenOptions.zig");

pub const CallingConvention = enum {
C,
Expand Down
27 changes: 27 additions & 0 deletions src/backend/CodeGenOptions.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// place uninitialized global variables in a common block
common: bool,
/// Place each function into its own section in the output file if the target supports arbitrary sections
func_sections: bool,
/// Place each data item into its own section in the output file if the target supports arbitrary sections
data_sections: bool,
pic_level: PicLevel,
/// Generate position-independent code that can only be linked into executables
is_pie: bool,

pub const PicLevel = enum(u8) {
/// Do not generate position-independent code
none = 0,
/// Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine.
one = 1,
/// If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding
/// any limit on the size of the global offset table.
two = 2,
};

pub const default: @This() = .{
.common = false,
.func_sections = false,
.data_sections = false,
.pic_level = .none,
.is_pie = false,
};
7 changes: 7 additions & 0 deletions test/cases/pic1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//aro-args --target=x86_64-linux-gnu -fpic

_Static_assert(__pic__ == 1, "");
_Static_assert(__PIC__ == 1, "");
#if defined __pie__ || defined __PIE__
#error __pie__ and __PIE__ should not be defined
#endif
7 changes: 7 additions & 0 deletions test/cases/pic2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//aro-args --target=x86_64-linux-gnu -fPIC

_Static_assert(__pic__ == 2, "");
_Static_assert(__PIC__ == 2, "");
#if defined __pie__ || defined __PIE__
#error __pie__ and __PIE__ should not be defined
#endif
6 changes: 6 additions & 0 deletions test/cases/pie1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//aro-args --target=x86_64-linux-gnu -fpie

_Static_assert(__pic__ == 1, "");
_Static_assert(__PIC__ == 1, "");
_Static_assert(__pie__ == 1, "");
_Static_assert(__PIE__ == 1, "");
6 changes: 6 additions & 0 deletions test/cases/pie2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//aro-args --target=x86_64-linux-gnu -fPIE

_Static_assert(__pic__ == 2, "");
_Static_assert(__PIC__ == 2, "");
_Static_assert(__pie__ == 2, "");
_Static_assert(__PIE__ == 2, "");

0 comments on commit 8a1c047

Please sign in to comment.